Merge "Update ListMenuItemView to use a single RelativeLayout"
diff --git a/Android.mk b/Android.mk
index 618f404..db6a704 100644
--- a/Android.mk
+++ b/Android.mk
@@ -125,6 +125,8 @@
 	core/java/android/hardware/ICameraClient.aidl \
 	core/java/android/hardware/IProCameraUser.aidl \
 	core/java/android/hardware/IProCameraCallbacks.aidl \
+	core/java/android/hardware/photography/ICameraDeviceUser.aidl \
+	core/java/android/hardware/photography/ICameraDeviceCallbacks.aidl \
 	core/java/android/hardware/ISerialManager.aidl \
 	core/java/android/hardware/display/IDisplayManager.aidl \
 	core/java/android/hardware/display/IDisplayManagerCallback.aidl \
@@ -160,7 +162,7 @@
 	core/java/android/print/IPrinterDiscoveryObserver.aidl \
 	core/java/android/print/IPrintAdapter.aidl \
 	core/java/android/print/IPrintClient.aidl \
-	core/java/android/print/IPrintProgressListener.aidl \
+	core/java/android/print/IPrintResultCallback.aidl \
 	core/java/android/print/IPrintManager.aidl \
 	core/java/android/print/IPrintSpoolerService.aidl \
 	core/java/android/print/IPrintSpoolerServiceCallbacks.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 0c3ccec..6118fc3 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -161,6 +161,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/view/IInputMethodCallback.*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/api/current.txt b/api/current.txt
index 4debd4d..ac3144d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2697,6 +2697,7 @@
     method public void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
     method public void closeContextMenu();
     method public void closeOptionsMenu();
+    method public void convertToOpaque();
     method public android.app.PendingIntent createPendingResult(int, android.content.Intent, int);
     method public final deprecated void dismissDialog(int);
     method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
@@ -2904,6 +2905,7 @@
     method public android.app.PendingIntent getRunningServiceControlPanel(android.content.ComponentName) throws java.lang.SecurityException;
     method public java.util.List<android.app.ActivityManager.RunningServiceInfo> getRunningServices(int) throws java.lang.SecurityException;
     method public java.util.List<android.app.ActivityManager.RunningTaskInfo> getRunningTasks(int) throws java.lang.SecurityException;
+    method public boolean isLowRamDevice();
     method public static boolean isRunningInTestHarness();
     method public static boolean isUserAMonkey();
     method public void killBackgroundProcesses(java.lang.String);
@@ -6155,6 +6157,7 @@
     field public static final java.lang.String ACTION_PROVIDER_CHANGED = "android.intent.action.PROVIDER_CHANGED";
     field public static final java.lang.String ACTION_QUICK_CLOCK = "android.intent.action.QUICK_CLOCK";
     field public static final java.lang.String ACTION_REBOOT = "android.intent.action.REBOOT";
+    field public static final java.lang.String ACTION_RESTRICTIONS_PIN_CHALLENGE = "android.intent.action.RESTRICTIONS_PIN_CHALLENGE";
     field public static final java.lang.String ACTION_RUN = "android.intent.action.RUN";
     field public static final java.lang.String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF";
     field public static final java.lang.String ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON";
@@ -9154,8 +9157,11 @@
     method public void draw(android.graphics.Canvas, android.graphics.RectF);
     method public void draw(android.graphics.Canvas, android.graphics.Rect);
     method public void draw(android.graphics.Canvas, android.graphics.Rect, android.graphics.Paint);
+    method public android.graphics.Bitmap getBitmap();
     method public int getDensity();
     method public int getHeight();
+    method public java.lang.String getName();
+    method public android.graphics.Paint getPaint();
     method public final android.graphics.Region getTransparentRegion(android.graphics.Rect);
     method public int getWidth();
     method public final boolean hasAlpha();
@@ -10653,7 +10659,7 @@
 
 package android.hardware.photography {
 
-  public class CameraAccessException extends java.lang.Exception {
+  public class CameraAccessException extends android.util.AndroidException {
     ctor public CameraAccessException(int);
     ctor public CameraAccessException(int, java.lang.String);
     ctor public CameraAccessException(int, java.lang.String, java.lang.Throwable);
@@ -10665,19 +10671,18 @@
     field public static final int MAX_CAMERAS_IN_USE = 2; // 0x2
   }
 
-  public final class CameraDevice implements java.lang.AutoCloseable {
-    ctor public CameraDevice();
-    method public void capture(android.hardware.photography.CaptureRequest, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
-    method public void captureBurst(java.util.List<android.hardware.photography.CaptureRequest>, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
-    method public void close();
-    method public void configureOutputs(java.util.List<android.view.Surface>);
-    method public android.hardware.photography.CaptureRequest createCaptureRequest(int) throws android.hardware.photography.CameraAccessException;
-    method public android.hardware.photography.CameraProperties getProperties() throws android.hardware.photography.CameraAccessException;
-    method public void setErrorListener(android.hardware.photography.CameraDevice.ErrorListener);
-    method public void setRepeatingBurst(java.util.List<android.hardware.photography.CaptureRequest>, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
-    method public void setRepeatingRequest(android.hardware.photography.CaptureRequest, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
-    method public void stopRepeating() throws android.hardware.photography.CameraAccessException;
-    method public void waitUntilIdle() throws android.hardware.photography.CameraAccessException;
+  public abstract interface CameraDevice implements java.lang.AutoCloseable {
+    method public abstract void capture(android.hardware.photography.CaptureRequest, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
+    method public abstract void captureBurst(java.util.List<android.hardware.photography.CaptureRequest>, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
+    method public abstract void close() throws java.lang.Exception;
+    method public abstract void configureOutputs(java.util.List<android.view.Surface>) throws android.hardware.photography.CameraAccessException;
+    method public abstract android.hardware.photography.CaptureRequest createCaptureRequest(int) throws android.hardware.photography.CameraAccessException;
+    method public abstract android.hardware.photography.CameraProperties getProperties() throws android.hardware.photography.CameraAccessException;
+    method public abstract void setErrorListener(android.hardware.photography.CameraDevice.ErrorListener);
+    method public abstract void setRepeatingBurst(java.util.List<android.hardware.photography.CaptureRequest>, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
+    method public abstract void setRepeatingRequest(android.hardware.photography.CaptureRequest, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
+    method public abstract void stopRepeating() throws android.hardware.photography.CameraAccessException;
+    method public abstract void waitUntilIdle() throws android.hardware.photography.CameraAccessException;
     field public static final int TEMPLATE_MANUAL = 5; // 0x5
     field public static final int TEMPLATE_PREVIEW = 1; // 0x1
     field public static final int TEMPLATE_RECORD = 2; // 0x2
@@ -10699,7 +10704,7 @@
 
   public final class CameraManager {
     method public android.hardware.photography.CameraProperties getCameraProperties(java.lang.String) throws android.hardware.photography.CameraAccessException;
-    method public java.lang.String[] getDeviceIdList();
+    method public java.lang.String[] getDeviceIdList() throws android.hardware.photography.CameraAccessException;
     method public android.hardware.photography.CameraDevice openCamera(java.lang.String) throws android.hardware.photography.CameraAccessException;
     method public void registerCameraListener(android.hardware.photography.CameraManager.CameraListener);
     method public void unregisterCameraListener(android.hardware.photography.CameraManager.CameraListener);
@@ -10710,10 +10715,12 @@
     method public abstract void onCameraUnavailable(java.lang.String);
   }
 
-  public class CameraMetadata implements android.os.Parcelable {
+  public class CameraMetadata implements java.lang.AutoCloseable android.os.Parcelable {
     ctor public CameraMetadata();
+    method public void close() throws java.lang.Exception;
     method public int describeContents();
     method public T get(android.hardware.photography.CameraMetadata.Key<T>);
+    method public void readFromParcel(android.os.Parcel);
     method public void set(android.hardware.photography.CameraMetadata.Key<T>, T);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
@@ -10742,9 +10749,10 @@
     field public static final android.hardware.photography.CameraMetadata.Key SENSOR_PIXEL_ARRAY_SIZE;
   }
 
-  public final class CaptureRequest extends android.hardware.photography.CameraMetadata {
+  public final class CaptureRequest extends android.hardware.photography.CameraMetadata implements android.os.Parcelable {
     method public void addTarget(android.view.Surface);
     method public void removeTarget(android.view.Surface);
+    field public static final android.os.Parcelable.Creator CREATOR;
     field public static final android.hardware.photography.CameraMetadata.Key SENSOR_EXPOSURE_TIME;
     field public static final android.hardware.photography.CameraMetadata.Key SENSOR_SENSITIVITY;
   }
@@ -11814,26 +11822,24 @@
     field public static final int EULER_Z = 2; // 0x2
   }
 
-  public abstract class Image implements java.lang.AutoCloseable {
-    ctor public Image();
+  public abstract interface Image implements java.lang.AutoCloseable {
     method public abstract void close();
-    method protected final void finalize();
-    method public int getFormat();
-    method public int getHeight();
-    method public android.media.Image.Plane[] getPlanes();
-    method public long getTimestamp();
-    method public int getWidth();
+    method public abstract int getFormat();
+    method public abstract int getHeight();
+    method public abstract android.media.Image.Plane[] getPlanes();
+    method public abstract long getTimestamp();
+    method public abstract int getWidth();
   }
 
-  public static final class Image.Plane {
-    ctor public Image.Plane();
-    method public java.nio.ByteBuffer getBuffer();
-    method public int getPixelStride();
-    method public int getRowStride();
+  public static abstract interface Image.Plane {
+    method public abstract java.nio.ByteBuffer getBuffer();
+    method public abstract int getPixelStride();
+    method public abstract int getRowStride();
   }
 
-  public final class ImageReader {
+  public final class ImageReader implements java.lang.AutoCloseable {
     ctor public ImageReader(int, int, int, int);
+    method public void close();
     method public int getHeight();
     method public int getImageFormat();
     method public int getMaxImages();
@@ -11841,7 +11847,7 @@
     method public android.view.Surface getSurface();
     method public int getWidth();
     method public void releaseImage(android.media.Image);
-    method public void setOnImageAvailableListener(android.media.ImageReader.OnImageAvailableListener);
+    method public void setImageAvailableListener(android.media.ImageReader.OnImageAvailableListener, android.os.Handler);
   }
 
   public static abstract interface ImageReader.OnImageAvailableListener {
@@ -17962,6 +17968,7 @@
     method public java.lang.String getUserName();
     method public android.os.Bundle getUserRestrictions();
     method public android.os.Bundle getUserRestrictions(android.os.UserHandle);
+    method public boolean hasRestrictionsPin();
     method public boolean isUserAGoat();
     method public boolean isUserRunning(android.os.UserHandle);
     method public boolean isUserRunningOrStopping(android.os.UserHandle);
@@ -18404,12 +18411,12 @@
     ctor public PrintAdapter();
     method public abstract android.print.PrintAdapterInfo getInfo();
     method public void onFinish();
-    method public abstract void onPrint(java.util.List<android.print.PageRange>, java.io.FileDescriptor, android.os.CancellationSignal, android.print.PrintAdapter.PrintProgressCallback);
+    method public abstract void onPrint(java.util.List<android.print.PageRange>, java.io.FileDescriptor, android.os.CancellationSignal, android.print.PrintAdapter.PrintResultCallback);
     method public boolean onPrintAttributesChanged(android.print.PrintAttributes);
     method public void onStart();
   }
 
-  public static abstract class PrintAdapter.PrintProgressCallback {
+  public static abstract class PrintAdapter.PrintResultCallback {
     method public void onPrintFailed(java.lang.CharSequence);
     method public void onPrintFinished(java.util.List<android.print.PageRange>);
   }
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 3bbdc48..87ea4fd 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -153,7 +153,7 @@
                 "        test runners.\n" +
                 "    --user <USER_ID> | current: Specify user instrumentation runs in;\n" +
                 "        current user if not specified.\n" +
-                "    --no-window-animation: turn off window animations will running.\n" +
+                "    --no-window-animation: turn off window animations while running.\n" +
                 "\n" +
                 "am profile: start and stop profiler on a process.  The given <PROCESS> argument\n" +
                 "  may be either a process name or pid.  Options are:\n" +
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 6f57ae0..d1ded10 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -147,6 +147,16 @@
             return;
         }
 
+        if ("block".equals(op)) {
+            runSetBlockedSetting(true);
+            return;
+        }
+
+        if ("unblock".equals(op)) {
+            runSetBlockedSetting(false);
+            return;
+        }
+
         if ("grant".equals(op)) {
             runGrantRevokePermission(true);
             return;
@@ -1256,6 +1266,36 @@
         }
     }
 
+    private void runSetBlockedSetting(boolean state) {
+        int userId = 0;
+        String option = nextOption();
+        if (option != null && option.equals("--user")) {
+            String optionData = nextOptionData();
+            if (optionData == null || !isNumber(optionData)) {
+                System.err.println("Error: no USER_ID specified");
+                showUsage();
+                return;
+            } else {
+                userId = Integer.parseInt(optionData);
+            }
+        }
+
+        String pkg = nextArg();
+        if (pkg == null) {
+            System.err.println("Error: no package or component specified");
+            showUsage();
+            return;
+        }
+        try {
+            mPm.setApplicationBlockedSettingAsUser(pkg, state, userId);
+            System.err.println("Package " + pkg + " new blocked state: "
+                    + mPm.getApplicationBlockedSettingAsUser(pkg, userId));
+        } catch (RemoteException e) {
+            System.err.println(e.toString());
+            System.err.println(PM_NOT_RUNNING_ERR);
+        }
+    }
+
     private void runGrantRevokePermission(boolean grant) {
         String pkg = nextArg();
         if (pkg == null) {
@@ -1482,6 +1522,8 @@
         System.err.println("       pm disable [--user USER_ID] PACKAGE_OR_COMPONENT");
         System.err.println("       pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
         System.err.println("       pm disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
+        System.err.println("       pm block [--user USER_ID] PACKAGE_OR_COMPONENT");
+        System.err.println("       pm unblock [--user USER_ID] PACKAGE_OR_COMPONENT");
         System.err.println("       pm grant PACKAGE PERMISSION");
         System.err.println("       pm revoke PACKAGE PERMISSION");
         System.err.println("       pm set-install-location [0/auto] [1/internal] [2/external]");
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 7f2f744..e87d805 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4862,6 +4862,25 @@
     }
 
     /**
+     * Convert a translucent themed Activity {@link android.R.attr#windowIsTranslucent} to a
+     * fullscreen opaque Activity.
+     *
+     * Call this whenever the background of a translucent Activity has changed to become opaque.
+     * Doing so will allow the previously visible Activity behind this one to be stopped. Stopped
+     * apps consume no CPU cycles and are eligible for removal when reclaiming memory.
+     *
+     * This call has no effect on non-translucent activities or on activities with the
+     * {@link android.R.attr#windowIsFloating} attribute.
+     */
+    public void convertToOpaque() {
+        try {
+            ActivityManagerNative.getDefault().convertToOpaque(mToken);
+        } catch (RemoteException e) {
+            // pass
+        }
+    }
+
+    /**
      * Adjust the current immersive mode setting.
      *
      * Note that changing this value will have no effect on the activity's
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 62ed697..780b522 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -16,11 +16,13 @@
 
 package android.app;
 
+import android.R;
 import android.os.BatteryStats;
 import android.os.IBinder;
 import com.android.internal.app.IUsageStats;
 import com.android.internal.os.PkgUsageStats;
 import com.android.internal.os.TransferPipe;
+import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.MemInfoReader;
 
 import android.content.ComponentName;
@@ -376,7 +378,23 @@
         String vmHeapSize = SystemProperties.get("dalvik.vm.heapsize", "16m");
         return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length()-1));
     }
-    
+
+    /**
+     * Returns true if this is a low-RAM device.  Exactly whether a device is low-RAM
+     * is ultimately up to the device configuration, but currently it generally means
+     * something in the class of a 512MB device with about a 800x480 or less screen.
+     * This is mostly intended to be used by apps to determine whether they should turn
+     * off certain features that require more RAM.
+     */
+    public boolean isLowRamDevice() {
+        return isLowRamDeviceStatic();
+    }
+
+    /** @hide */
+    public static boolean isLowRamDeviceStatic() {
+        return Resources.getSystem().getBoolean(com.android.internal.R.bool.config_lowRamDevice);
+    }
+
     /**
      * Used by persistent processes to determine if they are running on a
      * higher-end device so should be okay using hardware drawing acceleration
@@ -384,43 +402,8 @@
      * @hide
      */
     static public boolean isHighEndGfx() {
-        MemInfoReader reader = new MemInfoReader();
-        reader.readMemInfo();
-        if (reader.getTotalSize() >= (512*1024*1024)) {
-            // If the device has at least 512MB RAM available to the kernel,
-            // we can afford the overhead of graphics acceleration.
-            return true;
-        }
-
-        Display display = DisplayManagerGlobal.getInstance().getRealDisplay(
-                Display.DEFAULT_DISPLAY);
-        Point p = new Point();
-        display.getRealSize(p);
-        int pixels = p.x * p.y;
-        if (pixels >= (1024*600)) {
-            // If this is a sufficiently large screen, then there are enough
-            // pixels on it that we'd really like to use hw drawing.
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Use to decide whether the running device can be considered a "large
-     * RAM" device.  Exactly what memory limit large RAM is will vary, but
-     * it essentially means there is plenty of RAM to have lots of background
-     * processes running under decent loads.
-     * @hide
-     */
-    static public boolean isLargeRAM() {
-        MemInfoReader reader = new MemInfoReader();
-        reader.readMemInfo();
-        if (reader.getTotalSize() >= (640*1024*1024)) {
-            // Currently 640MB RAM available to the kernel is the point at
-            // which we have plenty of RAM to spare.
-            return true;
-        }
-        return false;
+        return !isLowRamDeviceStatic() &&
+                !Resources.getSystem().getBoolean(com.android.internal.R.bool.config_avoidGfxAccel);
     }
 
     /**
@@ -2206,12 +2189,14 @@
      */
     public static void dumpPackageStateStatic(FileDescriptor fd, String packageName) {
         FileOutputStream fout = new FileOutputStream(fd);
-        PrintWriter pw = new PrintWriter(fout);
-        dumpService(pw, fd, Context.ACTIVITY_SERVICE, new String[] { "package", packageName});
+        PrintWriter pw = new FastPrintWriter(fout);
+        dumpService(pw, fd, Context.ACTIVITY_SERVICE, new String[] { "package", packageName });
         pw.println();
-        dumpService(pw, fd, "package", new String[] { packageName});
+        dumpService(pw, fd, "procstats", new String[] { packageName });
         pw.println();
-        dumpService(pw, fd, BatteryStats.SERVICE_NAME, new String[] { packageName});
+        dumpService(pw, fd, "package", new String[] { packageName });
+        pw.println();
+        dumpService(pw, fd, BatteryStats.SERVICE_NAME, new String[] { packageName });
         pw.flush();
     }
 
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 1573398..b966d6d 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1499,6 +1499,14 @@
             return true;
         }
 
+        case CONVERT_TO_OPAQUE_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IBinder token = data.readStrongBinder();
+            convertToOpaque(token);
+            reply.writeNoException();
+            return true;
+        }
+
         case SET_IMMERSIVE_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
@@ -3823,7 +3831,19 @@
         data.recycle();
         reply.recycle();
     }
-    
+
+    public void convertToOpaque(IBinder token)
+            throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(token);
+        mRemote.transact(CONVERT_TO_OPAQUE_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
     public void setImmersive(IBinder token, boolean immersive)
             throws RemoteException {
         Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 4a41896..bf89fa6 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -16,6 +16,8 @@
 
 package android.app;
 
+import static android.view.DisplayAdjustments.DEVELOPMENT_RESOURCES_DEPEND_ON_ACTIVITY_TOKEN;
+
 import android.app.backup.BackupAgent;
 import android.content.BroadcastReceiver;
 import android.content.ComponentCallbacks2;
@@ -75,7 +77,7 @@
 import android.util.LogPrinter;
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
-import android.view.CompatibilityInfoHolder;
+import android.view.DisplayAdjustments;
 import android.view.Display;
 import android.view.HardwareRenderer;
 import android.view.View;
@@ -91,6 +93,7 @@
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.RuntimeInit;
 import com.android.internal.os.SamplingProfilerIntegration;
+import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.Objects;
 import com.android.org.conscrypt.OpenSSLSocketImpl;
 
@@ -209,8 +212,8 @@
             = new HashMap<String, WeakReference<LoadedApk>>();
     final HashMap<String, WeakReference<LoadedApk>> mResourcePackages
             = new HashMap<String, WeakReference<LoadedApk>>();
-    final HashMap<CompatibilityInfo, DisplayMetrics> mDefaultDisplayMetrics
-            = new HashMap<CompatibilityInfo, DisplayMetrics>();
+    final HashMap<DisplayAdjustments, DisplayMetrics> mDefaultDisplayMetrics
+            = new HashMap<DisplayAdjustments, DisplayMetrics>();
     final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
             = new HashMap<ResourcesKey, WeakReference<Resources> >();
     final ArrayList<ActivityClientRecord> mRelaunchingActivities
@@ -897,7 +900,7 @@
         public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, boolean checkin,
                 boolean dumpInfo, boolean dumpDalvik, String[] args) {
             FileOutputStream fout = new FileOutputStream(fd);
-            PrintWriter pw = new PrintWriter(fout);
+            PrintWriter pw = new FastPrintWriter(fout);
             try {
                 return dumpMemInfo(pw, checkin, dumpInfo, dumpDalvik);
             } finally {
@@ -1174,7 +1177,7 @@
 
         @Override
         public void dumpDbInfo(FileDescriptor fd, String[] args) {
-            PrintWriter pw = new PrintWriter(new FileOutputStream(fd));
+            PrintWriter pw = new FastPrintWriter(new FileOutputStream(fd));
             PrintWriterPrinter printer = new PrintWriterPrinter(pw);
             SQLiteDebug.dump(printer, args);
             pw.flush();
@@ -1554,6 +1557,7 @@
     }
 
     private class Idler implements MessageQueue.IdleHandler {
+        @Override
         public final boolean queueIdle() {
             ActivityClientRecord a = mNewActivities;
             boolean stopProfiling = false;
@@ -1592,6 +1596,7 @@
     }
 
     final class GcIdler implements MessageQueue.IdleHandler {
+        @Override
         public final boolean queueIdle() {
             doGcIfNeeded();
             return false;
@@ -1604,8 +1609,10 @@
         final private Configuration mOverrideConfiguration;
         final private float mScale;
         final private int mHash;
+        final private IBinder mToken;
 
-        ResourcesKey(String resDir, int displayId, Configuration overrideConfiguration, float scale) {
+        ResourcesKey(String resDir, int displayId, Configuration overrideConfiguration,
+                float scale, IBinder token) {
             mResDir = resDir;
             mDisplayId = displayId;
             if (overrideConfiguration != null) {
@@ -1621,6 +1628,12 @@
             hash = 31 * hash + (mOverrideConfiguration != null
                     ? mOverrideConfiguration.hashCode() : 0);
             hash = 31 * hash + Float.floatToIntBits(mScale);
+            if (DEVELOPMENT_RESOURCES_DEPEND_ON_ACTIVITY_TOKEN) {
+                mToken = token;
+                hash = 31 * hash + (mToken == null ? 0 : mToken.hashCode());
+            } else {
+                mToken = null;
+            }
             mHash = hash;
         }
 
@@ -1693,9 +1706,13 @@
         mDefaultDisplayMetrics.clear();
     }
 
-    DisplayMetrics getDisplayMetricsLocked(int displayId, CompatibilityInfo ci) {
+    DisplayMetrics getDisplayMetricsLocked(int displayId) {
+        return getDisplayMetricsLocked(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
+    }
+
+    DisplayMetrics getDisplayMetricsLocked(int displayId, DisplayAdjustments daj) {
         boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
-        DisplayMetrics dm = isDefaultDisplay ? mDefaultDisplayMetrics.get(ci) : null;
+        DisplayMetrics dm = isDefaultDisplay ? mDefaultDisplayMetrics.get(daj) : null;
         if (dm != null) {
             return dm;
         }
@@ -1709,12 +1726,10 @@
         }
 
         if (isDefaultDisplay) {
-            mDefaultDisplayMetrics.put(ci, dm);
+            mDefaultDisplayMetrics.put(daj, dm);
         }
 
-        CompatibilityInfoHolder cih = new CompatibilityInfoHolder();
-        cih.set(ci);
-        Display d = displayManager.getCompatibleDisplay(displayId, cih);
+        Display d = displayManager.getCompatibleDisplay(displayId, daj);
         if (d != null) {
             d.getMetrics(dm);
         } else {
@@ -1736,7 +1751,7 @@
         if (config == null) {
             return null;
         }
-        if (compat != null && !compat.supportsScreen()) {
+        if (!compat.supportsScreen()) {
             mMainThreadConfig.setTo(config);
             config = mMainThreadConfig;
             compat.applyToConfiguration(displayDensity, config);
@@ -1748,21 +1763,19 @@
      * Creates the top level Resources for applications with the given compatibility info.
      *
      * @param resDir the resource directory.
-     * @param compInfo the compability info. It will use the default compatibility info when it's
-     * null.
+     * @param compatInfo the compability info. Must not be null.
+     * @param token the application token for determining stack bounds.
      */
-    Resources getTopLevelResources(String resDir,
-            int displayId, Configuration overrideConfiguration,
-            CompatibilityInfo compInfo) {
-        ResourcesKey key = new ResourcesKey(resDir,
-                displayId, overrideConfiguration,
-                compInfo.applicationScale);
+    Resources getTopLevelResources(String resDir, int displayId,
+            Configuration overrideConfiguration, CompatibilityInfo compatInfo, IBinder token) {
+        final float scale = compatInfo.applicationScale;
+        ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfiguration, scale,
+                token);
         Resources r;
         synchronized (mPackages) {
             // Resources is app scale dependent.
             if (false) {
-                Slog.w(TAG, "getTopLevelResources: " + resDir + " / "
-                        + compInfo.applicationScale);
+                Slog.w(TAG, "getTopLevelResources: " + resDir + " / " + scale);
             }
             WeakReference<Resources> wr = mActiveResources.get(key);
             r = wr != null ? wr.get() : null;
@@ -1787,7 +1800,7 @@
         }
 
         //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
-        DisplayMetrics dm = getDisplayMetricsLocked(displayId, null);
+        DisplayMetrics dm = getDisplayMetricsLocked(displayId);
         Configuration config;
         boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
         if (!isDefaultDisplay || key.mOverrideConfiguration != null) {
@@ -1801,7 +1814,7 @@
         } else {
             config = getConfiguration();
         }
-        r = new Resources(assets, dm, config, compInfo);
+        r = new Resources(assets, dm, config, compatInfo, token);
         if (false) {
             Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
                     + r.getConfiguration() + " appScale="
@@ -1831,7 +1844,7 @@
             int displayId, Configuration overrideConfiguration,
             LoadedApk pkgInfo) {
         return getTopLevelResources(resDir, displayId, overrideConfiguration,
-                pkgInfo.mCompatibilityInfo.get());
+                pkgInfo.getCompatibilityInfo(), null);
     }
 
     final Handler getHandler() {
@@ -2005,10 +2018,8 @@
                 LoadedApk info = new LoadedApk(this, "android", context, null,
                         CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
                 context.init(info, null, this);
-                context.getResources().updateConfiguration(
-                        getConfiguration(), getDisplayMetricsLocked(
-                                Display.DEFAULT_DISPLAY,
-                                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO));
+                context.getResources().updateConfiguration(getConfiguration(),
+                        getDisplayMetricsLocked(Display.DEFAULT_DISPLAY));
                 mSystemContext = context;
                 //Slog.i(TAG, "Created system resources " + context.getResources()
                 //        + ": " + context.getResources().getConfiguration());
@@ -2034,7 +2045,7 @@
             dalvik.system.VMRuntime.getRuntime().startJitCompilation();
         }
     }
-    
+
     void scheduleGcIdler() {
         if (!mGcIdlerScheduled) {
             mGcIdlerScheduled = true;
@@ -2301,7 +2312,7 @@
             DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
             for (int displayId : dm.getDisplayIds()) {
                 if (displayId != Display.DEFAULT_DISPLAY) {
-                    Display display = dm.getRealDisplay(displayId);
+                    Display display = dm.getRealDisplay(displayId, r.token);
                     baseContext = appContext.createDisplayContext(display);
                     break;
                 }
@@ -2720,7 +2731,8 @@
         try {
             Service s = mServices.get(info.token);
             if (s != null) {
-                PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
+                PrintWriter pw = new FastPrintWriter(new FileOutputStream(
+                        info.fd.getFileDescriptor()));
                 s.dump(info.fd.getFileDescriptor(), pw, info.args);
                 pw.flush();
             }
@@ -2735,7 +2747,8 @@
         try {
             ActivityClientRecord r = mActivities.get(info.token);
             if (r != null && r.activity != null) {
-                PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
+                PrintWriter pw = new FastPrintWriter(new FileOutputStream(
+                        info.fd.getFileDescriptor()));
                 r.activity.dump(info.prefix, info.fd.getFileDescriptor(), pw, info.args);
                 pw.flush();
             }
@@ -2750,7 +2763,8 @@
         try {
             ProviderClientRecord r = mLocalProviders.get(info.token);
             if (r != null && r.mLocalProvider != null) {
-                PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
+                PrintWriter pw = new FastPrintWriter(new FileOutputStream(
+                        info.fd.getFileDescriptor()));
                 r.mLocalProvider.dump(info.fd.getFileDescriptor(), pw, info.args);
                 pw.flush();
             }
@@ -3408,11 +3422,11 @@
     private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) {
         LoadedApk apk = peekPackageInfo(data.pkg, false);
         if (apk != null) {
-            apk.mCompatibilityInfo.set(data.info);
+            apk.setCompatibilityInfo(data.info);
         }
         apk = peekPackageInfo(data.pkg, true);
         if (apk != null) {
-            apk.mCompatibilityInfo.set(data.info);
+            apk.setCompatibilityInfo(data.info);
         }
         handleConfigurationChanged(mConfiguration, data.info);
         WindowManagerGlobal.getInstance().reportNewConfiguration(mConfiguration);
@@ -3844,8 +3858,9 @@
                 for (ActivityClientRecord ar : mActivities.values()) {
                     Activity a = ar.activity;
                     if (a != null) {
-                        Configuration thisConfig = applyConfigCompatMainThread(mCurDefaultDisplayDpi,
-                                newConfig, ar.packageInfo.mCompatibilityInfo.getIfNeeded());
+                        Configuration thisConfig = applyConfigCompatMainThread(
+                                mCurDefaultDisplayDpi, newConfig,
+                                ar.packageInfo.getCompatibilityInfo());
                         if (!ar.activity.mFinished && (allActivities || !ar.paused)) {
                             // If the activity is currently resumed, its configuration
                             // needs to change right now.
@@ -3945,8 +3960,7 @@
         }
         int changes = mResConfiguration.updateFrom(config);
         flushDisplayMetricsLocked();
-        DisplayMetrics defaultDisplayMetrics = getDisplayMetricsLocked(
-                Display.DEFAULT_DISPLAY, null);
+        DisplayMetrics defaultDisplayMetrics = getDisplayMetricsLocked(Display.DEFAULT_DISPLAY);
 
         if (compat != null && (mResCompatibilityInfo == null ||
                 !mResCompatibilityInfo.equals(compat))) {
@@ -3986,7 +4000,7 @@
                     }
                     tmpConfig.setTo(config);
                     if (!isDefaultDisplay) {
-                        dm = getDisplayMetricsLocked(displayId, null);
+                        dm = getDisplayMetricsLocked(displayId);
                         applyNonDefaultDisplayMetricsToConfigurationLocked(dm, tmpConfig);
                     }
                     if (overrideConfig != null) {
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index 954476d..c117486 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -28,6 +28,7 @@
 import android.os.SystemProperties;
 import android.provider.Settings;
 import android.util.Printer;
+import com.android.internal.util.FastPrintWriter;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -327,7 +328,9 @@
          */
         public CrashInfo(Throwable tr) {
             StringWriter sw = new StringWriter();
-            tr.printStackTrace(new PrintWriter(sw));
+            PrintWriter pw = new FastPrintWriter(sw, false, 256);
+            tr.printStackTrace(pw);
+            pw.flush();
             stackTrace = sw.toString();
             exceptionMessage = tr.getMessage();
 
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 271494f..432e9b1 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1296,6 +1296,28 @@
         return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
     }
 
+    @Override
+    public boolean setApplicationBlockedSettingAsUser(String packageName, boolean blocked,
+            UserHandle user) {
+        try {
+            return mPM.setApplicationBlockedSettingAsUser(packageName, blocked,
+                    user.getIdentifier());
+        } catch (RemoteException re) {
+            // Should never happen!
+        }
+        return false;
+    }
+
+    @Override
+    public boolean getApplicationBlockedSettingAsUser(String packageName, UserHandle user) {
+        try {
+            return mPM.getApplicationBlockedSettingAsUser(packageName, user.getIdentifier());
+        } catch (RemoteException re) {
+            // Should never happen!
+        }
+        return false;
+    }
+
     /**
      * @hide
      */
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 1b1d341..89ee145 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -21,6 +21,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.LogWriter;
+import com.android.internal.util.FastPrintWriter;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -583,8 +584,9 @@
         if (FragmentManagerImpl.DEBUG) {
             Log.v(TAG, "Commit: " + this);
             LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
-            PrintWriter pw = new PrintWriter(logw);
+            PrintWriter pw = new FastPrintWriter(logw, false, 1024);
             dump("  ", null, pw, null);
+            pw.flush();
         }
         mCommitted = true;
         if (mAddToBackStack) {
@@ -691,8 +693,9 @@
         if (FragmentManagerImpl.DEBUG) {
             Log.v(TAG, "popFromBackStack: " + this);
             LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
-            PrintWriter pw = new PrintWriter(logw);
+            PrintWriter pw = new FastPrintWriter(logw, false, 1024);
             dump("  ", null, pw, null);
+            pw.flush();
         }
 
         bumpBackStackNesting(-1);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 992d8b7..a5106e4 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -99,7 +99,7 @@
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Slog;
-import android.view.CompatibilityInfoHolder;
+import android.view.DisplayAdjustments;
 import android.view.ContextThemeWrapper;
 import android.view.Display;
 import android.view.WindowManagerImpl;
@@ -205,6 +205,8 @@
 
     private static final String[] EMPTY_FILE_LIST = {};
 
+    final private DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
+
     /**
      * Override this class when the system service constructor needs a
      * ContextImpl.  Else, use StaticServiceFetcher below.
@@ -547,9 +549,9 @@
                 return new AppOpsManager(ctx, service);
             }});
 
-        registerService(CAMERA_SERVICE, new StaticServiceFetcher() {
-            public Object createStaticService() {
-                return new CameraManager();
+        registerService(CAMERA_SERVICE, new ServiceFetcher() {
+            public Object createService(ContextImpl ctx) {
+                return new CameraManager(ctx);
             }
         });
 
@@ -1830,10 +1832,8 @@
 
         ContextImpl c = new ContextImpl();
         c.init(mPackageInfo, null, mMainThread);
-        c.mResources = mMainThread.getTopLevelResources(
-                mPackageInfo.getResDir(),
-                getDisplayId(), overrideConfiguration,
-                mResources.getCompatibilityInfo());
+        c.mResources = mMainThread.getTopLevelResources(mPackageInfo.getResDir(), getDisplayId(),
+                overrideConfiguration, mResources.getCompatibilityInfo(), mActivityToken);
         return c;
     }
 
@@ -1844,17 +1844,13 @@
         }
 
         int displayId = display.getDisplayId();
-        CompatibilityInfo ci = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
-        CompatibilityInfoHolder cih = getCompatibilityInfo(displayId);
-        if (cih != null) {
-            ci = cih.get();
-        }
 
         ContextImpl context = new ContextImpl();
         context.init(mPackageInfo, null, mMainThread);
         context.mDisplay = display;
-        context.mResources = mMainThread.getTopLevelResources(
-                mPackageInfo.getResDir(), displayId, null, ci);
+        DisplayAdjustments daj = getDisplayAdjustments(displayId);
+        context.mResources = mMainThread.getTopLevelResources(mPackageInfo.getResDir(), displayId,
+                null, daj.getCompatibilityInfo(), null);
         return context;
     }
 
@@ -1868,8 +1864,8 @@
     }
 
     @Override
-    public CompatibilityInfoHolder getCompatibilityInfo(int displayId) {
-        return displayId == Display.DEFAULT_DISPLAY ? mPackageInfo.mCompatibilityInfo : null;
+    public DisplayAdjustments getDisplayAdjustments(int displayId) {
+        return mDisplayAdjustments;
     }
 
     private File getDataDirFile() {
@@ -1921,6 +1917,7 @@
         mUser = context.mUser;
         mDisplay = context.mDisplay;
         mOuterContext = this;
+        mDisplayAdjustments.setCompatibilityInfo(mPackageInfo.getCompatibilityInfo());
     }
 
     final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread) {
@@ -1933,16 +1930,26 @@
         mBasePackageName = basePackageName != null ? basePackageName : packageInfo.mPackageName;
         mResources = mPackageInfo.getResources(mainThread);
 
-        if (mResources != null && container != null
-                && container.getCompatibilityInfo().applicationScale !=
-                        mResources.getCompatibilityInfo().applicationScale) {
+        CompatibilityInfo compatInfo =
+                container == null ? null : container.getCompatibilityInfo();
+        if (mResources != null &&
+                ((compatInfo != null && compatInfo.applicationScale !=
+                        mResources.getCompatibilityInfo().applicationScale)
+                || activityToken != null)) {
             if (DEBUG) {
                 Log.d(TAG, "loaded context has different scaling. Using container's" +
                         " compatiblity info:" + container.getDisplayMetrics());
             }
-            mResources = mainThread.getTopLevelResources(
-                    mPackageInfo.getResDir(), Display.DEFAULT_DISPLAY,
-                    null, container.getCompatibilityInfo());
+            if (compatInfo == null) {
+                compatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
+            }
+            mDisplayAdjustments.setCompatibilityInfo(compatInfo);
+            mDisplayAdjustments.setActivityToken(activityToken);
+            mResources = mainThread.getTopLevelResources(mPackageInfo.getResDir(),
+                    Display.DEFAULT_DISPLAY, null, compatInfo, activityToken);
+        } else {
+            mDisplayAdjustments.setCompatibilityInfo(packageInfo.getCompatibilityInfo());
+            mDisplayAdjustments.setActivityToken(activityToken);
         }
         mMainThread = mainThread;
         mActivityToken = activityToken;
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 72c9156..7358f73 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -36,6 +36,7 @@
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
+import com.android.internal.util.FastPrintWriter;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -445,12 +446,13 @@
     private void throwException(RuntimeException ex) {
         Log.e(TAG, ex.getMessage());
         LogWriter logw = new LogWriter(Log.ERROR, TAG);
-        PrintWriter pw = new PrintWriter(logw);
+        PrintWriter pw = new FastPrintWriter(logw, false, 1024);
         if (mActivity != null) {
             Log.e(TAG, "Activity state:");
             try {
                 mActivity.dump("  ", null, pw, new String[] { });
             } catch (Exception e) {
+                pw.flush();
                 Log.e(TAG, "Failed dumping state", e);
             }
         } else {
@@ -458,9 +460,11 @@
             try {
                 dump("  ", null, pw, new String[] { });
             } catch (Exception e) {
+                pw.flush();
                 Log.e(TAG, "Failed dumping state", e);
             }
         }
+        pw.flush();
         throw ex;
     }
 
@@ -1806,8 +1810,9 @@
                     Log.v(TAG, "restoreAllState: back stack #" + i
                         + " (index " + bse.mIndex + "): " + bse);
                     LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
-                    PrintWriter pw = new PrintWriter(logw);
+                    PrintWriter pw = new FastPrintWriter(logw, false, 1024);
                     bse.dump("  ", pw, false);
+                    pw.flush();
                 }
                 mBackStack.add(bse);
                 if (bse.mIndex >= 0) {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index c8791a4..39f4cfa 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -301,6 +301,8 @@
 
     public void finishHeavyWeightApp() throws RemoteException;
 
+    public void convertToOpaque(IBinder token) throws RemoteException;
+
     public void setImmersive(IBinder token, boolean immersive) throws RemoteException;
     public boolean isImmersive(IBinder token) throws RemoteException;
     public boolean isTopActivityImmersive() throws RemoteException;
@@ -666,4 +668,5 @@
     int GET_STACK_BOXES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+170;
     int SET_FOCUSED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+171;
     int GET_STACK_BOX_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+172;
+    int CONVERT_TO_OPAQUE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+173;
 }
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 2224490..573a6aa 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -40,7 +40,7 @@
 import android.os.UserHandle;
 import android.util.AndroidRuntimeException;
 import android.util.Slog;
-import android.view.CompatibilityInfoHolder;
+import android.view.DisplayAdjustments;
 import android.view.Display;
 
 import java.io.File;
@@ -84,7 +84,7 @@
     private final ClassLoader mBaseClassLoader;
     private final boolean mSecurityViolation;
     private final boolean mIncludeCode;
-    public final CompatibilityInfoHolder mCompatibilityInfo = new CompatibilityInfoHolder();
+    private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
     Resources mResources;
     private ClassLoader mClassLoader;
     private Application mApplication;
@@ -132,7 +132,7 @@
         mBaseClassLoader = baseLoader;
         mSecurityViolation = securityViolation;
         mIncludeCode = includeCode;
-        mCompatibilityInfo.set(compatInfo);
+        mDisplayAdjustments.setCompatibilityInfo(compatInfo);
 
         if (mAppDir == null) {
             if (ActivityThread.mSystemContext == null) {
@@ -141,7 +141,7 @@
                 ActivityThread.mSystemContext.getResources().updateConfiguration(
                          mainThread.getConfiguration(),
                          mainThread.getDisplayMetricsLocked(
-                                 Display.DEFAULT_DISPLAY, compatInfo),
+                                 Display.DEFAULT_DISPLAY, mDisplayAdjustments),
                          compatInfo);
                 //Slog.i(TAG, "Created system resources "
                 //        + mSystemContext.getResources() + ": "
@@ -169,7 +169,7 @@
         mIncludeCode = true;
         mClassLoader = systemContext.getClassLoader();
         mResources = systemContext.getResources();
-        mCompatibilityInfo.set(compatInfo);
+        mDisplayAdjustments.setCompatibilityInfo(compatInfo);
     }
 
     public String getPackageName() {
@@ -184,6 +184,14 @@
         return mSecurityViolation;
     }
 
+    public CompatibilityInfo getCompatibilityInfo() {
+        return mDisplayAdjustments.getCompatibilityInfo();
+    }
+
+    public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
+        mDisplayAdjustments.setCompatibilityInfo(compatInfo);
+    }
+
     /**
      * Gets the array of shared libraries that are listed as
      * used by the given package.
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 7c9117c..d8bf6ba 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -35,7 +35,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.AttributeSet;
-import android.view.CompatibilityInfoHolder;
+import android.view.DisplayAdjustments;
 import android.view.Display;
 import android.view.WindowManager;
 
@@ -2760,15 +2760,15 @@
     public abstract Context createDisplayContext(Display display);
 
     /**
-     * Gets the compatibility info holder for this context.  This information
-     * is provided on a per-application basis and is used to simulate lower density
-     * display metrics for legacy applications.
+     * Gets the display adjustments holder for this context.  This information
+     * is provided on a per-application or activity basis and is used to simulate lower density
+     * display metrics for legacy applications and restricted screen sizes.
      *
      * @param displayId The display id for which to get compatibility info.
      * @return The compatibility info holder, or null if not required by the application.
      * @hide
      */
-    public abstract CompatibilityInfoHolder getCompatibilityInfo(int displayId);
+    public abstract DisplayAdjustments getDisplayAdjustments(int displayId);
 
     /**
      * Indicates whether this Context is restricted.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 2f1bf8c..606a1f4 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -35,7 +35,7 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.view.CompatibilityInfoHolder;
+import android.view.DisplayAdjustments;
 import android.view.Display;
 
 import java.io.File;
@@ -646,7 +646,7 @@
 
     /** @hide */
     @Override
-    public CompatibilityInfoHolder getCompatibilityInfo(int displayId) {
-        return mBase.getCompatibilityInfo(displayId);
+    public DisplayAdjustments getDisplayAdjustments(int displayId) {
+        return mBase.getDisplayAdjustments(displayId);
     }
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 897e6fe..bda7112 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2440,6 +2440,18 @@
             "android.intent.action.GET_RESTRICTION_ENTRIES";
 
     /**
+     * Activity to challenge the user for a PIN that was configured when setting up
+     * restrictions. Launch the activity using
+     * {@link android.app.Activity#startActivityForResult(Intent, int)} and check if the
+     * result is {@link android.app.Activity#RESULT_OK} for a successful response to the
+     * challenge.<p/>
+     * Before launching this activity, make sure that there is a PIN in effect, by calling
+     * {@link android.os.UserManager#hasRestrictionsPin()}.
+     */
+    public static final String ACTION_RESTRICTIONS_PIN_CHALLENGE =
+            "android.intent.action.RESTRICTIONS_PIN_CHALLENGE";
+
+    /**
      * Sent the first time a user is starting, to allow system apps to
      * perform one time initialization.  (This will not be seen by third
      * party applications because a newly initialized user does not have any
diff --git a/core/java/android/content/SyncStatusInfo.java b/core/java/android/content/SyncStatusInfo.java
index ff628d9..bb24ccd 100644
--- a/core/java/android/content/SyncStatusInfo.java
+++ b/core/java/android/content/SyncStatusInfo.java
@@ -42,7 +42,10 @@
     public long initialFailureTime;
     public boolean pending;
     public boolean initialize;
-    public ArrayList<Long> periodicSyncTimes;
+    
+  // Warning: It is up to the external caller to ensure there are
+  // no race conditions when accessing this list
+  private ArrayList<Long> periodicSyncTimes;
 
     private static final String TAG = "Sync";
 
@@ -126,11 +129,59 @@
         }
     }
 
+    public SyncStatusInfo(SyncStatusInfo other) {
+        authorityId = other.authorityId;
+        totalElapsedTime = other.totalElapsedTime;
+        numSyncs = other.numSyncs;
+        numSourcePoll = other.numSourcePoll;
+        numSourceServer = other.numSourceServer;
+        numSourceLocal = other.numSourceLocal;
+        numSourceUser = other.numSourceUser;
+        numSourcePeriodic = other.numSourcePeriodic;
+        lastSuccessTime = other.lastSuccessTime;
+        lastSuccessSource = other.lastSuccessSource;
+        lastFailureTime = other.lastFailureTime;
+        lastFailureSource = other.lastFailureSource;
+        lastFailureMesg = other.lastFailureMesg;
+        initialFailureTime = other.initialFailureTime;
+        pending = other.pending;
+        initialize = other.initialize;
+        if (other.periodicSyncTimes != null) {
+            periodicSyncTimes = new ArrayList<Long>(other.periodicSyncTimes);
+        }
+    }
+
     public void setPeriodicSyncTime(int index, long when) {
+        // The list is initialized lazily when scheduling occurs so we need to make sure
+        // we initialize elements < index to zero (zero is ignore for scheduling purposes)
         ensurePeriodicSyncTimeSize(index);
         periodicSyncTimes.set(index, when);
     }
 
+    public long getPeriodicSyncTime(int index) {
+        if (periodicSyncTimes != null && index < periodicSyncTimes.size()) {
+            return periodicSyncTimes.get(index);
+        } else {
+            return 0;
+        }
+    }
+
+    public void removePeriodicSyncTime(int index) {
+        if (periodicSyncTimes != null && index < periodicSyncTimes.size()) {
+            periodicSyncTimes.remove(index);
+        }
+    }
+
+    public static final Creator<SyncStatusInfo> CREATOR = new Creator<SyncStatusInfo>() {
+        public SyncStatusInfo createFromParcel(Parcel in) {
+            return new SyncStatusInfo(in);
+        }
+
+        public SyncStatusInfo[] newArray(int size) {
+            return new SyncStatusInfo[size];
+        }
+    };
+
     private void ensurePeriodicSyncTimeSize(int index) {
         if (periodicSyncTimes == null) {
             periodicSyncTimes = new ArrayList<Long>(0);
@@ -143,26 +194,4 @@
             }
         }
     }
-
-    public long getPeriodicSyncTime(int index) {
-        if (periodicSyncTimes == null || periodicSyncTimes.size() < (index + 1)) {
-            return 0;
-        }
-        return periodicSyncTimes.get(index);
-    }
-
-    public void removePeriodicSyncTime(int index) {
-        ensurePeriodicSyncTimeSize(index);
-        periodicSyncTimes.remove(index);
-    }
-
-    public static final Creator<SyncStatusInfo> CREATOR = new Creator<SyncStatusInfo>() {
-        public SyncStatusInfo createFromParcel(Parcel in) {
-            return new SyncStatusInfo(in);
-        }
-
-        public SyncStatusInfo[] newArray(int size) {
-            return new SyncStatusInfo[size];
-        }
-    };
 }
\ No newline at end of file
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 2250331..9c46d96 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -315,6 +315,14 @@
     public static final int FLAG_IS_DATA_ONLY = 1<<24;
 
     /**
+     * Value for {@link #flags}: set to {@code true} if the application
+     * is permitted to hold privileged permissions.
+     *
+     * {@hide}
+     */
+    public static final int FLAG_PRIVILEGED = 1<<30;
+
+    /**
      * Value for {@link #flags}: Set to true if the application has been
      * installed using the forward lock option.
      *
@@ -338,12 +346,11 @@
     public static final int FLAG_CANT_SAVE_STATE = 1<<28;
 
     /**
-     * Value for {@link #flags}: set to {@code true} if the application
-     * is permitted to hold privileged permissions.
-     *
+     * Value for {@link #flags}: true if the application is blocked via restrictions and for
+     * most purposes is considered as not installed.
      * {@hide}
      */
-    public static final int FLAG_PRIVILEGED = 1<<29;
+    public static final int FLAG_BLOCKED = 1<<27;
 
     /**
      * Flags associated with the application.  Any combination of
@@ -359,7 +366,7 @@
      * {@link #FLAG_INSTALLED}.
      */
     public int flags = 0;
-    
+
     /**
      * The required smallest screen width the application can run on.  If 0,
      * nothing has been specified.  Comes from
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index a0e1555..eaff7b2 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -399,4 +399,7 @@
 
     /** Reflects current DeviceStorageMonitorService state */
     boolean isStorageLow();
+
+    boolean setApplicationBlockedSettingAsUser(String packageName, boolean blocked, int userId);
+    boolean getApplicationBlockedSettingAsUser(String packageName, int userId);
 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 4266d85..8a8751e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3083,6 +3083,23 @@
     public abstract int getApplicationEnabledSetting(String packageName);
 
     /**
+     * Puts the package in a blocked state, which is almost like an uninstalled state,
+     * making the package unavailable, but it doesn't remove the data or the actual
+     * package file.
+     * @hide
+     */
+    public abstract boolean setApplicationBlockedSettingAsUser(String packageName, boolean blocked,
+            UserHandle userHandle);
+
+    /**
+     * Returns the blocked state of a package.
+     * @see #setApplicationBlockedSettingAsUser(String, boolean, UserHandle)
+     * @hide
+     */
+    public abstract boolean getApplicationBlockedSettingAsUser(String packageName,
+            UserHandle userHandle);
+
+    /**
      * Return whether the device has been booted into safe mode.
      */
     public abstract boolean isSafeMode();
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 883516e..8f0c62d 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -159,7 +159,8 @@
     private static WeakReference<byte[]> mReadBuffer;
 
     private static boolean sCompatibilityModeEnabled = true;
-    private static final int PARSE_DEFAULT_INSTALL_LOCATION = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+    private static final int PARSE_DEFAULT_INSTALL_LOCATION =
+            PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
 
     static class ParsePackageItemArgs {
         final Package owner;
@@ -274,15 +275,20 @@
                 grantedPermissions, state, UserHandle.getCallingUserId());
     }
 
-    private static boolean checkUseInstalled(int flags, PackageUserState state) {
-        return state.installed || ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0);
+    /**
+     * Returns true if the package is installed and not blocked, or if the caller
+     * explicitly wanted all uninstalled and blocked packages as well.
+     */
+    private static boolean checkUseInstalledOrBlocked(int flags, PackageUserState state) {
+        return (state.installed && !state.blocked)
+                || (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
     }
 
     public static PackageInfo generatePackageInfo(PackageParser.Package p,
             int gids[], int flags, long firstInstallTime, long lastUpdateTime,
             HashSet<String> grantedPermissions, PackageUserState state, int userId) {
 
-        if (!checkUseInstalled(flags, state)) {
+        if (!checkUseInstalledOrBlocked(flags, state)) {
             return null;
         }
         PackageInfo pi = new PackageInfo();
@@ -3724,7 +3730,7 @@
                 return true;
             }
         }
-        if (!state.installed) {
+        if (!state.installed || state.blocked) {
             return true;
         }
         if (state.stopped) {
@@ -3757,6 +3763,11 @@
         } else {
             ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
         }
+        if (state.blocked) {
+            ai.flags |= ApplicationInfo.FLAG_BLOCKED;
+        } else {
+            ai.flags &= ~ApplicationInfo.FLAG_BLOCKED;
+        }
         if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
             ai.enabled = true;
         } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
@@ -3771,7 +3782,7 @@
     public static ApplicationInfo generateApplicationInfo(Package p, int flags,
             PackageUserState state, int userId) {
         if (p == null) return null;
-        if (!checkUseInstalled(flags, state)) {
+        if (!checkUseInstalledOrBlocked(flags, state)) {
             return null;
         }
         if (!copyNeeded(flags, p, state, null, userId)
@@ -3855,7 +3866,7 @@
     public static final ActivityInfo generateActivityInfo(Activity a, int flags,
             PackageUserState state, int userId) {
         if (a == null) return null;
-        if (!checkUseInstalled(flags, state)) {
+        if (!checkUseInstalledOrBlocked(flags, state)) {
             return null;
         }
         if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
@@ -3892,7 +3903,7 @@
     public static final ServiceInfo generateServiceInfo(Service s, int flags,
             PackageUserState state, int userId) {
         if (s == null) return null;
-        if (!checkUseInstalled(flags, state)) {
+        if (!checkUseInstalledOrBlocked(flags, state)) {
             return null;
         }
         if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
@@ -3937,7 +3948,7 @@
     public static final ProviderInfo generateProviderInfo(Provider p, int flags,
             PackageUserState state, int userId) {
         if (p == null) return null;
-        if (!checkUseInstalled(flags, state)) {
+        if (!checkUseInstalledOrBlocked(flags, state)) {
             return null;
         }
         if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index dcd54fc..94e3f79 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -28,6 +28,7 @@
     public boolean stopped;
     public boolean notLaunched;
     public boolean installed;
+    public boolean blocked; // Is the app restricted by owner / admin
     public int enabled;
 
     public String lastDisableAppCaller;
@@ -37,6 +38,7 @@
 
     public PackageUserState() {
         installed = true;
+        blocked = false;
         enabled = COMPONENT_ENABLED_STATE_DEFAULT;
     }
 
@@ -45,6 +47,7 @@
         stopped = o.stopped;
         notLaunched = o.notLaunched;
         enabled = o.enabled;
+        blocked = o.blocked;
         lastDisableAppCaller = o.lastDisableAppCaller;
         disabledComponents = o.disabledComponents != null
                 ? new HashSet<String>(o.disabledComponents) : null;
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 28c751c..da35ee9 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -471,8 +471,7 @@
      * Compute the frame Rect for applications runs under compatibility mode.
      *
      * @param dm the display metrics used to compute the frame size.
-     * @param orientation the orientation of the screen.
-     * @param outRect the output parameter which will contain the result.
+     * @param outDm If non-null the width and height will be set to their scaled values.
      * @return Returns the scaling factor for the window.
      */
     public static float computeCompatibleScaling(DisplayMetrics dm, DisplayMetrics outDm) {
@@ -518,6 +517,9 @@
 
     @Override
     public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
         try {
             CompatibilityInfo oc = (CompatibilityInfo)o;
             if (mCompatibilityFlags != oc.mCompatibilityFlags) return false;
@@ -579,10 +581,12 @@
 
     public static final Parcelable.Creator<CompatibilityInfo> CREATOR
             = new Parcelable.Creator<CompatibilityInfo>() {
+        @Override
         public CompatibilityInfo createFromParcel(Parcel source) {
             return new CompatibilityInfo(source);
         }
 
+        @Override
         public CompatibilityInfo[] newArray(int size) {
             return new CompatibilityInfo[size];
         }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index cff974d..c24e0ee 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -28,6 +28,7 @@
 import android.graphics.drawable.Drawable.ConstantState;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.os.Trace;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
@@ -35,6 +36,7 @@
 import android.util.Slog;
 import android.util.TypedValue;
 import android.util.LongSparseArray;
+import android.view.DisplayAdjustments;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -117,8 +119,9 @@
     private final Configuration mConfiguration = new Configuration();
     /*package*/ final DisplayMetrics mMetrics = new DisplayMetrics();
     private NativePluralRules mPluralRule;
-    
-    private CompatibilityInfo mCompatibilityInfo;
+
+    private CompatibilityInfo mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
+    private WeakReference<IBinder> mToken;
 
     static {
         sPreloadedDrawables = new LongSparseArray[2];
@@ -173,7 +176,7 @@
      *               selecting/computing resource values (optional).
      */
     public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
-        this(assets, metrics, config, null);
+        this(assets, metrics, config, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
     }
 
     /**
@@ -184,15 +187,16 @@
      *                selecting/computing resource values.
      * @param config Desired device configuration to consider when 
      *               selecting/computing resource values (optional).
-     * @param compInfo this resource's compatibility info. It will use the default compatibility
-     *  info when it's null.
+     * @param compatInfo this resource's compatibility info. Must not be null.
+     * @param token The Activity token for determining stack affiliation. Usually null.
      * @hide
      */
-    public Resources(AssetManager assets, DisplayMetrics metrics,
-            Configuration config, CompatibilityInfo compInfo) {
+    public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config,
+            CompatibilityInfo compatInfo, IBinder token) {
         mAssets = assets;
         mMetrics.setToDefaults();
-        mCompatibilityInfo = compInfo;
+        mCompatibilityInfo = compatInfo;
+        mToken = new WeakReference<IBinder>(token);
         updateConfiguration(config, metrics);
         assets.ensureStringBlocks();
     }
diff --git a/core/java/android/hardware/ICameraService.aidl b/core/java/android/hardware/ICameraService.aidl
index b8fbfdb..2d0c099 100644
--- a/core/java/android/hardware/ICameraService.aidl
+++ b/core/java/android/hardware/ICameraService.aidl
@@ -20,6 +20,8 @@
 import android.hardware.ICameraClient;
 import android.hardware.IProCameraUser;
 import android.hardware.IProCameraCallbacks;
+import android.hardware.photography.ICameraDeviceUser;
+import android.hardware.photography.ICameraDeviceCallbacks;
 import android.hardware.ICameraServiceListener;
 import android.hardware.CameraInfo;
 
@@ -43,6 +45,10 @@
                               String clientPackageName,
                               int clientUid);
 
+    ICameraDeviceUser connectDevice(ICameraDeviceCallbacks callbacks, int cameraId,
+                              String clientPackageName,
+                              int clientUid);
+
     int addListener(ICameraServiceListener listener);
     int removeListener(ICameraServiceListener listener);
 }
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index dcf50cd..9e2e4ba 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -159,7 +159,7 @@
         Display display = mDisplays.get(displayId);
         if (display == null) {
             display = mGlobal.getCompatibleDisplay(displayId,
-                    mContext.getCompatibilityInfo(displayId));
+                    mContext.getDisplayAdjustments(displayId));
             if (display != null) {
                 mDisplays.put(displayId, display);
             }
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 3ab882d..320185d 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -28,7 +28,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.SparseArray;
-import android.view.CompatibilityInfoHolder;
+import android.view.DisplayAdjustments;
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.Surface;
@@ -164,18 +164,18 @@
      * Gets information about a logical display.
      *
      * The display metrics may be adjusted to provide compatibility
-     * for legacy applications.
+     * for legacy applications or limited screen areas.
      *
      * @param displayId The logical display id.
-     * @param cih The compatibility info, or null if none is required.
+     * @param daj The compatibility info and activityToken.
      * @return The display object, or null if there is no display with the given id.
      */
-    public Display getCompatibleDisplay(int displayId, CompatibilityInfoHolder cih) {
+    public Display getCompatibleDisplay(int displayId, DisplayAdjustments daj) {
         DisplayInfo displayInfo = getDisplayInfo(displayId);
         if (displayInfo == null) {
             return null;
         }
-        return new Display(this, displayId, displayInfo, cih);
+        return new Display(this, displayId, displayInfo, daj);
     }
 
     /**
@@ -185,7 +185,18 @@
      * @return The display object, or null if there is no display with the given id.
      */
     public Display getRealDisplay(int displayId) {
-        return getCompatibleDisplay(displayId, null);
+        return getCompatibleDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
+    }
+
+    /**
+     * Gets information about a logical display without applying any compatibility metrics.
+     *
+     * @param displayId The logical display id.
+     * @param IBinder the activity token for this display.
+     * @return The display object, or null if there is no display with the given id.
+     */
+    public Display getRealDisplay(int displayId, IBinder token) {
+        return getCompatibleDisplay(displayId, new DisplayAdjustments(token));
     }
 
     public void registerDisplayListener(DisplayListener listener, Handler handler) {
diff --git a/core/java/android/hardware/photography/CameraAccessException.java b/core/java/android/hardware/photography/CameraAccessException.java
index 01114df..fac5086 100644
--- a/core/java/android/hardware/photography/CameraAccessException.java
+++ b/core/java/android/hardware/photography/CameraAccessException.java
@@ -16,6 +16,8 @@
 
 package android.hardware.photography;
 
+import android.util.AndroidException;
+
 /**
  * <p><code>CameraAccessException</code> is thrown if a camera device could not
  * be queried or opened by the {@link CameraManager}, or if the connection to an
@@ -24,7 +26,7 @@
  * @see CameraManager
  * @see CameraDevice
  */
-public class CameraAccessException extends Exception {
+public class CameraAccessException extends AndroidException {
     /**
      * The camera device is in use already
      */
@@ -51,7 +53,10 @@
      */
     public static final int CAMERA_DISCONNECTED = 4;
 
-    private int mReason;
+    // Make the eclipse warning about serializable exceptions go away
+    private static final long serialVersionUID = 5630338637471475675L; // randomly generated
+
+    private final int mReason;
 
     /**
      * The reason for the failure to access the camera.
@@ -66,6 +71,7 @@
     }
 
     public CameraAccessException(int problem) {
+        super(getDefaultMessage(problem));
         mReason = problem;
     }
 
@@ -80,7 +86,25 @@
     }
 
     public CameraAccessException(int problem, Throwable cause) {
-        super(cause);
+        super(getDefaultMessage(problem), cause);
         mReason = problem;
     }
+
+    private static String getDefaultMessage(int problem) {
+        switch (problem) {
+            case CAMERA_IN_USE:
+                return "The camera device is in use already";
+            case MAX_CAMERAS_IN_USE:
+                return "The system-wide limit for number of open cameras has been reached, " +
+                       "and more camera devices cannot be opened until previous instances " +
+                       "are closed.";
+            case CAMERA_DISABLED:
+                return "The camera is disabled due to a device policy, and cannot be opened.";
+            case CAMERA_DISCONNECTED:
+                return "The camera device is removable and has been disconnected from the Android" +
+                       " device, or the camera service has shut down the connection due to a " +
+                       "higher-priority access request for the camera device.";
+        }
+        return null;
+    }
 }
diff --git a/core/java/android/hardware/photography/CameraDevice.java b/core/java/android/hardware/photography/CameraDevice.java
index 2062db2..5fb14dc 100644
--- a/core/java/android/hardware/photography/CameraDevice.java
+++ b/core/java/android/hardware/photography/CameraDevice.java
@@ -16,9 +16,6 @@
 
 package android.hardware.photography;
 
-import android.graphics.ImageFormat;
-import android.renderscript.Allocation;
-import android.renderscript.RenderScript;
 import android.view.Surface;
 
 import java.lang.AutoCloseable;
@@ -47,7 +44,7 @@
  * @see CameraManager#openCamera
  * @see android.Manifest.permission#CAMERA
  */
-public final class CameraDevice implements AutoCloseable {
+public interface CameraDevice extends AutoCloseable {
 
     /**
      * Create a request suitable for a camera preview window. Specifically, this
@@ -111,10 +108,7 @@
      *
      * @see CameraManager#getCameraProperties
      */
-    public CameraProperties getProperties() throws CameraAccessException {
-        return null;
-    }
-
+    public CameraProperties getProperties() throws CameraAccessException;
     /**
      * <p>Set up a new output set of Surfaces for the camera device.</p>
      *
@@ -196,8 +190,7 @@
      * @throws IllegalStateException if the camera device is not idle, or has
      * encountered a fatal error
      */
-    public void configureOutputs(List<Surface> outputs) {
-    }
+    public void configureOutputs(List<Surface> outputs) throws CameraAccessException;
 
     /**
      * <p>Create a {@link CaptureRequest} initialized with template for a target
@@ -223,9 +216,7 @@
      * @see #TEMPLATE_MANUAL
      */
     public CaptureRequest createCaptureRequest(int templateType)
-            throws CameraAccessException {
-        return null;
-    }
+            throws CameraAccessException;
 
     /**
      * <p>Submit a request for an image to be captured by this CameraDevice.</p>
@@ -257,8 +248,7 @@
      * @see #setRepeatingBurst
      */
     public void capture(CaptureRequest request, CaptureListener listener)
-            throws CameraAccessException {
-    }
+            throws CameraAccessException;
 
     /**
      * <p>Submit a list of requests to be captured in sequence as a burst. The
@@ -289,8 +279,7 @@
      * @see #setRepeatingBurst
      */
     public void captureBurst(List<CaptureRequest> requests,
-            CaptureListener listener) throws CameraAccessException {
-    }
+            CaptureListener listener) throws CameraAccessException;
 
     /**
      * <p>Request endlessly repeating capture of images by this
@@ -332,8 +321,7 @@
      * @see #setRepeatingBurst
      */
     public void setRepeatingRequest(CaptureRequest request, CaptureListener listener)
-            throws CameraAccessException {
-    }
+            throws CameraAccessException;
 
     /**
      * <p>Request endlessly repeating capture of a sequence of images by this
@@ -377,8 +365,7 @@
      * @see #setRepeatingRequest
      */
     public void setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener)
-            throws CameraAccessException {
-    }
+            throws CameraAccessException;
 
     /**
      * <p>Cancel any ongoing repeating capture set by either
@@ -404,8 +391,7 @@
      * device has encountered a fatal error, or if there is an active repeating
      * request or burst.
      */
-    public void stopRepeating() throws CameraAccessException {
-    }
+    public void stopRepeating() throws CameraAccessException;
 
     /**
      * <p>Wait until all the submitted requests have finished processing</p>
@@ -430,8 +416,7 @@
      * device has encountered a fatal error, or if there is an active repeating
      * request or burst.
      */
-    public void waitUntilIdle() throws CameraAccessException {
-    }
+    public void waitUntilIdle() throws CameraAccessException;
 
     /**
      * Set the error listener object to call when an asynchronous error
@@ -443,16 +428,17 @@
      * notifications to. Setting this to null will stop notifications about
      * asynchronous errors.
      */
-    public void setErrorListener(ErrorListener listener) {
-    }
+    public void setErrorListener(ErrorListener listener);
 
     /**
      * Close the connection to this camera device. After this call, all calls to
      * the camera device interface will throw a {@link IllegalStateException},
      * except for calls to close().
+     * @throws Exception
      */
-    public void close() {
-    }
+    @Override
+    public void close() throws Exception;
+    // TODO: We should decide on the behavior of in-flight requests should be on close.
 
     /**
      * A listener for receiving metadata about completed image captures. The
@@ -551,5 +537,4 @@
          */
         public void onCameraDeviceError(CameraDevice camera, int error);
     }
-
 }
diff --git a/core/java/android/hardware/photography/CameraManager.java b/core/java/android/hardware/photography/CameraManager.java
index 328ba4b..c1c9435 100644
--- a/core/java/android/hardware/photography/CameraManager.java
+++ b/core/java/android/hardware/photography/CameraManager.java
@@ -16,6 +16,22 @@
 
 package android.hardware.photography;
 
+import android.content.Context;
+import android.hardware.ICameraService;
+import android.hardware.ICameraServiceListener;
+import android.hardware.IProCameraUser;
+import android.hardware.photography.utils.CameraBinderDecorator;
+import android.hardware.photography.utils.CameraRuntimeException;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+
 /**
  * <p>An interface for iterating, listing, and connecting to
  * {@link CameraDevice CameraDevices}.</p>
@@ -32,9 +48,40 @@
 public final class CameraManager {
 
     /**
+     * This should match the ICameraService definition
+     */
+    private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
+    private static final int USE_CALLING_UID = -1;
+
+    private final ICameraService mCameraService;
+    private ArrayList<String> mDeviceIdList;
+    private HashSet<CameraListener> mListenerSet;
+    private final Context mContext;
+    private final Object mLock = new Object();
+
+    /**
      * @hide
      */
-    public CameraManager() {
+    public CameraManager(Context context) {
+        mContext = context;
+
+        IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME);
+        ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
+
+        /**
+         * Wrap the camera service in a decorator which automatically translates return codes
+         * into exceptions, and RemoteExceptions into other exceptions.
+         */
+        mCameraService = CameraBinderDecorator.newInstance(cameraServiceRaw);
+
+        try {
+            mCameraService.addListener(new CameraServiceListener());
+        } catch(CameraRuntimeException e) {
+            throw new IllegalStateException("Failed to register a camera service listener",
+                    e.asChecked());
+        } catch (RemoteException e) {
+            // impossible
+        }
     }
 
     /**
@@ -45,25 +92,43 @@
      *
      * @return The list of currently connected camera devices.
      */
-    public String[] getDeviceIdList() {
-        return null;
+    public String[] getDeviceIdList() throws CameraAccessException {
+        synchronized (mLock) {
+            try {
+                return getOrCreateDeviceIdListLocked().toArray(new String[0]);
+            } catch(CameraAccessException e) {
+                // this should almost never happen, except if mediaserver crashes
+                throw new IllegalStateException(
+                        "Failed to query camera service for device ID list", e);
+            }
+        }
     }
 
     /**
      * Register a listener to be notified about camera device availability.
      *
-     * @param listener the new listener to send camera availablity notices to.
+     * Registering a listener more than once has no effect.
+     *
+     * @param listener the new listener to send camera availability notices to.
      */
     public void registerCameraListener(CameraListener listener) {
+        synchronized (mLock) {
+            mListenerSet.add(listener);
+        }
     }
 
     /**
      * Remove a previously-added listener; the listener will no longer receive
      * connection and disconnection callbacks.
      *
+     * Removing a listener that isn't registered has no effect.
+     *
      * @param listener the listener to remove from the notification list
      */
     public void unregisterCameraListener(CameraListener listener) {
+        synchronized (mLock) {
+            mListenerSet.remove(listener);
+        }
     }
 
     /**
@@ -84,7 +149,18 @@
      */
     public CameraProperties getCameraProperties(String cameraId)
             throws CameraAccessException {
-        throw new IllegalArgumentException();
+
+        synchronized (mLock) {
+            if (!getOrCreateDeviceIdListLocked().contains(cameraId)) {
+                throw new IllegalArgumentException(String.format("Camera id %s does not match any" +
+                        " currently connected camera device", cameraId));
+            }
+        }
+
+        // TODO: implement and call a service function to get the capabilities on C++ side
+
+        // TODO: get properties from service
+        return new CameraProperties();
     }
 
     /**
@@ -107,7 +183,48 @@
      * @see android.app.admin.DevicePolicyManager#setCameraDisabled
      */
     public CameraDevice openCamera(String cameraId) throws CameraAccessException {
-        throw new IllegalArgumentException();
+
+        try {
+
+            synchronized (mLock) {
+
+                ICameraDeviceUser cameraUser;
+
+                android.hardware.photography.impl.CameraDevice device =
+                        new android.hardware.photography.impl.CameraDevice(cameraId);
+
+                cameraUser = mCameraService.connectDevice(device.getCallbacks(),
+                        Integer.parseInt(cameraId),
+                        mContext.getPackageName(), USE_CALLING_UID);
+
+                // TODO: change ICameraService#connectDevice to return status_t
+                if (cameraUser == null) {
+                    // TEMPORARY CODE.
+                    // catch-all exception since we aren't yet getting the actual error code
+                    throw new IllegalStateException("Failed to open camera device");
+                }
+
+                // TODO: factor out listener to be non-nested, then move setter to constructor
+                device.setRemoteDevice(cameraUser);
+
+                return device;
+
+            }
+
+        } catch (NumberFormatException e) {
+            throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: "
+                    + cameraId);
+        } catch (CameraRuntimeException e) {
+            if (e.getReason() == CameraAccessException.CAMERA_DISCONNECTED) {
+                throw new IllegalArgumentException("Invalid camera ID specified -- " +
+                        "perhaps the camera was physically disconnected", e);
+            } else {
+                throw e.asChecked();
+            }
+        } catch (RemoteException e) {
+            // impossible
+            return null;
+        }
     }
 
     /**
@@ -135,4 +252,135 @@
          */
         public void onCameraUnavailable(String cameraId);
     }
-}
+
+    private ArrayList<String> getOrCreateDeviceIdListLocked() throws CameraAccessException {
+        if (mDeviceIdList == null) {
+            int numCameras = 0;
+
+            try {
+                numCameras = mCameraService.getNumberOfCameras();
+            } catch(CameraRuntimeException e) {
+                throw e.asChecked();
+            } catch (RemoteException e) {
+                // impossible
+                return null;
+            }
+
+            mDeviceIdList = new ArrayList<String>();
+            for (int i = 0; i < numCameras; ++i) {
+                // Non-removable cameras use integers starting at 0 for their
+                // identifiers
+                mDeviceIdList.add(String.valueOf(i));
+            }
+
+        }
+        return mDeviceIdList;
+    }
+
+    // TODO: this class needs unit tests
+    // TODO: extract class into top level
+    private class CameraServiceListener extends Binder implements ICameraServiceListener  {
+
+        // Keep up-to-date with ICameraServiceListener.h
+
+        // Device physically unplugged
+        public static final int STATUS_NOT_PRESENT = 0;
+        // Device physically has been plugged in
+        // and the camera can be used exclusively
+        public static final int STATUS_PRESENT = 1;
+        // Device physically has been plugged in
+        // but it will not be connect-able until enumeration is complete
+        public static final int STATUS_ENUMERATING = 2;
+        // Camera is in use by another app and cannot be used exclusively
+        public static final int STATUS_NOT_AVAILABLE = 0x80000000;
+
+        // Camera ID -> Status map
+        private final HashMap<String, Integer> mDeviceStatus = new HashMap<String, Integer>();
+
+        private static final String TAG = "CameraServiceListener";
+
+        @Override
+        public IBinder asBinder() {
+            return this;
+        }
+
+        private boolean isAvailable(int status) {
+            switch (status) {
+                case STATUS_PRESENT:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        private boolean validStatus(int status) {
+            switch (status) {
+                case STATUS_NOT_PRESENT:
+                case STATUS_PRESENT:
+                case STATUS_ENUMERATING:
+                case STATUS_NOT_AVAILABLE:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        @Override
+        public void onStatusChanged(int status, int cameraId) throws RemoteException {
+            synchronized(CameraManager.this.mLock) {
+
+                Log.v(TAG,
+                        String.format("Camera id %d has status changed to 0x%x", cameraId, status));
+
+                String id = String.valueOf(cameraId);
+
+                if (!validStatus(status)) {
+                    Log.e(TAG, String.format("Ignoring invalid device %d status 0x%x", cameraId,
+                            status));
+                    return;
+                }
+
+                Integer oldStatus = mDeviceStatus.put(id, status);
+
+                if (oldStatus == status) {
+                    Log.v(TAG, String.format(
+                            "Device status changed to 0x%x, which is what it already was",
+                            status));
+                    return;
+                }
+
+                // TODO: consider abstracting out this state minimization + transition
+                // into a separate
+                // more easily testable class
+                // i.e. (new State()).addState(STATE_AVAILABLE)
+                //                   .addState(STATE_NOT_AVAILABLE)
+                //                   .addTransition(STATUS_PRESENT, STATE_AVAILABLE),
+                //                   .addTransition(STATUS_NOT_PRESENT, STATE_NOT_AVAILABLE)
+                //                   .addTransition(STATUS_ENUMERATING, STATE_NOT_AVAILABLE);
+                //                   .addTransition(STATUS_NOT_AVAILABLE, STATE_NOT_AVAILABLE);
+
+                // Translate all the statuses to either 'available' or 'not available'
+                //  available -> available         => no new update
+                //  not available -> not available => no new update
+                if (oldStatus != null && isAvailable(status) == isAvailable(oldStatus)) {
+
+                    Log.v(TAG,
+                            String.format(
+                                    "Device status was previously available (%d), " +
+                                            " and is now again available (%d)" +
+                                            "so no new client visible update will be sent",
+                                    isAvailable(status), isAvailable(status)));
+                    return;
+                }
+
+                for (CameraListener listener : mListenerSet) {
+                    if (isAvailable(status)) {
+                        listener.onCameraAvailable(id);
+                    } else {
+                        listener.onCameraUnavailable(id);
+                    }
+                } // for
+            } // synchronized
+        } // onStatusChanged
+    } // CameraServiceListener
+} // CameraManager
diff --git a/core/java/android/hardware/photography/CameraMetadata.aidl b/core/java/android/hardware/photography/CameraMetadata.aidl
new file mode 100644
index 0000000..b4dc9ac
--- /dev/null
+++ b/core/java/android/hardware/photography/CameraMetadata.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.photography;
+
+/** @hide */
+parcelable CameraMetadata;
diff --git a/core/java/android/hardware/photography/CameraMetadata.java b/core/java/android/hardware/photography/CameraMetadata.java
index 385a1b9..5488952 100644
--- a/core/java/android/hardware/photography/CameraMetadata.java
+++ b/core/java/android/hardware/photography/CameraMetadata.java
@@ -18,6 +18,8 @@
 
 import android.os.Parcelable;
 import android.os.Parcel;
+import android.util.Log;
+
 import java.util.HashMap;
 import java.util.Map;
 
@@ -32,27 +34,34 @@
  * @see CameraManager
  * @see CameraProperties
  **/
-public class CameraMetadata implements Parcelable {
+public class CameraMetadata implements Parcelable, AutoCloseable {
 
     public CameraMetadata() {
         mMetadataMap = new HashMap<Key<?>, Object>();
-    }
 
-    private CameraMetadata(Parcel in) {
-
+        mMetadataPtr = nativeAllocate();
+        if (mMetadataPtr == 0) {
+            throw new OutOfMemoryError("Failed to allocate native CameraMetadata");
+        }
     }
 
     public static final Parcelable.Creator<CameraMetadata> CREATOR =
             new Parcelable.Creator<CameraMetadata>() {
+        @Override
         public CameraMetadata createFromParcel(Parcel in) {
-            return new CameraMetadata(in);
+            CameraMetadata metadata = new CameraMetadata();
+            metadata.readFromParcel(in);
+            return metadata;
         }
 
+        @Override
         public CameraMetadata[] newArray(int size) {
             return new CameraMetadata[size];
         }
     };
 
+    private static final String TAG = "CameraMetadataJV";
+
     /**
      * Set a camera metadata field to a value. The field definitions can be
      * found in {@link CameraProperties}, {@link CaptureResult}, and
@@ -63,6 +72,8 @@
      * type to the key.
      */
     public <T> void set(Key<T> key, T value) {
+        Log.e(TAG, "Not fully implemented yet");
+
         mMetadataMap.put(key, value);
     }
 
@@ -76,6 +87,8 @@
      */
     @SuppressWarnings("unchecked")
     public <T> T get(Key<T> key) {
+        Log.e(TAG, "Not fully implemented yet");
+
         return (T) mMetadataMap.get(key);
     }
 
@@ -86,7 +99,15 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
+        nativeWriteToParcel(dest);
+    }
 
+    /**
+     * Expand this object from a Parcel.
+     * @param in The Parcel from which the object should be read
+     */
+    public void readFromParcel(Parcel in) {
+        nativeReadFromParcel(in);
     }
 
     public static class Key<T> {
@@ -125,5 +146,88 @@
         private final String mName;
     }
 
-    private Map<Key<?>, Object> mMetadataMap;
+    private final Map<Key<?>, Object> mMetadataMap;
+
+    /**
+     * @hide
+     */
+    private long mMetadataPtr; // native CameraMetadata*
+
+    private native long nativeAllocate();
+    private native synchronized void nativeWriteToParcel(Parcel dest);
+    private native synchronized void nativeReadFromParcel(Parcel source);
+    private native synchronized void nativeSwap(CameraMetadata other) throws NullPointerException;
+    private native synchronized void nativeClose();
+    private native synchronized boolean nativeIsEmpty();
+    private native synchronized int nativeGetEntryCount();
+    private static native void nativeClassInit();
+
+    /**
+     * <p>Perform a 0-copy swap of the internal metadata with another object.</p>
+     *
+     * <p>Useful to convert a CameraMetadata into e.g. a CaptureRequest.</p>
+     *
+     * @param other metadata to swap with
+     * @throws NullPointerException if other was null
+     * @hide
+     */
+    public void swap(CameraMetadata other) {
+        nativeSwap(other);
+    }
+
+    /**
+     * @hide
+     */
+    public int getEntryCount() {
+        return nativeGetEntryCount();
+    }
+
+    /**
+     * Does this metadata contain at least 1 entry?
+     *
+     * @hide
+     */
+    public boolean isEmpty() {
+        return nativeIsEmpty();
+    }
+
+    /**
+     * <p>Closes this object, and releases all native resources associated with it.</p>
+     *
+     * <p>Calling any other public method after this will result in an IllegalStateException
+     * being thrown.</p>
+     */
+    @Override
+    public void close() throws Exception {
+        // this sets mMetadataPtr to 0
+        nativeClose();
+        mMetadataPtr = 0; // set it to 0 again to prevent eclipse from making this field final
+    }
+
+    /**
+     * Whether or not {@link #close} has already been called (at least once) on this object.
+     * @hide
+     */
+    public boolean isClosed() {
+        synchronized (this) {
+            return mMetadataPtr == 0;
+        }
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            close();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * We use a class initializer to allow the native code to cache some field offsets
+     */
+    static {
+        System.loadLibrary("media_jni");
+        nativeClassInit();
+    }
 }
\ No newline at end of file
diff --git a/core/java/android/hardware/photography/CameraProperties.java b/core/java/android/hardware/photography/CameraProperties.java
index 1bfd712..ad42285 100644
--- a/core/java/android/hardware/photography/CameraProperties.java
+++ b/core/java/android/hardware/photography/CameraProperties.java
@@ -39,7 +39,7 @@
      * {@link #INFO_IDENTIFIER} can be used to distinguish between multiple
      * removable cameras of the same model.
      */
-    public static final Key INFO_MODEL =
+    public static final Key<String> INFO_MODEL =
             new Key<String>("android.info.model");
 
     /**
@@ -48,7 +48,7 @@
      * same model and manufacturer. For non-removable cameras, the
      * identifier is equal to the the device's id.
      */
-    public static final Key INFO_IDENTIFIER =
+    public static final Key<String> INFO_IDENTIFIER =
             new Key<String>("android.info.identifier");
 
     /**
@@ -58,7 +58,7 @@
      * to be disconnected during use. Use the {@link #INFO_IDENTIFIER} field to
      * determine if this camera is a match for a camera device seen earlier.</p>
      */
-    public static final Key INFO_REMOVABLE =
+    public static final Key<Boolean> INFO_REMOVABLE =
             new Key<Boolean>("android.info.isRemovable");
 
     /**
@@ -99,7 +99,7 @@
      * @see #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED
      * @see #INFO_SUPPORTED_HARDWARE_LEVEL_FULL
      */
-    public static final Key INFO_SUPPORTED_HARDWARE_LEVEL =
+    public static final Key<Integer> INFO_SUPPORTED_HARDWARE_LEVEL =
             new Key<Integer>("android.info.supportedHardwareLevel");
 
     /**
@@ -164,7 +164,7 @@
      * {@link android.graphics.ImageFormat#YUV_420_888} are guaranteed to be
      * supported.</p>
      */
-    public static final Key SCALER_AVAILABLE_FORMATS =
+    public static final Key<Integer[]> SCALER_AVAILABLE_FORMATS =
             new Key<Integer[]>("android.scaler.availableFormats");
 
     /**
@@ -173,7 +173,7 @@
      * target, the ImageReader must be configured to use one of these sizes
      * when using format {@link android.graphics.ImageFormat#JPEG}.</p>
      */
-    public static final Key SCALER_AVAILABLE_JPEG_SIZES =
+    public static final Key<Size[]> SCALER_AVAILABLE_JPEG_SIZES =
             new Key<Size[]>("android.scaler.availableJpegSizes");
 
     /**
@@ -193,7 +193,7 @@
      * when using format {@link android.graphics.ImageFormat#YUV_420_888}.</p>
      *
      */
-    public static final Key SCALER_AVAILABLE_PROCESSED_SIZES =
+    public static final Key<Size[]> SCALER_AVAILABLE_PROCESSED_SIZES =
             new Key<Size[]>("android.scaler.availableProcessedSizes");
 
     /**
@@ -206,7 +206,7 @@
      * target, the ImageReader must be configured to use one of these sizes
      * when using image format {@link android.graphics.ImageFormat#RAW_SENSOR}.</p>
      */
-    public static final Key SCALER_AVAILABLE_RAW_SIZES =
+    public static final Key<Size[]> SCALER_AVAILABLE_RAW_SIZES =
             new Key<Size[]>("android.scaler.availableRawSizes");
 
     /**
@@ -229,7 +229,7 @@
      * a coordinate system based on the active array dimensions, with (0,0)
      * being the top-left corner of the active array.</p>
      */
-    public static final Key SENSOR_ACTIVE_ARRAY_SIZE =
+    public static final Key<Rect> SENSOR_ACTIVE_ARRAY_SIZE =
             new Key<Rect>("android.sensor.activeArraySize");
 
     /**
@@ -239,7 +239,7 @@
      * this. If raw sensor capture is supported by this device, this is one of
      * the supported capture sizes.</p>
      */
-    public static final Key SENSOR_PIXEL_ARRAY_SIZE =
+    public static final Key<Size> SENSOR_PIXEL_ARRAY_SIZE =
             new Key<Size>("android.sensor.activeArraySize");
 
     // TODO: Many more of these.
diff --git a/core/java/android/hardware/photography/CaptureRequest.aidl b/core/java/android/hardware/photography/CaptureRequest.aidl
new file mode 100644
index 0000000..64fb6f2
--- /dev/null
+++ b/core/java/android/hardware/photography/CaptureRequest.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.photography;
+
+/** @hide */
+parcelable CaptureRequest;
diff --git a/core/java/android/hardware/photography/CaptureRequest.java b/core/java/android/hardware/photography/CaptureRequest.java
index a54c743..ac2041b 100644
--- a/core/java/android/hardware/photography/CaptureRequest.java
+++ b/core/java/android/hardware/photography/CaptureRequest.java
@@ -16,9 +16,11 @@
 
 package android.hardware.photography;
 
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.view.Surface;
 
-import java.util.List;
+import java.util.HashSet;
 
 
 /**
@@ -47,24 +49,30 @@
  * @see CameraDevice#setRepeatingRequest
  * @see CameraDevice#createRequest
  */
-public final class CaptureRequest extends CameraMetadata {
+public final class CaptureRequest extends CameraMetadata implements Parcelable {
+
+    private final Object mLock = new Object();
+    private final HashSet<Surface> mSurfaceSet = new HashSet<Surface>();
 
     /**
      * The exposure time for this capture, in nanoseconds.
      */
-    public static final Key SENSOR_EXPOSURE_TIME =
+    public static final Key<Long> SENSOR_EXPOSURE_TIME =
             new Key<Long>("android.sensor.exposureTime");
 
     /**
      * The sensor sensitivity (gain) setting for this camera.
      * This is represented as an ISO sensitivity value
      */
-    public static final Key SENSOR_SENSITIVITY =
+    public static final Key<Integer> SENSOR_SENSITIVITY =
             new Key<Integer>("android.sensor.sensitivity");
 
     // Many more settings
 
-    CaptureRequest() {
+    /**
+     * @hide
+     */
+    public CaptureRequest() {
     }
 
     /**
@@ -72,14 +80,76 @@
      *
      * <p>The Surface added must be one of the surfaces included in the last
      * call to {@link CameraDevice#configureOutputs}.</p>
+     *
+     * <p>Adding a target more than once has no effect.</p>
+     *
+     * @param outputTarget surface to use as an output target for this request
      */
     public void addTarget(Surface outputTarget) {
+        synchronized (mLock) {
+            mSurfaceSet.add(outputTarget);
+        }
     }
 
     /**
      * <p>Remove a surface from the list of targets for this request.</p>
+     *
+     * <p>Removing a target that is not currently added has no effect.</p>
+     *
+     * @param outputTarget surface to use as an output target for this request
      */
     public void removeTarget(Surface outputTarget) {
+        synchronized (mLock) {
+            mSurfaceSet.remove(outputTarget);
+        }
+    }
+
+    public static final Parcelable.Creator<CaptureRequest> CREATOR =
+            new Parcelable.Creator<CaptureRequest>() {
+        @Override
+        public CaptureRequest createFromParcel(Parcel in) {
+            CaptureRequest request = new CaptureRequest();
+            request.readFromParcel(in);
+            return request;
+        }
+
+        @Override
+        public CaptureRequest[] newArray(int size) {
+            return new CaptureRequest[size];
+        }
+    };
+
+    /**
+     * Expand this object from a Parcel.
+     * @param in The parcel from which the object should be read
+     */
+    @Override
+    public void readFromParcel(Parcel in) {
+        synchronized (mLock) {
+            super.readFromParcel(in);
+
+            mSurfaceSet.clear();
+
+            Parcelable[] parcelableArray = in.readParcelableArray(Surface.class.getClassLoader());
+
+            if (parcelableArray == null) {
+                return;
+            }
+
+            for (Parcelable p : parcelableArray) {
+                Surface s = (Surface) p;
+                mSurfaceSet.add(s);
+            }
+        }
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        synchronized (mLock) {
+            super.writeToParcel(dest, flags);
+
+            dest.writeParcelableArray(mSurfaceSet.toArray(new Surface[mSurfaceSet.size()]), flags);
+        }
     }
 
 }
\ No newline at end of file
diff --git a/core/java/android/hardware/photography/CaptureResult.java b/core/java/android/hardware/photography/CaptureResult.java
index dd36f1d..b502c4c 100644
--- a/core/java/android/hardware/photography/CaptureResult.java
+++ b/core/java/android/hardware/photography/CaptureResult.java
@@ -101,7 +101,10 @@
 
     // TODO: Many many more
 
-    CaptureResult() {
+    /**
+     * @hide
+     */
+    public CaptureResult() {
     }
 
     /**
diff --git a/core/java/android/hardware/photography/ICameraDeviceCallbacks.aidl b/core/java/android/hardware/photography/ICameraDeviceCallbacks.aidl
new file mode 100644
index 0000000..c506800
--- /dev/null
+++ b/core/java/android/hardware/photography/ICameraDeviceCallbacks.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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.photography;
+
+import android.hardware.photography.CameraMetadata;
+
+/** @hide */
+interface ICameraDeviceCallbacks
+{
+    /**
+     * Keep up-to-date with frameworks/av/include/camera/photography/ICameraDeviceCallbacks.h
+     */
+
+    void notifyCallback(int msgType, int ext1, int ext2);
+    void onResultReceived(int frameId, in CameraMetadata result);
+}
diff --git a/core/java/android/hardware/photography/ICameraDeviceUser.aidl b/core/java/android/hardware/photography/ICameraDeviceUser.aidl
new file mode 100644
index 0000000..d1310fb
--- /dev/null
+++ b/core/java/android/hardware/photography/ICameraDeviceUser.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.photography;
+
+import android.view.Surface;
+import android.hardware.photography.CameraMetadata;
+import android.hardware.photography.CaptureRequest;
+
+/** @hide */
+interface ICameraDeviceUser
+{
+    /**
+     * Keep up-to-date with frameworks/av/include/camera/photography/ICameraDeviceUser.h
+     */
+    void disconnect();
+
+    // ints here are status_t
+
+    // non-negative value is the requestId. negative value is status_t
+    int submitRequest(in CaptureRequest request, boolean streaming);
+
+    int cancelRequest(int requestId);
+
+    int deleteStream(int streamId);
+
+    // non-negative value is the stream ID. negative value is status_t
+    int createStream(int width, int height, int format, in Surface surface);
+
+    int createDefaultRequest(int templateId, out CameraMetadata request);
+}
diff --git a/core/java/android/hardware/photography/impl/CameraDevice.java b/core/java/android/hardware/photography/impl/CameraDevice.java
new file mode 100644
index 0000000..b1e3f6a
--- /dev/null
+++ b/core/java/android/hardware/photography/impl/CameraDevice.java
@@ -0,0 +1,322 @@
+/*
+ * 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.photography.impl;
+
+import android.hardware.photography.CameraMetadata;
+import android.hardware.photography.CaptureResult;
+import android.hardware.photography.ICameraDeviceUser;
+import android.hardware.photography.ICameraDeviceCallbacks;
+import android.hardware.photography.CameraAccessException;
+import android.hardware.photography.CameraProperties;
+import android.hardware.photography.CaptureRequest;
+import android.hardware.photography.utils.CameraRuntimeException;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.Surface;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Stack;
+
+/**
+ * HAL2.1+ implementation of CameraDevice Use CameraManager#open to instantiate
+ */
+public class CameraDevice implements android.hardware.photography.CameraDevice {
+
+    private final String TAG;
+
+    // TODO: guard every function with if (!mRemoteDevice) check (if it was closed)
+    private ICameraDeviceUser mRemoteDevice;
+
+    private final Object mLock = new Object();
+    private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks();
+
+    // XX: Make this a WeakReference<CaptureListener> ?
+    private final HashMap<Integer, CaptureListenerHolder> mCaptureListenerMap =
+            new HashMap<Integer, CaptureListenerHolder>();
+
+    private final Stack<Integer> mRepeatingRequestIdStack = new Stack<Integer>();
+
+    private final String mCameraId;
+
+    public CameraDevice(String cameraId) {
+        mCameraId = cameraId;
+        TAG = String.format("CameraDevice-%s-JV", mCameraId);
+    }
+
+    public CameraDeviceCallbacks getCallbacks() {
+        return mCallbacks;
+    }
+
+    /**
+     * @hide
+     */
+    public void setRemoteDevice(ICameraDeviceUser remoteDevice) {
+        mRemoteDevice = remoteDevice;
+    }
+
+    @Override
+    public CameraProperties getProperties() throws CameraAccessException {
+        // TODO
+        Log.v(TAG, "TODO: Implement getProperties");
+        return new CameraProperties();
+    }
+
+    @Override
+    public void configureOutputs(List<Surface> outputs) throws CameraAccessException {
+        synchronized (mLock) {
+            // TODO: delete outputs that aren't in this list that were configured previously
+            for (Surface s : outputs) {
+                try {
+                    // TODO: remove width,height,format since we are ignoring
+                    // it.
+                    mRemoteDevice.createStream(0, 0, 0, s);
+                } catch (CameraRuntimeException e) {
+                    throw e.asChecked();
+                } catch (RemoteException e) {
+                    // impossible
+                    return;
+                }
+            }
+        }
+    }
+
+    @Override
+    public CaptureRequest createCaptureRequest(int templateType) throws CameraAccessException {
+
+        synchronized (mLock) {
+
+            CameraMetadata templatedRequest = new CameraMetadata();
+
+            try {
+                mRemoteDevice.createDefaultRequest(templateType, /* out */templatedRequest);
+            } catch (CameraRuntimeException e) {
+                throw e.asChecked();
+            } catch (RemoteException e) {
+                // impossible
+                return null;
+            }
+
+            CaptureRequest request = new CaptureRequest();
+
+            // XX: could also change binder signature but that's more work than
+            // just using swap.
+            request.swap(templatedRequest);
+
+            return request;
+
+        }
+    }
+
+    @Override
+    public void capture(CaptureRequest request, CaptureListener listener)
+            throws CameraAccessException {
+        submitCaptureRequest(request, listener, /*streaming*/false);
+    }
+
+    @Override
+    public void captureBurst(List<CaptureRequest> requests, CaptureListener listener)
+            throws CameraAccessException {
+        // TODO
+        throw new UnsupportedOperationException("Burst capture implemented yet");
+
+    }
+
+    private void submitCaptureRequest(CaptureRequest request, CaptureListener listener,
+            boolean repeating) throws CameraAccessException {
+
+        synchronized (mLock) {
+
+            int requestId;
+
+            try {
+                requestId = mRemoteDevice.submitRequest(request, repeating);
+            } catch (CameraRuntimeException e) {
+                throw e.asChecked();
+            } catch (RemoteException e) {
+                // impossible
+                return;
+            }
+
+            mCaptureListenerMap.put(requestId, new CaptureListenerHolder(listener, request,
+                    repeating));
+
+            if (repeating) {
+                mRepeatingRequestIdStack.add(requestId);
+            }
+
+        }
+    }
+
+    @Override
+    public void setRepeatingRequest(CaptureRequest request, CaptureListener listener)
+            throws CameraAccessException {
+        submitCaptureRequest(request, listener, /*streaming*/true);
+    }
+
+    @Override
+    public void setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener)
+            throws CameraAccessException {
+        // TODO
+        throw new UnsupportedOperationException("Burst capture implemented yet");
+    }
+
+    @Override
+    public void stopRepeating() throws CameraAccessException {
+
+        synchronized (mLock) {
+
+            while (!mRepeatingRequestIdStack.isEmpty()) {
+                int requestId = mRepeatingRequestIdStack.pop();
+
+                try {
+                    mRemoteDevice.cancelRequest(requestId);
+                } catch (CameraRuntimeException e) {
+                    throw e.asChecked();
+                } catch (RemoteException e) {
+                    // impossible
+                    return;
+                }
+            }
+        }
+    }
+
+    @Override
+    public void waitUntilIdle() throws CameraAccessException {
+        // TODO: implement
+    }
+
+    @Override
+    public void setErrorListener(ErrorListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void close() throws Exception {
+
+        // TODO: every method should throw IllegalStateException after close has been called
+
+        synchronized (mLock) {
+
+            try {
+                mRemoteDevice.disconnect();
+            } catch (CameraRuntimeException e) {
+                throw e.asChecked();
+            } catch (RemoteException e) {
+                // impossible
+            }
+
+            mRemoteDevice = null;
+
+        }
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            close();
+        } catch (CameraRuntimeException e) {
+            Log.e(TAG, "Got error while trying to finalize, ignoring: " + e.getMessage());
+        }
+        finally {
+            super.finalize();
+        }
+    }
+
+    static class CaptureListenerHolder {
+
+        private final boolean mRepeating;
+        private final CaptureListener mListener;
+        private final CaptureRequest mRequest;
+
+        CaptureListenerHolder(CaptureListener listener, CaptureRequest request, boolean repeating) {
+            mRepeating = repeating;
+            mRequest = request;
+            mListener = listener;
+        }
+
+        public boolean isRepeating() {
+            return mRepeating;
+        }
+
+        public CaptureListener getListener() {
+            return mListener;
+        }
+
+        public CaptureRequest getRequest() {
+            return mRequest;
+        }
+    }
+
+    // TODO: unit tests
+    public class CameraDeviceCallbacks extends Binder implements ICameraDeviceCallbacks {
+
+        @Override
+        public IBinder asBinder() {
+            return this;
+        }
+
+        // TODO: consider rename to onMessageReceived
+        @Override
+        public void notifyCallback(int msgType, int ext1, int ext2) throws RemoteException {
+            Log.d(TAG, "Got message " + msgType + " ext1: " + ext1 + " , ext2: " + ext2);
+            // TODO implement rest
+        }
+
+        @Override
+        public void onResultReceived(int frameId, CameraMetadata result) throws RemoteException {
+            Log.d(TAG, "Received result for frameId " + frameId);
+
+            CaptureListenerHolder holder;
+
+            synchronized (mLock) {
+                // TODO: move this whole map into this class to make it more testable,
+                //        exposing the methods necessary like subscribeToRequest, unsubscribe..
+                // TODO: make class static class
+
+                holder = CameraDevice.this.mCaptureListenerMap.get(frameId);
+
+                // Clean up listener once we no longer expect to see it.
+
+                // TODO: how to handle repeating listeners?
+                // we probably want cancelRequest to return # of times it already enqueued and
+                // keep a counter.
+                if (holder != null && !holder.isRepeating()) {
+                    CameraDevice.this.mCaptureListenerMap.remove(frameId);
+                }
+            }
+
+            if (holder == null) {
+                Log.e(TAG, "Result had no listener holder associated with it, dropping result");
+                return;
+            }
+
+            CaptureResult resultAsCapture = new CaptureResult();
+            resultAsCapture.swap(result);
+
+            if (holder.getListener() != null) {
+                holder.getListener().onCaptureComplete(CameraDevice.this, holder.getRequest(),
+                        resultAsCapture);
+            }
+        }
+
+    }
+
+}
diff --git a/core/java/android/hardware/photography/impl/package.html b/core/java/android/hardware/photography/impl/package.html
new file mode 100644
index 0000000..783d0a1
--- /dev/null
+++ b/core/java/android/hardware/photography/impl/package.html
@@ -0,0 +1,3 @@
+<body>
+{@hide}
+</body>
diff --git a/core/java/android/hardware/photography/utils/CameraBinderDecorator.java b/core/java/android/hardware/photography/utils/CameraBinderDecorator.java
new file mode 100644
index 0000000..1a44b97f
--- /dev/null
+++ b/core/java/android/hardware/photography/utils/CameraBinderDecorator.java
@@ -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.
+ */
+
+package android.hardware.photography.utils;
+
+import static android.hardware.photography.CameraAccessException.CAMERA_DISABLED;
+import static android.hardware.photography.CameraAccessException.CAMERA_DISCONNECTED;
+import static android.hardware.photography.CameraAccessException.CAMERA_IN_USE;
+
+import android.os.DeadObjectException;
+import android.os.RemoteException;
+
+import java.lang.reflect.Method;
+
+/**
+ * Translate camera service status_t return values into exceptions.
+ *
+ * @see android.hardware.photography.utils.CameraBinderDecorator#newInstance
+ * @hide
+ */
+public class CameraBinderDecorator {
+
+    public static final int NO_ERROR = 0;
+    public static final int PERMISSION_DENIED = -1;
+    public static final int ALREADY_EXISTS = -17;
+    public static final int BAD_VALUE = -22;
+    public static final int DEAD_OBJECT = -32;
+
+    /**
+     * TODO: add as error codes in Errors.h
+     * - POLICY_PROHIBITS
+     * - RESOURCE_BUSY
+     * - NO_SUCH_DEVICE
+     */
+    public static final int EACCES = -13;
+    public static final int EBUSY = -16;
+    public static final int ENODEV = -19;
+
+    private static class CameraBinderDecoratorListener implements Decorator.DecoratorListener {
+
+        @Override
+        public void onBeforeInvocation(Method m, Object[] args) {
+        }
+
+        @Override
+        public void onAfterInvocation(Method m, Object[] args, Object result) {
+            // int return type => status_t => convert to exception
+            if (m.getReturnType() == Integer.TYPE) {
+                int returnValue = (Integer) result;
+
+                switch (returnValue) {
+                    case NO_ERROR:
+                        return;
+                    case PERMISSION_DENIED:
+                        throw new SecurityException("Lacking privileges to access camera service");
+                    case ALREADY_EXISTS:
+                        // This should be handled at the call site. Typically this isn't bad,
+                        // just means we tried to do an operation that already completed.
+                        return;
+                    case BAD_VALUE:
+                        throw new IllegalArgumentException("Bad argument passed to camera service");
+                    case DEAD_OBJECT:
+                        UncheckedThrow.throwAnyException(new CameraRuntimeException(
+                                CAMERA_DISCONNECTED));
+                        // TODO: Camera service (native side) should return
+                        // EACCES error
+                        // when there's a policy manager disabled causing this
+                    case EACCES:
+                        UncheckedThrow.throwAnyException(new CameraRuntimeException(
+                                CAMERA_DISABLED));
+                    case EBUSY:
+                        UncheckedThrow.throwAnyException(new CameraRuntimeException(
+                                CAMERA_IN_USE));
+                    case ENODEV:
+                        UncheckedThrow.throwAnyException(new CameraRuntimeException(
+                                CAMERA_DISCONNECTED));
+                }
+
+                /**
+                 * Trap the rest of the negative return values. If we have known
+                 * error codes i.e. ALREADY_EXISTS that aren't really runtime
+                 * errors, then add them to the top switch statement
+                 */
+                if (returnValue < 0) {
+                    throw new UnsupportedOperationException(String.format("Unknown error %d",
+                            returnValue));
+                }
+            }
+        }
+
+        @Override
+        public boolean onCatchException(Method m, Object[] args, Throwable t) {
+
+            if (t instanceof DeadObjectException) {
+                UncheckedThrow.throwAnyException(new CameraRuntimeException(
+                        CAMERA_DISCONNECTED,
+                        "Process hosting the camera service has died unexpectedly",
+                        t));
+            } else if (t instanceof RemoteException) {
+                throw new UnsupportedOperationException("An unknown RemoteException was thrown" +
+                        " which should never happen.", t);
+            }
+
+            return false;
+        }
+
+        @Override
+        public void onFinally(Method m, Object[] args) {
+        }
+
+    }
+
+    /**
+     * <p>
+     * Wraps the type T with a proxy that will check 'status_t' return codes
+     * from the native side of the camera service, and throw Java exceptions
+     * automatically based on the code.
+     * </p>
+     * <p>
+     * In addition it also rewrites binder's RemoteException into either a
+     * CameraAccessException or an UnsupportedOperationException.
+     * </p>
+     * <p>
+     * As a result of calling any method on the proxy, RemoteException is
+     * guaranteed never to be thrown.
+     * </p>
+     *
+     * @param obj object that will serve as the target for all method calls
+     * @param <T> the type of the element you want to wrap. This must be an interface.
+     * @return a proxy that will intercept all invocations to obj
+     */
+    public static <T> T newInstance(T obj) {
+        return Decorator.<T> newInstance(obj, new CameraBinderDecoratorListener());
+    }
+}
diff --git a/core/java/android/hardware/photography/utils/CameraRuntimeException.java b/core/java/android/hardware/photography/utils/CameraRuntimeException.java
new file mode 100644
index 0000000..25dfc62
--- /dev/null
+++ b/core/java/android/hardware/photography/utils/CameraRuntimeException.java
@@ -0,0 +1,63 @@
+package android.hardware.photography.utils;
+
+import android.hardware.photography.CameraAccessException;
+
+/**
+ * @hide
+ */
+public class CameraRuntimeException extends RuntimeException {
+
+    private final int mReason;
+    private String mMessage;
+    private Throwable mCause;
+
+    public final int getReason() {
+        return mReason;
+    }
+
+    public CameraRuntimeException(int problem) {
+        super();
+        mReason = problem;
+    }
+
+    public CameraRuntimeException(int problem, String message) {
+        super(message);
+        mReason = problem;
+        mMessage = message;
+    }
+
+    public CameraRuntimeException(int problem, String message, Throwable cause) {
+        super(message, cause);
+        mReason = problem;
+        mMessage = message;
+        mCause = cause;
+    }
+
+    public CameraRuntimeException(int problem, Throwable cause) {
+        super(cause);
+        mReason = problem;
+        mCause = cause;
+    }
+
+    /**
+     * Recreate this exception as the CameraAccessException equivalent.
+     * @return CameraAccessException
+     */
+    public CameraAccessException asChecked() {
+        CameraAccessException e;
+
+        if (mMessage != null && mCause != null) {
+            e = new CameraAccessException(mReason, mMessage, mCause);
+        } else if (mMessage != null) {
+            e = new CameraAccessException(mReason, mMessage);
+        } else if (mCause != null) {
+            e = new CameraAccessException(mReason, mCause);
+        } else {
+            e = new CameraAccessException(mReason);
+        }
+        // throw and catch, so java has a chance to fill out the stack trace
+        e.setStackTrace(this.getStackTrace());
+
+        return e;
+    }
+}
diff --git a/core/java/android/hardware/photography/utils/Decorator.java b/core/java/android/hardware/photography/utils/Decorator.java
new file mode 100644
index 0000000..ed05dd2
--- /dev/null
+++ b/core/java/android/hardware/photography/utils/Decorator.java
@@ -0,0 +1,92 @@
+
+package android.hardware.photography.utils;
+
+import java.lang.reflect.*;
+
+/**
+ * This is an implementation of the 'decorator' design pattern using Java's proxy mechanism.
+ *
+ * @see android.hardware.photography.utils.Decorator#newInstance
+ *
+ * @hide
+ */
+public class Decorator<T> implements InvocationHandler {
+
+    public interface DecoratorListener {
+        /**
+         * This method is called before the target method is invoked
+         * @param args arguments to target method
+         * @param m Method being called
+         */
+        void onBeforeInvocation(Method m, Object[] args);
+        /**
+         * This function is called after the target method is invoked
+         * if there were no uncaught exceptions
+         * @param args arguments to target method
+         * @param m Method being called
+         * @param result return value of target method
+         */
+        void onAfterInvocation(Method m, Object[] args, Object result);
+        /**
+         * This method is called only if there was an exception thrown by the target method
+         * during its invocation.
+         *
+         * @param args arguments to target method
+         * @param m Method being called
+         * @param t Throwable that was thrown
+         * @return false to rethrow exception, true if the exception was handled
+         */
+        boolean onCatchException(Method m, Object[] args, Throwable t);
+        /**
+         * This is called after the target method is invoked, regardless of whether or not
+         * there were any exceptions.
+         * @param args arguments to target method
+         * @param m Method being called
+         */
+        void onFinally(Method m, Object[] args);
+    }
+
+    private final T mObject;
+    private final DecoratorListener mListener;
+
+    /**
+     * Create a decorator wrapping the specified object's method calls.
+     *
+     * @param obj the object whose method calls you want to intercept
+     * @param listener the decorator handler for intercepted method calls
+     * @param <T> the type of the element you want to wrap. This must be an interface.
+     * @return a wrapped interface-compatible T
+     */
+    @SuppressWarnings("unchecked")
+    public static<T> T newInstance(T obj, DecoratorListener listener) {
+        return (T)java.lang.reflect.Proxy.newProxyInstance(
+                obj.getClass().getClassLoader(),
+                obj.getClass().getInterfaces(),
+                new Decorator<T>(obj, listener));
+    }
+
+    private Decorator(T obj, DecoratorListener listener) {
+        this.mObject = obj;
+        this.mListener = listener;
+    }
+
+    @Override
+    public Object invoke(Object proxy, Method m, Object[] args)
+            throws Throwable
+    {
+        Object result = null;
+        try {
+            mListener.onBeforeInvocation(m, args);
+            result = m.invoke(mObject, args);
+            mListener.onAfterInvocation(m, args, result);
+        } catch (InvocationTargetException e) {
+            Throwable t = e.getTargetException();
+            if (!mListener.onCatchException(m, args, t)) {
+                throw t;
+            }
+        } finally {
+            mListener.onFinally(m, args);
+        }
+        return result;
+    }
+}
diff --git a/core/java/android/hardware/photography/utils/UncheckedThrow.java b/core/java/android/hardware/photography/utils/UncheckedThrow.java
new file mode 100644
index 0000000..8eed6b1
--- /dev/null
+++ b/core/java/android/hardware/photography/utils/UncheckedThrow.java
@@ -0,0 +1,40 @@
+/*
+ * 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.photography.utils;
+
+/**
+ * @hide
+ */
+public class UncheckedThrow {
+
+    /**
+     * Throw any kind of exception without needing it to be checked
+     * @param e any instance of a Exception
+     */
+    public static void throwAnyException(Exception e) {
+        /**
+         *  Abuse type erasure by making the compiler think we are throwing RuntimeException,
+         *  which is unchecked, but then inserting any exception in there.
+         */
+        UncheckedThrow.<RuntimeException>throwAnyImpl(e);
+    }
+
+    @SuppressWarnings("unchecked")
+    private static<T extends Exception> void throwAnyImpl(Exception e) throws T {
+        throw (T) e;
+    }
+}
diff --git a/core/java/android/hardware/photography/utils/package.html b/core/java/android/hardware/photography/utils/package.html
new file mode 100644
index 0000000..783d0a1
--- /dev/null
+++ b/core/java/android/hardware/photography/utils/package.html
@@ -0,0 +1,3 @@
+<body>
+{@hide}
+</body>
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 7c09e89c..8e0935d 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1208,13 +1208,13 @@
         pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
         pw.print(uid); pw.print(',');
         pw.print(category); pw.print(',');
-        pw.print(type); 
+        pw.print(type);
         
         for (Object arg : args) {  
-            pw.print(','); 
-            pw.print(arg); 
+            pw.print(',');
+            pw.print(arg);
         }
-        pw.print('\n');
+        pw.println();
     }
     
     /**
@@ -1407,7 +1407,11 @@
                     
                     // Only log if we had at lease one wakelock...
                     if (sb.length() > 0) {
-                       dumpLine(pw, uid, category, WAKELOCK_DATA, ent.getKey(), sb.toString());
+                        String name = ent.getKey();
+                        if (name.indexOf(',') >= 0) {
+                            name = name.replace(',', '_');
+                        }
+                        dumpLine(pw, uid, category, WAKELOCK_DATA, name, sb.toString());
                     }
                 }
             }
@@ -2274,6 +2278,30 @@
             }
             oldState = rec.states;
         }
+
+        public void printNextItemCheckin(PrintWriter pw, HistoryItem rec, long now) {
+            pw.print(rec.time-now);
+            pw.print(",");
+            if (rec.cmd == HistoryItem.CMD_START) {
+                pw.print("start");
+            } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
+                pw.print("overflow");
+            } else {
+                pw.print(rec.batteryLevel);
+                pw.print(",");
+                pw.print(rec.states);
+                pw.print(",");
+                pw.print(rec.batteryStatus);
+                pw.print(",");
+                pw.print(rec.batteryHealth);
+                pw.print(",");
+                pw.print(rec.batteryPlugType);
+                pw.print(",");
+                pw.print((int)rec.batteryTemperature);
+                pw.print(",");
+                pw.print((int)rec.batteryVoltage);
+            }
+        }
     }
 
     /**
@@ -2351,6 +2379,21 @@
             PrintWriter pw, List<ApplicationInfo> apps, boolean isUnpluggedOnly) {
         prepareForDumpLocked();
         
+        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
+
+        final HistoryItem rec = new HistoryItem();
+        if (startIteratingHistoryLocked()) {
+            HistoryPrinter hprinter = new HistoryPrinter();
+            while (getNextHistoryLocked(rec)) {
+                pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+                pw.print(0); pw.print(',');
+                pw.print("h"); pw.print(',');
+                hprinter.printNextItemCheckin(pw, rec, now);
+                pw.println();
+            }
+            finishIteratingHistoryLocked();
+        }
+
         if (apps != null) {
             SparseArray<ArrayList<String>> uids = new SparseArray<ArrayList<String>>();
             for (int i=0; i<apps.size(); i++) {
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 362ae29..c5f473e 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.TypedProperties;
 
 import android.util.Log;
@@ -476,7 +477,7 @@
         PrintWriter outStream = null;
         try {
             FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
-            outStream = new PrintWriter(new OutputStreamWriter(fos));
+            outStream = new FastPrintWriter(fos);
             outStream.println("1");
         } catch (Exception e) {
         } finally {
@@ -504,7 +505,7 @@
         PrintWriter outStream = null;
         try {
             FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
-            outStream = new PrintWriter(new OutputStreamWriter(fos));
+            outStream = new FastPrintWriter(fos);
             outStream.println("0");
         } catch (Exception e) {
             // We could print an error message here but we probably want
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 9666d9a..97ea99d 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -60,6 +60,8 @@
 
     public static native int setPermissions(String file, int mode, int uid, int gid);
 
+    public static native int getUid(String file);
+
     /** returns the FAT file system volume ID for the volume mounted 
      * at the given mount point, or -1 for failure
      * @param mountPoint point for FAT volume
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index a11358a..7589a5a 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -46,4 +46,7 @@
             int userHandle);
     Bundle getApplicationRestrictions(in String packageName);
     Bundle getApplicationRestrictionsForUser(in String packageName, int userHandle);
+    boolean changeRestrictionsPin(in String newPin);
+    int checkRestrictionsPin(in String pin);
+    boolean hasRestrictionsPin();
 }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 93b1255..159d3eb 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -976,6 +976,8 @@
     /** @hide */
     public static final int PROC_PARENS = 0x200;
     /** @hide */
+    public static final int PROC_QUOTES = 0x400;
+    /** @hide */
     public static final int PROC_OUT_STRING = 0x1000;
     /** @hide */
     public static final int PROC_OUT_LONG = 0x2000;
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index a9abdc5..d794ca6 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -32,6 +32,7 @@
 
 import com.android.internal.os.RuntimeInit;
 
+import com.android.internal.util.FastPrintWriter;
 import dalvik.system.BlockGuard;
 import dalvik.system.CloseGuard;
 import dalvik.system.VMDebug;
@@ -1700,7 +1701,9 @@
     /* package */ static void readAndHandleBinderCallViolations(Parcel p) {
         // Our own stack trace to append
         StringWriter sw = new StringWriter();
-        new LogStackTrace().printStackTrace(new PrintWriter(sw));
+        PrintWriter pw = new FastPrintWriter(sw, false, 256);
+        new LogStackTrace().printStackTrace(pw);
+        pw.flush();
         String ourStack = sw.toString();
 
         int policyMask = getThreadPolicyMask();
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index cb5ed4f..c33a28a 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -140,6 +140,13 @@
      */
     public static final String DISALLOW_REMOVE_USER = "no_remove_user";
 
+    /** @hide */
+    public static final int PIN_VERIFICATION_FAILED_INCORRECT = -3;
+    /** @hide */
+    public static final int PIN_VERIFICATION_FAILED_NOT_SET = -2;
+    /** @hide */
+    public static final int PIN_VERIFICATION_SUCCESS = -1;
+
     private static UserManager sInstance = null;
 
     /** @hide */
@@ -620,4 +627,55 @@
             Log.w(TAG, "Could not set application restrictions for user " + user.getIdentifier());
         }
     }
+
+    /**
+     * @hide
+     * Sets a new restrictions PIN. This should only be called after verifying that there
+     * currently isn't a PIN set, or after the user successfully enters the current PIN.
+     * @param newPin
+     * @return Returns true if the PIN was changed successfully.
+     */
+    public boolean changeRestrictionsPin(String newPin) {
+        try {
+            return mService.changeRestrictionsPin(newPin);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not change restrictions pin");
+        }
+        return false;
+    }
+
+    /**
+     * @hide
+     * @param pin The PIN to verify, or null to get the number of milliseconds to wait for before
+     * allowing the user to enter the PIN.
+     * @return Returns a positive number (including zero) for how many milliseconds before
+     * you can accept another PIN, when the input is null or the input doesn't match the saved PIN.
+     * Returns {@link #PIN_VERIFICATION_SUCCESS} if the input matches the saved PIN. Returns
+     * {@link #PIN_VERIFICATION_FAILED_NOT_SET} if there is no PIN set.
+     */
+    public int checkRestrictionsPin(String pin) {
+        try {
+            return mService.checkRestrictionsPin(pin);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not check restrictions pin");
+        }
+        return PIN_VERIFICATION_FAILED_INCORRECT;
+    }
+
+    /**
+     * Checks whether the user has restrictions that are PIN-protected. An application that
+     * participates in restrictions can check if the owner has requested a PIN challenge for
+     * any restricted operations. If there is a PIN in effect, the application should launch
+     * the PIN challenge activity {@link android.content.Intent#ACTION_RESTRICTIONS_PIN_CHALLENGE}.
+     * @see android.content.Intent#ACTION_RESTRICTIONS_PIN_CHALLENGE
+     * @return whether a restrictions PIN is in effect.
+     */
+    public boolean hasRestrictionsPin() {
+        try {
+            return mService.hasRestrictionsPin();
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not change restrictions pin");
+        }
+        return false;
+    }
 }
diff --git a/core/java/android/print/IPrintAdapter.aidl b/core/java/android/print/IPrintAdapter.aidl
index a9b4fb7..f3ff8c4 100644
--- a/core/java/android/print/IPrintAdapter.aidl
+++ b/core/java/android/print/IPrintAdapter.aidl
@@ -17,7 +17,7 @@
 package android.print;
 
 import android.os.ParcelFileDescriptor;
-import android.print.IPrintProgressListener;
+import android.print.IPrintResultCallback;
 import android.print.PageRange;
 import android.print.PrintAttributes;
 
@@ -30,6 +30,6 @@
     void start();
     void printAttributesChanged(in PrintAttributes attributes);
     void print(in List<PageRange> pages, in ParcelFileDescriptor fd,
-            IPrintProgressListener progressListener);
+            IPrintResultCallback callback);
     void finish();
 }
diff --git a/core/java/android/print/IPrintProgressListener.aidl b/core/java/android/print/IPrintResultCallback.aidl
similarity index 81%
rename from core/java/android/print/IPrintProgressListener.aidl
rename to core/java/android/print/IPrintResultCallback.aidl
index 2c0d607..838377e 100644
--- a/core/java/android/print/IPrintProgressListener.aidl
+++ b/core/java/android/print/IPrintResultCallback.aidl
@@ -26,8 +26,8 @@
  *
  * @hide
  */
-oneway interface IPrintProgressListener {
-    void onWriteStarted(in PrintAdapterInfo info, ICancellationSignal cancellationSignal);
-    void onWriteFinished(in List<PageRange> pages);
-    void onWriteFailed(CharSequence error);
+oneway interface IPrintResultCallback {
+    void onPrintStarted(in PrintAdapterInfo info, ICancellationSignal cancellationSignal);
+    void onPrintFinished(in List<PageRange> pages);
+    void onPrintFailed(CharSequence error);
 }
diff --git a/core/java/android/print/PageRange.java b/core/java/android/print/PageRange.java
index 044a715..60e6229 100644
--- a/core/java/android/print/PageRange.java
+++ b/core/java/android/print/PageRange.java
@@ -21,7 +21,7 @@
 
 /**
  * Represents a range of pages. The start and end page indices of
- * the range are zero based and are inclusive.
+ * the range are zero based and inclusive.
  */
 public final class PageRange implements Parcelable {
 
diff --git a/core/java/android/print/PrintAdapter.java b/core/java/android/print/PrintAdapter.java
index a7f809b..6547c55 100644
--- a/core/java/android/print/PrintAdapter.java
+++ b/core/java/android/print/PrintAdapter.java
@@ -16,12 +16,11 @@
 
 package android.print;
 
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.util.List;
-
 import android.os.CancellationSignal;
 
+import java.io.FileDescriptor;
+import java.util.List;
+
 /**
  * Base class that provides data to be printed.
  *
@@ -33,19 +32,23 @@
  * This callback can be used to allocate resources.
  * </li>
  * <li>
- * Next you will get one or more calls to the pair
- *  {@link #onPrintAttributesChanged(PrintAttributes)} and {@link #onPrint(List,
- * FileDescriptor, CancellationSignal, PrintProgressCallback)}. The first callback
- * informs you that the print attributes (page size, density, etc) changed giving
- * you an opportunity to re-layout the content. The second method asks you to write
- * a PDF file with the content for specific pages.
+ * Next you will get one or more calls to {@link #onPrintAttributesChanged(
+ * PrintAttributes) to informs you that the print attributes (page size, density,
+ * etc) changed giving you an opportunity to re-layout the content.
+ * </li>
+ * <li>
+ * After every {@link #onPrintAttributesChanged(PrintAttributes) you will receive
+ * one or more calls to {@link #onPrint(List, FileDescriptor, CancellationSignal,
+ * PrintResultCallback)} asking you to write a PDF file with the content for
+ * specific pages.
  * </li>
  * <li>
  * Finally, you will receive a call on {@link #onFinish()} right after printing.
  * You can use this callback to release resources.
  * </li>
  * <li>
- * You can receive calls to {@link #getInfo()} at any point which should return
+ * You can receive calls to {@link #getInfo()} at any point after a call to
+ * {@link #onPrintAttributesChanged(PrintAttributes)} which should return
  * a {@link PrintAdapterInfo} describing your {@link PrintAdapter}.
  * </li>
  * </ul>
@@ -83,29 +86,28 @@
     /**
      * Called when specific pages of the content have to be printed in the from of
      * a PDF file to the given file descriptor. You should <strong>not</strong>
-     * close the file descriptor instead you have to invoke {@link PrintProgressCallback
-     * #onWriteFinished()} or {@link PrintProgressCallback#onPrintFailed(CharSequence)}.
+     * close the file descriptor instead you have to invoke {@link PrintResultCallback
+     * #onPrintFinished()} or {@link PrintResultCallback#onPrintFailed(CharSequence)}.
      * <p>
      * <strong>Note:</strong> If the printed content is large, it is a  good
      * practice to schedule writing it on a dedicated thread and register a
-     * callback in the provided {@link CancellationSignal} upon which to stop
-     * writing data. The cancellation callback will not be made on the main
-     * thread.
+     * callback in the provided {@link CancellationSignal} upon invocation of
+     * which you should stop writing data. The cancellation callback will not
+     * be made on the main thread.
      * </p>
      * <p>
      * <strong>Note:</strong> Invoked on the main thread.
      * </p>
-     * <p>
      *
-     * @param pages The pages whose content to write.
+     * @param pages The pages whose content to print.
      * @param destination The destination file descriptor to which to start writing.
-     * @param cancellationSignal Signal for observing cancel write requests.
+     * @param cancellationSignal Signal for observing cancel print requests.
      * @param progressListener Callback to inform the system with the write progress.
      *
      * @see CancellationSignal
      */
     public abstract void onPrint(List<PageRange> pages, FileDescriptor destination,
-            CancellationSignal cancellationSignal, PrintProgressCallback progressListener);
+            CancellationSignal cancellationSignal, PrintResultCallback progressListener);
 
     /**
      * Called when printing finished. You can use this callback to release
@@ -132,12 +134,12 @@
     public abstract PrintAdapterInfo getInfo();
 
     /**
-     * Base class for implementing a listener for the printing progress
+     * Base class for implementing a listener for the print result
      * of a {@link PrintAdapter}.
      */
-    public static abstract class PrintProgressCallback {
+    public static abstract class PrintResultCallback {
 
-        PrintProgressCallback() {
+        PrintResultCallback() {
             /* do nothing - hide constructor */
         }
 
diff --git a/core/java/android/print/PrintFileAdapter.java b/core/java/android/print/PrintFileAdapter.java
index bbfc394..dab9648 100644
--- a/core/java/android/print/PrintFileAdapter.java
+++ b/core/java/android/print/PrintFileAdapter.java
@@ -53,9 +53,9 @@
 
     @Override
     public void onPrint(List<PageRange> pages, FileDescriptor destination,
-            CancellationSignal cancellationSignal, PrintProgressCallback progressListener) {
+            CancellationSignal cancellationSignal, PrintResultCallback callback) {
         mWriteFileAsyncTask = new WriteFileAsyncTask(mFile, destination, cancellationSignal,
-                progressListener);
+                callback);
         mWriteFileAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
                 (Void[]) null);
         
@@ -73,15 +73,15 @@
 
         private final FileDescriptor mDestination;
 
-        private final PrintProgressCallback mProgressListener;
+        private final PrintResultCallback mResultCallback;
 
         private final CancellationSignal mCancellationSignal;
 
         public WriteFileAsyncTask(File source, FileDescriptor destination,
-                CancellationSignal cancellationSignal, PrintProgressCallback progressListener) {
+                CancellationSignal cancellationSignal, PrintResultCallback callback) {
             mSource = source;
             mDestination = destination;
-            mProgressListener = progressListener;
+            mResultCallback = callback;
             mCancellationSignal = cancellationSignal; 
             mCancellationSignal.setOnCancelListener(new OnCancelListener() {
                 @Override
@@ -113,9 +113,9 @@
                 if (!isCancelled()) {
                     List<PageRange> pages = new ArrayList<PageRange>();
                     pages.add(PageRange.ALL_PAGES);
-                    mProgressListener.onPrintFinished(pages);
+                    mResultCallback.onPrintFinished(pages);
                 } else {
-                    mProgressListener.onPrintFailed("Cancelled");
+                    mResultCallback.onPrintFailed("Cancelled");
                 }
             }
             return null;
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index 32a0f5a..be9b596 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -26,7 +26,7 @@
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
-import android.print.PrintAdapter.PrintProgressCallback;
+import android.print.PrintAdapter.PrintResultCallback;
 import android.util.Log;
 
 import com.android.internal.os.SomeArgs;
@@ -162,6 +162,8 @@
      * @param pdfFile The PDF file to print.
      * @param attributes The default print job attributes.
      * @return The created print job.
+     *
+     * @see PrintJob
      */
     public PrintJob print(String printJobName, File pdfFile, PrintAttributes attributes) {
         PrintFileAdapter printable = new PrintFileAdapter(pdfFile);
@@ -176,6 +178,8 @@
      * @param printAdapter The printable adapter to print.
      * @param attributes The default print job attributes.
      * @return The created print job.
+     *
+     * @see PrintJob
      */
     public PrintJob print(String printJobName, PrintAdapter printAdapter,
             PrintAttributes attributes) {
@@ -252,7 +256,7 @@
 
         @Override
         public void print(List<PageRange> pages, ParcelFileDescriptor fd,
-                IPrintProgressListener progressListener) {
+                IPrintResultCallback callback) {
             synchronized (mLock) {
                 if (isFinishedLocked()) {
                     return;
@@ -261,7 +265,7 @@
                 args.arg1 = mPrintAdapter;
                 args.arg2 = pages;
                 args.arg3 = fd.getFileDescriptor();
-                args.arg4 = progressListener;
+                args.arg4 = callback;
                 mHandler.obtainMessage(MyHandler.MESSAGE_PRINT, args).sendToTarget();
             }
         }
@@ -318,16 +322,16 @@
                         @SuppressWarnings("unchecked")
                         List<PageRange> pages = (List<PageRange>) args.arg2;
                         final FileDescriptor fd = (FileDescriptor) args.arg3;
-                        IPrintProgressListener listener = (IPrintProgressListener) args.arg4;
+                        IPrintResultCallback callback = (IPrintResultCallback) args.arg4;
                         args.recycle();
                         try {
                             ICancellationSignal remoteSignal = CancellationSignal.createTransport();
-                            listener.onWriteStarted(adapter.getInfo(), remoteSignal);
+                            callback.onPrintStarted(adapter.getInfo(), remoteSignal);
 
                             CancellationSignal localSignal = CancellationSignal.fromTransport(
                                     remoteSignal);
                             adapter.onPrint(pages, fd, localSignal,
-                                    new PrintProgressListenerWrapper(listener) {
+                                    new PrintResultCallbackWrapper(callback) {
                                         @Override
                                         public void onPrintFinished(List<PageRange> pages) {
                                             IoUtils.closeQuietly(fd);
@@ -363,29 +367,29 @@
         }
     }
 
-    private static abstract class PrintProgressListenerWrapper extends PrintProgressCallback {
+    private static abstract class PrintResultCallbackWrapper extends PrintResultCallback {
 
-        private final IPrintProgressListener mWrappedListener;
+        private final IPrintResultCallback mWrappedCallback;
 
-        public PrintProgressListenerWrapper(IPrintProgressListener listener) {
-            mWrappedListener = listener;
+        public PrintResultCallbackWrapper(IPrintResultCallback callback) {
+            mWrappedCallback = callback;
         }
 
         @Override
         public void onPrintFinished(List<PageRange> pages) {
             try {
-                mWrappedListener.onWriteFinished(pages);
+                mWrappedCallback.onPrintFinished(pages);
             } catch (RemoteException re) {
-                Log.e(LOG_TAG, "Error calling onWriteFinished", re);
+                Log.e(LOG_TAG, "Error calling onPrintFinished", re);
             }
         }
 
         @Override
         public void onPrintFailed(CharSequence error) {
             try {
-                mWrappedListener.onWriteFailed(error);
+                mWrappedCallback.onPrintFailed(error);
             } catch (RemoteException re) {
-                Log.e(LOG_TAG, "Error calling onWriteFailed", re);
+                Log.e(LOG_TAG, "Error calling onPrintFailed", re);
             }
         }
     }
diff --git a/core/java/android/print/pdf/PdfDocument.java b/core/java/android/print/pdf/PdfDocument.java
index 7fb170e..7ce036d 100644
--- a/core/java/android/print/pdf/PdfDocument.java
+++ b/core/java/android/print/pdf/PdfDocument.java
@@ -105,7 +105,7 @@
      * is created you can draw arbitrary content on the page's canvas which
      * you can get by calling {@link Page#getCanvas()}. After you are done
      * drawing the content you should finish the page by calling
-     * {@link #finishPage(Page). After the page is finished you should
+     * {@link #finishPage(Page)}. After the page is finished you should
      * no longer access the page or its canvas.
      * <p>
      * <strong>Note:</strong> Do not call this method after {@link #close()}.
diff --git a/core/java/android/printservice/PrintJob.java b/core/java/android/printservice/PrintJob.java
index 9688761..f490f91 100644
--- a/core/java/android/printservice/PrintJob.java
+++ b/core/java/android/printservice/PrintJob.java
@@ -62,7 +62,7 @@
      * <p>
      * <strong>Node:</strong>The returned info object is a snapshot of the
      * current print job state. Every call to this method returns a fresh
-     * info object that reflects the current print jobs state.
+     * info object that reflects the current print job state.
      * </p>
      *
      * @return The print job info.
@@ -100,7 +100,7 @@
      *
      * @see #complete()
      * @see #cancel()
-     * @see #fail()
+     * @see #fail(CharSequence)
      */
     public boolean isStarted() {
         return  getInfo().getState() == PrintJobInfo.STATE_STARTED;
@@ -140,7 +140,8 @@
      * Fails the print job. You should call this method if {@link
      * #isStarted()} returns true you filed while printing.
      *
-     * @return Whether the job as failed.
+     * @param error The reason for the failure.
+     * @return Whether the job was failed.
      *
      * @see #isStarted()
      */
@@ -191,6 +192,9 @@
      * Gets the data associated with this print job. It is a responsibility of
      * the print service to open a stream to the returned file descriptor
      * and fully read the content.
+     * <p>
+     * <strong>Note:</strong> It is your responsibility to close the file descriptor.
+     * </p>
      *
      * @return A file descriptor for reading the data or <code>null</code>.
      */
diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java
index d5cadc0..9256966 100644
--- a/core/java/android/printservice/PrintService.java
+++ b/core/java/android/printservice/PrintService.java
@@ -52,7 +52,7 @@
  * Calls to {@link #addDiscoveredPrinters(List)} and
  * {@link #removeDiscoveredPrinters(List)} before a call to
  * {@link #onStartPrinterDiscovery()} and after a call to
- * {@link #onStopPrinterDiscovery()} is a no-op.
+ * {@link #onStopPrinterDiscovery()} are a no-op.
  * </p>
  * <p>
  * For every printer discovery period all printers have to be added. Each
@@ -68,7 +68,7 @@
  * service may handle it immediately or schedule that for an appropriate
  * time in the future. The list of all print jobs for this service
  * are be available by calling {@link #getPrintJobs()}. A queued print
- * job is in a {@link PrintJobInfo#STATE_QUEUED} state.
+ * job is one whose {@link PrintJob#isQueued()} return true.
  * </p>
  * <p>
  * A print service is responsible for setting the print job state as
@@ -200,7 +200,7 @@
     /**
      * Callback requesting from this service to start printer discovery.
      * At the end of the printer discovery period the system will call
-     * {@link #onStopPrinterDiscovery(). Discovered printers should be
+     * {@link #onStopPrinterDiscovery()}. Discovered printers should be
      * reported by calling #addDiscoveredPrinters(List) and reported ones
      * that disappear should be reported by calling
      * {@link #removeDiscoveredPrinters(List)}.
@@ -299,8 +299,7 @@
     /**
      * Called when canceling of a print job is requested. The service
      * should do best effort to fulfill the request. After the print
-     * job is canceled it state has to be set to
-     * {@link PrintJobInfo#STATE_CANCELED}.
+     * job is canceled by calling {@link PrintJob#cancel()}.
      *
      * @param printJob The print job to be canceled.
      */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5dae599..9685fb0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3983,6 +3983,14 @@
          */
         public static final String VOICE_RECOGNITION_SERVICE = "voice_recognition_service";
 
+        /**
+         * Stores whether an user has consented to have apps verified through PAM.
+         * The value is boolean (1 or 0).
+         *
+         * @hide
+         */
+        public static final String PACKAGE_VERIFIER_USER_CONSENT =
+            "package_verifier_user_consent";
 
         /**
          * The {@link ComponentName} string of the selected spell checker service which is
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 1c3709f..6a6f027 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -17,6 +17,7 @@
 package android.util;
 
 import com.android.internal.os.RuntimeInit;
+import com.android.internal.util.FastPrintWriter;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -315,8 +316,9 @@
         }
 
         StringWriter sw = new StringWriter();
-        PrintWriter pw = new PrintWriter(sw);
+        PrintWriter pw = new FastPrintWriter(sw, false, 256);
         tr.printStackTrace(pw);
+        pw.flush();
         return sw.toString();
     }
 
diff --git a/core/java/android/view/CompatibilityInfoHolder.java b/core/java/android/view/CompatibilityInfoHolder.java
deleted file mode 100644
index fc8d684..0000000
--- a/core/java/android/view/CompatibilityInfoHolder.java
+++ /dev/null
@@ -1,45 +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 android.view;
-
-import android.content.res.CompatibilityInfo;
-
-/** @hide */
-public class CompatibilityInfoHolder {
-    private volatile CompatibilityInfo mCompatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
-
-    public void set(CompatibilityInfo compatInfo) {
-        if (compatInfo != null && (compatInfo.isScalingRequired()
-                || !compatInfo.supportsScreen())) {
-            mCompatInfo = compatInfo;
-        } else {
-            mCompatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
-        }
-    }
-
-    public CompatibilityInfo get() {
-        return mCompatInfo;
-    }
-
-    public CompatibilityInfo getIfNeeded() {
-        CompatibilityInfo ci = mCompatInfo;
-        if (ci == null || ci  == CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO) {
-            return null;
-        }
-        return ci;
-    }
-}
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 4d984fd..0e34435 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.content.res.CompatibilityInfo;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -60,7 +61,7 @@
     private final String mAddress;
     private final int mOwnerUid;
     private final String mOwnerPackageName;
-    private final CompatibilityInfoHolder mCompatibilityInfo;
+    private final DisplayAdjustments mDisplayAdjustments;
 
     private DisplayInfo mDisplayInfo; // never null
     private boolean mIsValid;
@@ -203,11 +204,11 @@
      */
     public Display(DisplayManagerGlobal global,
             int displayId, DisplayInfo displayInfo /*not null*/,
-            CompatibilityInfoHolder compatibilityInfo) {
+            DisplayAdjustments daj) {
         mGlobal = global;
         mDisplayId = displayId;
         mDisplayInfo = displayInfo;
-        mCompatibilityInfo = compatibilityInfo;
+        mDisplayAdjustments = daj;
         mIsValid = true;
 
         // Cache properties that cannot change as long as the display is valid.
@@ -348,11 +349,11 @@
     /**
      * Gets the compatibility info used by this display instance.
      *
-     * @return The compatibility info holder, or null if none is required.
+     * @return The display adjustments holder, or null if none is required.
      * @hide
      */
-    public CompatibilityInfoHolder getCompatibilityInfo() {
-        return mCompatibilityInfo;
+    public DisplayAdjustments getDisplayAdjustments() {
+        return mDisplayAdjustments;
     }
 
     /**
@@ -393,7 +394,7 @@
     public void getSize(Point outSize) {
         synchronized (this) {
             updateDisplayInfoLocked();
-            mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+            mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);
             outSize.x = mTempMetrics.widthPixels;
             outSize.y = mTempMetrics.heightPixels;
         }
@@ -408,7 +409,7 @@
     public void getRectSize(Rect outSize) {
         synchronized (this) {
             updateDisplayInfoLocked();
-            mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+            mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);
             outSize.set(0, 0, mTempMetrics.widthPixels, mTempMetrics.heightPixels);
         }
     }
@@ -573,7 +574,7 @@
     public void getMetrics(DisplayMetrics outMetrics) {
         synchronized (this) {
             updateDisplayInfoLocked();
-            mDisplayInfo.getAppMetrics(outMetrics, mCompatibilityInfo);
+            mDisplayInfo.getAppMetrics(outMetrics, mDisplayAdjustments);
         }
     }
 
@@ -611,7 +612,9 @@
     public void getRealMetrics(DisplayMetrics outMetrics) {
         synchronized (this) {
             updateDisplayInfoLocked();
-            mDisplayInfo.getLogicalMetrics(outMetrics, null);
+            mDisplayInfo.getLogicalMetrics(outMetrics,
+                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO,
+                    mDisplayAdjustments.getActivityToken());
         }
     }
 
@@ -658,7 +661,7 @@
         long now = SystemClock.uptimeMillis();
         if (now > mLastCachedAppSizeUpdate + CACHED_APP_SIZE_DURATION_MILLIS) {
             updateDisplayInfoLocked();
-            mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+            mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);
             mCachedAppWidthCompat = mTempMetrics.widthPixels;
             mCachedAppHeightCompat = mTempMetrics.heightPixels;
             mLastCachedAppSizeUpdate = now;
@@ -670,7 +673,7 @@
     public String toString() {
         synchronized (this) {
             updateDisplayInfoLocked();
-            mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+            mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);
             return "Display id " + mDisplayId + ": " + mDisplayInfo
                     + ", " + mTempMetrics + ", isValid=" + mIsValid;
         }
diff --git a/core/java/android/view/DisplayAdjustments.java b/core/java/android/view/DisplayAdjustments.java
new file mode 100644
index 0000000..4a234ad
--- /dev/null
+++ b/core/java/android/view/DisplayAdjustments.java
@@ -0,0 +1,93 @@
+/*
+ * 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.view;
+
+import android.content.res.CompatibilityInfo;
+import android.os.IBinder;
+
+import com.android.internal.util.Objects;
+
+/** @hide */
+public class DisplayAdjustments {
+    public static final boolean DEVELOPMENT_RESOURCES_DEPEND_ON_ACTIVITY_TOKEN = false;
+
+    public static final DisplayAdjustments DEFAULT_DISPLAY_ADJUSTMENTS = new DisplayAdjustments();
+
+    private volatile CompatibilityInfo mCompatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
+    private volatile IBinder mActivityToken;
+
+    public DisplayAdjustments() {
+    }
+
+    public DisplayAdjustments(IBinder token) {
+        mActivityToken = token;
+    }
+
+    public DisplayAdjustments(CompatibilityInfo compatInfo, IBinder token) {
+        setCompatibilityInfo(compatInfo);
+        mActivityToken = token;
+    }
+
+    public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
+        if (this == DEFAULT_DISPLAY_ADJUSTMENTS) {
+            throw new IllegalArgumentException(
+                    "setCompatbilityInfo: Cannot modify DEFAULT_DISPLAY_ADJUSTMENTS");
+        }
+        if (compatInfo != null && (compatInfo.isScalingRequired()
+                || !compatInfo.supportsScreen())) {
+            mCompatInfo = compatInfo;
+        } else {
+            mCompatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
+        }
+    }
+
+    public CompatibilityInfo getCompatibilityInfo() {
+        return mCompatInfo;
+    }
+
+    public void setActivityToken(IBinder token) {
+        if (this == DEFAULT_DISPLAY_ADJUSTMENTS) {
+            throw new IllegalArgumentException(
+                    "setActivityToken: Cannot modify DEFAULT_DISPLAY_ADJUSTMENTS");
+        }
+        mActivityToken = token;
+    }
+
+    public IBinder getActivityToken() {
+        return mActivityToken;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 17;
+        hash = hash * 31 + mCompatInfo.hashCode();
+        if (DEVELOPMENT_RESOURCES_DEPEND_ON_ACTIVITY_TOKEN) {
+            hash = hash * 31 + (mActivityToken == null ? 0 : mActivityToken.hashCode());
+        }
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof DisplayAdjustments)) {
+            return false;
+        }
+        DisplayAdjustments daj = (DisplayAdjustments)o;
+        return Objects.equal(daj.mCompatInfo, mCompatInfo) &&
+                Objects.equal(daj.mActivityToken, mActivityToken);
+    }
+}
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 1442cb7..9a9c4cd 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.content.res.CompatibilityInfo;
+import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.Process;
@@ -343,12 +344,22 @@
         return 0;
     }
 
-    public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfoHolder cih) {
-        getMetricsWithSize(outMetrics, cih, appWidth, appHeight);
+    public void getAppMetrics(DisplayMetrics outMetrics) {
+        getAppMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
     }
 
-    public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfoHolder cih) {
-        getMetricsWithSize(outMetrics, cih, logicalWidth, logicalHeight);
+    public void getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments) {
+        getMetricsWithSize(outMetrics, displayAdjustments.getCompatibilityInfo(),
+                displayAdjustments.getActivityToken(), appWidth, appHeight);
+    }
+
+    public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci, IBinder token) {
+        getMetricsWithSize(outMetrics, ci, token, appWidth, appHeight);
+    }
+
+    public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
+            IBinder token) {
+        getMetricsWithSize(outMetrics, compatInfo, token, logicalWidth, logicalHeight);
     }
 
     public int getNaturalWidth() {
@@ -368,8 +379,8 @@
         return Display.hasAccess(uid, flags, ownerUid);
     }
 
-    private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfoHolder cih,
-            int width, int height) {
+    private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
+            IBinder token, int width, int height) {
         outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi;
         outMetrics.noncompatWidthPixels  = outMetrics.widthPixels = width;
         outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
@@ -380,11 +391,8 @@
         outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi;
         outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi;
 
-        if (cih != null) {
-            CompatibilityInfo ci = cih.getIfNeeded();
-            if (ci != null) {
-                ci.applyToDisplayMetrics(outMetrics);
-            }
+        if (!compatInfo.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) {
+            compatInfo.applyToDisplayMetrics(outMetrics);
         }
     }
 
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 1f35c1d..a441c39 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -781,7 +781,7 @@
         int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
         try {
             final int nativePaint = paint == null ? 0 : paint.mNativePaint;
-            nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mChunk,
+            nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mNativeChunk,
                     dst.left, dst.top, dst.right, dst.bottom, nativePaint);
         } finally {
             if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
@@ -796,14 +796,14 @@
         int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
         try {
             final int nativePaint = paint == null ? 0 : paint.mNativePaint;
-            nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mChunk,
+            nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mNativeChunk,
                     dst.left, dst.top, dst.right, dst.bottom, nativePaint);
         } finally {
             if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
         }
     }
 
-    private static native void nDrawPatch(int renderer, int bitmap, byte[] chunks,
+    private static native void nDrawPatch(int renderer, int bitmap, int chunk,
             float left, float top, float right, float bottom, int paint);
 
     @Override
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index 9c5b33d..8b2a2ef 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -16,9 +16,7 @@
 
 package android.view;
 
-import android.graphics.Bitmap;
 import android.graphics.Matrix;
-import android.graphics.NinePatch;
 
 import java.util.ArrayList;
 
@@ -26,12 +24,6 @@
  * An implementation of display list for OpenGL ES 2.0.
  */
 class GLES20DisplayList extends DisplayList {
-    // These lists ensure that any Bitmaps and DisplayLists recorded by a DisplayList are kept
-    // alive as long as the DisplayList is alive.  The Bitmap and DisplayList lists
-    // are populated by the GLES20RecordingCanvas during appropriate drawing calls and are
-    // cleared at the start of a new drawing frame or when the view is detached from the window.
-    private ArrayList<Bitmap> mBitmaps;
-    private ArrayList<NinePatch> mNinePatches;
     private ArrayList<DisplayList> mChildDisplayLists;
 
     private GLES20RecordingCanvas mCanvas;
@@ -89,21 +81,9 @@
     }
 
     void clearReferences() {
-        if (mBitmaps != null) mBitmaps.clear();
-        if (mNinePatches != null) mNinePatches.clear();
         if (mChildDisplayLists != null) mChildDisplayLists.clear();
     }
 
-    ArrayList<Bitmap> getBitmaps() {
-        if (mBitmaps == null) mBitmaps = new ArrayList<Bitmap>(5);
-        return mBitmaps;
-    }
-
-    ArrayList<NinePatch> getNinePatches() {
-        if (mNinePatches == null) mNinePatches = new ArrayList<NinePatch>(5);
-        return mNinePatches;
-    }
-
     ArrayList<DisplayList> getChildDisplayLists() {
         if (mChildDisplayLists == null) mChildDisplayLists = new ArrayList<DisplayList>();
         return mChildDisplayLists;
diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java
index 273947f..b6fc38d 100644
--- a/core/java/android/view/GLES20RecordingCanvas.java
+++ b/core/java/android/view/GLES20RecordingCanvas.java
@@ -16,15 +16,7 @@
 
 package android.view;
 
-import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
-import android.graphics.Matrix;
-import android.graphics.NinePatch;
-import android.graphics.Paint;
-import android.graphics.Path;
 import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.Shader;
 import android.util.Pools.SynchronizedPool;
 
 /**
@@ -70,222 +62,10 @@
         return getDisplayList(nativeDisplayList);
     }
 
-    private void recordShaderBitmap(Paint paint) {
-        if (paint != null) {
-            final Shader shader = paint.getShader();
-            if (shader instanceof BitmapShader) {
-                mDisplayList.getBitmaps().add(((BitmapShader) shader).mBitmap);
-            }
-        }
-    }
-
-    @Override
-    public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
-        super.drawPatch(patch, dst, paint);
-        mDisplayList.getBitmaps().add(patch.getBitmap());
-        mDisplayList.getNinePatches().add(patch);
-        // Shaders in the Paint are ignored when drawing a Bitmap
-    }
-
-    @Override
-    public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
-        super.drawBitmap(bitmap, left, top, paint);
-        mDisplayList.getBitmaps().add(bitmap);
-        // Shaders in the Paint are ignored when drawing a Bitmap
-    }
-
-    @Override
-    public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
-        super.drawBitmap(bitmap, matrix, paint);
-        mDisplayList.getBitmaps().add(bitmap);
-        // Shaders in the Paint are ignored when drawing a Bitmap
-    }
-
-    @Override
-    public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
-        super.drawBitmap(bitmap, src, dst, paint);
-        mDisplayList.getBitmaps().add(bitmap);
-        // Shaders in the Paint are ignored when drawing a Bitmap
-    }
-
-    @Override
-    public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
-        super.drawBitmap(bitmap, src, dst, paint);
-        mDisplayList.getBitmaps().add(bitmap);
-        // Shaders in the Paint are ignored when drawing a Bitmap
-    }
-
-    @Override
-    public void drawBitmap(int[] colors, int offset, int stride, float x, float y, int width,
-            int height, boolean hasAlpha, Paint paint) {
-        super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
-        // Shaders in the Paint are ignored when drawing a Bitmap
-    }
-
-    @Override
-    public void drawBitmap(int[] colors, int offset, int stride, int x, int y, int width,
-            int height, boolean hasAlpha, Paint paint) {
-        super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
-        // Shaders in the Paint are ignored when drawing a Bitmap
-    }
-
-    @Override
-    public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
-            int vertOffset, int[] colors, int colorOffset, Paint paint) {
-        super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset,
-                colors, colorOffset, paint);
-        mDisplayList.getBitmaps().add(bitmap);
-        // Shaders in the Paint are ignored when drawing a Bitmap
-    }
-
-    @Override
-    public void drawCircle(float cx, float cy, float radius, Paint paint) {
-        super.drawCircle(cx, cy, radius, paint);
-        recordShaderBitmap(paint);
-    }
-
     @Override
     public int drawDisplayList(DisplayList displayList, Rect dirty, int flags) {
         int status = super.drawDisplayList(displayList, dirty, flags);
         mDisplayList.getChildDisplayLists().add(displayList);
         return status;
     }
-
-    @Override
-    public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
-        super.drawLine(startX, startY, stopX, stopY, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawLines(float[] pts, int offset, int count, Paint paint) {
-        super.drawLines(pts, offset, count, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawLines(float[] pts, Paint paint) {
-        super.drawLines(pts, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawOval(RectF oval, Paint paint) {
-        super.drawOval(oval, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawPaint(Paint paint) {
-        super.drawPaint(paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawPath(Path path, Paint paint) {
-        super.drawPath(path, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawPoint(float x, float y, Paint paint) {
-        super.drawPoint(x, y, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawPoints(float[] pts, int offset, int count, Paint paint) {
-        super.drawPoints(pts, offset, count, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawPoints(float[] pts, Paint paint) {
-        super.drawPoints(pts, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) {
-        super.drawPosText(text, index, count, pos, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawPosText(String text, float[] pos, Paint paint) {
-        super.drawPosText(text, pos, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawRect(float left, float top, float right, float bottom, Paint paint) {
-        super.drawRect(left, top, right, bottom, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
-        super.drawRoundRect(rect, rx, ry, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
-        super.drawText(text, index, count, x, y, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
-        super.drawText(text, start, end, x, y, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawText(String text, int start, int end, float x, float y, Paint paint) {
-        super.drawText(text, start, end, x, y, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawText(String text, float x, float y, Paint paint) {
-        super.drawText(text, x, y, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
-            float vOffset, Paint paint) {
-        super.drawTextOnPath(text, index, count, path, hOffset, vOffset, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
-        super.drawTextOnPath(text, path, hOffset, vOffset, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
-            float x, float y, int dir, Paint paint) {
-        super.drawTextRun(text, index, count, contextIndex, contextCount, x, y, dir, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawTextRun(CharSequence text, int start, int end, int contextStart,
-            int contextEnd, float x, float y, int dir, Paint paint) {
-        super.drawTextRun(text, start, end, contextStart, contextEnd, x, y, dir, paint);
-        recordShaderBitmap(paint);
-    }
-
-    @Override
-    public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
-            float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
-            int indexOffset, int indexCount, Paint paint) {
-        super.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset, colors,
-                colorOffset, indices, indexOffset, indexCount, paint);
-        recordShaderBitmap(paint);
-    }
 }
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index bcefdba..281bd7e 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -1360,7 +1360,7 @@
 
         @Override
         boolean validate() {
-            return checkCurrent() != SURFACE_STATE_ERROR;
+            return checkRenderContext() != SURFACE_STATE_ERROR;
         }
 
         @Override
@@ -1413,8 +1413,7 @@
                     return;
                 }
 
-                final int surfaceState = checkCurrent();
-                if (surfaceState != SURFACE_STATE_ERROR) {
+                if (checkRenderContext() != SURFACE_STATE_ERROR) {
                     int status = mCanvas.invokeFunctors(mRedrawClip);
                     handleFunctorStatus(attachInfo, status);
                 }
@@ -1433,7 +1432,8 @@
 
                 view.mPrivateFlags |= View.PFLAG_DRAWN;
 
-                final int surfaceState = checkCurrent();
+                // We are already on the correct thread
+                final int surfaceState = checkRenderContextUnsafe();
                 if (surfaceState != SURFACE_STATE_ERROR) {
                     HardwareCanvas canvas = mCanvas;
                     attachInfo.mHardwareCanvas = canvas;
@@ -1446,6 +1446,13 @@
 
                     DisplayList displayList = buildDisplayList(view, canvas);
 
+                    // buildDisplayList() calls into user code which can cause
+                    // an eglMakeCurrent to happen with a different surface/context.
+                    // We must therefore check again here.
+                    if (checkRenderContextUnsafe() == SURFACE_STATE_ERROR) {
+                        return;
+                    }
+
                     int saveCount = 0;
                     int status = DisplayList.STATUS_DONE;
 
@@ -1500,9 +1507,6 @@
                 HardwareCanvas canvas, DisplayList displayList) {
 
             if (mDebugOverdraw == OVERDRAW_TYPE_COUNT) {
-                // TODO: Use an alpha layer allocated from a GraphicBuffer
-                // The alpha format will help with rendering performance and
-                // the GraphicBuffer will let us skip the read pixels step
                 if (mDebugOverdrawLayer == null) {
                     mDebugOverdrawLayer = createHardwareLayer(mWidth, mHeight, true);
                 } else if (mDebugOverdrawLayer.getWidth() != mWidth ||
@@ -1725,21 +1729,39 @@
         }
 
         /**
-         * Ensures the current EGL context is the one we expect.
+         * Ensures the current EGL context and surface are the ones we expect.
+         * This method throws an IllegalStateException if invoked from a thread
+         * that did not initialize EGL.
          * 
          * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current,
          *         {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
          *         {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
+         *
+         * @see #checkRenderContextUnsafe()
          */
-        int checkCurrent() {
+        int checkRenderContext() {
             if (mEglThread != Thread.currentThread()) {
                 throw new IllegalStateException("Hardware acceleration can only be used with a " +
                         "single UI thread.\nOriginal thread: " + mEglThread + "\n" +
                         "Current thread: " + Thread.currentThread());
             }
 
-            if (!mEglContext.equals(sEgl.eglGetCurrentContext()) ||
-                    !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW))) {
+            return checkRenderContextUnsafe();
+        }
+
+        /**
+         * Ensures the current EGL context and surface are the ones we expect.
+         * This method does not check the current thread.
+         *
+         * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current,
+         *         {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
+         *         {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
+         *
+         * @see #checkRenderContext()
+         */
+        private int checkRenderContextUnsafe() {
+            if (!mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW)) ||
+                    !mEglContext.equals(sEgl.eglGetCurrentContext())) {
                 if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
                     Log.e(LOG_TAG, "eglMakeCurrent failed " +
                             GLUtils.getEGLErrorString(sEgl.eglGetError()));
@@ -2193,8 +2215,7 @@
 
         @Override
         boolean safelyRun(Runnable action) {
-            boolean needsContext = true;
-            if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false;
+            boolean needsContext = !isEnabled() || checkRenderContext() == SURFACE_STATE_ERROR;
 
             if (needsContext) {
                 Gl20RendererEglContext managedContext =
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 525b58f..0c1b192 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10063,8 +10063,10 @@
      * is inside the view, where the area of the view is expanded by the slop factor.
      * This method is called while processing touch-move events to determine if the event
      * is still within the view.
+     *
+     * @hide
      */
-    private boolean pointInView(float localX, float localY, float slop) {
+    public boolean pointInView(float localX, float localY, float slop) {
         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
                 localY < ((mBottom - mTop) + slop);
     }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9bc66be..50dbd5f4 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -239,7 +239,7 @@
     boolean mAdded;
     boolean mAddedTouchMode;
 
-    final CompatibilityInfoHolder mCompatibilityInfo;
+    final DisplayAdjustments mDisplayAdjustments;
 
     // These are accessed by multiple threads.
     final Rect mWinFrame; // frame given by window manager.
@@ -336,8 +336,7 @@
         mDisplay = display;
         mBasePackageName = context.getBasePackageName();
 
-        CompatibilityInfoHolder cih = display.getCompatibilityInfo();
-        mCompatibilityInfo = cih != null ? cih : new CompatibilityInfoHolder();
+        mDisplayAdjustments = display.getDisplayAdjustments();
 
         mThread = Thread.currentThread();
         mLocation = new WindowLeaked(null);
@@ -423,6 +422,8 @@
         synchronized (this) {
             if (mView == null) {
                 mView = view;
+                Slog.d(TAG, "setView: b9404689 setting mView to " + view + " mAdded=" + mAdded
+                        + " Callers=" + Debug.getCallers(4));
                 mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
                 mFallbackEventHandler.setView(view);
                 mWindowAttributes.copyFrom(attrs);
@@ -444,8 +445,9 @@
                     }
                 }
 
-                CompatibilityInfo compatibilityInfo = mCompatibilityInfo.get();
+                CompatibilityInfo compatibilityInfo = mDisplayAdjustments.getCompatibilityInfo();
                 mTranslator = compatibilityInfo.getTranslator();
+                mDisplayAdjustments.setActivityToken(attrs.token);
 
                 // If the application owns the surface, don't enable hardware acceleration
                 if (mSurfaceHolder == null) {
@@ -478,6 +480,8 @@
                             = panelParentView.getApplicationWindowToken();
                 }
                 mAdded = true;
+                Slog.d(TAG, "setView: b9404689 setting mAdded=true mView=" + mView
+                        + " Callers=" + Debug.getCallers(4));
                 int res; /* = WindowManagerImpl.ADD_OKAY; */
 
                 // Schedule the first layout -before- adding to the window
@@ -503,6 +507,8 @@
                     mFallbackEventHandler.setView(null);
                     unscheduleTraversals();
                     setAccessibilityFocus(null, null);
+                    Slog.d(TAG, "setView: b9404689 threw exception e=" + e
+                            + " Callers=" + Debug.getCallers(4));
                     throw new RuntimeException("Adding window failed", e);
                 } finally {
                     if (restore) {
@@ -1136,7 +1142,7 @@
             surfaceChanged = true;
             params = lp;
         }
-        CompatibilityInfo compatibilityInfo = mCompatibilityInfo.get();
+        CompatibilityInfo compatibilityInfo = mDisplayAdjustments.getCompatibilityInfo();
         if (compatibilityInfo.supportsScreen() == mLastInCompatMode) {
             params = lp;
             mFullRedrawNeeded = true;
@@ -2847,8 +2853,8 @@
                 + mWindowAttributes.getTitle()
                 + ": " + config);
 
-        CompatibilityInfo ci = mCompatibilityInfo.getIfNeeded();
-        if (ci != null) {
+        CompatibilityInfo ci = mDisplayAdjustments.getCompatibilityInfo();
+        if (!ci.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) {
             config = new Configuration(config);
             ci.applyToConfiguration(mNoncompatDensity, config);
         }
@@ -5158,11 +5164,14 @@
                 return;
             }
             mRemoved = true;
+            Slog.d(TAG, "doDie: b9404689 mAdded==true mView=" + mView
+                    + " Callers=" + Debug.getCallers(4));
             if (mAdded) {
                 dispatchDetachedFromWindow();
             }
 
             if (mAdded && !mFirst) {
+                Slog.d(TAG, "doDie: b9404689 mAdded && !mFirst");
                 invalidateDisplayLists();
                 destroyHardwareRenderer();
 
@@ -5186,6 +5195,8 @@
                 }
             }
 
+            Slog.d(TAG, "doDie: b9404689 setting mAdded=false mView=" + mView
+                    + " Callers=" + Debug.getCallers(4));
             mAdded = false;
         }
         WindowManagerGlobal.getInstance().doRemoveView(this);
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 7cda01c..6666545 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -21,6 +21,7 @@
 import android.content.ComponentCallbacks2;
 import android.content.res.Configuration;
 import android.opengl.ManagedEGLContext;
+import android.os.Debug;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -28,7 +29,9 @@
 import android.util.AndroidRuntimeException;
 import android.util.ArraySet;
 import android.util.Log;
+import android.util.Slog;
 import android.view.inputmethod.InputMethodManager;
+import com.android.internal.util.FastPrintWriter;
 
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
@@ -224,6 +227,7 @@
             if (index >= 0) {
                 if (mDyingViews.contains(view)) {
                     // Don't wait for MSG_DIE to make it's way through root's queue.
+                    Slog.d(TAG, "addView: b9404689 mDying contains view=" + view);
                     mRoots.get(index).doDie();
                 } else {
                     throw new IllegalStateException("View " + view
@@ -248,6 +252,7 @@
 
             view.setLayoutParams(wparams);
 
+            Slog.d(TAG, "addView: b9404689 adding view=" + view + " root=" + root);
             mViews.add(view);
             mRoots.add(root);
             mParams.add(wparams);
@@ -346,6 +351,8 @@
         if (view != null) {
             view.assignParent(null);
             if (deferred) {
+                Slog.d(TAG, "removeViewLocked: b9404689 mDyingViews adding view=" + view
+                        + " root=" + root + " Callers=" + Debug.getCallers(4));
                 mDyingViews.add(view);
             }
         }
@@ -355,10 +362,15 @@
         synchronized (mLock) {
             final int index = mRoots.indexOf(root);
             if (index >= 0) {
+                Slog.d(TAG, "doRemoveView: b9404689 removing view=" + mViews.get(index)
+                    + " Callers=" + Debug.getCallers(4));
                 mRoots.remove(index);
                 mParams.remove(index);
                 final View view = mViews.remove(index);
                 mDyingViews.remove(view);
+            } else {
+                Slog.d(TAG, "doRemoveView: b9404689 couldn't find root=" + root
+                    + " Callers=" + Debug.getCallers(4));
             }
         }
     }
@@ -414,7 +426,7 @@
 
     public void dumpGfxInfo(FileDescriptor fd) {
         FileOutputStream fout = new FileOutputStream(fd);
-        PrintWriter pw = new PrintWriter(fout);
+        PrintWriter pw = new FastPrintWriter(fout);
         try {
             synchronized (mLock) {
                 final int count = mViews.size();
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 312af71..fea6be6 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -296,7 +296,12 @@
         // in the UI thread. The WebViewClient and WebChromeClient functions
         // that check for a non-null callback are ok because java ensures atomic
         // 32-bit reads and writes.
-        if (messagesBlocked()) return;
+        if (messagesBlocked()) {
+            synchronized (this) {
+                notify();
+            }
+            return;
+        }
         switch (msg.what) {
             case PAGE_STARTED:
                 String startedUrl = msg.getData().getString("url");
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index bb1f954..1e20ab2 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -3369,68 +3369,62 @@
     }
 
     private void onTouchDown(MotionEvent ev) {
-        View v;
-        switch (mTouchMode) {
-        case TOUCH_MODE_OVERFLING: {
+        mActivePointerId = ev.getPointerId(0);
+
+        if (mTouchMode == TOUCH_MODE_OVERFLING) {
+            // Stopped the fling. It is a scroll.
             mFlingRunnable.endFling();
             if (mPositionScroller != null) {
                 mPositionScroller.stop();
             }
             mTouchMode = TOUCH_MODE_OVERSCROLL;
             mMotionX = (int) ev.getX();
-            mMotionY = mLastY = (int) ev.getY();
+            mMotionY = (int) ev.getY();
+            mLastY = mMotionY;
             mMotionCorrection = 0;
-            mActivePointerId = ev.getPointerId(0);
             mDirection = 0;
-            break;
-        }
-
-        default: {
-            mActivePointerId = ev.getPointerId(0);
+        } else {
             final int x = (int) ev.getX();
             final int y = (int) ev.getY();
             int motionPosition = pointToPosition(x, y);
+
             if (!mDataChanged) {
-                if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0)
-                        && (getAdapter().isEnabled(motionPosition))) {
-                    // User clicked on an actual view (and was not stopping a fling).
-                    // It might be a click or a scroll. Assume it is a click until
-                    // proven otherwise
+                if (mTouchMode == TOUCH_MODE_FLING) {
+                    // Stopped a fling. It is a scroll.
+                    createScrollingCache();
+                    mTouchMode = TOUCH_MODE_SCROLL;
+                    mMotionCorrection = 0;
+                    motionPosition = findMotionRow(y);
+                    mFlingRunnable.flywheelTouch();
+                } else if ((motionPosition >= 0) && getAdapter().isEnabled(motionPosition)) {
+                    // User clicked on an actual view (and was not stopping a
+                    // fling). It might be a click or a scroll. Assume it is a
+                    // click until proven otherwise.
                     mTouchMode = TOUCH_MODE_DOWN;
+
                     // FIXME Debounce
                     if (mPendingCheckForTap == null) {
                         mPendingCheckForTap = new CheckForTap();
                     }
+
                     postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
-                } else {
-                    if (mTouchMode == TOUCH_MODE_FLING) {
-                        // Stopped a fling. It is a scroll.
-                        createScrollingCache();
-                        mTouchMode = TOUCH_MODE_SCROLL;
-                        mMotionCorrection = 0;
-                        motionPosition = findMotionRow(y);
-                        mFlingRunnable.flywheelTouch();
-                    }
                 }
             }
 
             if (motionPosition >= 0) {
                 // Remember where the motion event started
-                v = getChildAt(motionPosition - mFirstPosition);
+                final View v = getChildAt(motionPosition - mFirstPosition);
                 mMotionViewOriginalTop = v.getTop();
             }
+
             mMotionX = x;
             mMotionY = y;
             mMotionPosition = motionPosition;
             mLastY = Integer.MIN_VALUE;
-            break;
-        }
         }
 
-        if (performButtonActionOnTouchDown(ev)) {
-            if (mTouchMode == TOUCH_MODE_DOWN) {
-                removeCallbacks(mPendingCheckForTap);
-            }
+        if (performButtonActionOnTouchDown(ev) && (mTouchMode == TOUCH_MODE_DOWN)) {
+            removeCallbacks(mPendingCheckForTap);
         }
     }
 
@@ -3460,10 +3454,8 @@
                 }
                 // Otherwise, check containment within list bounds. If we're
                 // outside bounds, cancel any active presses.
-                final float x = ev.getX();
-                final boolean inList = (x > mListPadding.left)
-                        && (x < getWidth() - mListPadding.right);
-                if (!inList) {
+                final float x = ev.getX(pointerIndex);
+                if (!pointInView(x, y, mTouchSlop)) {
                     setPressed(false);
                     final View motionView = getChildAt(mMotionPosition - mFirstPosition);
                     if (motionView != null) {
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 62e15786..d452f58 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -274,9 +274,14 @@
 
         mPreviewPadding = res.getDimensionPixelSize(R.dimen.fastscroll_overlay_padding);
 
+        final int textMinSize = Math.max(0, previewSize - mPreviewPadding);
         mPrimaryText = createPreviewTextView(context, ta);
+        mPrimaryText.setMinimumWidth(textMinSize);
+        mPrimaryText.setMinimumHeight(textMinSize);
         mOverlay.add(mPrimaryText);
         mSecondaryText = createPreviewTextView(context, ta);
+        mSecondaryText.setMinimumWidth(textMinSize);
+        mSecondaryText.setMinimumHeight(textMinSize);
         mOverlay.add(mSecondaryText);
 
         mPreviewResId[PREVIEW_LEFT] = ta.getResourceId(PREVIEW_BACKGROUND_LEFT, 0);
@@ -598,7 +603,11 @@
                 transitionToVisible();
                 break;
             case STATE_DRAGGING:
-                transitionToDragging();
+                if (transitionPreviewLayout(mCurrentSection)) {
+                    transitionToDragging();
+                } else {
+                    transitionToVisible();
+                }
                 break;
         }
 
@@ -673,10 +682,6 @@
         mDecorAnimation = new AnimatorSet();
         mDecorAnimation.playTogether(fadeIn, slideIn);
         mDecorAnimation.start();
-
-        // Ensure the preview text is correct.
-        final String previewText = getPreviewText();
-        transitionPreviewLayout(previewText);
     }
 
     private boolean isLongList(int visibleItemCount, int totalItemCount) {
@@ -853,42 +858,35 @@
             sectionIndex = -1;
         }
 
-        if (sectionIndex >= 0 && sectionIndex < sections.length) {
-            // If we moved sections, display section.
-            if (mCurrentSection != sectionIndex) {
-                mCurrentSection = sectionIndex;
-                final String section = sections[sectionIndex].toString();
+        if (mCurrentSection != sectionIndex) {
+            mCurrentSection = sectionIndex;
+
+            if (transitionPreviewLayout(sectionIndex)) {
                 transitionToDragging();
-                transitionPreviewLayout(section);
+            } else {
+                transitionToVisible();
             }
-        } else {
-            // No current section, transition out of preview.
-            transitionPreviewLayout(null);
-            transitionToVisible();
         }
     }
 
-    private String getPreviewText() {
-        final Object[] sections = mSections;
-        if (sections == null) {
-            return null;
-        }
-
-        final int sectionIndex = mCurrentSection;
-        if (sectionIndex < 0 || sectionIndex >= sections.length) {
-            return null;
-        }
-
-        return sections[sectionIndex].toString();
-    }
-
     /**
-     * Transitions the preview text to a new value. Handles animation,
-     * measurement, and layout.
+     * Transitions the preview text to a new section. Handles animation,
+     * measurement, and layout. If the new preview text is empty, returns false.
      *
-     * @param text The preview text to transition to.
+     * @param sectionIndex The section index to which the preview should
+     *            transition.
+     * @return False if the new preview text is empty.
      */
-    private void transitionPreviewLayout(CharSequence text) {
+    private boolean transitionPreviewLayout(int sectionIndex) {
+        final Object[] sections = mSections;
+        String text = null;
+        if (sections != null && sectionIndex >= 0 && sectionIndex < sections.length) {
+            final Object section = sections[sectionIndex];
+            if (section != null) {
+                text = section.toString();
+            }
+        }
+
         final Rect bounds = mTempBounds;
         final ImageView preview = mPreviewImage;
         final TextView showing;
@@ -952,6 +950,8 @@
         }
 
         mPreviewAnimation.start();
+
+        return (text != null && text.length() > 0);
     }
 
     /**
@@ -1012,26 +1012,46 @@
         final boolean hasSections = mSectionIndexer != null && mSections != null
                 && mSections.length > 0;
         if (!hasSections || !mMatchDragPosition) {
-            return firstVisibleItem / (totalItemCount - visibleItemCount);
+            return (float) firstVisibleItem / (totalItemCount - visibleItemCount);
         }
 
+        // Ignore headers.
         firstVisibleItem -= mHeaderCount;
         if (firstVisibleItem < 0) {
             return 0;
         }
-
         totalItemCount -= mHeaderCount;
 
+        // Hidden portion of the first visible row.
+        final View child = mList.getChildAt(0);
+        final float incrementalPos;
+        if (child == null || child.getHeight() == 0) {
+            incrementalPos = 0;
+        } else {
+            incrementalPos = (float) (mList.getPaddingTop() - child.getTop()) / child.getHeight();
+        }
+
+        // Number of rows in this section.
         final int section = mSectionIndexer.getSectionForPosition(firstVisibleItem);
         final int sectionPos = mSectionIndexer.getPositionForSection(section);
-        final int nextSectionPos = mSectionIndexer.getPositionForSection(section + 1);
         final int sectionCount = mSections.length;
-        final int positionsInSection = Math.max(1, nextSectionPos - sectionPos);
+        final int positionsInSection;
+        if (section < sectionCount - 1) {
+            final int nextSectionPos = mSectionIndexer.getPositionForSection(section + 1);
+            positionsInSection = nextSectionPos - sectionPos;
+        } else {
+            positionsInSection = totalItemCount - sectionPos;
+        }
 
-        final View child = mList.getChildAt(0);
-        final float incrementalPos = child == null ? 0 : firstVisibleItem +
-                (float) (mList.getPaddingTop() - child.getTop()) / Math.max(1, child.getHeight());
-        final float posWithinSection = (incrementalPos - sectionPos) / positionsInSection;
+        // Position within this section.
+        final float posWithinSection;
+        if (positionsInSection == 0) {
+            posWithinSection = 0;
+        } else {
+            posWithinSection = (firstVisibleItem + incrementalPos - sectionPos)
+                    / positionsInSection;
+        }
+
         return (section + posWithinSection) / sectionCount;
     }
 
diff --git a/core/java/com/android/internal/app/AlertActivity.java b/core/java/com/android/internal/app/AlertActivity.java
index 7251256..7456def 100644
--- a/core/java/com/android/internal/app/AlertActivity.java
+++ b/core/java/com/android/internal/app/AlertActivity.java
@@ -36,18 +36,18 @@
      * @see #mAlertParams
      */
     protected AlertController mAlert;
-    
+
     /**
      * The parameters for the alert.
      */
     protected AlertController.AlertParams mAlertParams;
-    
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        
+
         mAlert = new AlertController(this, this, getWindow());
-        mAlertParams = new AlertController.AlertParams(this);        
+        mAlertParams = new AlertController.AlertParams(this);
     }
 
     public void cancel() {
@@ -65,7 +65,7 @@
     /**
      * Sets up the alert, including applying the parameters to the alert model,
      * and installing the alert's content.
-     * 
+     *
      * @see #mAlert
      * @see #mAlertParams
      */
@@ -73,7 +73,7 @@
         mAlertParams.apply(mAlert);
         mAlert.installContent();
     }
-    
+
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
         if (mAlert.onKeyDown(keyCode, event)) return true;
@@ -85,6 +85,4 @@
         if (mAlert.onKeyUp(keyCode, event)) return true;
         return super.onKeyUp(keyCode, event);
     }
-    
-    
 }
diff --git a/core/java/com/android/internal/app/RestrictionsPinActivity.java b/core/java/com/android/internal/app/RestrictionsPinActivity.java
new file mode 100644
index 0000000..57436f7
--- /dev/null
+++ b/core/java/com/android/internal/app/RestrictionsPinActivity.java
@@ -0,0 +1,187 @@
+/*
+ * 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.app;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.os.UserManager;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+import com.android.internal.R;
+
+/**
+ * This activity is launched by Settings and other apps to either create a new PIN or
+ * challenge for an existing PIN. The PIN is maintained by UserManager.
+ */
+public class RestrictionsPinActivity extends AlertActivity
+        implements DialogInterface.OnClickListener, TextWatcher, OnEditorActionListener {
+
+    private UserManager mUserManager;
+
+    private EditText mPin1Text;
+    private EditText mPin2Text;
+    private TextView mPinErrorMessage;
+    private TextView mPinMessage;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        AlertController.AlertParams ap = mAlertParams;
+        ap.mTitle = getString(R.string.restr_pin_enter_pin);
+        ap.mPositiveButtonText = getString(R.string.ok);
+        ap.mNegativeButtonText = getString(R.string.cancel);
+        ap.mPositiveButtonListener = this;
+        ap.mNegativeButtonListener = this;
+        LayoutInflater inflater =
+                (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        ap.mView = inflater.inflate(R.layout.pin_challenge, null);
+
+        mPinMessage = (TextView) ap.mView.findViewById(R.id.pin_message);
+        mPin1Text = (EditText) ap.mView.findViewById(R.id.pin1_text);
+        mPin2Text = (EditText) ap.mView.findViewById(R.id.pin2_text);
+        mPinErrorMessage = (TextView) ap.mView.findViewById(R.id.pin_error_message);
+        mPin1Text.addTextChangedListener(this);
+        mPin2Text.addTextChangedListener(this);
+
+        mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
+
+        setupAlert();
+    }
+
+    protected boolean verifyingPin() {
+        return true;
+    }
+
+    public void onResume() {
+        super.onResume();
+
+        setPositiveButtonState(false);
+        boolean hasPin = mUserManager.hasRestrictionsPin();
+        if (verifyingPin()) {
+            if (hasPin) {
+                mPinMessage.setVisibility(View.GONE);
+                mPinErrorMessage.setVisibility(View.GONE);
+                mPin2Text.setVisibility(View.GONE);
+                mPin1Text.setOnEditorActionListener(this);
+                updatePinTimer(-1);
+            } else {
+                setResult(RESULT_OK);
+                finish();
+            }
+        } else if (hasPin) {
+            // Shouldn't really be in this state, exit
+            setResult(RESULT_OK);
+            finish();
+        }
+    }
+
+    private void setPositiveButtonState(boolean enabled) {
+        mAlert.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(enabled);
+    }
+
+    private void updatePinTimer(int pinTimerMs) {
+        if (pinTimerMs < 0) {
+            pinTimerMs = mUserManager.checkRestrictionsPin(null);
+        }
+        if (pinTimerMs >= 200) {
+            final int seconds = (pinTimerMs + 200) / 1000;
+            final String formatString = getResources().getQuantityString(
+                    R.plurals.restr_pin_countdown,
+                    seconds);
+            mPinErrorMessage.setText(String.format(formatString, seconds));
+            mPinErrorMessage.setVisibility(View.VISIBLE);
+            mPin1Text.setEnabled(false);
+            mPin1Text.setText("");
+            setPositiveButtonState(false);
+            mPin1Text.postDelayed(mCountdownRunnable, Math.min(1000, pinTimerMs));
+        } else {
+            mPinErrorMessage.setVisibility(View.INVISIBLE);
+            mPin1Text.setEnabled(true);
+            mPin1Text.setText("");
+        }
+    }
+
+    public void onClick(DialogInterface dialog, int which) {
+        setResult(RESULT_CANCELED);
+        if (which == AlertDialog.BUTTON_POSITIVE) {
+            performPositiveButtonAction();
+        } else if (which == AlertDialog.BUTTON_NEGATIVE) {
+            finish();
+        }
+    }
+
+    private void performPositiveButtonAction() {
+        if (verifyingPin()) {
+            int result = mUserManager.checkRestrictionsPin(mPin1Text.getText().toString());
+            if (result == UserManager.PIN_VERIFICATION_SUCCESS) {
+                setResult(RESULT_OK);
+                finish();
+            } else if (result >= 0) {
+                updatePinTimer(result);
+            }
+        } else {
+            if (mUserManager.changeRestrictionsPin(mPin1Text.getText().toString())) {
+                setResult(RESULT_OK);
+                finish();
+            }
+        }
+    }
+
+    @Override
+    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+    }
+
+    @Override
+    public void onTextChanged(CharSequence s, int start, int before, int count) {
+        CharSequence pin1 = mPin1Text.getText();
+        if (!verifyingPin()) {
+            CharSequence pin2 = mPin2Text.getText();
+            boolean match = pin1 != null && pin2 != null && pin1.length() >= 4
+                    && pin1.toString().equals(pin2.toString());
+            setPositiveButtonState(match);
+            mPinErrorMessage.setVisibility(match ? View.INVISIBLE : View.VISIBLE);
+        } else {
+            setPositiveButtonState(pin1 != null && pin1.length() >= 4);
+        }
+    }
+
+    @Override
+    public void afterTextChanged(Editable s) {
+    }
+
+    @Override
+    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+        performPositiveButtonAction();
+        return true;
+    }
+
+    private Runnable mCountdownRunnable = new Runnable() {
+        public void run() {
+            updatePinTimer(-1);
+        }
+    };
+}
diff --git a/core/java/com/android/internal/app/RestrictionsPinSetupActivity.java b/core/java/com/android/internal/app/RestrictionsPinSetupActivity.java
new file mode 100644
index 0000000..35f2967
--- /dev/null
+++ b/core/java/com/android/internal/app/RestrictionsPinSetupActivity.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+/**
+ * This activity is launched by Settings and other apps to either create a new PIN or
+ * challenge for an existing PIN. The PIN is maintained by UserManager.
+ */
+public class RestrictionsPinSetupActivity extends RestrictionsPinActivity {
+
+    protected boolean verifyingPin() {
+        return false;
+    }
+}
diff --git a/core/java/com/android/internal/logging/AndroidHandler.java b/core/java/com/android/internal/logging/AndroidHandler.java
index 12f6a4f..f55a31f 100644
--- a/core/java/com/android/internal/logging/AndroidHandler.java
+++ b/core/java/com/android/internal/logging/AndroidHandler.java
@@ -17,6 +17,7 @@
 package com.android.internal.logging;
 
 import android.util.Log;
+import com.android.internal.util.FastPrintWriter;
 import dalvik.system.DalvikLogging;
 import dalvik.system.DalvikLogHandler;
 
@@ -91,7 +92,7 @@
             Throwable thrown = r.getThrown();
             if (thrown != null) {
                 StringWriter sw = new StringWriter();
-                PrintWriter pw = new PrintWriter(sw);
+                PrintWriter pw = new FastPrintWriter(sw, false, 256);
                 sw.write(r.getMessage());
                 sw.write("\n");
                 thrown.printStackTrace(pw);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 949a499..061bf17 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -47,6 +47,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.net.NetworkStatsFactory;
+import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.JournaledFile;
 import com.google.android.collect.Sets;
 
@@ -301,7 +302,8 @@
     private static int sKernelWakelockUpdateVersion = 0;
 
     private static final int[] PROC_WAKELOCKS_FORMAT = new int[] {
-        Process.PROC_TAB_TERM|Process.PROC_OUT_STRING,                // 0: name
+        Process.PROC_TAB_TERM|Process.PROC_OUT_STRING|                // 0: name
+                              Process.PROC_QUOTES,
         Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 1: count
         Process.PROC_TAB_TERM,
         Process.PROC_TAB_TERM,
@@ -4461,12 +4463,13 @@
                 Slog.w(TAG, "New history ends before old history!");
             } else if (!out.same(mHistoryReadTmp)) {
                 long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
-                PrintWriter pw = new PrintWriter(new LogWriter(android.util.Log.WARN, TAG));
+                PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
                 pw.println("Histories differ!");
                 pw.println("Old history:");
                 (new HistoryPrinter()).printNextItem(pw, out, now);
                 pw.println("New history:");
                 (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, now);
+                pw.flush();
             }
         }
         return true;
diff --git a/core/java/com/android/internal/os/ProcessStats.java b/core/java/com/android/internal/os/ProcessStats.java
index bd0914d..874bc0e 100644
--- a/core/java/com/android/internal/os/ProcessStats.java
+++ b/core/java/com/android/internal/os/ProcessStats.java
@@ -18,10 +18,12 @@
 
 import static android.os.Process.*;
 
+import android.os.FileUtils;
 import android.os.Process;
 import android.os.StrictMode;
 import android.os.SystemClock;
 import android.util.Slog;
+import com.android.internal.util.FastPrintWriter;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -173,12 +175,15 @@
 
     public static class Stats {
         public final int pid;
+        public final int uid;
         final String statFile;
         final String cmdlineFile;
         final String threadsDir;
         final ArrayList<Stats> threadStats;
         final ArrayList<Stats> workingThreads;
-        
+
+        public BatteryStatsImpl.Uid.Proc batteryStats;
+
         public boolean interesting;
 
         public String baseName;
@@ -228,6 +233,7 @@
                 threadStats = null;
                 workingThreads = null;
             }
+            uid = FileUtils.getUid(statFile.toString());
         }
     }
 
@@ -675,13 +681,14 @@
     
     final public String printCurrentLoad() {
         StringWriter sw = new StringWriter();
-        PrintWriter pw = new PrintWriter(sw);
+        PrintWriter pw = new FastPrintWriter(sw, false, 128);
         pw.print("Load: ");
         pw.print(mLoad1);
         pw.print(" / ");
         pw.print(mLoad5);
         pw.print(" / ");
         pw.println(mLoad15);
+        pw.flush();
         return sw.toString();
     }
 
@@ -689,7 +696,7 @@
         buildWorkingProcs();
         
         StringWriter sw = new StringWriter();
-        PrintWriter pw = new PrintWriter(sw);
+        PrintWriter pw = new FastPrintWriter(sw, false, 1024);
         
         pw.print("CPU usage from ");
         if (now > mLastSampleTime) {
@@ -740,7 +747,8 @@
         
         printProcessCPU(pw, "", -1, "TOTAL", totalTime, mRelUserTime, mRelSystemTime,
                 mRelIoWaitTime, mRelIrqTime, mRelSoftIrqTime, 0, 0);
-        
+
+        pw.flush();
         return sw.toString();
     }
     
diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java
index 7b8c582..65b56ec 100644
--- a/core/java/com/android/internal/util/DumpUtils.java
+++ b/core/java/com/android/internal/util/DumpUtils.java
@@ -40,7 +40,7 @@
         if (handler.runWithScissors(new Runnable() {
             @Override
             public void run() {
-                PrintWriter lpw = new PrintWriter(sw);
+                PrintWriter lpw = new FastPrintWriter(sw);
                 dump.dump(lpw);
                 lpw.close();
             }
diff --git a/core/java/com/android/internal/util/FastPrintWriter.java b/core/java/com/android/internal/util/FastPrintWriter.java
index 6ad8e66..fa53cfa 100644
--- a/core/java/com/android/internal/util/FastPrintWriter.java
+++ b/core/java/com/android/internal/util/FastPrintWriter.java
@@ -1,7 +1,5 @@
 package com.android.internal.util;
 
-import java.io.File;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintWriter;
@@ -15,14 +13,39 @@
 import java.nio.charset.CodingErrorAction;
 
 public class FastPrintWriter extends PrintWriter {
-    private static final int BUFFER_LEN = 8192;
+    private static Writer sDummyWriter = new Writer() {
+        @Override
+        public void close() throws IOException {
+            UnsupportedOperationException ex
+                    = new UnsupportedOperationException("Shouldn't be here");
+            throw ex;
+        }
 
-    private final char[] mText = new char[BUFFER_LEN];
+        @Override
+        public void flush() throws IOException {
+            close();
+        }
+
+        @Override
+        public void write(char[] buf, int offset, int count) throws IOException {
+            close();
+        }
+    };
+
+    private final int mBufferLen;
+    private final char[] mText;
     private int mPos;
 
     final private OutputStream mOutputStream;
+    final private boolean mAutoFlush;
+    final private String mSeparator;
+
+    final private Writer mWriter;
+
     private CharsetEncoder mCharset;
-    final private ByteBuffer mBytes = ByteBuffer.allocate(BUFFER_LEN);
+    final private ByteBuffer mBytes;
+
+    private boolean mIoError;
 
     /**
      * Constructs a new {@code PrintWriter} with {@code out} as its target
@@ -35,9 +58,7 @@
      *             if {@code out} is {@code null}.
      */
     public FastPrintWriter(OutputStream out) {
-        super(out);
-        mOutputStream = out;
-        initDefaultEncoder();
+        this(out, false, 8192);
     }
 
     /**
@@ -55,8 +76,38 @@
      *             if {@code out} is {@code null}.
      */
     public FastPrintWriter(OutputStream out, boolean autoFlush) {
-        super(out, autoFlush);
+        this(out, autoFlush, 8192);
+    }
+
+    /**
+     * Constructs a new {@code PrintWriter} with {@code out} as its target
+     * stream and a custom buffer size. The parameter {@code autoFlush} determines
+     * if the print writer automatically flushes its contents to the target stream
+     * when a newline is encountered.
+     *
+     * @param out
+     *            the target output stream.
+     * @param autoFlush
+     *            indicates whether contents are flushed upon encountering a
+     *            newline sequence.
+     * @param bufferLen
+     *            specifies the size of the FastPrintWriter's internal buffer; the
+     *            default is 8192.
+     * @throws NullPointerException
+     *             if {@code out} is {@code null}.
+     */
+    public FastPrintWriter(OutputStream out, boolean autoFlush, int bufferLen) {
+        super(sDummyWriter, autoFlush);
+        if (out == null) {
+            throw new NullPointerException("out is null");
+        }
+        mBufferLen = bufferLen;
+        mText = new char[bufferLen];
+        mBytes = ByteBuffer.allocate(mBufferLen);
         mOutputStream = out;
+        mWriter = null;
+        mAutoFlush = autoFlush;
+        mSeparator = System.lineSeparator();
         initDefaultEncoder();
     }
 
@@ -65,15 +116,17 @@
      * writer. By default, the new print writer does not automatically flush its
      * contents to the target writer when a newline is encountered.
      *
+     * <p>NOTE: Unlike PrintWriter, this version will still do buffering inside of
+     * FastPrintWriter before sending data to the Writer.  This means you must call
+     * flush() before retrieving any data from the Writer.</p>
+     *
      * @param wr
      *            the target writer.
      * @throws NullPointerException
      *             if {@code wr} is {@code null}.
      */
     public FastPrintWriter(Writer wr) {
-        super(wr);
-        mOutputStream = null;
-        initDefaultEncoder();
+        this(wr, false, 8192);
     }
 
     /**
@@ -91,99 +144,41 @@
      *             if {@code out} is {@code null}.
      */
     public FastPrintWriter(Writer wr, boolean autoFlush) {
-        super(wr, autoFlush);
-        mOutputStream = null;
-        initDefaultEncoder();
+        this(wr, autoFlush, 8192);
     }
 
     /**
-     * Constructs a new {@code PrintWriter} with {@code file} as its target. The
-     * VM's default character set is used for character encoding.
-     * The print writer does not automatically flush its contents to the target
-     * file when a newline is encountered. The output to the file is buffered.
+     * Constructs a new {@code PrintWriter} with {@code out} as its target
+     * writer and a custom buffer size. The parameter {@code autoFlush} determines
+     * if the print writer automatically flushes its contents to the target writer
+     * when a newline is encountered.
      *
-     * @param file
-     *            the target file. If the file already exists, its contents are
-     *            removed, otherwise a new file is created.
-     * @throws java.io.FileNotFoundException
-     *             if an error occurs while opening or creating the target file.
-     */
-    public FastPrintWriter(File file) throws FileNotFoundException {
-        super(file);
-        mOutputStream = null;
-        initDefaultEncoder();
-    }
-
-    /**
-     * Constructs a new {@code PrintWriter} with {@code file} as its target. The
-     * character set named {@code csn} is used for character encoding.
-     * The print writer does not automatically flush its contents to the target
-     * file when a newline is encountered. The output to the file is buffered.
-     *
-     * @param file
-     *            the target file. If the file already exists, its contents are
-     *            removed, otherwise a new file is created.
-     * @param csn
-     *            the name of the character set used for character encoding.
-     * @throws FileNotFoundException
-     *             if an error occurs while opening or creating the target file.
+     * @param wr
+     *            the target writer.
+     * @param autoFlush
+     *            indicates whether to flush contents upon encountering a
+     *            newline sequence.
+     * @param bufferLen
+     *            specifies the size of the FastPrintWriter's internal buffer; the
+     *            default is 8192.
      * @throws NullPointerException
-     *             if {@code csn} is {@code null}.
-     * @throws java.io.UnsupportedEncodingException
-     *             if the encoding specified by {@code csn} is not supported.
+     *             if {@code wr} is {@code null}.
      */
-    public FastPrintWriter(File file, String csn) throws FileNotFoundException,
-            UnsupportedEncodingException {
-        super(file, csn);
+    public FastPrintWriter(Writer wr, boolean autoFlush, int bufferLen) {
+        super(sDummyWriter, autoFlush);
+        if (wr == null) {
+            throw new NullPointerException("wr is null");
+        }
+        mBufferLen = bufferLen;
+        mText = new char[bufferLen];
+        mBytes = null;
         mOutputStream = null;
-        initEncoder(csn);
-    }
-
-    /**
-     * Constructs a new {@code PrintWriter} with the file identified by {@code
-     * fileName} as its target. The VM's default character set is
-     * used for character encoding. The print writer does not automatically
-     * flush its contents to the target file when a newline is encountered. The
-     * output to the file is buffered.
-     *
-     * @param fileName
-     *            the target file's name. If the file already exists, its
-     *            contents are removed, otherwise a new file is created.
-     * @throws FileNotFoundException
-     *             if an error occurs while opening or creating the target file.
-     */
-    public FastPrintWriter(String fileName) throws FileNotFoundException {
-        super(fileName);
-        mOutputStream = null;
+        mWriter = wr;
+        mAutoFlush = autoFlush;
+        mSeparator = System.lineSeparator();
         initDefaultEncoder();
     }
 
-     /**
-     * Constructs a new {@code PrintWriter} with the file identified by {@code
-     * fileName} as its target. The character set named {@code csn} is used for
-     * character encoding. The print writer does not automatically flush its
-     * contents to the target file when a newline is encountered. The output to
-     * the file is buffered.
-     *
-     * @param fileName
-     *            the target file's name. If the file already exists, its
-     *            contents are removed, otherwise a new file is created.
-     * @param csn
-     *            the name of the character set used for character encoding.
-     * @throws FileNotFoundException
-     *             if an error occurs while opening or creating the target file.
-     * @throws NullPointerException
-     *             if {@code csn} is {@code null}.
-     * @throws UnsupportedEncodingException
-     *             if the encoding specified by {@code csn} is not supported.
-     */
-    public FastPrintWriter(String fileName, String csn)
-            throws FileNotFoundException, UnsupportedEncodingException {
-        super(fileName, csn);
-        mOutputStream = null;
-        initEncoder(csn);
-    }
-
     private final void initEncoder(String csn) throws UnsupportedEncodingException {
         try {
             mCharset = Charset.forName(csn).newEncoder();
@@ -194,61 +189,97 @@
         mCharset.onUnmappableCharacter(CodingErrorAction.REPLACE);
     }
 
+    /**
+     * Flushes this writer and returns the value of the error flag.
+     *
+     * @return {@code true} if either an {@code IOException} has been thrown
+     *         previously or if {@code setError()} has been called;
+     *         {@code false} otherwise.
+     * @see #setError()
+     */
+    public boolean checkError() {
+        flush();
+        synchronized (lock) {
+            return mIoError;
+        }
+    }
+
+    /**
+     * Sets the error state of the stream to false.
+     * @since 1.6
+     */
+    protected void clearError() {
+        synchronized (lock) {
+            mIoError = false;
+        }
+    }
+
+    /**
+     * Sets the error flag of this writer to true.
+     */
+    protected void setError() {
+        synchronized (lock) {
+            mIoError = true;
+        }
+    }
+
     private final void initDefaultEncoder() {
         mCharset = Charset.defaultCharset().newEncoder();
         mCharset.onMalformedInput(CodingErrorAction.REPLACE);
         mCharset.onUnmappableCharacter(CodingErrorAction.REPLACE);
     }
 
-    private void appendInner(char c) throws IOException {
+    private void appendLocked(char c) throws IOException {
         int pos = mPos;
-        if (pos >= (BUFFER_LEN-1)) {
-            flush();
+        if (pos >= (mBufferLen-1)) {
+            flushLocked();
             pos = mPos;
         }
         mText[pos] = c;
         mPos = pos+1;
     }
 
-    private void appendInner(String str, int i, final int length) throws IOException {
+    private void appendLocked(String str, int i, final int length) throws IOException {
+        final int BUFFER_LEN = mBufferLen;
         if (length > BUFFER_LEN) {
             final int end = i + length;
             while (i < end) {
                 int next = i + BUFFER_LEN;
-                appendInner(str, i, next<end ? BUFFER_LEN : (end-i));
+                appendLocked(str, i, next < end ? BUFFER_LEN : (end - i));
                 i = next;
             }
             return;
         }
         int pos = mPos;
         if ((pos+length) > BUFFER_LEN) {
-            flush();
+            flushLocked();
             pos = mPos;
         }
         str.getChars(i, i + length, mText, pos);
         mPos = pos + length;
     }
 
-    private void appendInner(char[] buf, int i, final int length) throws IOException {
+    private void appendLocked(char[] buf, int i, final int length) throws IOException {
+        final int BUFFER_LEN = mBufferLen;
         if (length > BUFFER_LEN) {
             final int end = i + length;
             while (i < end) {
                 int next = i + BUFFER_LEN;
-                appendInner(buf, i, next < end ? BUFFER_LEN : (end - i));
+                appendLocked(buf, i, next < end ? BUFFER_LEN : (end - i));
                 i = next;
             }
             return;
         }
         int pos = mPos;
         if ((pos+length) > BUFFER_LEN) {
-            flush();
+            flushLocked();
             pos = mPos;
         }
         System.arraycopy(buf, i, mText, pos, length);
         mPos = pos + length;
     }
 
-    private void flushBytesInner() throws IOException {
+    private void flushBytesLocked() throws IOException {
         int position;
         if ((position = mBytes.position()) > 0) {
             mBytes.flip();
@@ -257,7 +288,7 @@
         }
     }
 
-    private void flushInner() throws IOException {
+    private void flushLocked() throws IOException {
         //Log.i("PackageManager", "flush mPos=" + mPos);
         if (mPos > 0) {
             if (mOutputStream != null) {
@@ -267,17 +298,17 @@
                     if (result.isError()) {
                         throw new IOException(result.toString());
                     } else if (result.isOverflow()) {
-                        flushBytesInner();
+                        flushBytesLocked();
                         result = mCharset.encode(charBuffer, mBytes, true);
                         continue;
                     }
                     break;
                 }
-                flushBytesInner();
+                flushBytesLocked();
                 mOutputStream.flush();
             } else {
-                out.write(mText, 0, mPos);
-                out.flush();
+                mWriter.write(mText, 0, mPos);
+                mWriter.flush();
             }
             mPos = 0;
         }
@@ -290,11 +321,34 @@
      */
     @Override
     public void flush() {
-        try {
-            flushInner();
-        } catch (IOException e) {
+        synchronized (lock) {
+            try {
+                flushLocked();
+                if (mOutputStream != null) {
+                    mOutputStream.flush();
+                } else {
+                    mWriter.flush();
+                }
+            } catch (IOException e) {
+                setError();
+            }
         }
-        super.flush();
+    }
+
+    @Override
+    public void close() {
+        synchronized (lock) {
+            try {
+                flushLocked();
+                if (mOutputStream != null) {
+                    mOutputStream.close();
+                } else {
+                    mWriter.close();
+                }
+            } catch (IOException e) {
+                setError();
+            }
+        }
     }
 
     /**
@@ -306,9 +360,11 @@
      * @see #print(String)
      */
     public void print(char[] charArray) {
-        try {
-            appendInner(charArray, 0, charArray.length);
-        } catch (IOException e) {
+        synchronized (lock) {
+            try {
+                appendLocked(charArray, 0, charArray.length);
+            } catch (IOException e) {
+            }
         }
     }
 
@@ -321,9 +377,11 @@
      * @see #print(String)
      */
     public void print(char ch) {
-        try {
-            appendInner(ch);
-        } catch (IOException e) {
+        synchronized (lock) {
+            try {
+                appendLocked(ch);
+            } catch (IOException e) {
+            }
         }
     }
 
@@ -342,9 +400,65 @@
         if (str == null) {
             str = String.valueOf((Object) null);
         }
-        try {
-            appendInner(str, 0, str.length());
-        } catch (IOException e) {
+        synchronized (lock) {
+            try {
+                appendLocked(str, 0, str.length());
+            } catch (IOException e) {
+                setError();
+            }
+        }
+    }
+
+
+    @Override
+    public void print(int inum) {
+        if (inum == 0) {
+            print("0");
+        } else {
+            super.print(inum);
+        }
+    }
+
+    @Override
+    public void print(long lnum) {
+        if (lnum == 0) {
+            print("0");
+        } else {
+            super.print(lnum);
+        }
+    }
+
+    /**
+     * Prints a newline. Flushes this writer if the autoFlush flag is set to {@code true}.
+     */
+    public void println() {
+        synchronized (lock) {
+            try {
+                appendLocked(mSeparator, 0, mSeparator.length());
+                if (mAutoFlush) {
+                    flushLocked();
+                }
+            } catch (IOException e) {
+                setError();
+            }
+        }
+    }
+
+    @Override
+    public void println(int inum) {
+        if (inum == 0) {
+            println("0");
+        } else {
+            super.println(inum);
+        }
+    }
+
+    @Override
+    public void println(long lnum) {
+        if (lnum == 0) {
+            println("0");
+        } else {
+            super.print(lnum);
         }
     }
 
@@ -385,9 +499,11 @@
      */
     @Override
     public void write(char[] buf, int offset, int count) {
-        try {
-            appendInner(buf, offset, count);
-        } catch (IOException e) {
+        synchronized (lock) {
+            try {
+                appendLocked(buf, offset, count);
+            } catch (IOException e) {
+            }
         }
     }
 
@@ -403,9 +519,11 @@
      */
     @Override
     public void write(int oneChar) {
-        try {
-            appendInner((char) oneChar);
-        } catch (IOException e) {
+        synchronized (lock) {
+            try {
+                appendLocked((char) oneChar);
+            } catch (IOException e) {
+            }
         }
     }
 
@@ -417,9 +535,11 @@
      */
     @Override
     public void write(String str) {
-        try {
-            appendInner(str, 0, str.length());
-        } catch (IOException e) {
+        synchronized (lock) {
+            try {
+                appendLocked(str, 0, str.length());
+            } catch (IOException e) {
+            }
         }
     }
 
@@ -439,9 +559,11 @@
      */
     @Override
     public void write(String str, int offset, int count) {
-        try {
-            appendInner(str, offset, count);
-        } catch (IOException e) {
+        synchronized (lock) {
+            try {
+                appendLocked(str, offset, count);
+            } catch (IOException e) {
+            }
         }
     }
 
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index faaf588..0a694c7 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -131,6 +131,7 @@
 	android_media_RemoteDisplay.cpp \
 	android_media_ToneGenerator.cpp \
 	android_hardware_Camera.cpp \
+	android_hardware_photography_CameraMetadata.cpp \
 	android_hardware_SensorManager.cpp \
 	android_hardware_SerialPort.cpp \
 	android_hardware_UsbDevice.cpp \
@@ -164,6 +165,7 @@
 	$(call include-path-for, libhardware)/hardware \
 	$(call include-path-for, libhardware_legacy)/hardware_legacy \
 	$(TOP)/frameworks/av/include \
+	$(TOP)/system/media/camera/include \
 	external/skia/src/core \
 	external/skia/src/pdf \
 	external/skia/src/images \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 144cc84..1299579 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -76,6 +76,7 @@
 extern int register_android_opengl_jni_GLES30(JNIEnv* env);
 
 extern int register_android_hardware_Camera(JNIEnv *env);
+extern int register_android_hardware_photography_CameraMetadata(JNIEnv *env);
 extern int register_android_hardware_SensorManager(JNIEnv *env);
 extern int register_android_hardware_SerialPort(JNIEnv *env);
 extern int register_android_hardware_UsbDevice(JNIEnv *env);
@@ -1191,6 +1192,7 @@
     REG_JNI(register_android_os_MemoryFile),
     REG_JNI(register_com_android_internal_os_ZygoteInit),
     REG_JNI(register_android_hardware_Camera),
+    REG_JNI(register_android_hardware_photography_CameraMetadata),
     REG_JNI(register_android_hardware_SensorManager),
     REG_JNI(register_android_hardware_SerialPort),
     REG_JNI(register_android_hardware_UsbDevice),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index a7a9266..016c11e 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -296,23 +296,11 @@
     SkAutoTDelete<SkBitmap> adb(outputBitmap == NULL ? new SkBitmap : NULL);
     if (outputBitmap == NULL) outputBitmap = adb.get();
 
-    SkAutoTDelete<SkImageDecoder> add(decoder);
-
     NinePatchPeeker peeker(decoder);
     decoder->setPeeker(&peeker);
 
-    AutoDecoderCancel adc(options, decoder);
-
-    // To fix the race condition in case "requestCancelDecode"
-    // happens earlier than AutoDecoderCancel object is added
-    // to the gAutoDecoderCancelMutex linked list.
-    if (options != NULL && env->GetBooleanField(options, gOptions_mCancelID)) {
-        return nullObjectReturn("gOptions_mCancelID");
-    }
-
     SkImageDecoder::Mode decodeMode = isPurgeable ? SkImageDecoder::kDecodeBounds_Mode : mode;
 
-
     JavaPixelAllocator javaAllocator(env);
     RecyclingPixelAllocator recyclingAllocator(outputBitmap->pixelRef(), existingBufferSize);
     ScaleCheckingAllocator scaleCheckingAllocator(scale, existingBufferSize);
@@ -328,6 +316,20 @@
         }
     }
 
+    // Only setup the decoder to be deleted after its stack-based, refcounted
+    // components (allocators, peekers, etc) are declared. This prevents RefCnt
+    // asserts from firing due to the order objects are deleted from the stack.
+    SkAutoTDelete<SkImageDecoder> add(decoder);
+
+    AutoDecoderCancel adc(options, decoder);
+
+    // To fix the race condition in case "requestCancelDecode"
+    // happens earlier than AutoDecoderCancel object is added
+    // to the gAutoDecoderCancelMutex linked list.
+    if (options != NULL && env->GetBooleanField(options, gOptions_mCancelID)) {
+        return nullObjectReturn("gOptions_mCancelID");
+    }
+
     SkBitmap decodingBitmap;
     if (!decoder->decode(stream, &decodingBitmap, prefConfig, decodeMode)) {
         return nullObjectReturn("decoder->decode returned false");
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index 684b1c1..7e6aeae 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -21,22 +21,30 @@
 #include <androidfw/ResourceTypes.h>
 #include <utils/Log.h>
 
+#include <Caches.h>
+
 #include "SkCanvas.h"
 #include "SkRegion.h"
 #include "GraphicsJNI.h"
 
 #include "JNIHelp.h"
 
-extern void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds,
-                const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
-                           const SkPaint* paint, SkRegion** outRegion);
+extern void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds, const SkBitmap& bitmap,
+        const android::Res_png_9patch& chunk, const SkPaint* paint, SkRegion** outRegion);
 
 using namespace android;
 
+/**
+ * IMPORTANT NOTE: 9patch chunks can be manipuated either as an array of bytes
+ * or as a Res_png_9patch instance. It is important to note that the size of the
+ * array required to hold a 9patch chunk is greater than sizeof(Res_png_9patch).
+ * The code below manipulates chunks as Res_png_9patch* types to draw and as
+ * int8_t* to allocate and free the backing storage.
+ */
+
 class SkNinePatchGlue {
 public:
-    static jboolean isNinePatchChunk(JNIEnv* env, jobject, jbyteArray obj)
-    {
+    static jboolean isNinePatchChunk(JNIEnv* env, jobject, jbyteArray obj) {
         if (NULL == obj) {
             return false;
         }
@@ -45,126 +53,110 @@
         }
         const jbyte* array = env->GetByteArrayElements(obj, 0);
         if (array != NULL) {
-            const Res_png_9patch* chunk =
-                                reinterpret_cast<const Res_png_9patch*>(array);
+            const Res_png_9patch* chunk = reinterpret_cast<const Res_png_9patch*>(array);
             int8_t wasDeserialized = chunk->wasDeserialized;
-            env->ReleaseByteArrayElements(obj, const_cast<jbyte*>(array),
-                                          JNI_ABORT);
+            env->ReleaseByteArrayElements(obj, const_cast<jbyte*>(array), JNI_ABORT);
             return wasDeserialized != -1;
         }
         return false;
     }
 
-    static void validateNinePatchChunk(JNIEnv* env, jobject, jint, jbyteArray obj)
-    {
-        if (env->GetArrayLength(obj) < (int) (sizeof(Res_png_9patch))) {
+    static int8_t* validateNinePatchChunk(JNIEnv* env, jobject, jint, jbyteArray obj) {
+        size_t chunkSize = env->GetArrayLength(obj);
+        if (chunkSize < (int) (sizeof(Res_png_9patch))) {
             jniThrowRuntimeException(env, "Array too small for chunk.");
-            return;
+            return NULL;
         }
 
-        // XXX Also check that dimensions are correct.
+        int8_t* storage = new int8_t[chunkSize];
+        // This call copies the content of the jbyteArray
+        env->GetByteArrayRegion(obj, 0, chunkSize, reinterpret_cast<jbyte*>(storage));
+        // Deserialize in place, return the array we just allocated
+        return (int8_t*) Res_png_9patch::deserialize(storage);
     }
 
-    static void draw(JNIEnv* env, SkCanvas* canvas, SkRect& bounds,
-                      const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint,
-                      jint destDensity, jint srcDensity)
-    {
-        size_t chunkSize = env->GetArrayLength(chunkObj);
-        void* storage = alloca(chunkSize);
-        env->GetByteArrayRegion(chunkObj, 0, chunkSize,
-                                reinterpret_cast<jbyte*>(storage));
-        if (!env->ExceptionCheck()) {
-            // need to deserialize the chunk
-            Res_png_9patch* chunk = static_cast<Res_png_9patch*>(storage);
-            assert(chunkSize == chunk->serializedSize());
-            // this relies on deserialization being done in place
-            Res_png_9patch::deserialize(chunk);
+    static void finalize(JNIEnv* env, jobject, int8_t* patch) {
+#ifdef USE_OPENGL_RENDERER
+        if (android::uirenderer::Caches::hasInstance()) {
+            Res_png_9patch* p = (Res_png_9patch*) patch;
+            android::uirenderer::Caches::getInstance().resourceCache.destructor(p);
+            return;
+        }
+#endif // USE_OPENGL_RENDERER
+        delete[] patch;
+    }
 
-            if (destDensity == srcDensity || destDensity == 0
-                    || srcDensity == 0) {
-                ALOGV("Drawing unscaled 9-patch: (%g,%g)-(%g,%g)",
-                        SkScalarToFloat(bounds.fLeft), SkScalarToFloat(bounds.fTop),
-                        SkScalarToFloat(bounds.fRight), SkScalarToFloat(bounds.fBottom));
-                NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
-            } else {
-                canvas->save();
+    static void draw(JNIEnv* env, SkCanvas* canvas, SkRect& bounds, const SkBitmap* bitmap,
+            Res_png_9patch* chunk, const SkPaint* paint, jint destDensity, jint srcDensity) {
+        if (destDensity == srcDensity || destDensity == 0 || srcDensity == 0) {
+            ALOGV("Drawing unscaled 9-patch: (%g,%g)-(%g,%g)",
+                    SkScalarToFloat(bounds.fLeft), SkScalarToFloat(bounds.fTop),
+                    SkScalarToFloat(bounds.fRight), SkScalarToFloat(bounds.fBottom));
+            NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
+        } else {
+            canvas->save();
 
-                SkScalar scale = SkFloatToScalar(destDensity / (float)srcDensity);
-                canvas->translate(bounds.fLeft, bounds.fTop);
-                canvas->scale(scale, scale);
+            SkScalar scale = SkFloatToScalar(destDensity / (float)srcDensity);
+            canvas->translate(bounds.fLeft, bounds.fTop);
+            canvas->scale(scale, scale);
 
-                bounds.fRight = SkScalarDiv(bounds.fRight-bounds.fLeft, scale);
-                bounds.fBottom = SkScalarDiv(bounds.fBottom-bounds.fTop, scale);
-                bounds.fLeft = bounds.fTop = 0;
+            bounds.fRight = SkScalarDiv(bounds.fRight-bounds.fLeft, scale);
+            bounds.fBottom = SkScalarDiv(bounds.fBottom-bounds.fTop, scale);
+            bounds.fLeft = bounds.fTop = 0;
 
-                ALOGV("Drawing scaled 9-patch: (%g,%g)-(%g,%g) srcDensity=%d destDensity=%d",
-                        SkScalarToFloat(bounds.fLeft), SkScalarToFloat(bounds.fTop),
-                        SkScalarToFloat(bounds.fRight), SkScalarToFloat(bounds.fBottom),
-                        srcDensity, destDensity);
+            ALOGV("Drawing scaled 9-patch: (%g,%g)-(%g,%g) srcDensity=%d destDensity=%d",
+                    SkScalarToFloat(bounds.fLeft), SkScalarToFloat(bounds.fTop),
+                    SkScalarToFloat(bounds.fRight), SkScalarToFloat(bounds.fBottom),
+                    srcDensity, destDensity);
 
-                NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
+            NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
 
-                canvas->restore();
-            }
+            canvas->restore();
         }
     }
 
     static void drawF(JNIEnv* env, jobject, SkCanvas* canvas, jobject boundsRectF,
-                      const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint,
-                      jint destDensity, jint srcDensity)
-    {
+            const SkBitmap* bitmap, Res_png_9patch* chunk, const SkPaint* paint,
+            jint destDensity, jint srcDensity) {
         SkASSERT(canvas);
         SkASSERT(boundsRectF);
         SkASSERT(bitmap);
-        SkASSERT(chunkObj);
+        SkASSERT(chunk);
         // paint is optional
 
-        SkRect      bounds;
+        SkRect bounds;
         GraphicsJNI::jrectf_to_rect(env, boundsRectF, &bounds);
 
-        draw(env, canvas, bounds, bitmap, chunkObj, paint, destDensity, srcDensity);
+        draw(env, canvas, bounds, bitmap, chunk, paint, destDensity, srcDensity);
     }
 
     static void drawI(JNIEnv* env, jobject, SkCanvas* canvas, jobject boundsRect,
-                      const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint,
-                      jint destDensity, jint srcDensity)
-    {
+            const SkBitmap* bitmap, Res_png_9patch* chunk, const SkPaint* paint,
+            jint destDensity, jint srcDensity) {
         SkASSERT(canvas);
         SkASSERT(boundsRect);
         SkASSERT(bitmap);
-        SkASSERT(chunkObj);
+        SkASSERT(chunk);
         // paint is optional
 
-        SkRect      bounds;
+        SkRect bounds;
         GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds);
-        draw(env, canvas, bounds, bitmap, chunkObj, paint, destDensity, srcDensity);
+        draw(env, canvas, bounds, bitmap, chunk, paint, destDensity, srcDensity);
     }
 
-    static jint getTransparentRegion(JNIEnv* env, jobject,
-                    const SkBitmap* bitmap, jbyteArray chunkObj,
-                    jobject boundsRect)
-    {
+    static jint getTransparentRegion(JNIEnv* env, jobject, const SkBitmap* bitmap,
+            Res_png_9patch* chunk, jobject boundsRect) {
         SkASSERT(bitmap);
-        SkASSERT(chunkObj);
+        SkASSERT(chunk);
         SkASSERT(boundsRect);
 
-        SkRect      bounds;
+        SkRect bounds;
         GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds);
-        size_t chunkSize = env->GetArrayLength(chunkObj);
-        void* storage = alloca(chunkSize);
-        env->GetByteArrayRegion(chunkObj, 0, chunkSize,
-                                reinterpret_cast<jbyte*>(storage));
-        if (!env->ExceptionCheck()) {
-            // need to deserialize the chunk
-            Res_png_9patch* chunk = static_cast<Res_png_9patch*>(storage);
-            assert(chunkSize == chunk->serializedSize());
-            // this relies on deserialization being done in place
-            Res_png_9patch::deserialize(chunk);
-            SkRegion* region = NULL;
-            NinePatch_Draw(NULL, bounds, *bitmap, *chunk, NULL, &region);
-            return (jint)region;
-        }
-        return 0;
+
+        SkRegion* region = NULL;
+        NinePatch_Draw(NULL, bounds, *bitmap, *chunk, NULL, &region);
+
+        return (jint) region;
     }
 
 };
@@ -174,18 +166,16 @@
 #include <android_runtime/AndroidRuntime.h>
 
 static JNINativeMethod gNinePatchMethods[] = {
-    { "isNinePatchChunk", "([B)Z",                      (void*)SkNinePatchGlue::isNinePatchChunk   },
-    { "validateNinePatchChunk", "(I[B)V",               (void*)SkNinePatchGlue::validateNinePatchChunk   },
-    { "nativeDraw", "(ILandroid/graphics/RectF;I[BIII)V", (void*)SkNinePatchGlue::drawF   },
-    { "nativeDraw", "(ILandroid/graphics/Rect;I[BIII)V",  (void*)SkNinePatchGlue::drawI   },
-    { "nativeGetTransparentRegion", "(I[BLandroid/graphics/Rect;)I",
-                                                        (void*)SkNinePatchGlue::getTransparentRegion   }
+    { "isNinePatchChunk", "([B)Z",                        (void*) SkNinePatchGlue::isNinePatchChunk },
+    { "validateNinePatchChunk", "(I[B)I",                 (void*) SkNinePatchGlue::validateNinePatchChunk },
+    { "nativeFinalize", "(I)V",                           (void*) SkNinePatchGlue::finalize },
+    { "nativeDraw", "(ILandroid/graphics/RectF;IIIII)V",  (void*) SkNinePatchGlue::drawF },
+    { "nativeDraw", "(ILandroid/graphics/Rect;IIIII)V",   (void*) SkNinePatchGlue::drawI },
+    { "nativeGetTransparentRegion", "(IILandroid/graphics/Rect;)I",
+                                                          (void*) SkNinePatchGlue::getTransparentRegion }
 };
 
-int register_android_graphics_NinePatch(JNIEnv* env)
-{
+int register_android_graphics_NinePatch(JNIEnv* env) {
     return android::AndroidRuntime::registerNativeMethods(env,
-                                                       "android/graphics/NinePatch",
-                                                       gNinePatchMethods,
-                                                       SK_ARRAY_COUNT(gNinePatchMethods));
+            "android/graphics/NinePatch", gNinePatchMethods, SK_ARRAY_COUNT(gNinePatchMethods));
 }
diff --git a/core/jni/android_hardware_photography_CameraMetadata.cpp b/core/jni/android_hardware_photography_CameraMetadata.cpp
new file mode 100644
index 0000000..fa363f3
--- /dev/null
+++ b/core/jni/android_hardware_photography_CameraMetadata.cpp
@@ -0,0 +1,271 @@
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "CameraMetadata-JNI"
+#include <utils/Log.h>
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_os_Parcel.h"
+#include "android_runtime/AndroidRuntime.h"
+
+#include <camera/CameraMetadata.h>
+
+// fully-qualified class name
+#define CAMERA_METADATA_CLASS_NAME "android/hardware/photography/CameraMetadata"
+
+using namespace android;
+
+struct fields_t {
+    jfieldID    metadata_ptr;
+};
+
+static fields_t fields;
+
+extern "C" {
+
+static void CameraMetadata_classInit(JNIEnv *env, jobject thiz);
+
+// Less safe access to native pointer. Does NOT throw any Java exceptions if NULL.
+static CameraMetadata* CameraMetadata_getPointerNoThrow(JNIEnv *env, jobject thiz) {
+
+    if (thiz == NULL) {
+        return NULL;
+    }
+
+    return reinterpret_cast<CameraMetadata*>(env->GetLongField(thiz, fields.metadata_ptr));
+}
+
+// Safe access to native pointer from object. Throws if not possible to access.
+static CameraMetadata* CameraMetadata_getPointerThrow(JNIEnv *env, jobject thiz,
+                                                 const char* argName = "this") {
+
+    if (thiz == NULL) {
+        ALOGV("%s: Throwing java.lang.NullPointerException for null reference",
+              __FUNCTION__);
+        jniThrowNullPointerException(env, argName);
+        return NULL;
+    }
+
+    CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
+    if (metadata == NULL) {
+        ALOGV("%s: Throwing java.lang.IllegalStateException for closed object",
+              __FUNCTION__);
+        jniThrowException(env, "java/lang/IllegalStateException",
+                            "Metadata object was already closed");
+        return NULL;
+    }
+
+    return metadata;
+}
+
+static jlong CameraMetadata_allocate(JNIEnv *env, jobject thiz) {
+    ALOGV("%s", __FUNCTION__);
+
+    return reinterpret_cast<jlong>(new CameraMetadata());
+}
+
+static jboolean CameraMetadata_isEmpty(JNIEnv *env, jobject thiz) {
+    ALOGV("%s", __FUNCTION__);
+
+    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
+
+    if (metadata == NULL) {
+        ALOGW("%s: Returning early due to exception being thrown",
+               __FUNCTION__);
+        return JNI_TRUE; // actually throws java exc.
+    }
+
+    jboolean empty = metadata->isEmpty();
+
+    ALOGV("%s: Empty returned %d, entry count was %d",
+          __FUNCTION__, empty, metadata->entryCount());
+
+    return empty;
+}
+
+static jint CameraMetadata_getEntryCount(JNIEnv *env, jobject thiz) {
+    ALOGV("%s", __FUNCTION__);
+
+    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
+
+    if (metadata == NULL) return 0; // actually throws java exc.
+
+    return metadata->entryCount();
+}
+
+// idempotent. calling more than once has no effect.
+static void CameraMetadata_close(JNIEnv *env, jobject thiz) {
+    ALOGV("%s", __FUNCTION__);
+
+    CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
+
+    if (metadata != NULL) {
+        delete metadata;
+        env->SetLongField(thiz, fields.metadata_ptr, 0);
+    }
+
+    LOG_ALWAYS_FATAL_IF(CameraMetadata_getPointerNoThrow(env, thiz) != NULL,
+                        "Expected the native ptr to be 0 after #close");
+}
+
+static void CameraMetadata_swap(JNIEnv *env, jobject thiz, jobject other) {
+    ALOGV("%s", __FUNCTION__);
+
+    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
+
+    // order is important: we can't call another JNI method
+    // if there is an exception pending
+    if (metadata == NULL) return;
+
+    CameraMetadata* otherMetadata = CameraMetadata_getPointerThrow(env, other, "other");
+
+    if (otherMetadata == NULL) return;
+
+    metadata->swap(*otherMetadata);
+}
+
+static void CameraMetadata_readFromParcel(JNIEnv *env, jobject thiz, jobject parcel) {
+    ALOGV("%s", __FUNCTION__);
+    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
+    if (metadata == NULL) {
+        return;
+    }
+
+    Parcel* parcelNative = parcelForJavaObject(env, parcel);
+    if (parcelNative == NULL) {
+        jniThrowNullPointerException(env, "parcel");
+        return;
+    }
+
+    status_t err;
+    if ((err = metadata->readFromParcel(parcelNative)) != OK) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                             "Failed to read from parcel (error code %d)", err);
+        return;
+    }
+}
+
+static void CameraMetadata_writeToParcel(JNIEnv *env, jobject thiz, jobject parcel) {
+    ALOGV("%s", __FUNCTION__);
+    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
+    if (metadata == NULL) {
+        return;
+    }
+
+    Parcel* parcelNative = parcelForJavaObject(env, parcel);
+    if (parcelNative == NULL) {
+        jniThrowNullPointerException(env, "parcel");
+        return;
+    }
+
+    status_t err;
+    if ((err = metadata->writeToParcel(parcelNative)) != OK) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                                  "Failed to write to parcel (error code %d)", err);
+        return;
+    }
+}
+
+} // extern "C"
+
+//-------------------------------------------------
+
+static JNINativeMethod gCameraMetadataMethods[] = {
+  { "nativeClassInit",
+    "()V",
+    (void *)CameraMetadata_classInit },
+  { "nativeAllocate",
+    "()J",
+    (void*)CameraMetadata_allocate },
+  { "nativeIsEmpty",
+    "()Z",
+    (void*)CameraMetadata_isEmpty },
+  { "nativeGetEntryCount",
+    "()I",
+    (void*)CameraMetadata_getEntryCount },
+  { "nativeClose",
+    "()V",
+    (void*)CameraMetadata_close },
+  { "nativeSwap",
+    "(L" CAMERA_METADATA_CLASS_NAME ";)V",
+    (void *)CameraMetadata_swap },
+  { "nativeReadFromParcel",
+    "(Landroid/os/Parcel;)V",
+    (void *)CameraMetadata_readFromParcel },
+  { "nativeWriteToParcel",
+    "(Landroid/os/Parcel;)V",
+    (void *)CameraMetadata_writeToParcel },
+};
+
+struct field {
+    const char *class_name;
+    const char *field_name;
+    const char *field_type;
+    jfieldID   *jfield;
+};
+
+static int find_fields(JNIEnv *env, field *fields, int count)
+{
+    for (int i = 0; i < count; i++) {
+        field *f = &fields[i];
+        jclass clazz = env->FindClass(f->class_name);
+        if (clazz == NULL) {
+            ALOGE("Can't find %s", f->class_name);
+            return -1;
+        }
+
+        jfieldID field = env->GetFieldID(clazz, f->field_name, f->field_type);
+        if (field == NULL) {
+            ALOGE("Can't find %s.%s", f->class_name, f->field_name);
+            return -1;
+        }
+
+        *(f->jfield) = field;
+    }
+
+    return 0;
+}
+
+// Get all the required offsets in java class and register native functions
+int register_android_hardware_photography_CameraMetadata(JNIEnv *env)
+{
+    // Register native functions
+    return AndroidRuntime::registerNativeMethods(env,
+            CAMERA_METADATA_CLASS_NAME,
+            gCameraMetadataMethods,
+            NELEM(gCameraMetadataMethods));
+}
+
+extern "C" {
+static void CameraMetadata_classInit(JNIEnv *env, jobject thiz) {
+    // XX: Why do this separately instead of doing it in the register function?
+    ALOGV("%s", __FUNCTION__);
+
+    field fields_to_find[] = {
+        { CAMERA_METADATA_CLASS_NAME, "mMetadataPtr", "J", &fields.metadata_ptr },
+    };
+
+    // Do this here instead of in register_native_methods,
+    // since otherwise it will fail to find the fields.
+    if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0)
+        return;
+
+    jclass clazz = env->FindClass(CAMERA_METADATA_CLASS_NAME);
+}
+} // extern "C"
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 0827f7c..67c2cfd 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -271,6 +271,17 @@
     return (jint) AudioSystem::getPrimaryOutputFrameCount();
 }
 
+static jint
+android_media_AudioSystem_getOutputLatency(JNIEnv *env, jobject clazz, jint stream)
+{
+    uint32_t afLatency;
+    if (AudioSystem::getOutputLatency(&afLatency, static_cast <audio_stream_type_t>(stream))
+            != NO_ERROR) {
+        afLatency = -1;
+    }
+    return (jint) afLatency;
+}
+
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gMethods[] = {
@@ -296,6 +307,7 @@
     {"getDevicesForStream", "(I)I",     (void *)android_media_AudioSystem_getDevicesForStream},
     {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate},
     {"getPrimaryOutputFrameCount",   "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
+    {"getOutputLatency",    "(I)I",     (void *)android_media_AudioSystem_getOutputLatency},
 };
 
 int register_android_media_AudioSystem(JNIEnv *env)
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index e2d34c9..3ff9dda 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -728,6 +728,19 @@
 
 
 // ----------------------------------------------------------------------------
+static jint android_media_AudioTrack_get_latency(JNIEnv *env,  jobject thiz) {
+    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
+
+    if (lpTrack == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+            "Unable to retrieve AudioTrack pointer for latency()");
+        return AUDIOTRACK_ERROR;
+    }
+    return (jint)lpTrack->latency();
+}
+
+
+// ----------------------------------------------------------------------------
 static jint android_media_AudioTrack_set_loop(JNIEnv *env,  jobject thiz,
         jint loopStart, jint loopEnd, jint loopCount) {
     sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
@@ -854,6 +867,7 @@
                              "()I",      (void *)android_media_AudioTrack_get_pos_update_period},
     {"native_set_position",  "(I)I",     (void *)android_media_AudioTrack_set_position},
     {"native_get_position",  "()I",      (void *)android_media_AudioTrack_get_position},
+    {"native_get_latency",   "()I",      (void *)android_media_AudioTrack_get_latency},
     {"native_set_loop",      "(III)I",   (void *)android_media_AudioTrack_set_loop},
     {"native_reload_static", "()I",      (void *)android_media_AudioTrack_reload},
     {"native_get_output_sample_rate",
diff --git a/core/jni/android_os_FileUtils.cpp b/core/jni/android_os_FileUtils.cpp
index a07f5b7..0aaa2b1 100644
--- a/core/jni/android_os_FileUtils.cpp
+++ b/core/jni/android_os_FileUtils.cpp
@@ -55,6 +55,24 @@
     return chmod(file8.string(), mode) == 0 ? 0 : errno;
 }
 
+jint android_os_FileUtils_getUid(JNIEnv* env, jobject clazz, jstring file)
+{
+    struct stat stats;
+    const jchar* str = env->GetStringCritical(file, 0);
+    String8 file8;
+    if (str) {
+        file8 = String8(str, env->GetStringLength(file));
+        env->ReleaseStringCritical(file, str);
+    }
+    if (file8.size() <= 0) {
+        return ENOENT;
+    }
+    if (stat(file8.string(), &stats) < 0) {
+        return -1;
+    }
+    return stats.st_uid;
+}
+
 jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring path)
 {
     if (path == NULL) {
@@ -78,6 +96,7 @@
 
 static const JNINativeMethod methods[] = {
     {"setPermissions",  "(Ljava/lang/String;III)I", (void*)android_os_FileUtils_setPermissions},
+    {"getUid",          "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getUid},
     {"getFatVolumeId",  "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getFatVolumeId},
 };
 
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 61eb31b..33ded03 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -678,6 +678,7 @@
     PROC_SPACE_TERM = ' ',
     PROC_COMBINE = 0x100,
     PROC_PARENS = 0x200,
+    PROC_QUOTES = 0x400,
     PROC_OUT_STRING = 0x1000,
     PROC_OUT_LONG = 0x2000,
     PROC_OUT_FLOAT = 0x4000,
@@ -719,9 +720,15 @@
     jboolean res = JNI_TRUE;
 
     for (jsize fi=0; fi<NF; fi++) {
-        const jint mode = formatData[fi];
+        jint mode = formatData[fi];
         if ((mode&PROC_PARENS) != 0) {
             i++;
+        } else if ((mode&PROC_QUOTES != 0)) {
+            if (buffer[i] == '"') {
+                i++;
+            } else {
+                mode &= ~PROC_QUOTES;
+            }
         }
         const char term = (char)(mode&PROC_TERM_MASK);
         const jsize start = i;
@@ -737,6 +744,12 @@
             }
             end = i;
             i++;
+        } else if ((mode&PROC_QUOTES) != 0) {
+            while (buffer[i] != '"' && i < endIndex) {
+                i++;
+            }
+            end = i;
+            i++;
         }
         while (buffer[i] != term && i < endIndex) {
             i++;
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 5b6cff0..87ebbd2 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -432,15 +432,9 @@
 }
 
 static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz,
-        OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray chunks,
+        OpenGLRenderer* renderer, SkBitmap* bitmap, Res_png_9patch* patch,
         float left, float top, float right, float bottom, SkPaint* paint) {
-    jbyte* storage = env->GetByteArrayElements(chunks, NULL);
-    Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(storage);
-    Res_png_9patch::deserialize(patch);
-
     renderer->drawPatch(bitmap, patch, left, top, right, bottom, paint);
-
-    env->ReleaseByteArrayElements(chunks, storage, 0);
 }
 
 static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject clazz,
@@ -1031,7 +1025,7 @@
 
     { "nDrawBitmapMesh",    "(IIII[FI[III)V",  (void*) android_view_GLES20Canvas_drawBitmapMesh },
 
-    { "nDrawPatch",         "(II[BFFFFI)V",    (void*) android_view_GLES20Canvas_drawPatch },
+    { "nDrawPatch",         "(IIIFFFFI)V",     (void*) android_view_GLES20Canvas_drawPatch },
 
     { "nDrawColor",         "(III)V",          (void*) android_view_GLES20Canvas_drawColor },
     { "nDrawRect",          "(IFFFFI)V",       (void*) android_view_GLES20Canvas_drawRect },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ca274e3..7ddb0dc 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -185,6 +185,7 @@
     <protected-broadcast android:name="com.android.server.WifiManager.action.DELAYED_DRIVER_STOP" />
     <protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" />
     <protected-broadcast android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
+    <protected-broadcast android:name="android.net.wifi.WIFI_SCAN_AVAILABLE" />
     <protected-broadcast android:name="android.net.wifi.SCAN_RESULTS" />
     <protected-broadcast android:name="android.net.wifi.RSSI_CHANGED" />
     <protected-broadcast android:name="android.net.wifi.STATE_CHANGE" />
@@ -1221,6 +1222,13 @@
         android:label="@string/permlab_removeTasks"
         android:description="@string/permdesc_removeTasks" />
 
+    <!-- @hide Allows an application to create/manage/remove stacks -->
+    <permission android:name="android.permission.MANAGE_ACTIVITY_STACKS"
+        android:permissionGroup="android.permission-group.APP_INFO"
+        android:protectionLevel="signature"
+        android:label="@string/permlab_manageActivityStacks"
+        android:description="@string/permdesc_manageActivityStacks" />
+
     <!-- Allows an application to start any activity, regardless of permission
          protection or exported state. @hide -->
     <permission android:name="android.permission.START_ANY_ACTIVITY"
@@ -2432,6 +2440,29 @@
                 android:process=":ui">
         </activity>
 
+        <activity android:name="com.android.internal.app.RestrictionsPinSetupActivity"
+                android:theme="@style/Theme.Holo.Dialog.Alert"
+                android:permission="android.permission.MANAGE_USERS"
+                android:excludeFromRecents="true"
+                android:windowSoftInputMode="adjustPan"
+                android:process=":ui">
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.RESTRICTIONS_PIN_CREATE" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="com.android.internal.app.RestrictionsPinActivity"
+                android:theme="@style/Theme.Holo.Dialog.Alert"
+                android:excludeFromRecents="true"
+                android:windowSoftInputMode="adjustPan"
+                android:process=":ui">
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.RESTRICTIONS_PIN_CHALLENGE" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
         <receiver android:name="com.android.server.BootReceiver"
                 android:primaryUserOnly="true">
             <intent-filter>
@@ -2470,9 +2501,9 @@
         </receiver>
 
         <receiver android:name="com.android.server.MasterClearReceiver"
-            android:permission="android.permission.MASTER_CLEAR"
-            android:priority="100" >
-            <intent-filter>
+            android:permission="android.permission.MASTER_CLEAR">
+            <intent-filter
+                    android:priority="100" >
                 <!-- For Checkin, Settings, etc.: action=MASTER_CLEAR -->
                 <action android:name="android.intent.action.MASTER_CLEAR" />
 
diff --git a/core/res/res/layout/pin_challenge.xml b/core/res/res/layout/pin_challenge.xml
new file mode 100644
index 0000000..2cb14b4
--- /dev/null
+++ b/core/res/res/layout/pin_challenge.xml
@@ -0,0 +1,84 @@
+<?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.
+-->
+
+<!-- Layout used as the dialog's content View for EditTextPreference. -->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_marginTop="48dp"
+    android:layout_marginBottom="48dp"
+    android:overScrollMode="ifContentScrolls">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:padding="8dip"
+        android:orientation="vertical">
+
+        <TextView android:id="@+id/pin_message"
+            style="?android:attr/textAppearanceMedium"
+            android:layout_marginTop="16dp"
+            android:layout_marginBottom="16dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/restr_pin_create_pin"
+            android:textColor="?android:attr/textColorSecondary" />
+
+        <!-- TextView android:id="@+id/pin1_label"
+            style="?android:attr/textAppearanceSmall"
+            android:layout_marginBottom="16dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/restr_pin_enter_pin"
+            android:textColor="?android:attr/textColorSecondary" /-->
+
+        <EditText android:id="@+id/pin1_text"
+            style="?android:attr/textAppearanceMedium"
+            android:layout_marginBottom="16dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:hint="@string/restr_pin_enter_pin"
+            android:inputType="textPassword"
+            android:textColor="?android:attr/textColorPrimary" />
+
+        <!-- TextView android:id="@+id/pin2_label"
+            style="?android:attr/textAppearanceSmall"
+            android:layout_marginBottom="16dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/restr_pin_confirm_pin"
+            android:textColor="?android:attr/textColorSecondary" /-->
+
+        <EditText android:id="@+id/pin2_text"
+            style="?android:attr/textAppearanceMedium"
+            android:layout_marginBottom="16dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:hint="@string/restr_pin_confirm_pin"
+            android:inputType="textPassword"
+            android:textColor="?android:attr/textColorPrimary" />
+
+        <TextView android:id="@+id/pin_error_message"
+            style="?android:attr/textAppearanceSmall"
+            android:layout_marginBottom="16dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/restr_pin_error_doesnt_match"
+            android:textColor="#FFFF0000" />
+
+    </LinearLayout>
+
+</ScrollView>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 2512fd7..c0c71f9 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Dit laat die houer toe om aan die topvlak-koppelvlak van \'n invoermetode te bind. Dit moet nooit vir normale programme nodig wees nie."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"verbind aan \'n toeganklikheidsdiens"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Dit laat die houer toe om aan die top-koppelvlak van \'n toeganklikheidsdiens te verbind. Behoort nooit vir gewone programme nodig te wees nie."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"bind aan \'n teksdiens"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Dit laat die houer toe om aan die topvlak-koppelvlak van \'n teksdiens (bv SpellCheckerService) te bind. Dit moet nooit vir normale programme nodig wees nie."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"bind aan \'n VPN-diens"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Hierdie program werk nie met rekeninge vir beperkte profiele nie"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Geen program gevind om hierdie handeling te hanteer nie"</string>
     <string name="revoke" msgid="5404479185228271586">"Herroep"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 7cb0ad1..51fb415 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"ያዡ ግቤት ስልቱን ወደ ከፍተኛ-ደረጃ በይነገጽ ለመጠረዝ ይፈቅዳሉ። ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"ከአንድ የተደራሽነት አገልግሎት ጋር እሰር"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"ያዢው ወደ የአንድ ተደራሽነት አገልግሎት ከፍተኛ-ደረጃ በይነገጽ እንዲያስር ይፈቅድለታል። ለመደበኛ መተግበሪያዎች መቼም ቢሆን ሊያስፈልግ አይገባም።"</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"ለፅሁፍ አገልግሎት አሰረ"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"ያዡ ግቤት ለከፍተኛ-ደረጃ የፅሁፍ አገልግሎት ገፅታ ለመጠረዝ ይፈቅዳል። ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"ለVPN አገልግሎት ተገዛ"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"ይህ መተግበሪያ የተገደቡ መገለጫዎች መለያዎችን አይደግፍም"</string>
     <string name="app_not_found" msgid="3429141853498927379">"ይህን እርምጃ የሚያከናውን ምንም መተግበሪያ አልተገኘም"</string>
     <string name="revoke" msgid="5404479185228271586">"ሻር"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 40a0320..18fd4c9 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لأسلوب الإدخال. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"الالتزام بخدمة إمكانية الدخول"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لخدمة إمكانية الدخول. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"الالتزام بخدمة إدخال النصوص"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لخدمة إدخال النصوص (على سبيل المثال، SpellCheckerService). لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"الالتزام بخدمة VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"لا يتوافق هذا التطبيق مع حسابات الملفات الشخصية المقيدة"</string>
     <string name="app_not_found" msgid="3429141853498927379">"لم يتم العثور على تطبيق يمكنه التعامل مع هذا الإجراء."</string>
     <string name="revoke" msgid="5404479185228271586">"إلغاء"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 9ef8bba..9d87725 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Дазваляе ўладальніку прывязвацца да інтэрфейсу верхняга ўзроўню метада ўводу. Не патрабуецца для звычайных прыкладанняў."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"прывязацца да службы доступу"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Дазваляе ўладальніку прывязвацца да інтэрфейсу верхняга ўзроўню службы доступу. Не патрабуецца для звычайных прыкладанняў."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"звязаць з тэкставай службай"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Дазваляе ўладальніку прывязвацца да інтэрфейсу верхняга ўзроўню тэкставай паслугі (напрыклад, SpellCheckerService). Ніколі не патрабуецца для звычайных прыкладанняў."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"звязвацца з VPN сэрвісам"</string>
@@ -1503,4 +1511,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Гэта прыкладанне не падтрымлівае ўліковыя запісы для профiляў з абмежаваннямі"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Прыкладанне для гэтага дзеяння не знойдзенае"</string>
     <string name="revoke" msgid="5404479185228271586">"Ануляваць"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 5f11579..d1b4737 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на метод на въвеждане. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"обвързване с услуга за достъпност"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на услуга за достъпност. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"обвързване с текстова услуга"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на текстова услуга (напр. SpellCheckerService). Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"обвързване с услуга за VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Това приложение не поддържа профили за потребителски профили с ограничена функционалност"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Няма намерено приложение за извършване на това действие"</string>
     <string name="revoke" msgid="5404479185228271586">"Отмяна"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index b87296b..40db5d2 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Permet que el titular vinculi a la interfície de nivell superior d\'un mètode d\'entrada. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"vincular amb un servei d\'accessibilitat"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Permet vincular amb la interfície de nivell superior d\'un servei d\'accessibilitat. Les aplicacions normals no haurien de necessitar-ho."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"vincula a un servei de text"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Permet al titular vincular amb la interfície de nivell superior d\'un servei de text (per exemple, SpellCheckerService). Les aplicacions normals mai no ho haurien de necessitar."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"vincula a un servei de VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"L\'aplicació no és compatible amb comptes de perfils restringits"</string>
     <string name="app_not_found" msgid="3429141853498927379">"No s\'ha trobat cap aplicació per processar aquesta acció"</string>
     <string name="revoke" msgid="5404479185228271586">"Revoca"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index b43deec..33a68bd 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Umožňuje držiteli vázat se na nejvyšší úroveň rozhraní pro zadávání dat. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"navázat se na službu usnadnění přístupu"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Umožňuje držiteli navázat se na nejvyšší úroveň rozhraní služby usnadnění přístupu. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"navázat se na textovou službu"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Umožňuje držiteli připojit se k nejvyšší úrovni rozhraní textové služby (např. SpellCheckerService). Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"navázat se na službu VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Tato aplikace nepodporuje účty pro omezené profily"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Aplikace potřebná k provedení této akce nebyla nalezena"</string>
     <string name="revoke" msgid="5404479185228271586">"Zrušit"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 9806779..aacf74ad 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Tillader, at brugeren kan forpligter sig til en inputmetodes grænseflade på øverste niveau. Bør aldrig være nødvendigt til almindelige apps."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"bind dig til en tilgængelighedstjeneste"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Tillader, at brugeren binder sig til en grænseflade for en tilgængelighedstjeneste på øverste niveau. Bør aldrig være nødvendigt til almindelige apps."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"forpligte sig til en sms-tjeneste"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Tillader, at ejeren kan binde en teksttjenestes grænseflade (f. eks. SpellCheckerService) på øverste niveau. Dette bør aldrig være nødvendigt til normale apps."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"bind til en VPN-tjeneste"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Denne applikation understøtter ikke konti for begrænsede profiler"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Der blev ikke fundet nogen applikation, der kan håndtere denne handling"</string>
     <string name="revoke" msgid="5404479185228271586">"Tilbagekald"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index d8ded2a..a35a41a 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Ermöglicht dem Halter, sich an die Oberfläche einer Eingabemethode auf oberster Ebene zu binden. Sollte nie für normale Apps benötigt werden."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"An eine Bedienungshilfe binden"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Ermöglicht dem Halter, sich an die Oberfläche einer Bedienungshilfe auf oberster Ebene zu binden. Sollte nie für normale Apps benötigt werden."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"An einen Textdienst binden"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Ermöglicht dem Halter, sich an die Oberfläche eines Textdienstes auf oberster Ebene zu binden, z. B. eines Rechtschreibprüfungsdienstes. Sollte nie für normale Apps benötigt werden."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"An einen VPN-Dienst binden"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Diese App unterstützt keine Konten für eingeschränkte Profile."</string>
     <string name="app_not_found" msgid="3429141853498927379">"Für diese Aktion wurde keine App gefunden."</string>
     <string name="revoke" msgid="5404479185228271586">"Aufheben"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index db6d161..6592bde 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας μεθόδου εισόδου. Δεν απαιτείται για συνήθεις εφαρμογές."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"δέσμευση σε υπηρεσία προσβασιμότητας"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανώτατου επιπέδου μιας υπηρεσίας προσβασιμότητας. Δεν απαιτείται σε κανονικές εφαρμογές."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"δέσμευση σε υπηρεσία ανταλλαγής μηνυμάτων"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Επιτρέπει στον κάτοχο τη σύνδεση με τη διεπαφή ανωτέρου επιπέδου μιας υπηρεσίας ανταλλαγής μηνυμάτων (π.χ. SpellCheckerService). Δεν είναι απαραίτητο για κανονικές εφαρμογές."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"δέσμευση σε υπηρεσία VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Αυτή η εφαρμογή δεν υποστηρίζει λογαριασμούς για περιορισμένα προφίλ"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Δεν υπάρχει εφαρμογή για τη διαχείριση αυτής της ενέργειας"</string>
     <string name="revoke" msgid="5404479185228271586">"Ανάκληση"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 5a32c1e..8ad86c2 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Allows the holder to bind to the top-level interface of an input method. Should never be needed for normal apps."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"bind to an accessibility service"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Allows the holder to bind to the top-level interface of an accessibility service. Should never be needed for normal apps."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"bind to a text service"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Allows the holder to bind to the top-level interface of a text service (e.g. SpellCheckerService). Should never be needed for normal applications."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"bind to a VPN service"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"This app doesn\'t support accounts for restricted profiles"</string>
     <string name="app_not_found" msgid="3429141853498927379">"No application found to handle this action"</string>
     <string name="revoke" msgid="5404479185228271586">"Revoke"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 991e9e0..5756a31 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Permite al propietario vincularse a la interfaz de nivel superior de un método de entrada. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"vincular a un servicio de accesibilidad"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Permite al propietario vincularse a la interfaz de nivel superior de un servicio de accesibilidad. Las aplicaciones normales no deberían necesitar este permiso."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"vincular a un servicio de texto"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Permite al titular vincularse a la interfaz de nivel superior de un servicio de texto (p. ej., SpellCheckerService). Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"vincular con un servicio de VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Esta aplicación no admite cuentas de perfiles restringidos."</string>
     <string name="app_not_found" msgid="3429141853498927379">"No se encontró una aplicación para manejar esta acción."</string>
     <string name="revoke" msgid="5404479185228271586">"Revocar"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 72e5694..2c7ca39 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Permite que se enlace con la interfaz de nivel superior de un método de introducción de texto. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"enlazar con un servicio de accesibilidad"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Permite enlazar con la interfaz de nivel superior de un servicio de accesibilidad. Las aplicaciones normales no deberían necesitar este permiso."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"enlazar con un servicio de texto"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Permite enlazar con la interfaz de nivel superior de un servicio de texto (por ejemplo, SpellCheckerService). Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"enlazar con un servicio VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Esta aplicación no admite cuentas de perfiles restringidos"</string>
     <string name="app_not_found" msgid="3429141853498927379">"No se ha encontrado ninguna aplicación que pueda realizar esta acción."</string>
     <string name="revoke" msgid="5404479185228271586">"Revocar"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 89851e8..5c31f97 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Lubab omanikul siduda sisestusmeetodi ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"sidumine juurdepääsuteenusega"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Lubab omanikul luua sideme juurdepääsuteenuse ülataseme liidesega. Tavarakenduste puhul ei tohiks seda kunagi vaja minna."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"tekstiteenusega sidumine"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Võimaldab omanikul siduda tekstiteenuse (nt SpellCheckerService) ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"seo VPN-teenusega"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"See rakendus ei toeta piiratud profiilide kontosid"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Selle toimingu käsitlemiseks ei leitud ühtegi rakendust"</string>
     <string name="revoke" msgid="5404479185228271586">"Tühista"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 65853a1..c62b131 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"به دارنده این دستگاه اجازه می‎دهد تا به رابط سطح بالای یک روش ورودی متصل شود. این ویژگی هیچگاه برای برنامه‎های معمولی ضروری نمی‎باشد."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"اتصال به سرویس دسترسی"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"به دارنده اجازه می‌دهد که به رابط سطح بالای سرویس دسترسی متصل شود. هرگز برای برنامه‌های معمولی مورد نیاز نیست."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"اتصال به یک سرویس متنی"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"به دارنده اجازه می‌دهد خود را به یک رابط سطح بالای خدمات متنی مرتبط کند (برای مثال SpellCheckerService). هرگز برای برنامه‌های عادی لازم نیست."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"اتصال به یک سرویس VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"این برنامه از حساب‌های متعلق به نمایه‌های محدود پشتیبانی نمی‌کند"</string>
     <string name="app_not_found" msgid="3429141853498927379">"برنامه‌ای برای انجام این عملکرد موجود نیست"</string>
     <string name="revoke" msgid="5404479185228271586">"لغو"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index c29ed64..ded0f00 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Antaa sovelluksen sitoutua syötetavan ylätason käyttöliittymään. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"sitoudu esteettömyyspalveluun"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Antaa sovelluksen sitoutua esteettömyyspalvelun ylemmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"tekstipalveluun sitoutuminen"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Antaa sovelluksen sitoutua tekstipalvelun (kuten SpellCheckerServicen) ylätason liittymään. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"sitoudu VPN-palveluun"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Tämä sovellus ei tue rajoitettujen profiilien tilejä"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Tätä toimintoa käsittelevää sovellusta ei löydy"</string>
     <string name="revoke" msgid="5404479185228271586">"Peruuta"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 6df108f..c162cf1 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un mode de saisie. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"associer à un service d\'accessibilité"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service d\'accessibilité. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"associer à un service de texte"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Permet à l\'application de s\'associer à l\'interface de haut niveau d\'un service de texte (par exemple, SpellCheckerService). Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"associer à un service VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Les comptes des profils en accès limité ne sont pas compatibles avec cette application."</string>
     <string name="app_not_found" msgid="3429141853498927379">"Aucune application trouvée pour gérer cette action."</string>
     <string name="revoke" msgid="5404479185228271586">"Révoquer"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 76c62ea..218cb89 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"धारक को किसी इनपुट विधि के शीर्ष-स्‍तर इंटरफ़ेस से आबद्ध होने देता है. सामान्‍य एप्‍लिकेशन के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"पहुंच-योग्‍यता सेवा से आबद्ध करें"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"धारक को किसी पहुंच-योग्यता सेवा के शीर्ष-स्‍तर इंटरफ़ेस से आबद्ध होने देता है. सामान्‍य एप्‍लिकेशन के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"किसी पाठ सेवा पर बने रहें"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"धारक को किसी पाठ सेवा (उदा. SpellCheckerService) के शीर्ष-स्‍तर इंटरफ़ेस पर आबद्ध होने देता है. सामान्‍य एप्‍लिकेशन के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"किसी VPN सेवा से आबद्ध करें"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"यह एप्लिकेशन प्रतिबंधित प्रोफ़ाइल के खातों का समर्थन नहीं करता है"</string>
     <string name="app_not_found" msgid="3429141853498927379">"इस कार्यवाही को प्रबंधित करने के लिए कोई एप्लिकेशन नहीं मिला"</string>
     <string name="revoke" msgid="5404479185228271586">"निरस्‍त करें"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index e53fb2d..bda36de 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Nositelju omogućuje povezivanje sučelja najviše razine načina unosa. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"vezivanje uz uslugu dostupnosti"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Nositelju omogućuje vezanje uz sučelje najviše razine usluge dostupnosti. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"vezanje na tekstualnu uslugu"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Omogućuje korisniku povezivanje s najvišom razinom sučelja tekstualne usluge (npr. SpellCheckerService). Ne bi smjelo biti potrebno za normalne aplikacije."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"vezanje na VPN uslugu"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Aplikacija ne podržava račune za ograničene profile"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Nije pronađena aplikacija za upravljanje ovom radnjom"</string>
     <string name="revoke" msgid="5404479185228271586">"Opozovi"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index c4c7f0a..9efb6b3 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Lehetővé teszi, hogy a tulajdonos kötelezővé tegye egy beviteli mód legfelső szintű felületét. A normál alkalmazásoknak erre soha nincs szüksége."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"csatlakozás egy kisegítő szolgáltatáshoz"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Lehetővé teszi a használó számára, hogy csatlakozzon egy kisegítő szolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"csatlakozás szövegszolgáltatáshoz"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Lehetővé teszi, hogy a tulajdonos egy szöveges szolgáltatás felső szintjéhez kapcsolódjon (pl. SpellCheckerService). A normál alkalmazásoknak erre soha nincs szüksége."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"csatlakozás egy VPN-szolgáltatáshoz"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ez az alkalmazás nem támogatja a korlátozott profilokkal rendelkező fiókokat"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Nincs megfelelő alkalmazás a művelet elvégzésére."</string>
     <string name="revoke" msgid="5404479185228271586">"Visszavonás"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index e0e3fca..de45c42 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu metode masukan. Tidak pernah diperlukan oleh apl normal."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"mengikat ke layanan aksesibilitas"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Mengizinkan pemegang untuk mengikat antarmuka tingkat tinggi dari suatu layanan. Tidak pernah diperlukan oleh aplikasi normal."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"mengikat ke layanan SMS"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu layanan teks (misal: SpellCheckerService). Tidak pernah diperlukan oleh apl normal."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"mengikat ke layanan VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Aplikasi ini tidak mendukung akun untuk profil yang dibatasi"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Tidak ada aplikasi yang ditemukan untuk menangani tindakan ini"</string>
     <string name="revoke" msgid="5404479185228271586">"Cabut"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 8079b41..5861679 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Consente l\'associazione di un metodo di inserimento all\'interfaccia principale. Non dovrebbe mai essere necessaria per le normali applicazioni."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"collegamento a un servizio di accessibilità"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Consente al titolare di collegarsi all\'interfaccia di primo livello di un servizio di accessibilità. Non dovrebbe essere mai necessaria per le normali applicazioni."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"associazione a un servizio di testo"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Consente al titolare di collegarsi all\'interfaccia di primo livello di un servizio di testo (ad esempio SpellCheckerService). Non dovrebbe essere mai necessaria per le normali applicazioni."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"associazione a un servizio VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Questa app non supporta account relativi a profili con limitazioni"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Nessuna applicazione trovata in grado di gestire questa azione"</string>
     <string name="revoke" msgid="5404479185228271586">"Revoca"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 4926a11..37444e9 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"מאפשר למשתמש לבצע איגוד לממשק ברמה עליונה של שיטת קלט. הרשאה זו לעולם אינה נחוצה ליישומים רגילים."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"הכפפה לשירות נגישות"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"מתיר לבעלים להכפיף לממשק ברמה העליונה של שירות זמינות. הרשאה זו אף פעם אינה אמורה להיות נחוצה ליישומים רגילים."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"הכפפה לשירות טקסט"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"מאפשר למשתמש ליצור איגוד לממשק הרמה העליונה של שירות טקסט (למשל, SpellCheckerService). הרשאה זו לעולם אינה נחוצה ליישומים רגילים."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"אגד לשירות VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"האפליקציה הזו לא תומכת בחשבונות עבור פרופילים מוגבלים"</string>
     <string name="app_not_found" msgid="3429141853498927379">"לא נמצא יישום שתומך בפעולה זו"</string>
     <string name="revoke" msgid="5404479185228271586">"בטל"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 89354bf..5fd3105 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"入力方法のトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"ユーザー補助サービスにバインド"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"ユーザー補助サービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"テキストサービスにバインド"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"テキストサービス(SpellCheckerServiceなど)のトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"VPNサービスにバインド"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"このアプリでは制限付きプロフィールのアカウントはサポートしていません"</string>
     <string name="app_not_found" msgid="3429141853498927379">"この操作を行うアプリが見つかりません"</string>
     <string name="revoke" msgid="5404479185228271586">"取り消し"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index b9f2459..a15e777 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"권한을 가진 프로그램이 입력 방법에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"접근성 서비스와 연결"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"권한을 가진 프로그램이 접근성 서비스에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"텍스트 서비스 연결"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"권한을 가진 프로그램이 텍스트 서비스(예: SpellCheckerService)에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"VPN 서비스와 연결"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"이 앱은 제한된 프로필의 계정을 지원하지 않습니다."</string>
     <string name="app_not_found" msgid="3429141853498927379">"이 작업을 처리하는 애플리케이션을 찾을 수 없습니다."</string>
     <string name="revoke" msgid="5404479185228271586">"취소"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index bcd82a9..267171c 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Leidžiama savininką susaistyti su įvesties metodo aukščiausio lygio sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"susisaistyti su pasiekiamumo paslauga"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Savininkui leidžiama susisaistyti su aukščiausio lygio pasiekiamumo paslaugos sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"priskirti teksto paslaugą"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Leidžiama savininkui priskirti aukščiausio lygio teksto paslaugos (pvz., „SpellCheckerService“) sąsają. Įprastoms programoms to neturėtų prireikti."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"susaistyti su VPN paslauga"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ši programa nepalaiko apribotų profilių paskyrų"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Nerasta programa šiam veiksmui apdoroti"</string>
     <string name="revoke" msgid="5404479185228271586">"Anuliuoti"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 3e35a45..79eb3ec 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Ļauj īpašniekam izveidot saiti ar ievades metodes augstākā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"saistīt ar pieejamības pakalpojumu"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Ļauj īpašniekam izveidot saiti ar pieejamības pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm šī atļauja nav nepieciešama."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"saistīt ar īsziņu pakalpojumu"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Ļauj īpašniekam veikt saistīšanu ar īsziņu pakalpojuma augstākā līmeņa saskarni (piem., SpellCheckerService). Parastajām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"saistīt ar VPN pakalpojumu"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Šajā lietotnē netiek atbalstīti ierobežotu profilu konti."</string>
     <string name="app_not_found" msgid="3429141853498927379">"Netika atrasta neviena lietojumprogramma, kas var veikt šo darbību."</string>
     <string name="revoke" msgid="5404479185228271586">"Atsaukt"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 45ed50f..cd27bba 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi kaedah input itu. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"terikat kepada perkhidmatan yang boleh diakses"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan yang boleh diakses. Tidak sekali-kali diperlukan untuk apl biasa."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"terikat kepada perkhidmatan teks"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Membenarkan pemegang mengikat kepada antara muka peringkat atasan perkhidmatan teks(mis. PerkhidmatanPenyemakEjaan). Tidak seharusnya diperlukan untuk apl biasa."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"terikat kepada perkhidmatan VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Apl ini tidak menyokong akaun untuk profil yang disekat"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Tidak menemui aplikasi untuk mengendalikan tindakan ini"</string>
     <string name="revoke" msgid="5404479185228271586">"Batalkan"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 5aa260d..8bc91eda 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Lar innehaveren binde det øverste nivået av grensesnittet til en inndatametode. Skal aldri være nødvendig for normale apper."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"binde seg til en tilgjengelighetstjeneste"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Gir innehaveren tillatelse til å bindes til det øverste nivået av grensesnittet for en tilgjengelighetstjeneste. Skal aldri være nødvendig for vanlige apper."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"binde til en teksttjeneste"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Lar innehaveren binde seg til øverste grensesnittnivå for en teksttjeneste (f.eks. SpellCheckerService). Skal aldri være nødvendig for vanlige apper."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"binde deg til en VPN-tjeneste"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Denne appen støtter ikke kontoer for begrensede profiler"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Finner ingen apper som kan utføre denne handlingen"</string>
     <string name="revoke" msgid="5404479185228271586">"Opphev"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 7f902b2..4101c47 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Hiermee kan de houder zich verbinden met de hoofdinterface van een invoermethode. Nooit vereist voor normale apps."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"koppelen aan een toegankelijkheidsservice"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Hiermee wordt de houder toegestaan verbinding te maken met de hoofdinterface van een toegankelijkheidsservice. Nooit vereist voor normale apps."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"koppelen aan een sms-service"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Hiermee kan de gebruiker koppelen met de hoofdinterface van een tekstservice (zoals SpellCheckerService). Dit is niet nodig voor normale apps."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"koppelen aan een VPN-service"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Deze app biedt geen ondersteuning voor accounts voor beperkte profielen"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Er is geen app gevonden om deze actie uit te voeren"</string>
     <string name="revoke" msgid="5404479185228271586">"Intrekken"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index e0daead..9623ab9 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Pozwala na powiązanie wybranego sposobu wprowadzania tekstu z interfejsem najwyższego poziomu. To uprawnienie nie powinno być nigdy wymagane przez zwykłe aplikacje."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"tworzenie powiązania z usługą ułatwień dostępu"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi ułatwień dostępu. Nieprzeznaczone dla zwykłych aplikacji."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"tworzenie powiązania z usługą tekstową"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Pozwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi tekstowej (np. SpellCheckerService). Nie powinno być nigdy potrzebne w przypadku zwykłych aplikacji."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"tworzenie powiązania z usługą VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ta aplikacja nie obsługuje kont w profilach z ograniczeniami"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Nie znaleziono aplikacji do obsługi tej akcji"</string>
     <string name="revoke" msgid="5404479185228271586">"Cofnij"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index bbf6f84..b139363 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Permite ao titular vincular-se à interface de nível superior de um método de entrada. Nunca deve ser necessário para aplicações normais."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"vincular a um serviço de acessibilidade"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Permite que o titular vincule a interface de nível superior de um serviço de acessibilidade. Nunca deverá ser necessário para aplicações normais."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"vincular a um serviço de texto"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Permite ao titular ligar-se à interface de nível superior de um serviço de texto (por exemplo SpellCheckerService). Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"vincular a um serviço VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Esta aplicação não suporta contas de perfis restritos"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Não foram encontradas aplicações para executar esta ação"</string>
     <string name="revoke" msgid="5404479185228271586">"Revogar"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index c5fe686..457a7a6 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Permite que o proprietário utilize a interface de nível superior de um método de entrada. Nunca deve ser necessário para aplicativos normais."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"usar um serviço de acessibilidade"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Permite que o proprietário use a interface de nível superior de um serviço de acessibilidade. Nunca deve ser necessário para aplicativos comuns."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"sujeitar-se a um serviço de texto"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Permite que o proprietário utilize interface de nível superior de um serviço de texto (por exemplo, SpellCheckerService). Nunca deve ser necessário para aplicativos normais."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"se ligam a um serviço de VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Este aplicativo não suporta contas para perfis restritos"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Nenhum aplicativo encontrado para executar a ação"</string>
     <string name="revoke" msgid="5404479185228271586">"Revogar"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 787c92b..b124437 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -553,6 +553,14 @@
     <skip />
     <!-- no translation found for permdesc_bindAccessibilityService (7034615928609331368) -->
     <skip />
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
     <skip />
     <!-- no translation found for permdesc_bindTextService (8151968910973998670) -->
@@ -2443,4 +2451,82 @@
     <skip />
     <!-- no translation found for revoke (5404479185228271586) -->
     <skip />
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index f5d8b9e..708b632 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unei metode de introducere. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"conectare la un serviciu de accesibilitate"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unui serviciu de accesibilitate. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"conectare la un serviciu text"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Permite proprietarului să se conecteze la o interfaţă de nivel superior a unui serviciu text (de ex., SpellCheckerService). Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"conectare la un serviciu VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Această aplicație nu acceptă conturi pentru profilurile cu permisiuni limitate"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Nicio aplicație pentru gestionarea acestei acțiuni"</string>
     <string name="revoke" msgid="5404479185228271586">"Revocați"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 70da18e..66136de 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Приложение сможет подключаться к базовому интерфейсу системы ввода. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"Подключение к службе специальных возможностей"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Приложение сможет подключаться к базовому интерфейсу службы специальных возможностей. Это разрешение не используется обычными приложениями."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"Подключение к службе текстовых сообщений"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Позволяет подключаться к базовому интерфейсу службы текстовых сообщений (например, SpellCheckerService). Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"Подключение к VPN-службе"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Это приложение не поддерживается в аккаунтах для профилей с ограниченным доступом"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Невозможно обработать это действие"</string>
     <string name="revoke" msgid="5404479185228271586">"Отменить"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index fde5bbb..aa24702 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania metódy vstupu. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"viazať na službu zjednodušeného ovládania"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby zjednodušeného ovládania. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"väzba na textovú službu"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania textovej služby (napr. SpellCheckerService). Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"Zaviazať k službe VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Táto aplikácia nepodporuje účty pre profily s obmedzením"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Aplikácia potrebná na spracovanie tejto akcie sa nenašla"</string>
     <string name="revoke" msgid="5404479185228271586">"Odvolať"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 6166e2f..298d0cc 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Lastniku omogoča, da se poveže z vmesnikom načina vnosa najvišje ravni. Tega nikoli ni treba uporabiti za navadne programe."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"povezovanje s storitvijo za ljudi s posebnimi potrebami"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Lastniku omogoča povezovanje z vmesnikom najvišje ravni storitve za ljudi s posebnimi potrebami. Tega nikoli ni treba uporabiti za navadne aplikacije."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"poveži z besedilno storitvijo"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Dovoljuje, da se lastnik poveže z vmesnikom besedilne storitve najvišje ravni (npr. SpellCheckerService). Tega nikoli ni treba uporabiti za navadne programe."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"povezava s storitvijo navideznega zasebnega omrežja"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ta aplikacija ne podpira računov za profile z omejitvami"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Najdena ni bila nobena aplikacija za izvedbo tega dejanja"</string>
     <string name="revoke" msgid="5404479185228271586">"Prekliči"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 616787a..a762056 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Омогућава да се власник обавеже на интерфејс методе уноса највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"повезивање са услугом приступачности"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Дозвољава власнику да се повеже са интерфејсом услуге приступачности највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"обавезивање на текстуалну услугу"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Омогућава власнику да се обавеже на интерфејс текстуалне услуге највишег нивоа (нпр. SpellCheckerService). Обичне апликације никада не би требало да је користе."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"везивање за VPN услугу"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ова апликација не подржава налоге за ограничене профиле"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Није пронађена ниједна апликација која би могла да обави ову радњу"</string>
     <string name="revoke" msgid="5404479185228271586">"Опозови"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 89426d1..9e4b548 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en inmatningsmetod. Ska inte behövas för vanliga appar."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"bind till en tillgänglighetstjänst"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en tillgänglighetstjänst. Ska inte behövas för vanliga appar."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"bind till en texttjänst"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Tillåter innehavaren att binda mot den högsta gränssnittsnivån i en texttjänst (t.ex. SpellCheckerService). Bör aldrig behövas för normala appar."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"bind till en VPN-tjänst"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Den här appen stöder inte konton för begränsade profiler"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Ingen app som kan hantera åtgärden hittades"</string>
     <string name="revoke" msgid="5404479185228271586">"Återkalla"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 7f5144f..2e21886 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Inaruhusu mmiliki kushurutisha kwenye kusano ya kiwango cha juu ya mbinu ya ingizo. Haipaswi kuhitajika kwa programu za kawaida."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"funga kwa huduma ya ufikiaji"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Inamuruhusu mmiliki kufunga kipengee kinachojitokeza katika nyanja mbalimbali za kiwango cha juu cha huduma ya afikiaji. Hapaswi kuhitajika kwa programu za kawaida."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"Imefungwa kwa huduma ya maandishi"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Inaruhusu kishikiliaji kushurutisha kusano ya kiwango cha juu ya huduma ya matini(k.m.SpellCheckerService). Haipaswi kuhitajika kwa programu za kawaida."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"funga kwa huduma ya VPN"</string>
@@ -795,8 +803,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Hakuna SIM kadi katika kompyuta ndogo."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Hakuna SIM kadi kwenye simu."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Ingiza SIM kadi."</string>
-    <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"Kadi ya SIM haiko au haisomeki. Tafadhali ingiza SIM kadi."</string>
-    <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"Kadi ya SIM isiyotumika."</string>
+    <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"SIM kadi haipatikani au haisomeki. Tafadhali ingiza SIM kadi."</string>
+    <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"SIM kadi isiyotumika."</string>
     <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"SIM kadi yako imelemezwa kabisa."\n" Wasiliana na mtoa huduma wako wa pasi waya ili upate SIM kadi nyingine."</string>
     <string name="lockscreen_transport_prev_description" msgid="201594905152746886">"Kitufe cha awali cha wimbo"</string>
     <string name="lockscreen_transport_next_description" msgid="6089297650481292363">"Kitufe cha wimbo unaofuata"</string>
@@ -805,9 +813,9 @@
     <string name="lockscreen_transport_stop_description" msgid="4562318378766987601">"Kitufe cha kusitisha"</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Simu za dharura pekee"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Mtandao umefungwa"</string>
-    <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Kadi ya SIM imefungwa na PUK."</string>
+    <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM kadi imefungwa kwa PUK."</string>
     <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Angalia Mwongozo wa Mtumiaji au wasiliana na Huduma ya Wateja."</string>
-    <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Kadi ya SIM imefungwa."</string>
+    <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM kadi imefungwa."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Inafungua SIM kadi..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"Umekosea katika kuchora ruwaza yako ya kufungua mara <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n" Jaribu tena kwa sekunde <xliff:g id="NUMBER_1">%d</xliff:g>."</string>
     <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"Umekosea mara <xliff:g id="NUMBER_0">%d</xliff:g> katika kuingiza nenosiri lako. "\n\n" Jaribu tena katika sekunde <xliff:g id="NUMBER_1">%d</xliff:g>."</string>
@@ -1172,10 +1180,10 @@
     <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Unaweza kubadilisha hii baadaye kwenye Mipangilio &gt; Programu"</string>
     <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Ruhusu Kila mara"</string>
     <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Usiruhusu Kamwe"</string>
-    <string name="sim_removed_title" msgid="6227712319223226185">"Kadi ya SIM imeondolewa"</string>
+    <string name="sim_removed_title" msgid="6227712319223226185">"SIM kadi imeondolewa"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"mtandao wa simu hutapatika hadi uanzishe upya na SIM kadi halali iliyoingizwa."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Kwisha"</string>
-    <string name="sim_added_title" msgid="3719670512889674693">"Kadi ya SIM imeongezwa"</string>
+    <string name="sim_added_title" msgid="3719670512889674693">"SIM kadi imeongezwa"</string>
     <string name="sim_added_message" msgid="6599945301141050216">"Anzisha upya kifaa chako ili kufikia mtandao wa simu."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Anza upya"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Weka muda"</string>
@@ -1467,7 +1475,7 @@
     <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM sasa imelemazwa. Ingiza msimbo wa PUK ili kuendelea. Wasiliana na mtoa huduma kwa maelezo."</string>
     <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Ingiza msimbo wa PIN unaopendelewa"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Thibitisha msimbo wa PIN unaopendelewa"</string>
-    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Inafungua kadi ya SIM..."</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Inafungua SIM kadi..."</string>
     <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Msimbo wa PIN usio sahihi."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Charaza PIN iliyo na tarakimu kati ya 4 na 8."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Msimbo wa PUK unafaa kuwa na nambari 8 au zaidi."</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Programu hii haiwezi kutumiwa na akaunti za wasifu zilizowekewa vikwazo"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Hakuna programu iliyopatikana ili kushughulikia kitendo hiki"</string>
     <string name="revoke" msgid="5404479185228271586">"Batilisha"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 8d730a5..60c22ea 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"อนุญาตให้ผู้ใช้เชื่อมโยงกับส่วนติดต่อผู้ใช้ระดับสูงสุดของวิธีการป้อนข้อมูล ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"เชื่อมโยงกับบริการการเข้าถึง"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"อนุญาตให้เจ้าของเชื่อมโยงกับส่วนติดต่อระดับบนสุดของบริการการเข้าถึง ซึ่งแอปพลิเคชันทั่วไปไม่จำเป็นต้องใช้"</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"เชื่อมโยงกับบริการข้อความ"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"อนุญาตให้ผู้ใช้เชื่อมโยงกับส่วนติดต่อผู้ใช้ระดับสูงสุดของบริการข้อความ (เช่น บริการเครื่องตรวจตัวสะกด) ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"เชื่อมโยงกับบริการ VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"แอปนี้ไม่สนับสนุนบัญชีที่โปรไฟล์ถูกจำกัด"</string>
     <string name="app_not_found" msgid="3429141853498927379">"ไม่พบแอปพลิเคชันสำหรับการทำงานนี้"</string>
     <string name="revoke" msgid="5404479185228271586">"เพิกถอน"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index ac771173..e1dfbad 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Pinapayagan ang may-hawak na sumailalim sa nangungunang interface ng pamamaraan ng pag-input. Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"sumailalim sa isang serbisyo sa accessibility"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Binibigyang-daan ang may-ari na sumailalim sa nasa nangungunang antas na interface ng isang serbisyo sa accessibility. Hindi dapat kailanman kailanganin para sa normal na apps."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"sumailalim sa serbisyo ng teksto"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Pinapayagan ang may-hawak na sumailalim sa nangungunang antas na interface (hal. SpellCheckerService). Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"sumailalim sa isang serbisyo ng VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Hindi sinusuportahan ng app na ito ang mga account para sa mga pinaghihigpitang profile"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Walang nakitang application na mangangasiwa sa pagkilos na ito"</string>
     <string name="revoke" msgid="5404479185228271586">"Bawiin"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 0e7710d..419d1ca 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Cihazın sahibine, bir giriş yönteminin en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"erişilebilirlik hizmetine bağlan"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"İzin sahibine bir erişilebilirlik hizmetinin en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"kısa mesaj hizmetine bağla"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Cihazın sahibine, bir metin hizmetinin (ör. SpellCheckerService) en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerekmez."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"VPN hizmetine bağlan"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Bu uygulama, kısıtlanmış profillerin hesaplarını desteklemez"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Bu eylemi gerçekleştirecek bir uygulama bulunamadı"</string>
     <string name="revoke" msgid="5404479185228271586">"İptal et"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index d3e8b2e..047e288 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Дозволяє власнику прив’язуватися до інтерфейсу верхнього рівня методу введення. Ніколи не застосовується для звичайних програм."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"прив’язуватися до служби доступності"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня служби доступності. Ніколи не застосовується для звичайних програм."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"прив’язати до текстової служби"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня текстової служби (напр. SpellCheckerService). Ніколи не застосовується для звичайних програм."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"прив’язуватися до служби VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ця програма не підтримує облікові записи для обмежених профілів"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Не знайдено програму для обробки цієї дії"</string>
     <string name="revoke" msgid="5404479185228271586">"Анулювати"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 871a244e..4f1f931 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của phương thức nhập. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"liên kết với dịch vụ truy cập"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ truy cập. Không cần thiết cho các ứng dụng thông thường."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"liên kết với dịch vụ văn bản"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ văn bản (ví dụ: SpellCheckerService). Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"liên kết với dịch vụ VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ứng dụng này không hỗ trợ tài khoản đối với các tiểu sử bị hạn chế"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Không tìm thấy ứng dụng nào để xử lý tác vụ này"</string>
     <string name="revoke" msgid="5404479185228271586">"Thu hồi"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index c04017a..685e43f 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"允许用户绑定至输入法的顶级接口。普通应用绝不需要此权限。"</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"绑定至辅助服务"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"允许应用绑定至辅助服务的顶级接口。普通应用绝不需要此权限。"</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"绑定至文字服务"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"允许用户绑定至文字服务(如 SpellCheckerService)的顶级接口。普通应用绝不需要此权限。"</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"绑定到 VPN 服务"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"此应用不支持受限个人资料的帐户"</string>
     <string name="app_not_found" msgid="3429141853498927379">"找不到可处理此操作的应用"</string>
     <string name="revoke" msgid="5404479185228271586">"撤消"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index a7df755..50af84b 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"允許應用程式繫結至輸入法的頂層介面 (一般應用程式不需使用)。"</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"繫結至協助工具服務"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"允許應用程式繫結至協助工具服務的頂層介面 (一般應用程式不需使用)。"</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"繫結至文字服務"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"允許應用程式繫結至文字服務 (例如 SpellCheckerService) 的頂層介面 (一般應用程式不需使用)。"</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"繫結至 VPN 服務"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"這個應用程式不支援設有限制的個人資料所屬帳戶"</string>
     <string name="app_not_found" msgid="3429141853498927379">"找不到支援此操作的應用程式"</string>
     <string name="revoke" msgid="5404479185228271586">"撤銷"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 6d3e3ad..127743e 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -356,6 +356,14 @@
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Ivumela isimeli ukuhlanganisa uxhumano nomsebenzisi wezinga eliphezulu lendlela yokufaka. Ayisoze yadingeka kwizinhlelo ezivamile."</string>
     <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"hlanganisa kusevisi yokufinyeleleka"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Ivumela isibambi ukuhlanganisa uxhumo nomsebenzisi kwezinga eliphezulu lesevisi yesinqunjwana. Akusoze kwadingekela izinhlelo zokusebenza ezivamile."</string>
+    <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+    <skip />
+    <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+    <skip />
+    <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+    <skip />
+    <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+    <skip />
     <string name="permlab_bindTextService" msgid="7358378401915287938">"bophezela kunsizakalo yombhalo"</string>
     <string name="permdesc_bindTextService" msgid="8151968910973998670">"Ivumela umbambi ukuhlanganisa uxhumano nomsebenzisi kwezinga eliphezulu lwesixhumi esibonakalayo sensizakalo yombhalo(isb. InsizakaloYokuhlolaUkubhala). Akusoze kwadingeka kwezinhlelo zokusebenza ezivamile."</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"hlanganisa kwinsizakalo ye-VPN"</string>
@@ -1502,4 +1510,82 @@
     <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Lolu hlelo lokusebenza alusekeli ama-akhawunti wamaphrofayela akhawulelwe"</string>
     <string name="app_not_found" msgid="3429141853498927379">"Alukho uhlelo lokusebenza olutholakele lokuphatha lesi senzo"</string>
     <string name="revoke" msgid="5404479185228271586">"Chitha"</string>
+    <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+    <skip />
+    <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+    <skip />
+    <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4bd1c9b..d844076 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -123,6 +123,17 @@
          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
+         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. -->
+    <bool name="config_avoidGfxAccel">false</bool>
+
     <!-- The duration (in milliseconds) that the radio will scan for a signal
          when there's no network connection. If the scan doesn't timeout, use zero -->
     <integer name="config_radioScanningTimeout">0</integer>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 1938b88..75ff8b2 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -712,6 +712,15 @@
         tasks and kill their apps. Malicious apps may disrupt
         the behavior of other apps.</string>
 
+    <!-- [CHAR LIMIT=NONE] Title of an application permission, allowing an application to create,
+         change, remove activity stacks. -->
+    <string name="permlab_manageActivityStacks">manage activity stacks</string>
+    <!-- [CHAR LIMIT=NONE] Description of an application permission, allowing an application to create,
+             change, remove activity stacks. -->
+    <string name="permdesc_manageActivityStacks">Allows the app to add, remove, and
+        modify the activity stacks in which other apps run.  Malicious apps may disrupt
+        the behavior of other apps.</string>
+
     <!-- Title of an application permission, allowing an application to start any activity, regardless of permission protection or exported state. -->
     <string name="permlab_startAnyActivity">start any activity</string>
     <!-- Description of an application permission, allowing an application to start any activity, regardless of permission protection or exported state. -->
@@ -4018,7 +4027,7 @@
     <!-- Message shown when user enters wrong PIN -->
     <string name="kg_wrong_pin">Wrong PIN</string>
     <!-- Countdown message shown after too many failed unlock attempts -->
-    <string name="kg_too_many_failed_attempts_countdown">Try again in <xliff:g id="number">%d</xliff:g> seconds.</string>
+    <string name="kg_too_many_failed_attempts_countdown">Try again in <xliff:g id="number">%1$d</xliff:g> seconds.</string>
     <!-- Instructions for using the pattern unlock screen -->
     <string name="kg_pattern_instructions">Draw your pattern</string>
     <!-- Instructions for using the SIM PIN unlock screen -->
@@ -4227,4 +4236,20 @@
     <!-- North America Tabloid media size: 11" × 17" -->
     <string name="mediaSize_na_tabloid">Tabloid</string>
 
+    <!-- PIN creation dialog message [CHAR LIMIT=none] -->
+    <string name="restr_pin_create_pin">Create a PIN for modifying restrictions</string>
+    <!-- PIN entry dialog label for PIN [CHAR LIMIT=none] -->
+    <string name="restr_pin_enter_pin">Enter PIN</string>
+    <!-- PIN entry dialog label for PIN confirmation [CHAR LIMIT=none] -->
+    <string name="restr_pin_confirm_pin">Confirm PIN</string>
+    <!-- PIN entry dialog error when PINs are not the same [CHAR LIMIT=none] -->
+    <string name="restr_pin_error_doesnt_match">PINs don\'t match. Try again.</string>
+    <!-- PIN entry dialog error when PIN is too short [CHAR LIMIT=none] -->
+    <string name="restr_pin_error_too_short">PIN is too short. Must be at least 4 digits.</string>
+    <!-- PIN entry dialog countdown message for next chance to enter the PIN [CHAR LIMIT=none] -->
+    <!-- Phrase describing a time duration using seconds [CHAR LIMIT=16] -->
+    <plurals name="restr_pin_countdown">
+        <item quantity="one">Incorrect PIN. Try again in 1 second.</item>
+        <item quantity="other">Incorrect PIN. Try again in <xliff:g id="count">%d</xliff:g> seconds.</item>
+    </plurals>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7f39364..38aa2a0 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -213,6 +213,10 @@
   <java-symbol type="id" name="sms_short_code_remember_undo_instruction" />
   <java-symbol type="id" name="breadcrumb_section" />
   <java-symbol type="id" name="action_bar_spinner" />
+  <java-symbol type="id" name="pin_message" />
+  <java-symbol type="id" name="pin1_text" />
+  <java-symbol type="id" name="pin2_text" />
+  <java-symbol type="id" name="pin_error_message" />
 
   <java-symbol type="attr" name="actionModeShareDrawable" />
   <java-symbol type="attr" name="alertDialogCenterButtons" />
@@ -239,6 +243,7 @@
   <java-symbol type="bool" name="action_bar_embed_tabs" />
   <java-symbol type="bool" name="action_bar_embed_tabs_pre_jb" />
   <java-symbol type="bool" name="action_bar_expanded_action_views_exclusive" />
+  <java-symbol type="bool" name="config_avoidGfxAccel" />
   <java-symbol type="bool" name="config_allowActionMenuItemTextWithIcon" />
   <java-symbol type="bool" name="config_bluetooth_address_validation" />
   <java-symbol type="bool" name="config_bluetooth_sco_off_call" />
@@ -246,6 +251,7 @@
   <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" />
@@ -898,6 +904,7 @@
   <java-symbol type="string" name="mediaSize_na_junior_legal" />
   <java-symbol type="string" name="mediaSize_na_ledger" />
   <java-symbol type="string" name="mediaSize_na_tabloid" />
+  <java-symbol type="string" name="restr_pin_enter_pin" />
 
   <java-symbol type="plurals" name="abbrev_in_num_days" />
   <java-symbol type="plurals" name="abbrev_in_num_hours" />
@@ -920,6 +927,7 @@
   <java-symbol type="plurals" name="num_hours_ago" />
   <java-symbol type="plurals" name="num_minutes_ago" />
   <java-symbol type="plurals" name="num_seconds_ago" />
+  <java-symbol type="plurals" name="restr_pin_countdown" />
 
   <java-symbol type="array" name="carrier_properties" />
   <java-symbol type="array" name="config_data_usage_network_types" />
@@ -1145,6 +1153,7 @@
   <java-symbol type="layout" name="sms_short_code_confirmation_dialog" />
   <java-symbol type="layout" name="action_bar_up_container" />
   <java-symbol type="layout" name="app_not_authorized" />
+  <java-symbol type="layout" name="pin_challenge" />
 
   <java-symbol type="anim" name="slide_in_child_bottom" />
   <java-symbol type="anim" name="slide_in_right" />
diff --git a/docs/html/training/location/activity-recognition.jd b/docs/html/training/location/activity-recognition.jd
index 79804db..47ba5f8 100644
--- a/docs/html/training/location/activity-recognition.jd
+++ b/docs/html/training/location/activity-recognition.jd
@@ -171,11 +171,9 @@
             return true;
         // Google Play services was not available for some reason
         } else {
-            // Get the error code
-            int errorCode = connectionResult.getErrorCode();
             // Get the error dialog from Google Play services
             Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
-                    errorCode,
+                    resultCode,
                     this,
                     CONNECTION_FAILURE_RESOLUTION_REQUEST);
 
@@ -649,7 +647,7 @@
 public class MainActivity extends FragmentActivity implements
         ConnectionCallbacks, OnConnectionFailedListener {
     ...
-    public enum REQUEST_TYPE = {START, STOP}
+    public enum REQUEST_TYPE {START, STOP}
     private REQUEST_TYPE mRequestType;
     ...
 }
@@ -664,7 +662,7 @@
     ...
     public void startUpdates() {
         // Set the request type to START
-        mRequestType = START;
+        mRequestType = REQUEST_TYPE.START;
         /*
          * Test for Google Play services after setting the request type.
          * If Google Play services isn't present, the proper request type
@@ -686,9 +684,16 @@
                  */
                 mActivityRecognitionClient.requestActivityUpdates(
                         DETECTION_INTERVAL_MILLISECONDS,
-                        mActivityRecognitionPendingIntent());
+                        mActivityRecognitionPendingIntent);
                 break;
-            ...
+                ...
+                /*
+                 * An enum was added to the definition of REQUEST_TYPE,
+                 * but it doesn't match a known case. Throw an exception.
+                 */
+                default :
+                throw new Exception("Unknown request type in onConnected().");
+                break;
         }
         ...
     }
@@ -712,7 +717,7 @@
      */
     public void stopUpdates() {
         // Set the request type to STOP
-        mRequestType = STOP;
+        mRequestType = REQUEST_TYPE.STOP;
         /*
          * Test for Google Play services after setting the request type.
          * If Google Play services isn't present, the request can be
@@ -760,7 +765,7 @@
             mActivityRecognitionClient.removeActivityUpdates(
                     mActivityRecognitionPendingIntent);
             break;
-
+            ...
         }
         ...
     }
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index bd871c4..14ac901 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -61,6 +61,7 @@
     protected int mScreenDensity = Bitmap.DENSITY_NONE;
     
     // Used by native code
+    @SuppressWarnings("UnusedDeclaration")
     private int mSurfaceFormat;
 
     /**
@@ -381,8 +382,8 @@
      */
     public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
         return native_saveLayer(mNativeCanvas, bounds,
-                                paint != null ? paint.mNativePaint : 0,
-                                saveFlags);
+                paint != null ? paint.mNativePaint : 0,
+                saveFlags);
     }
     
     /**
@@ -391,8 +392,8 @@
     public int saveLayer(float left, float top, float right, float bottom, Paint paint,
             int saveFlags) {
         return native_saveLayer(mNativeCanvas, left, top, right, bottom,
-                                paint != null ? paint.mNativePaint : 0,
-                                saveFlags);
+                paint != null ? paint.mNativePaint : 0,
+                saveFlags);
     }
 
     /**
@@ -1039,7 +1040,7 @@
             throw new NullPointerException();
         }
         native_drawArc(mNativeCanvas, oval, startAngle, sweepAngle,
-                       useCenter, paint.mNativePaint);
+                useCenter, paint.mNativePaint);
     }
 
     /**
@@ -1079,8 +1080,6 @@
     /**
      * Draws the specified bitmap as an N-patch (most often, a 9-patches.)
      *
-     * Note: Only supported by hardware accelerated canvas at the moment.
-     *
      * @param patch The ninepatch object to render
      * @param dst The destination rectangle.
      * @param paint The paint to draw the bitmap with. may be null
@@ -1088,13 +1087,12 @@
      * @hide
      */
     public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
+        patch.drawSoftware(this, dst, paint);
     }
 
     /**
      * Draws the specified bitmap as an N-patch (most often, a 9-patches.)
      *
-     * Note: Only supported by hardware accelerated canvas at the moment.
-     *
      * @param patch The ninepatch object to render
      * @param dst The destination rectangle.
      * @param paint The paint to draw the bitmap with. may be null
@@ -1102,6 +1100,7 @@
      * @hide
      */
     public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
+        patch.drawSoftware(this, dst, paint);
     }
 
     /**
@@ -1188,7 +1187,7 @@
         }
         throwIfRecycled(bitmap);
         native_drawBitmap(mNativeCanvas, bitmap.ni(), src, dst,
-                          paint != null ? paint.mNativePaint : 0, mScreenDensity, bitmap.mDensity);
+                paint != null ? paint.mNativePaint : 0, mScreenDensity, bitmap.mDensity);
     }
     
     /**
@@ -1309,8 +1308,8 @@
             checkRange(colors.length, colorOffset, count);
         }
         nativeDrawBitmapMesh(mNativeCanvas, bitmap.ni(), meshWidth, meshHeight,
-                             verts, vertOffset, colors, colorOffset,
-                             paint != null ? paint.mNativePaint : 0);
+                verts, vertOffset, colors, colorOffset,
+                paint != null ? paint.mNativePaint : 0);
     }
 
     public enum VertexMode {
@@ -1372,8 +1371,8 @@
             checkRange(indices.length, indexOffset, indexCount);
         }
         nativeDrawVertices(mNativeCanvas, mode.nativeInt, vertexCount, verts,
-                           vertOffset, texs, texOffset, colors, colorOffset,
-                          indices, indexOffset, indexCount, paint.mNativePaint);
+                vertOffset, texs, texOffset, colors, colorOffset,
+                indices, indexOffset, indexCount, paint.mNativePaint);
     }
     
     /**
@@ -1444,10 +1443,10 @@
         if (text instanceof String || text instanceof SpannedString ||
             text instanceof SpannableString) {
             native_drawText(mNativeCanvas, text.toString(), start, end, x, y,
-                            paint.mBidiFlags, paint.mNativePaint);
+                    paint.mBidiFlags, paint.mNativePaint);
         } else if (text instanceof GraphicsOperations) {
             ((GraphicsOperations) text).drawText(this, start, end, x, y,
-                                                     paint);
+                    paint);
         } else {
             char[] buf = TemporaryBuffer.obtain(end - start);
             TextUtils.getChars(text, start, end, buf, 0);
@@ -1568,7 +1567,7 @@
             throw new IndexOutOfBoundsException();
         }
         native_drawPosText(mNativeCanvas, text, index, count, pos,
-                           paint.mNativePaint);
+                paint.mNativePaint);
     }
 
     /**
@@ -1609,8 +1608,8 @@
             throw new ArrayIndexOutOfBoundsException();
         }
         native_drawTextOnPath(mNativeCanvas, text, index, count,
-                              path.ni(), hOffset, vOffset,
-                              paint.mBidiFlags, paint.mNativePaint);
+                path.ni(), hOffset, vOffset,
+                paint.mBidiFlags, paint.mNativePaint);
     }
 
     /**
diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java
index 932e474..528d9de 100644
--- a/graphics/java/android/graphics/NinePatch.java
+++ b/graphics/java/android/graphics/NinePatch.java
@@ -18,11 +18,8 @@
 
 
 /**
- * The NinePatch class permits drawing a bitmap in nine sections.
- * The four corners are unscaled; the four edges are scaled in one axis,
- * and the middle is scaled in both axes. Normally, the middle is 
- * transparent so that the patch can provide a selection about a rectangle.
- * Essentially, it allows the creation of custom graphics that will scale the 
+ * The NinePatch class permits drawing a bitmap in nine or more sections.
+ * Essentially, it allows the creation of custom graphics that will scale the
  * way that you define, when content added within the image exceeds the normal
  * bounds of the graphic. For a thorough explanation of a NinePatch image, 
  * read the discussion in the 
@@ -36,19 +33,23 @@
  */
 public class NinePatch {
     private final Bitmap mBitmap;
+
     /**
+     * Used by native code. This pointer is an instance of Res_png_9patch*.
+     *
      * @hide
      */
-    public final byte[] mChunk;
+    public final int mNativeChunk;
+
     private Paint mPaint;
-    private String mSrcName;  // Useful for debugging
+    private String mSrcName;
 
     /**
      * Create a drawable projection from a bitmap to nine patches.
      *
-     * @param bitmap    The bitmap describing the patches.
-     * @param chunk     The 9-patch data chunk describing how the underlying
-     *                  bitmap is split apart and drawn.
+     * @param bitmap The bitmap describing the patches.
+     * @param chunk The 9-patch data chunk describing how the underlying bitmap
+     *              is split apart and drawn.
      */
     public NinePatch(Bitmap bitmap, byte[] chunk) {
         this(bitmap, chunk, null);
@@ -57,16 +58,15 @@
     /** 
      * Create a drawable projection from a bitmap to nine patches.
      *
-     * @param bitmap    The bitmap describing the patches.
-     * @param chunk     The 9-patch data chunk describing how the underlying
-     *                  bitmap is split apart and drawn.
-     * @param srcName   The name of the source for the bitmap. Might be null.
+     * @param bitmap The bitmap describing the patches.
+     * @param chunk The 9-patch data chunk describing how the underlying
+     *              bitmap is split apart and drawn.
+     * @param srcName The name of the source for the bitmap. Might be null.
      */
     public NinePatch(Bitmap bitmap, byte[] chunk, String srcName) {
         mBitmap = bitmap;
-        mChunk = chunk;
         mSrcName = srcName;
-        validateNinePatchChunk(mBitmap.ni(), chunk);
+        mNativeChunk = validateNinePatchChunk(mBitmap.ni(), chunk);
     }
 
     /**
@@ -74,74 +74,103 @@
      */
     public NinePatch(NinePatch patch) {
         mBitmap = patch.mBitmap;
-        mChunk = patch.mChunk;
         mSrcName = patch.mSrcName;
         if (patch.mPaint != null) {
             mPaint = new Paint(patch.mPaint);
         }
-        validateNinePatchChunk(mBitmap.ni(), mChunk);
+        // No need to validate the 9patch chunk again, it was done by
+        // the instance we're copying from
+        mNativeChunk = patch.mNativeChunk;
     }
 
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            nativeFinalize(mNativeChunk);
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * Returns the name of this NinePatch object if one was specified
+     * when calling the constructor.
+     */
+    public String getName() {
+        return mSrcName;
+    }
+
+    /**
+     * Returns the paint used to draw this NinePatch. The paint can be null.
+     *
+     * @see #setPaint(Paint)
+     * @see #draw(Canvas, Rect)
+     * @see #draw(Canvas, RectF)
+     */
+    public Paint getPaint() {
+        return mPaint;
+    }
+
+    /**
+     * Sets the paint to use when drawing the NinePatch.
+     *
+     * @param p The paint that will be used to draw this NinePatch.
+     *
+     * @see #getPaint()
+     * @see #draw(Canvas, Rect)
+     * @see #draw(Canvas, RectF)
+     */
     public void setPaint(Paint p) {
         mPaint = p;
     }
 
     /**
-     * @hide
+     * Returns the bitmap used to draw this NinePatch.
      */
     public Bitmap getBitmap() {
         return mBitmap;
     }
     
     /** 
-     * Draw a bitmap of nine patches.
+     * Draws the NinePatch. This method will use the paint returned by {@link #getPaint()}.
      *
-     * @param canvas    A container for the current matrix and clip used to draw the bitmap.
-     * @param location  Where to draw the bitmap.
+     * @param canvas A container for the current matrix and clip used to draw the NinePatch.
+     * @param location Where to draw the NinePatch.
      */
     public void draw(Canvas canvas, RectF location) {
-        if (canvas.isHardwareAccelerated()) {
-            canvas.drawPatch(this, location, mPaint);
-        } else {
-            nativeDraw(canvas.mNativeCanvas, location,
-                       mBitmap.ni(), mChunk,
-                       mPaint != null ? mPaint.mNativePaint : 0,
-                       canvas.mDensity, mBitmap.mDensity);
-        }
-    }
-    
-    /** 
-     * Draw a bitmap of nine patches.
-     *
-     * @param canvas    A container for the current matrix and clip used to draw the bitmap.
-     * @param location  Where to draw the bitmap.
-     */
-    public void draw(Canvas canvas, Rect location) {
-        if (canvas.isHardwareAccelerated()) {
-            canvas.drawPatch(this, location, mPaint);
-        } else {
-            nativeDraw(canvas.mNativeCanvas, location,
-                        mBitmap.ni(), mChunk,
-                        mPaint != null ? mPaint.mNativePaint : 0,
-                        canvas.mDensity, mBitmap.mDensity);
-        }
+        canvas.drawPatch(this, location, mPaint);
     }
 
     /** 
-     * Draw a bitmap of nine patches.
+     * Draws the NinePatch. This method will use the paint returned by {@link #getPaint()}.
      *
-     * @param canvas    A container for the current matrix and clip used to draw the bitmap.
-     * @param location  Where to draw the bitmap.
-     * @param paint     The Paint to draw through.
+     * @param canvas A container for the current matrix and clip used to draw the NinePatch.
+     * @param location Where to draw the NinePatch.
+     */
+    public void draw(Canvas canvas, Rect location) {
+        canvas.drawPatch(this, location, mPaint);
+    }
+
+    /** 
+     * Draws the NinePatch. This method will ignore the paint returned
+     * by {@link #getPaint()} and use the specified paint instead.
+     *
+     * @param canvas A container for the current matrix and clip used to draw the NinePatch.
+     * @param location Where to draw the NinePatch.
+     * @param paint The Paint to draw through.
      */
     public void draw(Canvas canvas, Rect location, Paint paint) {
-        if (canvas.isHardwareAccelerated()) {
-            canvas.drawPatch(this, location, paint);
-        } else {
-            nativeDraw(canvas.mNativeCanvas, location,
-                    mBitmap.ni(), mChunk, paint != null ? paint.mNativePaint : 0,
-                    canvas.mDensity, mBitmap.mDensity);
-        }
+        canvas.drawPatch(this, location, paint);
+    }
+
+    void drawSoftware(Canvas canvas, RectF location, Paint paint) {
+        nativeDraw(canvas.mNativeCanvas, location, mBitmap.ni(), mNativeChunk,
+                paint != null ? paint.mNativePaint : 0, canvas.mDensity, mBitmap.mDensity);
+    }
+
+    void drawSoftware(Canvas canvas, Rect location, Paint paint) {
+        nativeDraw(canvas.mNativeCanvas, location, mBitmap.ni(), mNativeChunk,
+                paint != null ? paint.mNativePaint : 0, canvas.mDensity, mBitmap.mDensity);
     }
 
     /**
@@ -151,32 +180,67 @@
     public int getDensity() {
         return mBitmap.mDensity;
     }
-    
+
+    /**
+     * Returns the intrinsic width, in pixels, of this NinePatch. This is equivalent
+     * to querying the width of the underlying bitmap returned by {@link #getBitmap()}.
+     */
     public int getWidth() {
         return mBitmap.getWidth();
     }
 
+    /**
+     * Returns the intrinsic height, in pixels, of this NinePatch. This is equivalent
+     * to querying the height of the underlying bitmap returned by {@link #getBitmap()}.
+     */
     public int getHeight() {
         return mBitmap.getHeight();
     }
 
+    /**
+     * Indicates whether this NinePatch contains transparent or translucent pixels.
+     * This is equivalent to calling <code>getBitmap().hasAlpha()</code> on this
+     * NinePatch.
+     */
     public final boolean hasAlpha() {
         return mBitmap.hasAlpha();
     }
 
-    public final Region getTransparentRegion(Rect location) {
-        int r = nativeGetTransparentRegion(mBitmap.ni(), mChunk, location);
+    /**
+     * Returns a {@link Region} representing the parts of the NinePatch that are
+     * completely transparent.
+     *
+     * @param bounds The location and size of the NinePatch.
+     *
+     * @return null if the NinePatch has no transparent region to
+     * report, else a {@link Region} holding the parts of the specified bounds
+     * that are transparent.
+     */
+    public final Region getTransparentRegion(Rect bounds) {
+        int r = nativeGetTransparentRegion(mBitmap.ni(), mNativeChunk, bounds);
         return r != 0 ? new Region(r) : null;
     }
-    
+
+    /**
+     * Verifies that the specified byte array is a valid 9-patch data chunk.
+     *
+     * @param chunk A byte array representing a 9-patch data chunk.
+     *
+     * @return True if the specified byte array represents a 9-patch data chunk,
+     *         false otherwise.
+     */
     public native static boolean isNinePatchChunk(byte[] chunk);
 
-    private static native void validateNinePatchChunk(int bitmap, byte[] chunk);
+    /**
+     * Validates the 9-patch chunk and throws an exception if the chunk is invalid.
+     * If validation is successful, this method returns a native Res_png_9patch*
+     * object used by the renderers.
+     */
+    private static native int validateNinePatchChunk(int bitmap, byte[] chunk);
+    private static native void nativeFinalize(int chunk);
     private static native void nativeDraw(int canvas_instance, RectF loc, int bitmap_instance,
-                                          byte[] c, int paint_instance_or_null,
-                                          int destDensity, int srcDensity);
+            int c, int paint_instance_or_null, int destDensity, int srcDensity);
     private static native void nativeDraw(int canvas_instance, Rect loc, int bitmap_instance,
-                                          byte[] c, int paint_instance_or_null,
-                                          int destDensity, int srcDensity);
-    private static native int nativeGetTransparentRegion(int bitmap, byte[] chunk, Rect location);
+            int c, int paint_instance_or_null, int destDensity, int srcDensity);
+    private static native int nativeGetTransparentRegion(int bitmap, int chunk, Rect location);
 }
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 1089b7c..6de8c8c 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -286,6 +286,7 @@
 void Caches::clearGarbage() {
     textureCache.clearGarbage();
     pathCache.clearGarbage();
+    patchCache.clearGarbage();
 
     Vector<DisplayList*> displayLists;
     Vector<Layer*> layers;
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 0d4dd1a..cebfd26 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -100,6 +100,10 @@
         caches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i));
     }
 
+    for (size_t i = 0; i < mPatchResources.size(); i++) {
+        caches.resourceCache.decrementRefcountLocked(mPatchResources.itemAt(i));
+    }
+
     for (size_t i = 0; i < mShaders.size(); i++) {
         caches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
         caches.resourceCache.destructorLocked(mShaders.itemAt(i));
@@ -134,6 +138,7 @@
     mBitmapResources.clear();
     mOwnedBitmapResources.clear();
     mFilterResources.clear();
+    mPatchResources.clear();
     mShaders.clear();
     mSourcePaths.clear();
     mPaints.clear();
@@ -201,6 +206,13 @@
         caches.resourceCache.incrementRefcountLocked(resource);
     }
 
+    const Vector<Res_png_9patch*>& patchResources = recorder.getPatchResources();
+    for (size_t i = 0; i < patchResources.size(); i++) {
+        Res_png_9patch* resource = patchResources.itemAt(i);
+        mPatchResources.add(resource);
+        caches.resourceCache.incrementRefcountLocked(resource);
+    }
+
     const Vector<SkiaShader*>& shaders = recorder.getShaders();
     for (size_t i = 0; i < shaders.size(); i++) {
         SkiaShader* resource = shaders.itemAt(i);
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 1417df7..194be9e 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -30,8 +30,11 @@
 #include <utils/SortedVector.h>
 #include <utils/String8.h>
 #include <utils/Vector.h>
+
 #include <cutils/compiler.h>
 
+#include <androidfw/ResourceTypes.h>
+
 #include "utils/LinearAllocator.h"
 
 #include "Debug.h"
@@ -484,6 +487,7 @@
     Vector<SkBitmap*> mBitmapResources;
     Vector<SkBitmap*> mOwnedBitmapResources;
     Vector<SkiaColorFilter*> mFilterResources;
+    Vector<Res_png_9patch*> mPatchResources;
 
     Vector<SkPaint*> mPaints;
     Vector<SkPath*> mPaths;
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 5d23e1d..9113092 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -57,6 +57,10 @@
         mCaches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i));
     }
 
+    for (size_t i = 0; i < mPatchResources.size(); i++) {
+        mCaches.resourceCache.decrementRefcountLocked(mPatchResources.itemAt(i));
+    }
+
     for (size_t i = 0; i < mShaders.size(); i++) {
         mCaches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
     }
@@ -74,6 +78,7 @@
     mBitmapResources.clear();
     mOwnedBitmapResources.clear();
     mFilterResources.clear();
+    mPatchResources.clear();
     mSourcePaths.clear();
 
     mShaders.clear();
@@ -318,6 +323,7 @@
 status_t DisplayListRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
         float left, float top, float right, float bottom, SkPaint* paint) {
     bitmap = refBitmap(bitmap);
+    patch = refPatch(patch);
     paint = refPaint(paint);
 
     addDrawOp(new (alloc()) DrawPatchOp(bitmap, patch, left, top, right, bottom, paint));
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 85d6107..03f50c8 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -156,6 +156,10 @@
         return mFilterResources;
     }
 
+    const Vector<Res_png_9patch*>& getPatchResources() const {
+        return mPatchResources;
+    }
+
     const Vector<SkiaShader*>& getShaders() const {
         return mShaders;
     }
@@ -315,9 +319,16 @@
         return colorFilter;
     }
 
+    inline Res_png_9patch* refPatch(Res_png_9patch* patch) {
+        mPatchResources.add(patch);
+        mCaches.resourceCache.incrementRefcount(patch);
+        return patch;
+    }
+
     Vector<SkBitmap*> mBitmapResources;
     Vector<SkBitmap*> mOwnedBitmapResources;
     Vector<SkiaColorFilter*> mFilterResources;
+    Vector<Res_png_9patch*> mPatchResources;
 
     Vector<SkPaint*> mPaints;
     DefaultKeyedVector<SkPaint*, SkPaint*> mPaintMap;
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 9e3e701..7656f85 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -79,8 +79,8 @@
     uint32_t maxVertices = ((xCount + 1) * (yCount + 1) - emptyQuads) * 4;
     if (maxVertices == 0) return NULL;
 
-    vertices = new TextureVertex[maxVertices];
-    TextureVertex* vertex = vertices;
+    TextureVertex* tempVertices = new TextureVertex[maxVertices];
+    TextureVertex* vertex = tempVertices;
 
     const int32_t* xDivs = patch->xDivs;
     const int32_t* yDivs = patch->yDivs;
@@ -159,6 +159,14 @@
                 width, bitmapWidth, quadCount);
     }
 
+    if (verticesCount == maxVertices) {
+        vertices = tempVertices;
+    } else {
+        vertices = new TextureVertex[verticesCount];
+        memcpy(vertices, tempVertices, verticesCount * sizeof(TextureVertex));
+        delete[] tempVertices;
+    }
+
     return vertices;
 }
 
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index dc69d7f..dc0d98c 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -32,7 +32,7 @@
 
 PatchCache::PatchCache():
         mSize(0), mCache(LruCache<PatchDescription, Patch*>::kUnlimitedCapacity),
-        mMeshBuffer(0), mGenerationId(0) {
+        mMeshBuffer(0), mFreeBlocks(NULL), mGenerationId(0) {
     char property[PROPERTY_VALUE_MAX];
     if (property_get(PROPERTY_PATCH_CACHE_SIZE, property, NULL) > 0) {
         INIT_LOGD("  Setting patch cache size to %skB", property);
@@ -97,14 +97,130 @@
         delete i.value();
     }
     mCache.clear();
+
+    BufferBlock* block = mFreeBlocks;
+    while (block) {
+        BufferBlock* next = block->next;
+        delete block;
+        block = next;
+    }
+    mFreeBlocks = NULL;
+}
+
+void PatchCache::remove(Vector<patch_pair_t>& patchesToRemove, Res_png_9patch* patch) {
+    LruCache<PatchDescription, Patch*>::Iterator i(mCache);
+    while (i.next()) {
+        const PatchDescription& key = i.key();
+        if (key.getPatch() == patch) {
+            patchesToRemove.push(patch_pair_t(&key, i.value()));
+        }
+    }
+}
+
+void PatchCache::removeDeferred(Res_png_9patch* patch) {
+    Mutex::Autolock _l(mLock);
+    mGarbage.push(patch);
+}
+
+void PatchCache::clearGarbage() {
+    Vector<patch_pair_t> patchesToRemove;
+
+    { // scope for the mutex
+        Mutex::Autolock _l(mLock);
+        size_t count = mGarbage.size();
+        for (size_t i = 0; i < count; i++) {
+            remove(patchesToRemove, mGarbage[i]);
+        }
+        mGarbage.clear();
+    }
+
+    // TODO: We could sort patchesToRemove by offset to merge
+    // adjacent free blocks
+    for (size_t i = 0; i < patchesToRemove.size(); i++) {
+        const patch_pair_t& pair = patchesToRemove[i];
+
+        // Add a new free block to the list
+        const Patch* patch = pair.getSecond();
+        BufferBlock* block = new BufferBlock(patch->offset, patch->getSize());
+        block->next = mFreeBlocks;
+        mFreeBlocks = block;
+
+        mSize -= patch->getSize();
+
+        mCache.remove(*pair.getFirst());
+    }
+
+#if DEBUG_PATCHES
+    if (patchesToRemove.size() > 0) {
+        dumpFreeBlocks("Removed garbage");
+    }
+#endif
 }
 
 void PatchCache::createVertexBuffer() {
     glBufferData(GL_ARRAY_BUFFER, mMaxSize, NULL, GL_DYNAMIC_DRAW);
     mSize = 0;
+    mFreeBlocks = new BufferBlock(0, mMaxSize);
     mGenerationId++;
 }
 
+/**
+ * Sets the mesh's offsets and copies its associated vertices into
+ * the mesh buffer (VBO).
+ */
+void PatchCache::setupMesh(Patch* newMesh, TextureVertex* vertices) {
+    // This call ensures the VBO exists and that it is bound
+    init(Caches::getInstance());
+
+    // If we're running out of space, let's clear the entire cache
+    uint32_t size = newMesh->getSize();
+    if (mSize + size > mMaxSize) {
+        clearCache();
+        createVertexBuffer();
+    }
+
+    // Find a block where we can fit the mesh
+    BufferBlock* previous = NULL;
+    BufferBlock* block = mFreeBlocks;
+    while (block) {
+        // The mesh fits
+        if (block->size >= size) {
+            break;
+        }
+        previous = block;
+        block = block->next;
+    }
+
+    // We have enough space left in the buffer, but it's
+    // too fragmented, let's clear the cache
+    if (!block) {
+        clearCache();
+        createVertexBuffer();
+        previous = NULL;
+        block = mFreeBlocks;
+    }
+
+    // Copy the 9patch mesh in the VBO
+    newMesh->offset = (GLintptr) (block->offset);
+    newMesh->textureOffset = newMesh->offset + gMeshTextureOffset;
+    glBufferSubData(GL_ARRAY_BUFFER, newMesh->offset, size, vertices);
+
+    // Remove the block since we've used it entirely
+    if (block->size == size) {
+        if (previous) {
+            previous->next = block->next;
+        } else {
+            mFreeBlocks = block->next;
+        }
+    } else {
+        // Resize the block now that it's occupied
+        block->offset += size;
+        block->size -= size;
+    }
+
+    mSize += size;
+}
+
 const Patch* PatchCache::get(const AssetAtlas::Entry* entry,
         const uint32_t bitmapWidth, const uint32_t bitmapHeight,
         const float pixelWidth, const float pixelHeight, const Res_png_9patch* patch) {
@@ -117,6 +233,7 @@
         TextureVertex* vertices;
 
         if (entry) {
+            // An atlas entry has a UV mapper
             vertices = newMesh->createMesh(bitmapWidth, bitmapHeight,
                     pixelWidth, pixelHeight, entry->uvMapper, patch);
         } else {
@@ -125,24 +242,13 @@
         }
 
         if (vertices) {
-            // This call ensures the VBO exists and that it is bound
-            init(Caches::getInstance());
-
-            // TODO: Simply remove the oldest items until we have enough room
-            // This will require to keep a list of free blocks in the VBO
-            uint32_t size = newMesh->getSize();
-            if (mSize + size > mMaxSize) {
-                clearCache();
-                createVertexBuffer();
-            }
-
-            newMesh->offset = (GLintptr) mSize;
-            newMesh->textureOffset = newMesh->offset + gMeshTextureOffset;
-            mSize += size;
-
-            glBufferSubData(GL_ARRAY_BUFFER, newMesh->offset, size, vertices);
+            setupMesh(newMesh, vertices);
         }
 
+#if DEBUG_PATCHES
+        dumpFreeBlocks("Adding patch");
+#endif
+
         mCache.put(description, newMesh);
         return newMesh;
     }
@@ -150,5 +256,17 @@
     return mesh;
 }
 
+#if DEBUG_PATCHES
+void PatchCache::dumpFreeBlocks(const char* prefix) {
+    String8 dump;
+    BufferBlock* block = mFreeBlocks;
+    while (block) {
+        dump.appendFormat("->(%d, %d)", block->offset, block->size);
+        block = block->next;
+    }
+    ALOGD("%s: Free blocks%s", prefix, dump.string());
+}
+#endif
+
 }; // namespace uirenderer
 }; // namespace android
diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h
index 1829b89..9f2c9a5 100644
--- a/libs/hwui/PatchCache.h
+++ b/libs/hwui/PatchCache.h
@@ -26,6 +26,7 @@
 #include "AssetAtlas.h"
 #include "Debug.h"
 #include "Patch.h"
+#include "utils/Pair.h"
 
 namespace android {
 namespace uirenderer {
@@ -74,10 +75,20 @@
         return mGenerationId;
     }
 
-private:
-    void clearCache();
-    void createVertexBuffer();
+    /**
+     * Removes the entries associated with the specified 9-patch. This is meant
+     * to be called from threads that are not the EGL context thread (GC thread
+     * on the VM side for instance.)
+     */
+    void removeDeferred(Res_png_9patch* patch);
 
+    /**
+     * Process deferred removals.
+     */
+    void clearGarbage();
+
+
+private:
     struct PatchDescription {
         PatchDescription(): mPatch(NULL), mBitmapWidth(0), mBitmapHeight(0),
                 mPixelWidth(0), mPixelHeight(0) {
@@ -91,6 +102,8 @@
 
         hash_t hash() const;
 
+        const Res_png_9patch* getPatch() const { return mPatch; }
+
         static int compare(const PatchDescription& lhs, const PatchDescription& rhs);
 
         bool operator==(const PatchDescription& other) const {
@@ -124,14 +137,50 @@
 
     }; // struct PatchDescription
 
+    /**
+     * A buffer block represents an empty range in the mesh buffer
+     * that can be used to store vertices.
+     *
+     * The patch cache maintains a linked-list of buffer blocks
+     * to track available regions of memory in the VBO.
+     */
+    struct BufferBlock {
+        BufferBlock(uint32_t offset, uint32_t size): offset(offset), size(size), next(NULL) {
+        }
+
+        uint32_t offset;
+        uint32_t size;
+
+        BufferBlock* next;
+    }; // struct BufferBlock
+
+    typedef Pair<const PatchDescription*, Patch*> patch_pair_t;
+
+    void clearCache();
+    void createVertexBuffer();
+
+    void setupMesh(Patch* newMesh, TextureVertex* vertices);
+
+    void remove(Vector<patch_pair_t>& patchesToRemove, Res_png_9patch* patch);
+
+#if DEBUG_PATCHES
+    void dumpFreeBlocks(const char* prefix);
+#endif
+
     uint32_t mMaxSize;
     uint32_t mSize;
 
     LruCache<PatchDescription, Patch*> mCache;
 
     GLuint mMeshBuffer;
+    // First available free block inside the mesh buffer
+    BufferBlock* mFreeBlocks;
 
     uint32_t mGenerationId;
+
+    // Garbage tracking, required to handle GC events on the VM side
+    Vector<Res_png_9patch*> mGarbage;
+    mutable Mutex mLock;
 }; // class PatchCache
 
 }; // namespace uirenderer
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 3ab40da..70ab6e7 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -350,8 +350,7 @@
 // Paths
 ///////////////////////////////////////////////////////////////////////////////
 
-void PathCache::remove(const path_pair_t& pair) {
-    Vector<PathDescription> pathsToRemove;
+void PathCache::remove(Vector<PathDescription>& pathsToRemove, const path_pair_t& pair) {
     LruCache<PathDescription, PathTexture*>::Iterator i(mCache);
 
     while (i.next()) {
@@ -362,10 +361,6 @@
             pathsToRemove.push(key);
         }
     }
-
-    for (size_t i = 0; i < pathsToRemove.size(); i++) {
-        mCache.remove(pathsToRemove.itemAt(i));
-    }
 }
 
 void PathCache::removeDeferred(SkPath* path) {
@@ -374,12 +369,20 @@
 }
 
 void PathCache::clearGarbage() {
-    Mutex::Autolock l(mLock);
-    size_t count = mGarbage.size();
-    for (size_t i = 0; i < count; i++) {
-        remove(mGarbage.itemAt(i));
+    Vector<PathDescription> pathsToRemove;
+
+    { // scope for the mutex
+        Mutex::Autolock l(mLock);
+        size_t count = mGarbage.size();
+        for (size_t i = 0; i < count; i++) {
+            remove(pathsToRemove, mGarbage.itemAt(i));
+        }
+        mGarbage.clear();
     }
-    mGarbage.clear();
+
+    for (size_t i = 0; i < pathsToRemove.size(); i++) {
+        mCache.remove(pathsToRemove.itemAt(i));
+    }
 }
 
 /**
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index a191f0e..16d20a8 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -269,7 +269,7 @@
      * Removes an entry.
      * The pair must define first=path, second=sourcePath
      */
-    void remove(const path_pair_t& pair);
+    void remove(Vector<PathDescription>& pathsToRemove, const path_pair_t& pair);
 
     /**
      * Ensures there is enough space in the cache for a texture of the specified
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 347bd78..58fa21c 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "OpenGLRenderer"
+
 #include <SkPixelRef.h>
 #include "ResourceCache.h"
 #include "Caches.h"
@@ -79,6 +81,10 @@
     incrementRefcount((void*) filterResource, kColorFilter);
 }
 
+void ResourceCache::incrementRefcount(Res_png_9patch* patchResource) {
+    incrementRefcount((void*) patchResource, kNinePatch);
+}
+
 void ResourceCache::incrementRefcount(Layer* layerResource) {
     incrementRefcount((void*) layerResource, kLayer);
 }
@@ -113,6 +119,10 @@
     incrementRefcountLocked((void*) filterResource, kColorFilter);
 }
 
+void ResourceCache::incrementRefcountLocked(Res_png_9patch* patchResource) {
+    incrementRefcountLocked((void*) patchResource, kNinePatch);
+}
+
 void ResourceCache::incrementRefcountLocked(Layer* layerResource) {
     incrementRefcountLocked((void*) layerResource, kLayer);
 }
@@ -142,6 +152,10 @@
     decrementRefcount((void*) filterResource);
 }
 
+void ResourceCache::decrementRefcount(Res_png_9patch* patchResource) {
+    decrementRefcount((void*) patchResource);
+}
+
 void ResourceCache::decrementRefcount(Layer* layerResource) {
     decrementRefcount((void*) layerResource);
 }
@@ -179,6 +193,10 @@
     decrementRefcountLocked((void*) filterResource);
 }
 
+void ResourceCache::decrementRefcountLocked(Res_png_9patch* patchResource) {
+    decrementRefcountLocked((void*) patchResource);
+}
+
 void ResourceCache::decrementRefcountLocked(Layer* layerResource) {
     decrementRefcountLocked((void*) layerResource);
 }
@@ -265,6 +283,30 @@
     }
 }
 
+void ResourceCache::destructor(Res_png_9patch* resource) {
+    Mutex::Autolock _l(mLock);
+    destructorLocked(resource);
+}
+
+void ResourceCache::destructorLocked(Res_png_9patch* resource) {
+    ssize_t index = mCache->indexOfKey(resource);
+    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
+    if (ref == NULL) {
+        if (Caches::hasInstance()) {
+            Caches::getInstance().patchCache.removeDeferred(resource);
+        }
+        // If we're not tracking this resource, just delete it
+        // A Res_png_9patch is actually an array of byte that's larger
+        // than sizeof(Res_png_9patch). It must be freed as an array.
+        delete[] (int8_t*) resource;
+        return;
+    }
+    ref->destroyed = true;
+    if (ref->refCount == 0) {
+        deleteResourceReferenceLocked(resource, ref);
+    }
+}
+
 /**
  * Return value indicates whether resource was actually recycled, which happens when RefCnt
  * reaches 0.
@@ -335,6 +377,16 @@
                 delete filter;
             }
             break;
+            case kNinePatch: {
+                if (Caches::hasInstance()) {
+                    Caches::getInstance().patchCache.removeDeferred((Res_png_9patch*) resource);
+                }
+                // A Res_png_9patch is actually an array of byte that's larger
+                // than sizeof(Res_png_9patch). It must be freed as an array.
+                int8_t* patch = (int8_t*) resource;
+                delete[] patch;
+            }
+            break;
             case kLayer: {
                 Layer* layer = (Layer*) resource;
                 Caches::getInstance().deleteLayerDeferred(layer);
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index ab493e5..ea0c1b5 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -22,7 +22,11 @@
 #include <SkBitmap.h>
 #include <SkiaColorFilter.h>
 #include <SkiaShader.h>
+
 #include <utils/KeyedVector.h>
+
+#include <androidfw/ResourceTypes.h>
+
 #include "Layer.h"
 
 namespace android {
@@ -35,6 +39,7 @@
     kBitmap,
     kShader,
     kColorFilter,
+    kNinePatch,
     kPath,
     kLayer
 };
@@ -69,35 +74,41 @@
     void incrementRefcount(SkBitmap* resource);
     void incrementRefcount(SkiaShader* resource);
     void incrementRefcount(SkiaColorFilter* resource);
+    void incrementRefcount(Res_png_9patch* resource);
     void incrementRefcount(Layer* resource);
 
     void incrementRefcountLocked(SkPath* resource);
     void incrementRefcountLocked(SkBitmap* resource);
     void incrementRefcountLocked(SkiaShader* resource);
     void incrementRefcountLocked(SkiaColorFilter* resource);
+    void incrementRefcountLocked(Res_png_9patch* resource);
     void incrementRefcountLocked(Layer* resource);
 
     void decrementRefcount(SkBitmap* resource);
     void decrementRefcount(SkPath* resource);
     void decrementRefcount(SkiaShader* resource);
     void decrementRefcount(SkiaColorFilter* resource);
+    void decrementRefcount(Res_png_9patch* resource);
     void decrementRefcount(Layer* resource);
 
     void decrementRefcountLocked(SkBitmap* resource);
     void decrementRefcountLocked(SkPath* resource);
     void decrementRefcountLocked(SkiaShader* resource);
     void decrementRefcountLocked(SkiaColorFilter* resource);
+    void decrementRefcountLocked(Res_png_9patch* resource);
     void decrementRefcountLocked(Layer* resource);
 
     void destructor(SkPath* resource);
     void destructor(SkBitmap* resource);
     void destructor(SkiaShader* resource);
     void destructor(SkiaColorFilter* resource);
+    void destructor(Res_png_9patch* resource);
 
     void destructorLocked(SkPath* resource);
     void destructorLocked(SkBitmap* resource);
     void destructorLocked(SkiaShader* resource);
     void destructorLocked(SkiaColorFilter* resource);
+    void destructorLocked(Res_png_9patch* resource);
 
     bool recycle(SkBitmap* resource);
     bool recycleLocked(SkBitmap* resource);
diff --git a/location/lib/java/com/android/location/provider/LocationProviderBase.java b/location/lib/java/com/android/location/provider/LocationProviderBase.java
index 8a5a739..150c289 100644
--- a/location/lib/java/com/android/location/provider/LocationProviderBase.java
+++ b/location/lib/java/com/android/location/provider/LocationProviderBase.java
@@ -35,6 +35,7 @@
 import com.android.internal.location.ILocationProvider;
 import com.android.internal.location.ProviderProperties;
 import com.android.internal.location.ProviderRequest;
+import com.android.internal.util.FastPrintWriter;
 
 /**
  * Base class for location providers implemented as unbundled services.
@@ -106,7 +107,7 @@
         }
         @Override
         public void dump(FileDescriptor fd, String[] args) {
-            PrintWriter pw = new PrintWriter(new FileOutputStream(fd));
+            PrintWriter pw = new FastPrintWriter(new FileOutputStream(fd));
             onDump(fd, pw, args);
             pw.flush();
         }
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 32e5446..3144e8a 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2556,4 +2556,15 @@
         }
     }
 
+    /**
+     * Returns the estimated latency for the given stream type in milliseconds.
+     *
+     * DO NOT UNHIDE. The existing approach for doing A/V sync has too many problems. We need
+     * a better solution.
+     * @hide
+     */
+    public int getOutputLatency(int streamType) {
+        return AudioSystem.getOutputLatency(streamType);
+    }
+
 }
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 4a33743..d42bfd44 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -401,5 +401,6 @@
     // helpers for android.media.AudioManager.getProperty(), see description there for meaning
     public static native int getPrimaryOutputSamplingRate();
     public static native int getPrimaryOutputFrameCount();
+    public static native int getOutputLatency(int stream);
 
 }
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 60eaa92..7322716 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -651,6 +651,18 @@
     }
 
     /**
+     * Returns this track's estimated latency in milliseconds. This includes the latency due
+     * to AudioTrack buffer size, AudioMixer (if any) and audio hardware driver.
+     *
+     * DO NOT UNHIDE. The existing approach for doing A/V sync has too many problems. We need
+     * a better solution.
+     * @hide
+     */
+    public int getLatency() {
+        return native_get_latency();
+    }
+
+    /**
      *  Returns the output sample rate in Hz for the specified stream type.
      */
     static public int getNativeOutputSampleRate(int streamType) {
@@ -1315,6 +1327,8 @@
     private native final int native_set_position(int position);
     private native final int native_get_position();
 
+    private native final int native_get_latency();
+
     private native final int native_set_loop(int start, int end, int loopCount);
 
     static private native final int native_get_output_sample_rate(int streamType);
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index eb94346..f55756c 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -44,7 +44,7 @@
  *
  * @see ImageReader
  */
-public abstract class Image implements AutoCloseable {
+public interface Image extends AutoCloseable {
     /**
      * Get the format for this image. This format determines the number of
      * ByteBuffers needed to represent the image, and the general layout of the
@@ -87,25 +87,19 @@
      *
      * @see android.graphics.ImageFormat
      */
-    public int getFormat() {
-        return ImageFormat.UNKNOWN;
-    }
+    public int getFormat();
 
     /**
      * The width of the image in pixels. For formats where some color channels
      * are subsampled, this is the width of the largest-resolution plane.
      */
-    public int getWidth() {
-        return 0;
-    }
+    public int getWidth();
 
     /**
      * The height of the image in pixels. For formats where some color channels
      * are subsampled, this is the height of the largest-resolution plane.
      */
-    public int getHeight() {
-        return 0;
-    }
+    public int getHeight();
 
     /**
      * Get the timestamp associated with this frame. The timestamp is measured
@@ -113,17 +107,13 @@
      * and whether the timestamp can be compared against other sources of time
      * or images depend on the source of this image.
      */
-    public long getTimestamp() {
-        return 0;
-    }
+    public long getTimestamp();
 
     /**
      * Get the array of pixel planes for this Image. The number of planes is
      * determined by the format of the Image.
      */
-    public Plane[] getPlanes() {
-        return null;
-    }
+    public Plane[] getPlanes();
 
     /**
      * Free up this frame for reuse. After calling this method, calling any
@@ -131,11 +121,7 @@
      * attempting to read from ByteBuffers returned by an earlier
      * {@code Plane#getBuffer} call will have undefined behavior.
      */
-    public abstract void close();
-
-    protected final void finalize() {
-        close();
-    }
+    public void close();
 
     /**
      * <p>A single color plane of image data.</p>
@@ -148,17 +134,14 @@
      *
      * @see #getFormat
      */
-    public static final class Plane {
+    public interface Plane {
         /**
          * <p>The row stride for this color plane, in bytes.
          *
          * <p>This is the distance between the start of two consecutive rows of
          * pixels in the image.</p>
          */
-        public int getRowStride() {
-            return 0;
-        }
-
+        public int getRowStride();
         /**
          * <p>The distance between adjacent pixel samples, in bytes.</p>
          *
@@ -166,19 +149,14 @@
          * of pixels. It may be larger than the size of a single pixel to
          * account for interleaved image data or padded formats.</p>
          */
-        public int getPixelStride() {
-            return 0;
-        }
-
+        public int getPixelStride();
         /**
          * <p>Get a set of direct {@link java.nio.ByteBuffer byte buffers}
          * containing the frame data.</p>
          *
          * @return the byte buffer containing the image data for this plane.
          */
-        public ByteBuffer getBuffer() {
-            return null;
-        }
+        public ByteBuffer getBuffer();
     }
 
 }
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index 9384c14..8f09b54 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -16,8 +16,15 @@
 
 package android.media;
 
+import android.graphics.ImageFormat;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
 import android.view.Surface;
-import java.lang.AutoCloseable;
+
+import java.lang.ref.WeakReference;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 
 /**
  * <p>The ImageReader class allows direct application access to image data
@@ -39,7 +46,7 @@
  * ImageReader does not obtain and release Images at a rate equal to the
  * production rate.</p>
  */
-public final class ImageReader {
+public final class ImageReader implements AutoCloseable {
 
     /**
      * <p>Create a new reader for images of the desired size and format.</p>
@@ -62,7 +69,7 @@
      * access simultaneously. This should be as small as possible to limit
      * memory use. Once maxImages Images are obtained by the user, one of them
      * has to be released before a new Image will become available for access
-     * through getImage(). Must be greater than 0.
+     * through getNextImage(). Must be greater than 0.
      *
      * @see Image
      */
@@ -80,6 +87,12 @@
             throw new IllegalArgumentException(
                 "Maximum outstanding image count must be at least 1");
         }
+
+        mNumPlanes = getNumPlanesFromFormat();
+
+        nativeInit(new WeakReference<ImageReader>(this), width, height, format, maxImages);
+
+        mSurface = nativeGetSurface();
     }
 
     public int getWidth() {
@@ -111,7 +124,7 @@
      * @return A Surface to use for a drawing target for various APIs.
      */
     public Surface getSurface() {
-        return null;
+        return mSurface;
     }
 
     /**
@@ -122,6 +135,13 @@
      * available.
      */
     public Image getNextImage() {
+        SurfaceImage si = new SurfaceImage();
+        if (nativeImageSetup(si)) {
+            // create SurfacePlane objects
+            si.createSurfacePlanes();
+            si.setImageValid(true);
+            return si;
+        }
         return null;
     }
 
@@ -138,34 +158,307 @@
             throw new IllegalArgumentException(
                 "This image was not produced by this ImageReader");
         }
+
+        si.clearSurfacePlanes();
+        nativeReleaseImage(i);
+        si.setImageValid(false);
     }
 
-    public void setOnImageAvailableListener(OnImageAvailableListener l) {
-        mImageListener = l;
+    /**
+     * Register a listener to be invoked when a new image becomes available
+     * from the ImageReader.
+     * @param listener the listener that will be run
+     * @param handler The handler on which the listener should be invoked, or null
+     * if the listener should be invoked on the calling thread's looper.
+     */
+   public void setImageAvailableListener(OnImageAvailableListener listener, Handler handler) {
+        mImageListener = listener;
+
+        Looper looper;
+        mHandler = handler;
+        if (mHandler == null) {
+            if ((looper = Looper.myLooper()) != null) {
+                mHandler = new Handler();
+            } else {
+                throw new IllegalArgumentException(
+                        "Looper doesn't exist in the calling thread");
+            }
+        }
     }
 
+    /**
+     * Callback interface for being notified that a new image is available.
+     * The onImageAvailable is called per image basis, that is, callback fires for every new frame
+     * available from ImageReader.
+     */
     public interface OnImageAvailableListener {
+        /**
+         * Callback that is called when a new image is available from ImageReader.
+         * @param reader the ImageReader the callback is associated with.
+         * @see ImageReader
+         * @see Image
+         */
         void onImageAvailable(ImageReader reader);
     }
 
+    /**
+     * Free up all the resources associated with this ImageReader. After
+     * Calling this method, this ImageReader can not be used. calling
+     * any methods on this ImageReader and Images previously provided by {@link #getNextImage}
+     * will result in an IllegalStateException, and attempting to read from
+     * ByteBuffers returned by an earlier {@code Plane#getBuffer} call will
+     * have undefined behavior.
+     */
+    @Override
+    public void close() {
+        nativeClose();
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            close();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    private int getNumPlanesFromFormat() {
+        switch (mFormat) {
+            case ImageFormat.YV12:
+            case ImageFormat.YUV_420_888:
+            case ImageFormat.NV21:
+                return 3;
+            case ImageFormat.NV16:
+                return 2;
+            case ImageFormat.RGB_565:
+            case ImageFormat.JPEG:
+            case ImageFormat.YUY2:
+            case ImageFormat.Y8:
+            case ImageFormat.Y16:
+            case ImageFormat.RAW_SENSOR:
+                return 1;
+            default:
+                throw new UnsupportedOperationException(
+                        String.format("Invalid format specified %d", mFormat));
+        }
+    }
+
+    /**
+     * Called from Native code when an Event happens.
+     */
+    private static void postEventFromNative(Object selfRef) {
+        WeakReference weakSelf = (WeakReference)selfRef;
+        final ImageReader ir = (ImageReader)weakSelf.get();
+        if (ir == null) {
+            return;
+        }
+
+        if (ir.mHandler != null) {
+            ir.mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    ir.mImageListener.onImageAvailable(ir);
+                }
+              });
+        }
+    }
+
     private final int mWidth;
     private final int mHeight;
     private final int mFormat;
     private final int mMaxImages;
+    private final int mNumPlanes;
+    private final Surface mSurface;
 
+    private Handler mHandler;
     private OnImageAvailableListener mImageListener;
 
-    private class SurfaceImage extends android.media.Image {
+    /**
+     * This field is used by native code, do not access or modify.
+     */
+    private long mNativeContext;
+
+    private class SurfaceImage implements android.media.Image {
         public SurfaceImage() {
+            mIsImageValid = false;
         }
 
         @Override
         public void close() {
-            ImageReader.this.releaseImage(this);
+            if (mIsImageValid) {
+                ImageReader.this.releaseImage(this);
+            }
         }
 
         public ImageReader getReader() {
             return ImageReader.this;
         }
+
+        @Override
+        public int getFormat() {
+            if (mIsImageValid) {
+                return ImageReader.this.mFormat;
+            } else {
+                throw new IllegalStateException("Image is already released");
+            }
+        }
+
+        @Override
+        public int getWidth() {
+            if (mIsImageValid) {
+                return ImageReader.this.mWidth;
+            } else {
+                throw new IllegalStateException("Image is already released");
+            }
+        }
+
+        @Override
+        public int getHeight() {
+            if (mIsImageValid) {
+                return ImageReader.this.mHeight;
+            } else {
+                throw new IllegalStateException("Image is already released");
+            }
+        }
+
+        @Override
+        public long getTimestamp() {
+            if (mIsImageValid) {
+                return mTimestamp;
+            } else {
+                throw new IllegalStateException("Image is already released");
+            }
+        }
+
+        @Override
+        public Plane[] getPlanes() {
+            if (mIsImageValid) {
+                // Shallow copy is fine.
+                return mPlanes.clone();
+            } else {
+                throw new IllegalStateException("Image is already released");
+            }
+        }
+
+        @Override
+        protected final void finalize() throws Throwable {
+            try {
+                close();
+            } finally {
+                super.finalize();
+            }
+        }
+
+        private void setImageValid(boolean isValid) {
+            mIsImageValid = isValid;
+        }
+
+        private boolean isImageValid() {
+            return mIsImageValid;
+        }
+
+        private void clearSurfacePlanes() {
+            if (mIsImageValid) {
+                for (int i = 0; i < mPlanes.length; i++) {
+                    if (mPlanes[i] != null) {
+                        mPlanes[i].clearBuffer();
+                        mPlanes[i] = null;
+                    }
+                }
+            }
+        }
+
+        private void createSurfacePlanes() {
+            mPlanes = new SurfacePlane[ImageReader.this.mNumPlanes];
+            for (int i = 0; i < ImageReader.this.mNumPlanes; i++) {
+                mPlanes[i] = nativeCreatePlane(i);
+            }
+        }
+        private class SurfacePlane implements android.media.Image.Plane {
+            // SurfacePlane instance is created by native code when a new SurfaceImage is created
+            private SurfacePlane(int index, int rowStride, int pixelStride) {
+                mIndex = index;
+                mRowStride = rowStride;
+                mPixelStride = pixelStride;
+            }
+
+            @Override
+            public ByteBuffer getBuffer() {
+                if (SurfaceImage.this.isImageValid() == false) {
+                    throw new IllegalStateException("Image is already released");
+                }
+                if (mBuffer != null) {
+                    return mBuffer;
+                } else {
+                    mBuffer = SurfaceImage.this.nativeImageGetBuffer(mIndex);
+                    // Set the byteBuffer order according to host endianness (native order),
+                    // otherwise, the byteBuffer order defaults to ByteOrder.BIG_ENDIAN.
+                    return mBuffer.order(ByteOrder.nativeOrder());
+                }
+            }
+
+            @Override
+            public int getPixelStride() {
+                if (SurfaceImage.this.isImageValid()) {
+                    return mPixelStride;
+                } else {
+                    throw new IllegalStateException("Image is already released");
+                }
+            }
+
+            @Override
+            public int getRowStride() {
+                if (SurfaceImage.this.isImageValid()) {
+                    return mRowStride;
+                } else {
+                    throw new IllegalStateException("Image is already released");
+                }
+            }
+
+            private void clearBuffer() {
+                mBuffer = null;
+            }
+
+            final private int mIndex;
+            final private int mPixelStride;
+            final private int mRowStride;
+
+            private ByteBuffer mBuffer;
+        }
+
+        /**
+         * This field is used to keep track of native object and used by native code only.
+         * Don't modify.
+         */
+        private long mLockedBuffer;
+
+        /**
+         * This field is set by native code during nativeImageSetup().
+         */
+        private long mTimestamp;
+
+        private SurfacePlane[] mPlanes;
+        private boolean mIsImageValid;
+
+        private synchronized native ByteBuffer nativeImageGetBuffer(int idx);
+        private synchronized native SurfacePlane nativeCreatePlane(int idx);
+    }
+
+    private synchronized native void nativeInit(Object weakSelf, int w, int h,
+                                                    int fmt, int maxImgs);
+    private synchronized native void nativeClose();
+    private synchronized native void nativeReleaseImage(Image i);
+    private synchronized native Surface nativeGetSurface();
+    private synchronized native boolean nativeImageSetup(Image i);
+
+    /*
+     * We use a class initializer to allow the native code to cache some
+     * field offsets.
+     */
+    private static native void nativeClassInit();
+    static {
+        System.loadLibrary("media_jni");
+        nativeClassInit();
     }
 }
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index d703642c..8cf0b4b 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -164,7 +164,8 @@
      *
      * The following is a partial list of defined mime types and their semantics:
      * <ul>
-     * <li>"video/x-vnd.on2.vp8" - VPX video (i.e. video in .webm)
+     * <li>"video/x-vnd.on2.vp8" - VP8 video (i.e. video in .webm)
+     * <li>"video/x-vnd.on2.vp9" - VP9 video (i.e. video in .webm)
      * <li>"video/avc" - H.264/AVC video
      * <li>"video/mp4v-es" - MPEG4 video
      * <li>"video/3gpp" - H.263 video
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 416a2a1..01b3174 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -2,6 +2,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
+    android_media_ImageReader.cpp \
     android_media_MediaCrypto.cpp \
     android_media_MediaCodec.cpp \
     android_media_MediaCodecList.cpp \
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
new file mode 100644
index 0000000..bdb07a6
--- /dev/null
+++ b/media/jni/android_media_ImageReader.cpp
@@ -0,0 +1,747 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ImageReader_JNI"
+#include <utils/Log.h>
+#include <utils/misc.h>
+#include <utils/List.h>
+
+#include <cstdio>
+
+#include <gui/CpuConsumer.h>
+#include <gui/Surface.h>
+
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_view_Surface.h>
+
+#include <jni.h>
+#include <JNIHelp.h>
+
+#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
+
+#define ANDROID_MEDIA_IMAGEREADER_JNI_ID           "mCpuConsumer"
+#define ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID       "mNativeContext"
+#define ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID   "mLockedBuffer"
+#define ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID       "mTimestamp"
+
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+enum {
+    IMAGE_READER_MAX_NUM_PLANES = 3,
+};
+
+struct fields_t {
+    // For ImageReader class
+    jfieldID  imageReaderContext;
+    jmethodID postEvent;
+    // For SurfaceImage class
+    jfieldID  buffer;
+    jfieldID  timeStamp;
+};
+
+struct classInfo_t {
+    jclass clazz;
+    jmethodID ctor;
+};
+
+static fields_t    fields;
+static classInfo_t surfPlaneClassInfo;
+
+// ----------------------------------------------------------------------------
+
+class JNIImageReaderContext : public CpuConsumer::FrameAvailableListener
+{
+public:
+    JNIImageReaderContext(JNIEnv* env, jobject weakThiz, jclass clazz, int maxImages);
+
+    virtual ~JNIImageReaderContext();
+
+    virtual void onFrameAvailable();
+
+    CpuConsumer::LockedBuffer* getLockedBuffer();
+
+    void returnLockedBuffer(CpuConsumer::LockedBuffer* buffer);
+
+    CpuConsumer* getCpuConsumer() { return mConsumer.get(); }
+
+    void setCpuConsumer(sp<CpuConsumer> consumer) { mConsumer = consumer; }
+
+    void setBufferFormat(int format) { mFormat = format; }
+    int getBufferFormat() { return mFormat; }
+
+    void setBufferWidth(int width) { mWidth = width; }
+    int getBufferWidth() { return mWidth; }
+
+    void setBufferHeight(int height) { mHeight = height; }
+    int getBufferHeight() { return mHeight; }
+
+private:
+    static JNIEnv* getJNIEnv(bool* needsDetach);
+    static void detachJNI();
+
+    List<CpuConsumer::LockedBuffer*> mBuffers;
+    sp<CpuConsumer> mConsumer;
+    jobject mWeakThiz;
+    jclass mClazz;
+    int mFormat;
+    int mWidth;
+    int mHeight;
+};
+
+JNIImageReaderContext::JNIImageReaderContext(JNIEnv* env,
+        jobject weakThiz, jclass clazz, int maxImages) :
+    mWeakThiz(env->NewGlobalRef(weakThiz)),
+    mClazz((jclass)env->NewGlobalRef(clazz)) {
+    for (int i = 0; i < maxImages; i++) {
+        CpuConsumer::LockedBuffer *buffer = new CpuConsumer::LockedBuffer;
+        mBuffers.push_back(buffer);
+    }
+}
+
+JNIEnv* JNIImageReaderContext::getJNIEnv(bool* needsDetach) {
+    LOG_ALWAYS_FATAL_IF(needsDetach == NULL, "needsDetach is null!!!");
+    *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;
+}
+
+void JNIImageReaderContext::detachJNI() {
+    JavaVM* vm = AndroidRuntime::getJavaVM();
+    int result = vm->DetachCurrentThread();
+    if (result != JNI_OK) {
+        ALOGE("thread detach failed: %#x", result);
+    }
+}
+
+CpuConsumer::LockedBuffer* JNIImageReaderContext::getLockedBuffer() {
+    if (mBuffers.empty()) {
+        return NULL;
+    }
+    // Return a LockedBuffer pointer and remove it from the list
+    List<CpuConsumer::LockedBuffer*>::iterator it = mBuffers.begin();
+    CpuConsumer::LockedBuffer* buffer = *it;
+    mBuffers.erase(it);
+    return buffer;
+}
+
+void JNIImageReaderContext::returnLockedBuffer(CpuConsumer::LockedBuffer * buffer) {
+    mBuffers.push_back(buffer);
+}
+
+JNIImageReaderContext::~JNIImageReaderContext() {
+    bool needsDetach = false;
+    JNIEnv* env = getJNIEnv(&needsDetach);
+    if (env != NULL) {
+        env->DeleteGlobalRef(mWeakThiz);
+        env->DeleteGlobalRef(mClazz);
+    } else {
+        ALOGW("leaking JNI object references");
+    }
+    if (needsDetach) {
+        detachJNI();
+    }
+
+    // Delete LockedBuffers
+    for (List<CpuConsumer::LockedBuffer *>::iterator it = mBuffers.begin();
+            it != mBuffers.end(); it++) {
+        delete *it;
+    }
+    mBuffers.clear();
+    mConsumer.clear();
+}
+
+void JNIImageReaderContext::onFrameAvailable()
+{
+    ALOGV("%s: frame available", __FUNCTION__);
+    bool needsDetach = false;
+    JNIEnv* env = getJNIEnv(&needsDetach);
+    if (env != NULL) {
+        env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz);
+    } else {
+        ALOGW("onFrameAvailable event will not posted");
+    }
+    if (needsDetach) {
+        detachJNI();
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+extern "C" {
+
+static JNIImageReaderContext* ImageReader_getContext(JNIEnv* env, jobject thiz)
+{
+    JNIImageReaderContext *ctx;
+    ctx = reinterpret_cast<JNIImageReaderContext *>
+              (env->GetLongField(thiz, fields.imageReaderContext));
+    return ctx;
+}
+
+static CpuConsumer* ImageReader_getCpuConsumer(JNIEnv* env, jobject thiz)
+{
+    ALOGV("%s:", __FUNCTION__);
+    JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
+    if (ctx == NULL) {
+        jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
+        return NULL;
+    }
+    return ctx->getCpuConsumer();
+}
+
+static void ImageReader_setNativeContext(JNIEnv* env,
+        jobject thiz, sp<JNIImageReaderContext> ctx)
+{
+    ALOGV("%s:", __FUNCTION__);
+    JNIImageReaderContext* const p = ImageReader_getContext(env, thiz);
+    if (ctx != 0) {
+        ctx->incStrong((void*)ImageReader_setNativeContext);
+    }
+    if (p) {
+        p->decStrong((void*)ImageReader_setNativeContext);
+    }
+    env->SetLongField(thiz, fields.imageReaderContext, reinterpret_cast<jlong>(ctx.get()));
+}
+
+static CpuConsumer::LockedBuffer* Image_getLockedBuffer(JNIEnv* env, jobject image)
+{
+    return reinterpret_cast<CpuConsumer::LockedBuffer*>(env->GetLongField(image, fields.buffer));
+}
+
+static void Image_setBuffer(JNIEnv* env, jobject thiz,
+        const CpuConsumer::LockedBuffer* buffer)
+{
+    env->SetLongField(thiz, fields.buffer, reinterpret_cast<jlong>(buffer));
+}
+
+// Some formats like JPEG defined with different values between android.graphics.ImageFormat and
+// graphics.h, need convert to the one defined in graphics.h here.
+static int Image_getPixelFormat(JNIEnv* env, int format)
+{
+    int jpegFormat, rawSensorFormat;
+    jfieldID fid;
+
+    ALOGV("%s: format = 0x%x", __FUNCTION__, format);
+
+    jclass imageFormatClazz = env->FindClass("android/graphics/ImageFormat");
+    ALOG_ASSERT(imageFormatClazz != NULL);
+
+    fid = env->GetStaticFieldID(imageFormatClazz, "JPEG", "I");
+    jpegFormat = env->GetStaticIntField(imageFormatClazz, fid);
+    fid = env->GetStaticFieldID(imageFormatClazz, "RAW_SENSOR", "I");
+    rawSensorFormat = env->GetStaticIntField(imageFormatClazz, fid);
+
+    // Translate the JPEG to BLOB for camera purpose, an add more if more mismatch is found.
+    if (format == jpegFormat) {
+        format = HAL_PIXEL_FORMAT_BLOB;
+    }
+    // Same thing for RAW_SENSOR format
+    if (format == rawSensorFormat) {
+        format = HAL_PIXEL_FORMAT_RAW_SENSOR;
+    }
+
+    return format;
+}
+
+static void Image_getLockedBufferInfo(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx,
+                                uint8_t **base, uint32_t *size)
+{
+    ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!");
+    ALOG_ASSERT(base != NULL, "base is NULL!!!");
+    ALOG_ASSERT(size != NULL, "size is NULL!!!");
+    ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0));
+
+    ALOGV("%s: buffer: 0x%p", __FUNCTION__, buffer);
+
+    uint32_t dataSize, ySize, cSize, cStride;
+    uint8_t *cb, *cr;
+    uint8_t *pData = NULL;
+
+    dataSize = ySize = cSize = cStride = 0;
+    int32_t fmt = buffer->format;
+    switch (fmt) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_888:
+            pData =
+                (idx == 0) ?
+                    buffer->data :
+                (idx == 1) ?
+                    buffer->dataCb :
+                buffer->dataCr;
+            if (idx == 0) {
+                dataSize = buffer->stride * buffer->height;
+            } else {
+                dataSize = buffer->chromaStride * buffer->height / 2;
+            }
+            break;
+        // NV21
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            cr = buffer->data + (buffer->stride * buffer->height);
+            cb = cr + 1;
+            ySize = buffer->width * buffer->height;
+            cSize = buffer->width * buffer->height / 2;
+
+            pData =
+                (idx == 0) ?
+                    buffer->data :
+                (idx == 1) ?
+                    cb:
+                cr;
+
+            dataSize = (idx == 0) ? ySize : cSize;
+            break;
+        case HAL_PIXEL_FORMAT_YV12:
+            // Y and C stride need to be 16 pixel aligned.
+            LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
+                                "Stride is not 16 pixel aligned %d", buffer->stride);
+
+            ySize = buffer->stride * buffer->height;
+            cStride = ALIGN(buffer->stride / 2, 16);
+            cr = buffer->data + ySize;
+            cSize = cStride * buffer->height / 2;
+            cb = cr + cSize;
+
+            pData =
+                (idx == 0) ?
+                    buffer->data :
+                (idx == 1) ?
+                    cb :
+                cr;
+            dataSize = (idx == 0) ? ySize : cSize;
+            break;
+        case HAL_PIXEL_FORMAT_Y8:
+            // Single plane, 8bpp.
+            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+
+            pData = buffer->data;
+            dataSize = buffer->stride * buffer->height;
+            break;
+        case HAL_PIXEL_FORMAT_Y16:
+            // Single plane, 16bpp, strides are specified in pixels, not in bytes
+            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+
+            pData = buffer->data;
+            dataSize = buffer->stride * buffer->height * 2;
+            break;
+        case HAL_PIXEL_FORMAT_BLOB:
+            // Used for JPEG data, height must be 1, width == size, single plane.
+            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+            ALOG_ASSERT(buffer->height == 1, "JPEG should has height value %d", buffer->height);
+
+            pData = buffer->data;
+            dataSize = buffer->width;
+            break;
+        case HAL_PIXEL_FORMAT_RAW_SENSOR:
+            // Single plane 16bpp bayer data.
+            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+            pData = buffer->data;
+            dataSize = buffer->width * 2 * buffer->height;
+            break;
+        default:
+            jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
+                                 "Pixel format: 0x%x is unsupported", fmt);
+            break;
+    }
+
+    *base = pData;
+    *size = dataSize;
+}
+
+static jint Image_imageGetPixelStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx)
+{
+    ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
+    ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0), "Index is out of range:%d", idx);
+
+    int pixelStride = 0;
+    ALOG_ASSERT(buffer != NULL, "buffer is NULL");
+
+    int32_t fmt = buffer->format;
+    switch (fmt) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_888:
+            pixelStride = (idx == 0) ? 1 : buffer->chromaStep;
+            break;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            pixelStride = (idx == 0) ? 1 : 2;
+            break;
+        case HAL_PIXEL_FORMAT_Y8:
+            // Single plane 8bpp data.
+            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+            pixelStride;
+            break;
+        case HAL_PIXEL_FORMAT_YV12:
+            pixelStride = 1;
+            break;
+        case HAL_PIXEL_FORMAT_BLOB:
+            // Used for JPEG data, single plane, row and pixel strides are 0
+            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+            pixelStride = 0;
+            break;
+        case HAL_PIXEL_FORMAT_Y16:
+        case HAL_PIXEL_FORMAT_RAW_SENSOR:
+            // Single plane 16bpp data.
+            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+            pixelStride = 2;
+            break;
+        default:
+            jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
+                                 "Pixel format: 0x%x is unsupported", fmt);
+            break;
+    }
+
+    return pixelStride;
+}
+
+static jint Image_imageGetRowStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx)
+{
+    ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
+    ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0));
+
+    int rowStride = 0;
+    ALOG_ASSERT(buffer != NULL, "buffer is NULL");
+
+    int32_t fmt = buffer->format;
+
+    switch (fmt) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_888:
+            rowStride = (idx == 0) ? buffer->stride : buffer->chromaStride;
+            break;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            rowStride = buffer->width;
+            break;
+        case HAL_PIXEL_FORMAT_YV12:
+            LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
+                                "Stride is not 16 pixel aligned %d", buffer->stride);
+            rowStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);
+            break;
+        case HAL_PIXEL_FORMAT_BLOB:
+            // Used for JPEG data, single plane, row and pixel strides are 0
+            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+            rowStride = 0;
+            break;
+        case HAL_PIXEL_FORMAT_Y8:
+            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+            LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
+                                "Stride is not 16 pixel aligned %d", buffer->stride);
+            rowStride = buffer->stride;
+            break;
+        case HAL_PIXEL_FORMAT_Y16:
+        case HAL_PIXEL_FORMAT_RAW_SENSOR:
+            // In native side, strides are specified in pixels, not in bytes.
+            // Single plane 16bpp bayer data. even width/height,
+            // row stride multiple of 16 pixels (32 bytes)
+            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+            LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
+                                "Stride is not 16 pixel aligned %d", buffer->stride);
+            rowStride = buffer->stride * 2;
+            break;
+        default:
+            ALOGE("%s Pixel format: 0x%x is unsupported", __FUNCTION__, fmt);
+            jniThrowException(env, "java/lang/UnsupportedOperationException",
+                              "unsupported buffer format");
+          break;
+    }
+
+    return rowStride;
+}
+
+// ----------------------------------------------------------------------------
+
+static void ImageReader_classInit(JNIEnv* env, jclass clazz)
+{
+    ALOGV("%s:", __FUNCTION__);
+
+    jclass imageClazz = env->FindClass("android/media/ImageReader$SurfaceImage");
+    LOG_ALWAYS_FATAL_IF(imageClazz == NULL,
+                        "can't find android/graphics/ImageReader$SurfaceImage");
+    fields.buffer = env->GetFieldID(imageClazz, ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID, "J");
+    LOG_ALWAYS_FATAL_IF(fields.buffer == NULL,
+                        "can't find android/graphics/ImageReader.%s",
+                        ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID);
+
+    fields.timeStamp = env->GetFieldID(imageClazz, ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID, "J");
+    LOG_ALWAYS_FATAL_IF(fields.timeStamp == NULL,
+                        "can't find android/graphics/ImageReader.%s",
+                        ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID);
+
+    fields.imageReaderContext = env->GetFieldID(clazz, ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID, "J");
+    LOG_ALWAYS_FATAL_IF(fields.imageReaderContext == NULL,
+                        "can't find android/graphics/ImageReader.%s",
+                          ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID);
+
+    fields.postEvent = env->GetStaticMethodID(clazz, "postEventFromNative",
+                                              "(Ljava/lang/Object;)V");
+    LOG_ALWAYS_FATAL_IF(fields.postEvent == NULL,
+                        "can't find android/graphics/ImageReader.postEventFromNative");
+
+    jclass planeClazz = env->FindClass("android/media/ImageReader$SurfaceImage$SurfacePlane");
+    LOG_ALWAYS_FATAL_IF(planeClazz == NULL, "Can not find SurfacePlane class");
+    // FindClass only gives a local reference of jclass object.
+    surfPlaneClassInfo.clazz = (jclass) env->NewGlobalRef(planeClazz);
+    surfPlaneClassInfo.ctor = env->GetMethodID(surfPlaneClassInfo.clazz, "<init>",
+                                               "(Landroid/media/ImageReader$SurfaceImage;III)V");
+    LOG_ALWAYS_FATAL_IF(surfPlaneClassInfo.ctor == NULL, "Can not find SurfacePlane constructor");
+}
+
+static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz,
+                             jint width, jint height, jint format, jint maxImages)
+{
+    status_t res;
+    int nativeFormat;
+
+    ALOGV("%s: width:%d, height: %d, format: 0x%x, maxImages:%d",
+          __FUNCTION__, width, height, format, maxImages);
+
+    nativeFormat = Image_getPixelFormat(env, format);
+
+    sp<CpuConsumer> consumer = new CpuConsumer(maxImages);
+    // TODO: throw dvm exOutOfMemoryError?
+    if (consumer == NULL) {
+        jniThrowRuntimeException(env, "Failed to allocate native CpuConsumer");
+        return;
+    }
+
+    jclass clazz = env->GetObjectClass(thiz);
+    if (clazz == NULL) {
+        jniThrowRuntimeException(env, "Can't find android/graphics/ImageReader");
+        return;
+    }
+    sp<JNIImageReaderContext> ctx(new JNIImageReaderContext(env, weakThiz, clazz, maxImages));
+    ctx->setCpuConsumer(consumer);
+    consumer->setFrameAvailableListener(ctx);
+    ImageReader_setNativeContext(env, thiz, ctx);
+    ctx->setBufferFormat(nativeFormat);
+    ctx->setBufferWidth(width);
+    ctx->setBufferHeight(height);
+
+    // Set the width/height/format to the CpuConsumer
+    res = consumer->setDefaultBufferSize(width, height);
+    if (res != OK) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+                          "Failed to set CpuConsumer buffer size");
+        return;
+    }
+    res = consumer->setDefaultBufferFormat(nativeFormat);
+    if (res != OK) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+                          "Failed to set CpuConsumer buffer format");
+    }
+}
+
+static void ImageReader_close(JNIEnv* env, jobject thiz)
+{
+    ALOGV("%s:", __FUNCTION__);
+
+    JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
+    if (ctx == NULL) {
+        // ImageReader is already closed.
+        return;
+    }
+
+    CpuConsumer* consumer = ImageReader_getCpuConsumer(env, thiz);
+    if (consumer != NULL) {
+        consumer->abandon();
+        consumer->setFrameAvailableListener(NULL);
+    }
+    ImageReader_setNativeContext(env, thiz, NULL);
+}
+
+static void ImageReader_imageRelease(JNIEnv* env, jobject thiz, jobject image)
+{
+    ALOGV("%s:", __FUNCTION__);
+    JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
+    if (ctx == NULL) {
+        ALOGW("ImageReader#close called before Image#close, consider calling Image#close first");
+        return;
+    }
+
+    CpuConsumer* consumer = ctx->getCpuConsumer();
+    CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, image);
+    if (!buffer) {
+        ALOGW("Image already released!!!");
+        return;
+    }
+    consumer->unlockBuffer(*buffer);
+    Image_setBuffer(env, image, NULL);
+    ctx->returnLockedBuffer(buffer);
+}
+
+static jboolean ImageReader_imageSetup(JNIEnv* env, jobject thiz,
+                                             jobject image)
+{
+    ALOGV("%s:", __FUNCTION__);
+    JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
+    if (ctx == NULL) {
+        jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
+        return false;
+    }
+
+    CpuConsumer* consumer = ctx->getCpuConsumer();
+    CpuConsumer::LockedBuffer* buffer = ctx->getLockedBuffer();
+    if (buffer == NULL) {
+        ALOGE("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
+            "maxImages buffers");
+        return false;
+    }
+    status_t res = consumer->lockNextBuffer(buffer);
+    if (res != NO_ERROR) {
+        ALOGE("%s Fail to lockNextBuffer with error: 0x%x ", __FUNCTION__, res);
+        return false;
+    }
+
+
+    // Check if the left-top corner of the crop rect is origin, we currently assume this point is
+    // zero, will revist this once this assumption turns out problematic.
+    Point lt = buffer->crop.leftTop();
+    if (lt.x != 0 || lt.y != 0) {
+        ALOGE("crop left: %d, top = %d", lt.x, lt.y);
+        jniThrowException(env, "java/lang/UnsupportedOperationException",
+                          "crop left top corner need to at origin");
+    }
+
+    // Check if the producer buffer configurations match what ImageReader configured.
+    // We want to fail for the very first image because this case is too bad.
+    int outputWidth = buffer->crop.getWidth() + 1;
+    int outputHeight = buffer->crop.getHeight() + 1;
+    int imageReaderWidth = ctx->getBufferWidth();
+    int imageReaderHeight = ctx->getBufferHeight();
+    if ((imageReaderWidth != outputWidth) ||
+        (imageReaderHeight != outputHeight)) {
+        // Spew warning for now, since MediaCodec decoder has a bug to setup the right crop
+        // TODO: make it throw exception once the decoder bug is fixed.
+        ALOGW("Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d",
+              outputWidth, outputHeight, imageReaderWidth, imageReaderHeight);
+    }
+
+    if (ctx->getBufferFormat() != buffer->format) {
+        // Return the buffer to the queue.
+        consumer->unlockBuffer(*buffer);
+        ctx->returnLockedBuffer(buffer);
+
+        // Throw exception
+        ALOGE("Producer output buffer format: 0x%x, ImageReader configured format: 0x%x",
+              buffer->format, ctx->getBufferFormat());
+        jniThrowException(env, "java/lang/UnsupportedOperationException",
+                          "The producer output buffer configuration doesn't match the ImageReader"
+                          "configured");
+        return false;
+    }
+    // Set SurfaceImage instance member variables
+    Image_setBuffer(env, image, buffer);
+    env->SetLongField(image, fields.timeStamp, static_cast<jlong>(buffer->timestamp));
+
+    return true;
+}
+
+static jobject ImageReader_getSurface(JNIEnv* env, jobject thiz)
+{
+    ALOGV("%s: ", __FUNCTION__);
+
+    CpuConsumer* consumer = ImageReader_getCpuConsumer(env, thiz);
+    if (consumer == NULL) {
+        jniThrowRuntimeException(env, "CpuConsumer is uninitialized");
+        return NULL;
+    }
+
+    // Wrap the IGBP in a Java-language Surface.
+    return android_view_Surface_createFromIGraphicBufferProducer(env,
+                                                                 consumer->getProducerInterface());
+}
+
+static jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx)
+{
+    int rowStride, pixelStride;
+    ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
+
+    CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
+
+    ALOG_ASSERT(buffer != NULL);
+    if (buffer == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
+    }
+    rowStride = Image_imageGetRowStride(env, buffer, idx);
+    pixelStride = Image_imageGetPixelStride(env, buffer, idx);
+
+    jobject surfPlaneObj = env->NewObject(surfPlaneClassInfo.clazz, surfPlaneClassInfo.ctor,
+                                          thiz, idx, rowStride, pixelStride);
+
+    return surfPlaneObj;
+}
+
+static jobject Image_getByteBuffer(JNIEnv* env, jobject thiz, int idx)
+{
+    uint8_t *base = NULL;
+    uint32_t size = 0;
+    jobject byteBuffer;
+
+    ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
+
+    CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
+
+    if (buffer == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
+    }
+
+    // Create byteBuffer from native buffer
+    Image_getLockedBufferInfo(env, buffer, idx, &base, &size);
+    byteBuffer = env->NewDirectByteBuffer(base, size);
+    // TODO: throw dvm exOutOfMemoryError?
+    if ((byteBuffer == NULL) && (env->ExceptionCheck() == false)) {
+        jniThrowException(env, "java/lang/IllegalStateException", "Failed to allocate ByteBuffer");
+    }
+
+    return byteBuffer;
+}
+
+} // extern "C"
+
+// ----------------------------------------------------------------------------
+
+static JNINativeMethod gImageReaderMethods[] = {
+    {"nativeClassInit",        "()V",                        (void*)ImageReader_classInit },
+    {"nativeInit",             "(Ljava/lang/Object;IIII)V",  (void*)ImageReader_init },
+    {"nativeClose",            "()V",                        (void*)ImageReader_close },
+    {"nativeReleaseImage",     "(Landroid/media/Image;)V",   (void*)ImageReader_imageRelease },
+    {"nativeImageSetup",       "(Landroid/media/Image;)Z",    (void*)ImageReader_imageSetup },
+    {"nativeGetSurface",       "()Landroid/view/Surface;",   (void*)ImageReader_getSurface },
+};
+
+static JNINativeMethod gImageMethods[] = {
+    {"nativeImageGetBuffer",   "(I)Ljava/nio/ByteBuffer;",   (void*)Image_getByteBuffer },
+    {"nativeCreatePlane",      "(I)Landroid/media/ImageReader$SurfaceImage$SurfacePlane;",
+                                                             (void*)Image_createSurfacePlane },
+};
+
+int register_android_media_ImageReader(JNIEnv *env) {
+
+    int ret1 = AndroidRuntime::registerNativeMethods(env,
+                   "android/media/ImageReader", gImageReaderMethods, NELEM(gImageReaderMethods));
+
+    int ret2 = AndroidRuntime::registerNativeMethods(env,
+                   "android/media/ImageReader$SurfaceImage", gImageMethods, NELEM(gImageMethods));
+
+    return (ret1 || ret2);
+}
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 0f78649..9b66c06 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -896,6 +896,7 @@
                 "android/media/MediaPlayer", gMethods, NELEM(gMethods));
 }
 
+extern int register_android_media_ImageReader(JNIEnv *env);
 extern int register_android_media_Crypto(JNIEnv *env);
 extern int register_android_media_Drm(JNIEnv *env);
 extern int register_android_media_MediaCodec(JNIEnv *env);
@@ -923,6 +924,11 @@
     }
     assert(env != NULL);
 
+    if (register_android_media_ImageReader(env) < 0) {
+        ALOGE("ERROR: ImageReader native registration failed");
+        goto bail;
+    }
+
     if (register_android_media_MediaPlayer(env) < 0) {
         ALOGE("ERROR: MediaPlayer native registration failed\n");
         goto bail;
diff --git a/media/tests/MediaFrameworkTest/Android.mk b/media/tests/MediaFrameworkTest/Android.mk
index c9afa19..1e6b2e7 100644
--- a/media/tests/MediaFrameworkTest/Android.mk
+++ b/media/tests/MediaFrameworkTest/Android.mk
@@ -7,7 +7,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := easymocklib
+LOCAL_STATIC_JAVA_LIBRARIES := easymocklib mockito-target
 
 LOCAL_PACKAGE_NAME := mediaframeworktest
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkIntegrationTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkIntegrationTestRunner.java
index 88c5b0c..7751fcc 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkIntegrationTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkIntegrationTestRunner.java
@@ -19,8 +19,10 @@
 import android.os.Bundle;
 import android.test.InstrumentationTestRunner;
 import android.test.InstrumentationTestSuite;
+import android.util.Log;
 
 import com.android.mediaframeworktest.integration.CameraBinderTest;
+import com.android.mediaframeworktest.integration.CameraDeviceBinderTest;
 
 import junit.framework.TestSuite;
 
@@ -34,11 +36,15 @@
 
 public class MediaFrameworkIntegrationTestRunner extends InstrumentationTestRunner {
 
+    private static final String TAG = "MediaFrameworkIntegrationTestRunner";
+
+    public static int mCameraId = 0;
 
     @Override
     public TestSuite getAllTests() {
         TestSuite suite = new InstrumentationTestSuite(this);
         suite.addTestSuite(CameraBinderTest.class);
+        suite.addTestSuite(CameraDeviceBinderTest.class);
         return suite;
     }
 
@@ -50,5 +56,17 @@
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
+
+        String cameraId = (String) icicle.get("camera_id");
+        if (cameraId != null) {
+            try {
+                Log.v(TAG,
+                        String.format("Reading camera_id from icicle: '%s'", cameraId));
+                mCameraId = Integer.parseInt(cameraId);
+            }
+            catch (NumberFormatException e) {
+                Log.e(TAG, String.format("Failed to convert camera_id to integer"));
+            }
+        }
     }
 }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
index 62af3f3..ecdc287 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
@@ -48,6 +48,7 @@
         addMediaRecorderStateUnitTests(suite);
         addMediaPlayerStateUnitTests(suite);
         addMediaScannerUnitTests(suite);
+        addCameraUnitTests(suite);
         return suite;
     }
 
@@ -56,6 +57,14 @@
         return MediaFrameworkUnitTestRunner.class.getClassLoader();
     }
 
+    private void addCameraUnitTests(TestSuite suite) {
+        suite.addTestSuite(CameraUtilsDecoratorTest.class);
+        suite.addTestSuite(CameraUtilsRuntimeExceptionTest.class);
+        suite.addTestSuite(CameraUtilsUncheckedThrowTest.class);
+        suite.addTestSuite(CameraUtilsBinderDecoratorTest.class);
+        suite.addTestSuite(CameraMetadataTest.class);
+    }
+
     // Running all unit tests checking the state machine may be time-consuming.
     private void addMediaMetadataRetrieverStateUnitTests(TestSuite suite) {
         suite.addTestSuite(MediaMetadataRetrieverTest.class);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index ba2859b..bc3adc9 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -16,122 +16,72 @@
 
 package com.android.mediaframeworktest.integration;
 
-import android.content.Context;
-import android.content.pm.FeatureInfo;
-import android.content.pm.PackageManager;
 import android.hardware.CameraInfo;
 import android.hardware.ICamera;
 import android.hardware.ICameraClient;
-import android.hardware.ICameraService;
 import android.hardware.ICameraServiceListener;
 import android.hardware.IProCameraCallbacks;
 import android.hardware.IProCameraUser;
+import android.hardware.photography.CameraMetadata;
+import android.hardware.photography.ICameraDeviceCallbacks;
+import android.hardware.photography.ICameraDeviceUser;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 
 /**
+ * <p>
  * Junit / Instrumentation test case for the camera2 api
+ * </p>
+ * <p>
+ * To run only tests in this class:
+ * </p>
  *
- * To run only tests in
- * this class:
- *
+ * <pre>
  * adb shell am instrument \
- *      -e class com.android.mediaframeworktest.integration.CameraBinderTest \
- *      -w com.android.mediaframeworktest/.MediaFrameworkIntegrationTestRunner
+ *   -e class com.android.mediaframeworktest.integration.CameraBinderTest \
+ *   -w com.android.mediaframeworktest/.MediaFrameworkIntegrationTestRunner
+ * </pre>
  */
 public class CameraBinderTest extends AndroidTestCase {
-    private static String TAG = "CameraBinderTest";
+    static String TAG = "CameraBinderTest";
 
-    private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
-    private static final int NO_ERROR = 0;
-    private static final int ALREADY_EXISTS = -17;
-    private static final int BAD_VALUE = -22;
-
-    private static final int USE_CALLING_UID = -1;
-
-    private ICameraService mCameraService;
-    private int mGuessedNumCameras = 0;
+    protected CameraBinderTestUtils mUtils;
 
     public CameraBinderTest() {
     }
 
-    private final static boolean isFeatureAvailable(Context context, String feature) {
-        final PackageManager packageManager = context.getPackageManager();
-        final FeatureInfo[] featuresList = packageManager.getSystemAvailableFeatures();
-        for (FeatureInfo f : featuresList) {
-            if (f.name != null && f.name.equals(feature)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    // Guess the lower bound for how many cameras there are
-    private void guessNumCameras() {
-
-        /**
-         * Why do we need this? This way we have no dependency on getNumCameras
-         * actually working. On most systems there are only 0, 1, or 2 cameras,
-         * and this covers that 'usual case'. On other systems there might be 3+
-         * cameras, but this will at least check the first 2.
-         */
-        mGuessedNumCameras = 0;
-
-        // Front facing camera
-        if (isFeatureAvailable(getContext(), PackageManager.FEATURE_CAMERA_FRONT)) {
-            mGuessedNumCameras++;
-        }
-
-        // Back facing camera
-        if (isFeatureAvailable(getContext(), PackageManager.FEATURE_CAMERA)) {
-            mGuessedNumCameras++;
-        }
-
-        // Any facing camera
-        if (mGuessedNumCameras == 0
-                && isFeatureAvailable(getContext(), PackageManager.FEATURE_CAMERA_ANY)) {
-            mGuessedNumCameras++;
-        }
-
-        Log.v(TAG, "Guessing there are at least " + mGuessedNumCameras + " cameras");
-    }
-
+    @Override
     protected void setUp() throws Exception {
         super.setUp();
 
-        guessNumCameras();
-
-        IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME);
-        assertNotNull("Camera service IBinder should not be null", cameraServiceBinder);
-
-        mCameraService = ICameraService.Stub.asInterface(cameraServiceBinder);
-        assertNotNull("Camera service should not be null", mCameraService);
+        mUtils = new CameraBinderTestUtils(getContext());
     }
 
     @SmallTest
     public void testNumberOfCameras() throws Exception {
-        int numCameras = mCameraService.getNumberOfCameras();
-        assertTrue("At least this many cameras: " + mGuessedNumCameras,
-                numCameras >= mGuessedNumCameras);
+
+        int numCameras = mUtils.getCameraService().getNumberOfCameras();
+        assertTrue("At least this many cameras: " + mUtils.getGuessedNumCameras(),
+                numCameras >= mUtils.getGuessedNumCameras());
         Log.v(TAG, "Number of cameras " + numCameras);
     }
 
     @SmallTest
     public void testCameraInfo() throws Exception {
-        for (int cameraId = 0; cameraId < mGuessedNumCameras; ++cameraId) {
+        for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
 
             CameraInfo info = new CameraInfo();
             info.info.facing = -1;
             info.info.orientation = -1;
 
-            assertTrue("Camera service returned info for camera " + cameraId,
-                    mCameraService.getCameraInfo(cameraId, info) == NO_ERROR);
+            assertTrue(
+                    "Camera service returned info for camera " + cameraId,
+                    mUtils.getCameraService().getCameraInfo(cameraId, info) ==
+                    CameraBinderTestUtils.NO_ERROR);
             assertTrue("Facing was not set for camera " + cameraId, info.info.facing != -1);
             assertTrue("Orientation was not set for camera " + cameraId,
                     info.info.orientation != -1);
@@ -153,14 +103,15 @@
 
     @SmallTest
     public void testConnect() throws Exception {
-        for (int cameraId = 0; cameraId < mGuessedNumCameras; ++cameraId) {
+        for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
 
             ICameraClient dummyCallbacks = new DummyCameraClient();
 
             String clientPackageName = getContext().getPackageName();
 
-            ICamera cameraUser = mCameraService.connect(dummyCallbacks, cameraId, clientPackageName,
-                    USE_CALLING_UID);
+            ICamera cameraUser = mUtils.getCameraService().connect(dummyCallbacks, cameraId,
+                    clientPackageName,
+                    CameraBinderTestUtils.USE_CALLING_UID);
             assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
 
             Log.v(TAG, String.format("Camera %s connected", cameraId));
@@ -174,14 +125,45 @@
 
     @SmallTest
     public void testConnectPro() throws Exception {
-        for (int cameraId = 0; cameraId < mGuessedNumCameras; ++cameraId) {
+        for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
 
             IProCameraCallbacks dummyCallbacks = new DummyProCameraCallbacks();
 
             String clientPackageName = getContext().getPackageName();
 
-            IProCameraUser cameraUser = mCameraService.connectPro(dummyCallbacks, cameraId,
-                    clientPackageName, USE_CALLING_UID);
+            IProCameraUser cameraUser = mUtils.getCameraService().connectPro(dummyCallbacks,
+                    cameraId,
+                    clientPackageName, CameraBinderTestUtils.USE_CALLING_UID);
+            assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
+
+            Log.v(TAG, String.format("Camera %s connected", cameraId));
+
+            cameraUser.disconnect();
+        }
+    }
+
+    static class DummyCameraDeviceCallbacks extends DummyBase implements ICameraDeviceCallbacks {
+
+        @Override
+        public void notifyCallback(int msgType, int ext1, int ext2) throws RemoteException {
+        }
+
+        @Override
+        public void onResultReceived(int frameId, CameraMetadata result) throws RemoteException {
+        }
+    }
+
+    @SmallTest
+    public void testConnectDevice() throws Exception {
+        for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
+
+            ICameraDeviceCallbacks dummyCallbacks = new DummyCameraDeviceCallbacks();
+
+            String clientPackageName = getContext().getPackageName();
+
+            ICameraDeviceUser cameraUser = mUtils.getCameraService().connectDevice(dummyCallbacks,
+                    cameraId,
+                    clientPackageName, CameraBinderTestUtils.USE_CALLING_UID);
             assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
 
             Log.v(TAG, String.format("Camera %s connected", cameraId));
@@ -199,27 +181,39 @@
     }
 
     /**
+     * <pre>
      * adb shell am instrument \
-     *     -e class 'com.android.mediaframeworktest.integration.CameraBinderTest#testAddRemoveListeners' \
-     *     -w com.android.mediaframeworktest/.MediaFrameworkIntegrationTestRunner
+     *   -e class 'com.android.mediaframeworktest.integration.CameraBinderTest#testAddRemoveListeners' \
+     *   -w com.android.mediaframeworktest/.MediaFrameworkIntegrationTestRunner
+     * </pre>
      */
     @SmallTest
     public void testAddRemoveListeners() throws Exception {
-        for (int cameraId = 0; cameraId < mGuessedNumCameras; ++cameraId) {
+        for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
 
             ICameraServiceListener listener = new DummyCameraServiceListener();
 
-            assertTrue("Listener was removed before added",
-                    mCameraService.removeListener(listener) == BAD_VALUE);
+            assertTrue(
+                    "Listener was removed before added",
+                    mUtils.getCameraService().removeListener(listener) ==
+                    CameraBinderTestUtils.BAD_VALUE);
 
-            assertTrue("Listener was not added", mCameraService.addListener(listener) == NO_ERROR);
-            assertTrue("Listener was wrongly added again",
-                    mCameraService.addListener(listener) == ALREADY_EXISTS);
+            assertTrue("Listener was not added",
+                    mUtils.getCameraService().addListener(listener) ==
+                    CameraBinderTestUtils.NO_ERROR);
+            assertTrue(
+                    "Listener was wrongly added again",
+                    mUtils.getCameraService().addListener(listener) ==
+                    CameraBinderTestUtils.ALREADY_EXISTS);
 
-            assertTrue("Listener was not removed",
-                    mCameraService.removeListener(listener) == NO_ERROR);
-            assertTrue("Listener was wrongly removed again",
-                    mCameraService.removeListener(listener) == BAD_VALUE);
+            assertTrue(
+                    "Listener was not removed",
+                    mUtils.getCameraService().removeListener(listener) ==
+                    CameraBinderTestUtils.NO_ERROR);
+            assertTrue(
+                    "Listener was wrongly removed again",
+                    mUtils.getCameraService().removeListener(listener) ==
+                    CameraBinderTestUtils.BAD_VALUE);
         }
     }
 }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java
new file mode 100644
index 0000000..f0fc817
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java
@@ -0,0 +1,92 @@
+
+package com.android.mediaframeworktest.integration;
+
+import static org.junit.Assert.assertNotNull;
+
+import android.content.Context;
+import android.content.pm.FeatureInfo;
+import android.content.pm.PackageManager;
+import android.hardware.ICameraService;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.util.Log;
+
+public class CameraBinderTestUtils {
+    private final ICameraService mCameraService;
+    private int mGuessedNumCameras;
+
+    static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
+
+    protected static final int USE_CALLING_UID = -1;
+    protected static final int BAD_VALUE = -22;
+    protected static final int ALREADY_EXISTS = -17;
+    protected static final int NO_ERROR = 0;
+    private final Context mContext;
+
+    public CameraBinderTestUtils(Context context) {
+
+        mContext = context;
+
+        guessNumCameras();
+
+        IBinder cameraServiceBinder = ServiceManager
+                .getService(CameraBinderTestUtils.CAMERA_SERVICE_BINDER_NAME);
+        assertNotNull("Camera service IBinder should not be null", cameraServiceBinder);
+
+        this.mCameraService = ICameraService.Stub.asInterface(cameraServiceBinder);
+        assertNotNull("Camera service should not be null", getCameraService());
+    }
+
+    private void guessNumCameras() {
+
+        /**
+         * Why do we need this? This way we have no dependency on getNumCameras
+         * actually working. On most systems there are only 0, 1, or 2 cameras,
+         * and this covers that 'usual case'. On other systems there might be 3+
+         * cameras, but this will at least check the first 2.
+         */
+        this.mGuessedNumCameras = 0;
+
+        // Front facing camera
+        if (CameraBinderTestUtils.isFeatureAvailable(mContext,
+                PackageManager.FEATURE_CAMERA_FRONT)) {
+            this.mGuessedNumCameras = getGuessedNumCameras() + 1;
+        }
+
+        // Back facing camera
+        if (CameraBinderTestUtils.isFeatureAvailable(mContext,
+                PackageManager.FEATURE_CAMERA)) {
+            this.mGuessedNumCameras = getGuessedNumCameras() + 1;
+        }
+
+        // Any facing camera
+        if (getGuessedNumCameras() == 0
+                && CameraBinderTestUtils.isFeatureAvailable(mContext,
+                        PackageManager.FEATURE_CAMERA_ANY)) {
+            this.mGuessedNumCameras = getGuessedNumCameras() + 1;
+        }
+
+        Log.v(CameraBinderTest.TAG, "Guessing there are at least " + getGuessedNumCameras()
+                + " cameras");
+    }
+
+    final static public boolean isFeatureAvailable(Context context, String feature) {
+        final PackageManager packageManager = context.getPackageManager();
+        final FeatureInfo[] featuresList = packageManager.getSystemAvailableFeatures();
+        for (FeatureInfo f : featuresList) {
+            if (f.name != null && f.name.equals(feature)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    ICameraService getCameraService() {
+        return mCameraService;
+    }
+
+    int getGuessedNumCameras() {
+        return mGuessedNumCameras;
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
new file mode 100644
index 0000000..0cbb989
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -0,0 +1,297 @@
+/*
+ * 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.mediaframeworktest.integration;
+
+import android.graphics.SurfaceTexture;
+import android.hardware.photography.CameraMetadata;
+import android.hardware.photography.CaptureRequest;
+import android.hardware.photography.ICameraDeviceCallbacks;
+import android.hardware.photography.ICameraDeviceUser;
+import android.os.RemoteException;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+import android.view.Surface;
+
+import static android.hardware.photography.CameraDevice.TEMPLATE_PREVIEW;
+
+import com.android.mediaframeworktest.MediaFrameworkIntegrationTestRunner;
+import com.android.mediaframeworktest.integration.CameraBinderTest.DummyBase;
+
+public class CameraDeviceBinderTest extends AndroidTestCase {
+    private static String TAG = "CameraDeviceBinderTest";
+
+    private int mCameraId;
+    private ICameraDeviceUser mCameraUser;
+    private CameraBinderTestUtils mUtils;
+
+    public CameraDeviceBinderTest() {
+    }
+
+    static class DummyCameraDeviceCallbacks extends DummyBase implements ICameraDeviceCallbacks {
+
+        @Override
+        public void notifyCallback(int msgType, int ext1, int ext2) throws RemoteException {
+        }
+
+        @Override
+        public void onResultReceived(int frameId, CameraMetadata result) throws RemoteException {
+        }
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mUtils = new CameraBinderTestUtils(getContext());
+
+        // This cannot be set in the constructor, since the onCreate isn't
+        // called yet
+        mCameraId = MediaFrameworkIntegrationTestRunner.mCameraId;
+
+        ICameraDeviceCallbacks dummyCallbacks = new DummyCameraDeviceCallbacks();
+
+        String clientPackageName = getContext().getPackageName();
+
+        mCameraUser = mUtils.getCameraService().connectDevice(dummyCallbacks, mCameraId,
+                clientPackageName, CameraBinderTestUtils.USE_CALLING_UID);
+        assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser);
+
+        Log.v(TAG, String.format("Camera %s connected", mCameraId));
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mCameraUser.disconnect();
+        mCameraUser = null;
+    }
+
+    @SmallTest
+    public void testCreateDefaultRequest() throws Exception {
+        CameraMetadata metadata = new CameraMetadata();
+        assertTrue(metadata.isEmpty());
+
+        int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata);
+        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+        assertFalse(metadata.isEmpty());
+
+        metadata.close();
+    }
+
+    @SmallTest
+    public void testCreateStream() throws Exception {
+        SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
+        surfaceTexture.setDefaultBufferSize(640, 480);
+        Surface surface = new Surface(surfaceTexture);
+
+        int streamId = mCameraUser.createStream(/* ignored */10, /* ignored */20, /* ignored */30,
+                surface);
+
+        assertEquals(0, streamId);
+
+        assertEquals(CameraBinderTestUtils.ALREADY_EXISTS,
+                mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0, surface));
+
+        assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId));
+    }
+
+    @SmallTest
+    public void testDeleteInvalidStream() throws Exception {
+        assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(-1));
+        assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0));
+        assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(1));
+        assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0xC0FFEE));
+    }
+
+    @SmallTest
+    public void testCreateStreamTwo() throws Exception {
+
+        // Create first stream
+
+        SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
+        surfaceTexture.setDefaultBufferSize(640, 480);
+        Surface surface = new Surface(surfaceTexture);
+
+        int streamId = mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0,
+                surface);
+
+        assertEquals(0, streamId);
+
+        assertEquals(CameraBinderTestUtils.ALREADY_EXISTS,
+                mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0, surface));
+
+        // Create second stream.
+
+        SurfaceTexture surfaceTexture2 = new SurfaceTexture(/* ignored */0);
+        surfaceTexture2.setDefaultBufferSize(640, 480);
+        Surface surface2 = new Surface(surfaceTexture2);
+
+        int streamId2 = mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0,
+                surface2);
+
+        assertEquals(1, streamId2);
+
+        // Clean up streams
+
+        assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId));
+        assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId2));
+    }
+
+    @SmallTest
+    public void testSubmitBadRequest() throws Exception {
+
+        CameraMetadata metadata = new CameraMetadata();
+        assertTrue(metadata.isEmpty());
+
+        CaptureRequest request = new CaptureRequest();
+        assertTrue(request.isEmpty());
+
+        int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata);
+        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+        assertFalse(metadata.isEmpty());
+
+        request.swap(metadata);
+        assertFalse(request.isEmpty());
+        assertTrue(metadata.isEmpty());
+
+        status = mCameraUser.submitRequest(request, /* streaming */false);
+        assertEquals("Expected submitRequest to return BAD_VALUE " +
+                "since we had 0 surface targets set.", CameraBinderTestUtils.BAD_VALUE, status);
+
+        SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
+        surfaceTexture.setDefaultBufferSize(640, 480);
+        Surface surface = new Surface(surfaceTexture);
+        request.addTarget(surface);
+
+        status = mCameraUser.submitRequest(request, /* streaming */false);
+        assertEquals("Expected submitRequest to return BAD_VALUE since " +
+                "the target surface wasn't registered with createStream.",
+                CameraBinderTestUtils.BAD_VALUE, status);
+
+        request.close();
+        metadata.close();
+        surface.release();
+    }
+
+    @SmallTest
+    public void testSubmitGoodRequest() throws Exception {
+
+        CameraMetadata metadata = new CameraMetadata();
+        assertTrue(metadata.isEmpty());
+
+        CaptureRequest request = new CaptureRequest();
+        assertTrue(request.isEmpty());
+
+        // Create default request from template.
+
+        int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata);
+        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+        assertFalse(metadata.isEmpty());
+
+        request.swap(metadata);
+        assertFalse(request.isEmpty());
+        assertTrue(metadata.isEmpty());
+
+        SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
+        surfaceTexture.setDefaultBufferSize(640, 480);
+        Surface surface = new Surface(surfaceTexture);
+
+        // Create stream first. Pre-requisite to submitting a request using that
+        // stream.
+
+        int streamId = mCameraUser.createStream(/* ignored */10, /* ignored */20, /* ignored */30,
+                surface);
+        assertEquals(0, streamId);
+
+        request.addTarget(surface);
+
+        // Submit valid request twice.
+
+        int requestId1;
+        requestId1 = mCameraUser.submitRequest(request, /* streaming */false);
+        assertTrue("Request IDs should be non-negative", requestId1 >= 0);
+
+        int requestId2 = mCameraUser.submitRequest(request, /* streaming */false);
+        assertTrue("Request IDs should be non-negative", requestId2 >= 0);
+        assertNotSame("Request IDs should be unique for multiple requests", requestId1, requestId2);
+
+        surface.release();
+        request.close();
+        metadata.close();
+    }
+
+    @SmallTest
+    public void testSubmitStreamingRequest() throws Exception {
+
+        CameraMetadata metadata = new CameraMetadata();
+        assertTrue(metadata.isEmpty());
+
+        CaptureRequest request = new CaptureRequest();
+        assertTrue(request.isEmpty());
+
+        // Create default request from template.
+
+        int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata);
+        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+        assertFalse(metadata.isEmpty());
+
+        request.swap(metadata);
+        assertFalse(request.isEmpty());
+        assertTrue(metadata.isEmpty());
+
+        SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
+        surfaceTexture.setDefaultBufferSize(640, 480);
+        Surface surface = new Surface(surfaceTexture);
+
+        // Create stream first. Pre-requisite to submitting a request using that
+        // stream.
+
+        int streamId = mCameraUser.createStream(/* ignored */10, /* ignored */20, /* ignored */30,
+                surface);
+        assertEquals(0, streamId);
+
+        request.addTarget(surface);
+
+        // Submit valid request once (non-streaming), and another time
+        // (streaming)
+
+        int requestId1;
+        requestId1 = mCameraUser.submitRequest(request, /* streaming */true);
+        assertTrue("Request IDs should be non-negative", requestId1 >= 0);
+
+        int requestIdStreaming = mCameraUser.submitRequest(request, /* streaming */false);
+        assertTrue("Request IDs should be non-negative", requestIdStreaming >= 0);
+        assertNotSame("Request IDs should be unique for multiple requests", requestId1,
+                requestIdStreaming);
+
+        status = mCameraUser.cancelRequest(-1);
+        assertEquals("Invalid request IDs should not be cancellable",
+                CameraBinderTestUtils.BAD_VALUE, status);
+
+        status = mCameraUser.cancelRequest(requestId1);
+        assertEquals("Non-streaming request IDs should not be cancellable",
+                CameraBinderTestUtils.BAD_VALUE, status);
+
+        status = mCameraUser.cancelRequest(requestIdStreaming);
+        assertEquals("Streaming request IDs should be cancellable", CameraBinderTestUtils.NO_ERROR,
+                status);
+
+        surface.release();
+        request.close();
+        metadata.close();
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
new file mode 100644
index 0000000..3400434
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.mediaframeworktest.unit;
+
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.hardware.photography.CameraMetadata;
+
+/**
+ * <pre>
+ * adb shell am instrument \
+ *      -e class 'com.android.mediaframeworktest.unit.CameraMetadataTest' \
+ *      -w com.android.mediaframeworktest/.MediaFrameworkUnitTestRunner
+ * </pre>
+ */
+public class CameraMetadataTest extends junit.framework.TestCase {
+
+    CameraMetadata mMetadata;
+    Parcel mParcel;
+
+    @Override
+    public void setUp() {
+        mMetadata = new CameraMetadata();
+        mParcel = Parcel.obtain();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        mMetadata.close();
+        mMetadata = null;
+
+        mParcel.recycle();
+        mParcel = null;
+    }
+
+    @SmallTest
+    public void testNew() {
+        assertEquals(0, mMetadata.getEntryCount());
+        assertTrue(mMetadata.isEmpty());
+    }
+
+    @SmallTest
+    public void testClose() throws Exception {
+        mMetadata.isEmpty(); // no throw
+
+        assertFalse(mMetadata.isClosed());
+
+        mMetadata.close();
+
+        assertTrue(mMetadata.isClosed());
+
+        // OK: second close should not throw
+        mMetadata.close();
+
+        assertTrue(mMetadata.isClosed());
+
+        // All other calls after close should throw IllegalStateException
+
+        try {
+            mMetadata.isEmpty();
+            fail("Unreachable -- isEmpty after close should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // good: we expect calling this method after close to fail
+        }
+
+        try {
+            mMetadata.getEntryCount();
+            fail("Unreachable -- getEntryCount after close should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // good: we expect calling this method after close to fail
+        }
+
+
+        try {
+            mMetadata.swap(mMetadata);
+            fail("Unreachable -- swap after close should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+         // good: we expect calling this method after close to fail
+        }
+
+        try {
+            mMetadata.readFromParcel(mParcel);
+            fail("Unreachable -- readFromParcel after close should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+         // good: we expect calling this method after close to fail
+        }
+
+        try {
+            mMetadata.writeToParcel(mParcel, /*flags*/0);
+            fail("Unreachable -- writeToParcel after close should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+         // good: we expect calling this method after close to fail
+        }
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java
new file mode 100644
index 0000000..7c48992
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java
@@ -0,0 +1,172 @@
+/*
+ * 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.mediaframeworktest.unit;
+
+import android.hardware.photography.CameraAccessException;
+import android.hardware.photography.utils.CameraBinderDecorator;
+import android.hardware.photography.utils.CameraRuntimeException;
+import android.os.DeadObjectException;
+import android.os.RemoteException;
+import android.os.TransactionTooLargeException;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import static org.mockito.Mockito.*;
+import static android.hardware.photography.utils.CameraBinderDecorator.*;
+import static android.hardware.photography.CameraAccessException.*;
+
+import junit.framework.Assert;
+
+public class CameraUtilsBinderDecoratorTest extends junit.framework.TestCase {
+
+    private interface ICameraBinderStereotype {
+
+        double doNothing();
+
+        // int is a 'status_t'
+        int doSomethingPositive();
+
+        int doSomethingNoError();
+
+        int doSomethingPermissionDenied();
+
+        int doSomethingAlreadyExists();
+
+        int doSomethingBadValue();
+
+        int doSomethingDeadObject() throws CameraRuntimeException;
+
+        int doSomethingBadPolicy() throws CameraRuntimeException;
+
+        int doSomethingDeviceBusy() throws CameraRuntimeException;
+
+        int doSomethingNoSuchDevice() throws CameraRuntimeException;
+
+        int doSomethingUnknownErrorCode();
+
+        int doSomethingThrowDeadObjectException() throws RemoteException;
+
+        int doSomethingThrowTransactionTooLargeException() throws RemoteException;
+    }
+
+    private static final double SOME_ARBITRARY_DOUBLE = 1.0;
+    private static final int SOME_ARBITRARY_POSITIVE_INT = 5;
+    private static final int SOME_ARBITRARY_NEGATIVE_INT = -0xC0FFEE;
+
+    @SmallTest
+    public void testStereotypes() {
+
+        ICameraBinderStereotype mock = mock(ICameraBinderStereotype.class);
+        try {
+            when(mock.doNothing()).thenReturn(SOME_ARBITRARY_DOUBLE);
+            when(mock.doSomethingPositive()).thenReturn(SOME_ARBITRARY_POSITIVE_INT);
+            when(mock.doSomethingNoError()).thenReturn(NO_ERROR);
+            when(mock.doSomethingPermissionDenied()).thenReturn(PERMISSION_DENIED);
+            when(mock.doSomethingAlreadyExists()).thenReturn(ALREADY_EXISTS);
+            when(mock.doSomethingBadValue()).thenReturn(BAD_VALUE);
+            when(mock.doSomethingDeadObject()).thenReturn(DEAD_OBJECT);
+            when(mock.doSomethingBadPolicy()).thenReturn(EACCES);
+            when(mock.doSomethingDeviceBusy()).thenReturn(EBUSY);
+            when(mock.doSomethingNoSuchDevice()).thenReturn(ENODEV);
+            when(mock.doSomethingUnknownErrorCode()).thenReturn(SOME_ARBITRARY_NEGATIVE_INT);
+            when(mock.doSomethingThrowDeadObjectException()).thenThrow(new DeadObjectException());
+            when(mock.doSomethingThrowTransactionTooLargeException()).thenThrow(
+                    new TransactionTooLargeException());
+        } catch (RemoteException e) {
+            Assert.fail("Unreachable");
+        }
+
+        ICameraBinderStereotype decoratedMock = CameraBinderDecorator.newInstance(mock);
+
+        // ignored by decorator because return type is double, not int
+        assertEquals(SOME_ARBITRARY_DOUBLE, decoratedMock.doNothing());
+
+        // pass through for positive values
+        assertEquals(SOME_ARBITRARY_POSITIVE_INT, decoratedMock.doSomethingPositive());
+
+        // pass through NO_ERROR
+        assertEquals(NO_ERROR, decoratedMock.doSomethingNoError());
+
+        try {
+            decoratedMock.doSomethingPermissionDenied();
+            Assert.fail("Should've thrown SecurityException");
+        } catch (SecurityException e) {
+        }
+
+        assertEquals(ALREADY_EXISTS, decoratedMock.doSomethingAlreadyExists());
+
+        try {
+            decoratedMock.doSomethingBadValue();
+            Assert.fail("Should've thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+        }
+
+        try {
+            decoratedMock.doSomethingDeadObject();
+            Assert.fail("Should've thrown CameraRuntimeException");
+        } catch (CameraRuntimeException e) {
+            assertEquals(CAMERA_DISCONNECTED, e.getReason());
+        }
+
+        try {
+            decoratedMock.doSomethingBadPolicy();
+            Assert.fail("Should've thrown CameraRuntimeException");
+        } catch (CameraRuntimeException e) {
+            assertEquals(CAMERA_DISABLED, e.getReason());
+        }
+
+        try {
+            decoratedMock.doSomethingDeviceBusy();
+            Assert.fail("Should've thrown CameraRuntimeException");
+        } catch (CameraRuntimeException e) {
+            assertEquals(CAMERA_IN_USE, e.getReason());
+        }
+
+        try {
+            decoratedMock.doSomethingNoSuchDevice();
+            Assert.fail("Should've thrown CameraRuntimeException");
+        } catch (CameraRuntimeException e) {
+            assertEquals(CAMERA_DISCONNECTED, e.getReason());
+        }
+
+        try {
+            decoratedMock.doSomethingUnknownErrorCode();
+            Assert.fail("Should've thrown UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+            assertEquals(String.format("Unknown error %d",
+                    SOME_ARBITRARY_NEGATIVE_INT), e.getMessage());
+        }
+
+        try {
+            decoratedMock.doSomethingThrowDeadObjectException();
+            Assert.fail("Should've thrown CameraRuntimeException");
+        } catch (CameraRuntimeException e) {
+            assertEquals(CAMERA_DISCONNECTED, e.getReason());
+        } catch (RemoteException e) {
+            Assert.fail("Should not throw a DeadObjectException directly, but rethrow");
+        }
+
+        try {
+            decoratedMock.doSomethingThrowTransactionTooLargeException();
+            Assert.fail("Should've thrown UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+            assertTrue(e.getCause() instanceof TransactionTooLargeException);
+        } catch (RemoteException e) {
+            Assert.fail("Should not throw a TransactionTooLargeException directly, but rethrow");
+        }
+    }
+
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java
new file mode 100644
index 0000000..bae17fa
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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.mediaframeworktest.unit;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.hardware.photography.utils.*;
+import android.hardware.photography.utils.Decorator.DecoratorListener;
+
+import junit.framework.Assert;
+
+import java.lang.reflect.Method;
+
+/**
+ * adb shell am instrument -e class 'com.android.mediaframeworktest.unit.CameraUtilsDecoratorTest' \
+ *      -w com.android.mediaframeworktest/.MediaFrameworkUnitTestRunner
+ */
+public class CameraUtilsDecoratorTest extends junit.framework.TestCase {
+    private DummyListener mDummyListener;
+    private DummyInterface mIface;
+
+    @Override
+    public void setUp() {
+        mDummyListener = new DummyListener();
+        mIface = Decorator.newInstance(new DummyImpl(), mDummyListener);
+    }
+
+    interface DummyInterface {
+        int addValues(int x, int y, int z);
+
+        void raiseException() throws Exception;
+
+        void raiseUnsupportedOperationException() throws UnsupportedOperationException;
+    }
+
+    class DummyImpl implements DummyInterface {
+        @Override
+        public int addValues(int x, int y, int z) {
+            return x + y + z;
+        }
+
+        @Override
+        public void raiseException() throws Exception {
+            throw new Exception("Test exception");
+        }
+
+        @Override
+        public void raiseUnsupportedOperationException() throws UnsupportedOperationException {
+            throw new UnsupportedOperationException("Test exception");
+        }
+    }
+
+    class DummyListener implements DecoratorListener {
+
+        public boolean beforeCalled = false;
+        public boolean afterCalled = false;
+        public boolean catchCalled = false;
+        public boolean finallyCalled = false;
+        public Object resultValue = null;
+
+        public boolean raiseException = false;
+
+        @Override
+        public void onBeforeInvocation(Method m, Object[] args) {
+            beforeCalled = true;
+        }
+
+        @Override
+        public void onAfterInvocation(Method m, Object[] args, Object result) {
+            afterCalled = true;
+            resultValue = result;
+
+            if (raiseException) {
+                throw new UnsupportedOperationException("Test exception");
+            }
+        }
+
+        @Override
+        public boolean onCatchException(Method m, Object[] args, Throwable t) {
+            catchCalled = true;
+            return false;
+        }
+
+        @Override
+        public void onFinally(Method m, Object[] args) {
+            finallyCalled = true;
+        }
+
+    };
+
+    @SmallTest
+    public void testDecorator() {
+
+        // TODO rewrite this using mocks
+
+        assertTrue(mIface.addValues(1, 2, 3) == 6);
+        assertTrue(mDummyListener.beforeCalled);
+        assertTrue(mDummyListener.afterCalled);
+
+        int resultValue = (Integer)mDummyListener.resultValue;
+        assertTrue(resultValue == 6);
+        assertTrue(mDummyListener.finallyCalled);
+        assertFalse(mDummyListener.catchCalled);
+    }
+
+    @SmallTest
+    public void testDecoratorExceptions() {
+
+        boolean gotExceptions = false;
+        try {
+            mIface.raiseException();
+        } catch (Exception e) {
+            gotExceptions = true;
+            assertTrue(e.getMessage() == "Test exception");
+        }
+        assertTrue(gotExceptions);
+        assertTrue(mDummyListener.beforeCalled);
+        assertFalse(mDummyListener.afterCalled);
+        assertTrue(mDummyListener.catchCalled);
+        assertTrue(mDummyListener.finallyCalled);
+    }
+
+    @SmallTest
+    public void testDecoratorUnsupportedOperationException() {
+
+        boolean gotExceptions = false;
+        try {
+            mIface.raiseUnsupportedOperationException();
+        } catch (UnsupportedOperationException e) {
+            gotExceptions = true;
+            assertTrue(e.getMessage() == "Test exception");
+        }
+        assertTrue(gotExceptions);
+        assertTrue(mDummyListener.beforeCalled);
+        assertFalse(mDummyListener.afterCalled);
+        assertTrue(mDummyListener.catchCalled);
+        assertTrue(mDummyListener.finallyCalled);
+    }
+
+    @SmallTest
+    public void testDecoratorRaisesException() {
+
+        boolean gotExceptions = false;
+        try {
+            mDummyListener.raiseException = true;
+            mIface.addValues(1, 2, 3);
+            Assert.fail("unreachable");
+        } catch (UnsupportedOperationException e) {
+            gotExceptions = true;
+            assertTrue(e.getMessage() == "Test exception");
+        }
+        assertTrue(gotExceptions);
+        assertTrue(mDummyListener.beforeCalled);
+        assertTrue(mDummyListener.afterCalled);
+        assertFalse(mDummyListener.catchCalled);
+        assertTrue(mDummyListener.finallyCalled);
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java
new file mode 100644
index 0000000..8c2dd4d
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.mediaframeworktest.unit;
+
+import android.hardware.photography.CameraAccessException;
+import android.hardware.photography.utils.CameraRuntimeException;
+import android.hardware.photography.utils.UncheckedThrow;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.Assert;
+
+public class CameraUtilsRuntimeExceptionTest extends junit.framework.TestCase {
+
+    @SmallTest
+    public void testCameraRuntimeException1() {
+        try {
+            CameraRuntimeException runtimeExc = new CameraRuntimeException(12345);
+            throw runtimeExc.asChecked();
+        } catch (CameraAccessException e) {
+            assertEquals(12345, e.getReason());
+            assertNull(e.getMessage());
+            assertNull(e.getCause());
+        }
+    }
+
+    @SmallTest
+    public void testCameraRuntimeException2() {
+        try {
+            CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, "Hello");
+            throw runtimeExc.asChecked();
+        } catch (CameraAccessException e) {
+            assertEquals(12345, e.getReason());
+            assertEquals("Hello", e.getMessage());
+            assertNull(e.getCause());
+        }
+    }
+
+    @SmallTest
+    public void testCameraRuntimeException3() {
+        Throwable cause = new IllegalStateException("For great justice");
+        try {
+            CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, cause);
+            throw runtimeExc.asChecked();
+        } catch (CameraAccessException e) {
+            assertEquals(12345, e.getReason());
+            assertNull(e.getMessage());
+            assertEquals(cause, e.getCause());
+        }
+    }
+
+    @SmallTest
+    public void testCameraRuntimeException4() {
+        Throwable cause = new IllegalStateException("For great justice");
+        try {
+            CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, "Hello", cause);
+            throw runtimeExc.asChecked();
+        } catch (CameraAccessException e) {
+            assertEquals(12345, e.getReason());
+            assertEquals("Hello", e.getMessage());
+            assertEquals(cause, e.getCause());
+        }
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsUncheckedThrowTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsUncheckedThrowTest.java
new file mode 100644
index 0000000..cbe123c
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsUncheckedThrowTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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.mediaframeworktest.unit;
+
+import android.hardware.photography.CameraAccessException;
+import android.hardware.photography.utils.UncheckedThrow;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.Assert;
+
+public class CameraUtilsUncheckedThrowTest extends junit.framework.TestCase {
+
+    private void fakeNeverThrowsCameraAccess() throws CameraAccessException {
+    }
+
+    @SmallTest
+    public void testUncheckedThrow() {
+        try {
+            UncheckedThrow.throwAnyException(new CameraAccessException(
+                    CameraAccessException.CAMERA_DISCONNECTED));
+            Assert.fail("unreachable");
+            fakeNeverThrowsCameraAccess();
+        } catch (CameraAccessException e) {
+        }
+    }
+}
diff --git a/packages/Keyguard/res/values-sw/strings.xml b/packages/Keyguard/res/values-sw/strings.xml
index a022655..014c732 100644
--- a/packages/Keyguard/res/values-sw/strings.xml
+++ b/packages/Keyguard/res/values-sw/strings.xml
@@ -104,7 +104,7 @@
     <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM sasa imelemazwa. Ingiza msimbo wa PUK ili kuendelea. Wasiliana na mtoa huduma kwa maelezo."</string>
     <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Ingiza msimbo wa PIN unaopendelewa"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Thibitisha msimbo wa PIN unaopendelewa"</string>
-    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Inafungua kadi ya SIM..."</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Inafungua SIM kadi..."</string>
     <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Msimbo wa PIN usio sahihi."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Charaza PIN iliyo na tarakimu kati ya 4 na 8."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Msimbo wa PUK unafaa kuwa na nambari 8 au zaidi."</string>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/RemotePrintAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/RemotePrintAdapter.java
index 7537218..c81b00c 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/RemotePrintAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/RemotePrintAdapter.java
@@ -20,7 +20,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.print.IPrintAdapter;
-import android.print.IPrintProgressListener;
+import android.print.IPrintResultCallback;
 import android.print.PageRange;
 import android.print.PrintAdapterInfo;
 import android.print.PrintAttributes;
@@ -50,7 +50,7 @@
 
     private final File mFile;
 
-    private final IPrintProgressListener mIPrintProgressListener;
+    private final IPrintResultCallback mIPrintProgressListener;
 
     private PrintAdapterInfo mInfo;
 
@@ -61,12 +61,12 @@
     public RemotePrintAdapter(IPrintAdapter printAdatper, File file) {
         mRemoteInterface = printAdatper;
         mFile = file;
-        mIPrintProgressListener = new IPrintProgressListener.Stub() {
+        mIPrintProgressListener = new IPrintResultCallback.Stub() {
             @Override
-            public void onWriteStarted(PrintAdapterInfo info,
+            public void onPrintStarted(PrintAdapterInfo info,
                     ICancellationSignal cancellationSignal) {
                 if (DEBUG) {
-                    Log.i(LOG_TAG, "IPrintProgressListener#onWriteStarted()");
+                    Log.i(LOG_TAG, "IPrintProgressListener#onPrintStarted()");
                 }
                 synchronized (mLock) {
                     mInfo = info;
@@ -75,9 +75,9 @@
             }
 
             @Override
-            public void onWriteFinished(List<PageRange> pages) {
+            public void onPrintFinished(List<PageRange> pages) {
                 if (DEBUG) {
-                    Log.i(LOG_TAG, "IPrintProgressListener#onWriteFinished(" + pages + ")");
+                    Log.i(LOG_TAG, "IPrintProgressListener#onPrintFinished(" + pages + ")");
                 }
                 synchronized (mLock) {
                     if (isPrintingLocked()) {
@@ -88,9 +88,9 @@
             }
 
             @Override
-            public void onWriteFailed(CharSequence error) {
+            public void onPrintFailed(CharSequence error) {
                 if (DEBUG) {
-                    Log.i(LOG_TAG, "IPrintProgressListener#onWriteFailed(" + error + ")");
+                    Log.i(LOG_TAG, "IPrintProgressListener#onPrintFailed(" + error + ")");
                 }
                 synchronized (mLock) {
                     if (isPrintingLocked()) {
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index fc70f7a..f8f064a 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -6,7 +6,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
     src/com/android/systemui/EventLogTags.logtags
 
-LOCAL_JAVA_LIBRARIES := services telephony-common
+LOCAL_JAVA_LIBRARIES := telephony-common
 
 LOCAL_PACKAGE_NAME := SystemUI
 LOCAL_CERTIFICATE := platform
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 4bb44af..dfc68f4 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -38,7 +38,6 @@
     <uses-permission android:name="android.permission.MANAGE_USB" />
     <uses-permission android:name="android.permission.DEVICE_POWER" />
     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
-    <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
     <uses-permission android:name="android.permission.MASTER_CLEAR" />
     <uses-permission android:name="android.permission.VIBRATE" />
 
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 7d5959c..aa66811 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Kennisgewings verskyn hier"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Verkry enige tyd toegang tot hulle deur af te sleep."\n"Sleep weer af vir stelselkontroles."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Sleep rand van skerm om balk te wys"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Sleep van rand van skerm af om stelselbalk te wys"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index e66149e..a0d2960 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ራስ-ሰር"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"ማሳወቂያዎች እዚህ ላይ ይታያሉ"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"ወደ ታች በማንሸራተት በማንኛውም ጊዜ ይድረሱባቸው።"\n"Swipe የስርዓት መቆጣጠሪያዎችን ለማምጣት እንደገና ወደ ታች ያንሸራትቱ።"</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"አሞሌውን ለማሳየት የማያ ገጹን ጠርዝ ላይ ያንሸራትቱ"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"አሞሌውን ለማሳየት ከማያ ገጹ ጠርዝ ጀምረው ያንሸራትቱ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 20347db..1571531 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"تلقائي"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"تظهر الإشعارات هنا"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"يمكنك الدخول إليها في أي وقت بالتمرير السريع إلى أسفل."\n"يمكنك التمرير السريع إلى أسفل مرة أخرى للوصول إلى عناصر تحكم النظام."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"مرر سريعًا لحافة الشاشة لإظهار الشريط"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"مرر سريعًا من حافة الشاشة لإظهار شريط النظام"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 6cd66e3..6cce40b 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТ."</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Известията се показват тук"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Осъществявайте достъп до тях по всяко време, като прекарате пръст надолу."\n"Направете го отново за системните контроли."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Прекарайте пръст по ръба на екрана, за да се покаже лентата"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Прекарайте пръст от ръба на екрана, за да се покаже системната лента"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 34b39e2..cf34d5a 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Underretninger vises her"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Få adgang til dem når som helst ved at stryge ned."\n"Stryg ned igen for at komme til systemindstillingerne."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Stryg kanten af skærmen for at se bjælken"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Stryg fra skærmens kant for at se systembjælken"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 16968e5..43cde46 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -201,8 +201,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Benachrichtigungen erscheinen hier"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Greifen Sie jederzeit auf sie zu, indem Sie nach unten wischen."\n"Wischen Sie für Systemeinstellungen erneut nach unten."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Zum Einblenden der Leiste vom Rand wischen"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Zum Einblenden der Systemleiste vom Display-Rand weg wischen"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index f7aa31c..6a04819 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -201,8 +201,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ΑΥΤΟΜΑΤΗ"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Οι ειδοποιήσεις εμφανίζονται εδώ"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Μεταβείτε σε αυτές ανά πάσα στιγμή σύροντας προς τα κάτω."\n"Σύρετε ξανά προς τα κάτω για τα στοιχεία ελέγχου συστήματος."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Σύρετε από την άκρη της οθόνης για να εμφανίσετε τη γραμμή"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Σύρετε από την άκρη της οθόνης για να εμφανίσετε τη γραμμή συστήματος"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 68da06a..2f8e0cf 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Notifications appear here"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Access them any time by swiping down."\n"Swipe down again for system controls."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Swipe edge of screen to reveal bar"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Swipe from edge of screen to reveal system bar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 770b440..d8ea0d4 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -201,8 +201,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÁTICO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Las notificaciones aparecen aquí."</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Desliza el dedo hacia abajo para acceder al contenido."\n"Vuelve a deslizar el dedo hacia abajo para acceder a los controles del sistema."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Desliza el dedo desde el borde de la pantalla para mostrar la barra."</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Desliza el dedo desde el borde de la pantalla para mostrar la barra del sistema."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 5295079..3ae2401 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Las notificaciones aparecen aquí"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Desliza el dedo hacia abajo para acceder al contenido."\n"Vuelve a deslizar el dedo hacia abajo para acceder a los controles del sistema."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Desliza el borde de la pantalla para mostrar la barra"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Desliza el borde de la pantalla para mostrar la barra del sistema"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index f084d2d..4dcf12c 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMAATNE"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Märguanded ilmuvad siia"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Juurdepääs igal ajal sõrmega alla pühkides."\n"Süsteemi juhtnuppude jaoks pühkige uuesti alla."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Riba kuvamiseks pühkige ekraani serva"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Süsteemiriba kuvamiseks pühkige ekraani servast"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 6c48bed..62b9bd7 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"خودکار"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"اعلان‌ها در اینجا نمایش داده می‌شوند"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"با کشیدن انگشت به طرف پایین به آنها دسترسی پیدا کنید."\n"برای کنترل‌های سیستم دوباره انگشت خود را به سمت پایین بکشید."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"برای نمایش نوار، انگشت خود را از لبه‌ صفحه به داخل بکشید"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"برای نمایش نوار سیستم، انگشت خود را از لبه‌ صفحه به داخل بکشید"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 9f97fdb..a7915a6 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Ilmoitukset näkyvät tässä"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Näet ilmoitukset liu\'uttamalla sormea alas ruudulla."\n"Voit palauttaa järjestelmän ohjaimet näkyviin liu\'uttamalla sormea alas uudelleen."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Tuo palkki näkyviin liu\'uttamalla ruudun reunasta"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Tuo järjestelmäpalkki näkyviin liu\'uttamalla ruudun reunasta"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index aefcfe0..dd2cee6 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -201,8 +201,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATIQUE"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Les notifications s’affichent ici"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Accédez-y à tout moment en faisant glisser le doigt vers le bas."\n"Répétez l\'opération pour accéder aux commandes du système."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Faites glisser votre doigt sur le côté de l\'écran pour afficher la barre."</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Faites glisser votre doigt à partir d\'un côté de l\'écran pour afficher la barre système."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index e8c07dd..702469e 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"स्वत:"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"सूचनाएं यहां दिखाई देती हैं"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"नीचे स्वाइप करके उन तक कभी भी पहुंचें."\n"सिस्टम नियंत्रणों के लिए पुन: नीचे स्वाइप करें."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"बार दिखाने के लिए स्क्रीन के किनारे को स्वाइप करें"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"सिस्टम बार दिखाने के लिए स्क्रीन के किनारे से स्वाइप करें"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index a91eda5..ebdc5dd 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATSKI"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Obavijesti se prikazuju ovdje"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Pristupite im u bilo kojem trenutku tako da prstom trznete prema dolje. "\n"Ponovo prstom trznite prema dolje za kontrole sustava."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Prijeđite prstom po rubu zaslona da bi se prikazala traka"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Prijeđite prstom od ruba zaslona da bi se prikazala traka sustava"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index a26575c..9b05a07 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"automatikus"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Az értesítések itt jelennek meg."</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Bármikor elérheti őket, ha lefelé húzza az ujját."\n"Húzza le az ujját még egyszer a rendszerbeállítások eléréséhez."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Csúsztassa ujját a képernyő szélén a sáv megjelenítéséhez"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Csúsztassa ujját a képernyő szélétől a rendszersáv megjelenítéséhez"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 93cfd86..f8b03c6 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OTOMATIS"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Pemberitahuan muncul di sini"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Akses kapan saja dengan menggesek ke bawah."\n"Gesek ke bawah sekali lagi untuk kontrol sistem."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Gesek tepi layar untuk membuka bilah"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Gesek dari bagian tepi layar untuk membuka bilah sistem"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index cef3733..5a6b285 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -201,8 +201,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Le notifiche vengono visualizzate qui"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Puoi accedervi in qualsiasi momento scorrendo verso il basso."\n"Fai scorrere di nuovo verso il basso per visualizzare i controlli del sistema."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Fai scorrere il bordo dello schermo per visualizzare la barra"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Fai scorrere il dito dal bordo dello schermo per visualizzare la barra di sistema"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index d352972..653bb78 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"אוטומטי"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"הודעות מופיעות כאן"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"גש אליהם בכל עת על ידי החלקה למטה."\n"החלק למטה שוב למעבר למרכז הבקרה של המערכת."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"החלק מקצה המסך כדי להציג את הסרגל"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"החלק מקצה המסך כדי להציג את סרגל המערכת"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b57898a..a57938d 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -201,8 +201,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"ここに通知が表示されます"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"下にスワイプすると、いつでも通知を表示できます。"\n"システムを管理するにはもう一度下にスワイプしてください。"</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"バーを表示するには、画面の端からスワイプします"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"システムバーを表示するには、画面の端からスワイプします"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index c9585fc..ba9bcbf 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"자동"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"알림이 여기에 표시됨"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"아래로 스와이프하여 언제든 액세스하세요."\n"한 번 더 아래로 스와이프하면 시스템 관리로 이동합니다."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"화면 가장자리에서 스와이프하여 표시줄 표시"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"화면 가장자리에서 스와이프하여 시스템 표시줄 표시"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 9c57358..4947298 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATINIS"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Pranešimai rodomi čia"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Perbraukę žemyn bet kuriuo metu pasieksite pranešimus."\n"Jei norite naudoti sistemos valdiklius, perbraukite žemyn dar kartą."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Jei norite, kad būtų rodoma juosta, perbraukite ekrano krašte"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Jei norite, kad būtų rodoma sistemos juosta, perbraukite iš ekrano krašto"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 65cadd5..c8a1a1d 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMĀTISKI"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Šeit tiek rādīti paziņojumi"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Piekļūstiet tiem jebkurā laikā, velkot uz leju."\n"Vēlreiz velciet, lai tiktu parādītas sistēmas vadīklas."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Velciet no ekrāna malas, lai piekļūtu joslai."</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Velciet no ekrāna malas, lai piekļūtu sistēmas joslai."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 1bbe4df..4b71cb4 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Pemberitahuan dipaparkan di sini"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Akses panel pada bila-bila masa dengan meleret ke bawah."\n"Leret ke bawah sekali lagi untuk mendapatkan kawalan sistem."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Leret ke bahagian tepi skrin untuk menampakkan bar"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Leret dari tepi skrin untuk menampakkan bar sistem"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index acda153..4764da6 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Varslene vises her"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Bruk dem når som helst ved å sveipe nedover."\n"Sveip nedover igjen for å gå til systemkontrollene."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Sveip på kanten av skjermen for å få frem feltet"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Sveip fra kanten på skjermen for å få frem systemfeltet"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 90faf36..5e18d0a 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATISCH"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Meldingen worden hier weergegeven"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"U kunt de meldingen op elk gewenst moment openen door met uw vinger omlaag te vegen."\n"Veeg nogmaals met uw vinger omlaag om de systeembesturingselementen weer te geven."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Veeg vanaf de rand om balk weer te geven"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Veeg vanaf de rand van het scherm om de systeembalk weer te geven"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index a7eb487..13374ae 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATYCZNA"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Tutaj pokazują się powiadomienia"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Możesz je otworzyć w dowolnej chwili, przesuwając w dół."\n"Przesuń jeszcze raz w dół, by otworzyć ustawienia systemowe."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Przesuń palcem od krawędzi ekranu, by odkryć pasek"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Przesuń palcem od krawędzi ekranu, by odkryć pasek systemu"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 93a47b0..a55aaa4 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÁTICO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"As notificações são apresentadas aqui"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Pode aceder em qualquer altura, deslizando rapidamente para baixo com o dedo."\n"Deslize novamente para baixo para aceder aos controlos do sistema."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Deslize da extremidade do ecrã para revelar a barra"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Deslize da extremidade do ecrã para revelar a barra do sistema"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 5d326d1..37b1819 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMAT"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Notificările se afişează aici"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Accesaţi-le oricând glisând în jos."\n"Glisaţi în jos din nou pentru comenzile sistemului."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Glisați dinspre marginea ecranului pentru a afișa bara"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Glisați dinspre marginea ecranului pentru a afișa bara de sistem"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index f09e192..e2abc0c 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -203,8 +203,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТОНАСТРОЙКА"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Это панель уведомлений"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Ее можно открыть, пролистнув экран вниз."\n"Чтобы открыть настройки, проведите пальцем вниз ещё раз."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Чтобы открыть панель, проведите пальцем от края к центру экрана"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Чтобы открыть панель навигации, проведите пальцем от края к центру экрана"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 4396daa..e9aec22 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -201,8 +201,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATICKY"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Tu sa zobrazujú upozornenia"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Môžete ich kedykoľvek zobraziť tak, že posuniete prstom nadol."\n"Ak posuniete prstom nadol ešte raz, zobrazia sa ovládacie prvky systému."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Panel zobrazíte posunutím cez okraj obrazovky"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Systémový panel zobrazíte posunutím cez okraj obrazovky"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 4a67b94..a4ad396 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"SAMODEJNO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Obvestila so prikazana tukaj"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Do njih lahko kadar koli dostopate tako, da povlečete navzdol."\n"Za prikaz sistemskih kontrolnikov znova povlecite navzdol."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Vrstico prikažete tako, da povlečete z roba zaslona"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Sistemsko vrstico prikažete tako, da povlečete z roba zaslona"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index d37800f..e1a585d 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АУТОМАТСКА"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Обавештења се појављују овде"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Приступите им у било ком тренутку листањем надоле."\n"Поново листајте надоле да би се приказале системске контроле."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Превуците по ивици екрана да би се приказала трака"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Превуците од ивице екрана да би се приказала системска трака"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 0e81a4b..d39c533 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Meddelanden visas här"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Du kommer åt dem när som helst genom att dra nedåt."\n"Dra nedåt igen om du vill visa systemkontroller."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Dra från kanten av skärmen om du vill visa fältet"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Dra från kanten av skärmen om du vill visa systemfältet"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 85bcfb9..4e29d81 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -197,8 +197,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"KIOTOMATIKI"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Arifa zitaonekana hapa"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Zifikie wakati wowote kwa kutelezesha chini."\n"Telezesha chini tena kupata vidhibiti vya mfumo."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Papasa kwa kasi kutoka ukingo wa skrini ili kuonyesha upau"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Papasa kwa kasi kutoka ukingo wa skrini ili kuonyesha upau wa mfumo"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 18ed6e0..a0cd9a6 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"อัตโนมัติ"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"การแจ้งเตือนจะแสดงขึ้นที่นี่"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"เข้าถึงได้ทุกเมื่อด้วยการกวาดนิ้วลง"\n"กวาดนิ้วลงอีกครั้งสำหรับการควบคุมระบบ"</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"กวาดขอบของหน้าจอเพื่อแสดงแถบ"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"กวาดจากขอบของหน้าจอเพื่อแสดงแถบระบบ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 043a23e..4ba399a 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Dito lumalabas ang mga notification"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"I-access ang mga ito anumang oras sa pamamagitan ng pag-swipe pababa."\n"Muling mag-swipe pababa para sa mga kontrol ng system."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Mag-swipe sa gilid ng screen upang ipakita ang bar"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Mag-swipe mula sa gilid ng screen upang ipakita ang system bar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 96c64d3..6808f30 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OTOMATİK"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Bildirimler burada görünür"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Aşağıya hızlıca kaydırarak bunlara istediğiniz zaman erişebilirsiniz."\n"Sistem denetimleri için tekrar hızlıca aşağı kaydırın."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Çubuğu görüntülemek için ekranın kenarından hızlıca kaydırın"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Sistem çubuğunu görüntülemek için ekranın kenarından hızlıca kaydırın"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index d470e64..bb507d9 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТО"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Сповіщення з’являються тут"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Отримуйте до них доступ будь-коли, провівши пальцем униз."\n"Знову проведіть униз, щоб відкрити елементи керування системи."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Гортайте від краю екрана, щоб з’явилась панель"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Проведіть пальцем від краю екрана, щоб з’явилась навігаційна панель"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index a4eee9d..59e5d1d 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"TỰ ĐỘNG"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Thông báo xuất hiện tại đây"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Truy cập vào chúng bất kỳ lúc nào bằng cách vuốt xuống."\n"Vuốt lại xuống để hiển thị các điều khiển hệ thống."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Vuốt cạnh màn hình để hiển thị thanh"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Vuốt từ cạnh màn hình để hiển thị thanh hệ thống"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index ee8de82..af2228b 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -201,8 +201,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自动"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"通知会显示在这里"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"向下滑动可随时查看通知。"\n"再次向下滑动可使用系统控制功能。"</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"从边缘向里滑可显示系统栏"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"从屏幕边缘向里滑动即可显示系统栏"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 299f255..c0e5bac 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -201,8 +201,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"系統會在這裡顯示通知"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"向下滑動即可隨時存取通知。"\n"再次向下滑動即可使用系統控制項。"</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"滑動螢幕邊緣即可顯示導覽列"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"從螢幕邊緣向內滑動即可顯示導覽列"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 53837be..295db6e 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -199,8 +199,6 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OKUZENZAKALELAYO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Izaziso zivela lapha"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Kufinyelele noma kunini ngokuswayiphela phansi."\n"Swayiphela phansi futhi ngezilawuli zesistimu."</string>
-    <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
-    <skip />
-    <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
-    <skip />
+    <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Swayipha unqenqema wesikrini ukuze uveze ibha"</string>
+    <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Swayipha kusukela kunqenqema ukuze uveze ibha yesistimu"</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
new file mode 100644
index 0000000..323905f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
@@ -0,0 +1,30 @@
+/*
+ * 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.systemui;
+
+import android.view.Display;
+import android.view.View;
+
+public interface RecentsComponent {
+    void toggleRecents(Display display, int layoutDirection, View statusBarView);
+
+    void preloadRecentTasksList();
+
+    void cancelPreloadingRecentTasksList();
+
+    void closeRecents();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUI.java b/packages/SystemUI/src/com/android/systemui/SystemUI.java
index 6c38cea..fec7329 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUI.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUI.java
@@ -21,9 +21,11 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.Map;
 
 public abstract class SystemUI {
     public Context mContext;
+    public Map<Class<?>, Object> mComponents;
 
     public abstract void start();
     
@@ -32,4 +34,15 @@
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
     }
+
+    @SuppressWarnings("unchecked")
+    public <T> T getComponent(Class<T> interfaceType) {
+        return (T) (mComponents != null ? mComponents.get(interfaceType) : null);
+    }
+
+    public <T, C extends T> void putComponent(Class<T> interfaceType, C component) {
+        if (mComponents != null) {
+            mComponents.put(interfaceType, component);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index f130993..ca5f7d1 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -24,6 +24,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.HashMap;
 
 public class SystemUIService extends Service {
     private static final String TAG = "SystemUIService";
@@ -32,7 +33,9 @@
      * The classes of the stuff to start.
      */
     private final Class<?>[] SERVICES = new Class[] {
+            com.android.systemui.recent.Recents.class,
             com.android.systemui.statusbar.SystemBars.class,
+            com.android.systemui.usb.StorageNotification.class,
             com.android.systemui.power.PowerUI.class,
             com.android.systemui.media.RingtonePlayer.class,
             com.android.systemui.settings.SettingsUI.class,
@@ -45,6 +48,7 @@
 
     @Override
     public void onCreate() {
+        HashMap<Class<?>, Object> components = new HashMap<Class<?>, Object>();
         final int N = SERVICES.length;
         for (int i=0; i<N; i++) {
             Class<?> cl = SERVICES[i];
@@ -57,6 +61,7 @@
                 throw new RuntimeException(ex);
             }
             mServices[i].mContext = this;
+            mServices[i].mComponents = components;
             Log.d(TAG, "running: " + mServices[i]);
             mServices[i].start();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Recents.java b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
new file mode 100644
index 0000000..f51e34b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
@@ -0,0 +1,212 @@
+/*
+ * 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.systemui.recent;
+
+import android.app.ActivityOptions;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Paint;
+import android.os.UserHandle;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Display;
+import android.view.View;
+
+import com.android.systemui.R;
+import com.android.systemui.RecentsComponent;
+import com.android.systemui.SystemUI;
+
+public class Recents extends SystemUI implements RecentsComponent {
+    private static final String TAG = "Recents";
+    private static final boolean DEBUG = false;
+
+    @Override
+    public void start() {
+        putComponent(RecentsComponent.class, this);
+    }
+
+    @Override
+    public void toggleRecents(Display display, int layoutDirection, View statusBarView) {
+        if (DEBUG) Log.d(TAG, "toggle recents panel");
+        try {
+            TaskDescription firstTask = RecentTasksLoader.getInstance(mContext).getFirstTask();
+
+            Intent intent = new Intent(RecentsActivity.TOGGLE_RECENTS_INTENT);
+            intent.setClassName("com.android.systemui",
+                    "com.android.systemui.recent.RecentsActivity");
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+
+            if (firstTask == null) {
+                if (RecentsActivity.forceOpaqueBackground(mContext)) {
+                    ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
+                            R.anim.recents_launch_from_launcher_enter,
+                            R.anim.recents_launch_from_launcher_exit);
+                    mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
+                            UserHandle.USER_CURRENT));
+                } else {
+                    // The correct window animation will be applied via the activity's style
+                    mContext.startActivityAsUser(intent, new UserHandle(
+                            UserHandle.USER_CURRENT));
+                }
+
+            } else {
+                Bitmap first = firstTask.getThumbnail();
+                final Resources res = mContext.getResources();
+
+                float thumbWidth = res
+                        .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_width);
+                float thumbHeight = res
+                        .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_height);
+                if (first == null) {
+                    throw new RuntimeException("Recents thumbnail is null");
+                }
+                if (first.getWidth() != thumbWidth || first.getHeight() != thumbHeight) {
+                    first = Bitmap.createScaledBitmap(first, (int) thumbWidth, (int) thumbHeight,
+                            true);
+                    if (first == null) {
+                        throw new RuntimeException("Recents thumbnail is null");
+                    }
+                }
+
+
+                DisplayMetrics dm = new DisplayMetrics();
+                display.getMetrics(dm);
+                // calculate it here, but consider moving it elsewhere
+                // first, determine which orientation you're in.
+                final Configuration config = res.getConfiguration();
+                int x, y;
+
+                if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
+                    float appLabelLeftMargin = res.getDimensionPixelSize(
+                            R.dimen.status_bar_recents_app_label_left_margin);
+                    float appLabelWidth = res.getDimensionPixelSize(
+                            R.dimen.status_bar_recents_app_label_width);
+                    float thumbLeftMargin = res.getDimensionPixelSize(
+                            R.dimen.status_bar_recents_thumbnail_left_margin);
+                    float thumbBgPadding = res.getDimensionPixelSize(
+                            R.dimen.status_bar_recents_thumbnail_bg_padding);
+
+                    float width = appLabelLeftMargin +
+                            +appLabelWidth
+                            + thumbLeftMargin
+                            + thumbWidth
+                            + 2 * thumbBgPadding;
+
+                    x = (int) ((dm.widthPixels - width) / 2f + appLabelLeftMargin + appLabelWidth
+                            + thumbBgPadding + thumbLeftMargin);
+                    y = (int) (dm.heightPixels
+                            - res.getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_height)
+                            - thumbBgPadding);
+                    if (layoutDirection == View.LAYOUT_DIRECTION_RTL) {
+                        x = dm.widthPixels - x - res.getDimensionPixelSize(
+                                R.dimen.status_bar_recents_thumbnail_width);
+                    }
+
+                } else { // if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+                    float thumbTopMargin = res.getDimensionPixelSize(
+                            R.dimen.status_bar_recents_thumbnail_top_margin);
+                    float thumbBgPadding = res.getDimensionPixelSize(
+                            R.dimen.status_bar_recents_thumbnail_bg_padding);
+                    float textPadding = res.getDimensionPixelSize(
+                            R.dimen.status_bar_recents_text_description_padding);
+                    float labelTextSize = res.getDimensionPixelSize(
+                            R.dimen.status_bar_recents_app_label_text_size);
+                    Paint p = new Paint();
+                    p.setTextSize(labelTextSize);
+                    float labelTextHeight = p.getFontMetricsInt().bottom
+                            - p.getFontMetricsInt().top;
+                    float descriptionTextSize = res.getDimensionPixelSize(
+                            R.dimen.status_bar_recents_app_description_text_size);
+                    p.setTextSize(descriptionTextSize);
+                    float descriptionTextHeight = p.getFontMetricsInt().bottom
+                            - p.getFontMetricsInt().top;
+
+                    float statusBarHeight = res.getDimensionPixelSize(
+                            com.android.internal.R.dimen.status_bar_height);
+                    float recentsItemTopPadding = statusBarHeight;
+
+                    float height = thumbTopMargin
+                            + thumbHeight
+                            + 2 * thumbBgPadding + textPadding + labelTextHeight
+                            + recentsItemTopPadding + textPadding + descriptionTextHeight;
+                    float recentsItemRightPadding = res
+                            .getDimensionPixelSize(R.dimen.status_bar_recents_item_padding);
+                    float recentsScrollViewRightPadding = res
+                            .getDimensionPixelSize(R.dimen.status_bar_recents_right_glow_margin);
+                    x = (int) (dm.widthPixels - res
+                            .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_width)
+                            - thumbBgPadding - recentsItemRightPadding
+                            - recentsScrollViewRightPadding);
+                    y = (int) ((dm.heightPixels - statusBarHeight - height) / 2f + thumbTopMargin
+                            + recentsItemTopPadding + thumbBgPadding + statusBarHeight);
+                }
+
+                ActivityOptions opts = ActivityOptions.makeThumbnailScaleDownAnimation(
+                        statusBarView,
+                        first, x, y,
+                        new ActivityOptions.OnAnimationStartedListener() {
+                            public void onAnimationStarted() {
+                                Intent intent =
+                                        new Intent(RecentsActivity.WINDOW_ANIMATION_START_INTENT);
+                                intent.setPackage("com.android.systemui");
+                                mContext.sendBroadcastAsUser(intent,
+                                        new UserHandle(UserHandle.USER_CURRENT));
+                            }
+                        });
+                intent.putExtra(RecentsActivity.WAITING_FOR_WINDOW_ANIMATION_PARAM, true);
+                mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
+                        UserHandle.USER_CURRENT));
+            }
+        } catch (ActivityNotFoundException e) {
+            Log.e(TAG, "Failed to launch RecentAppsIntent", e);
+        }
+    }
+
+    @Override
+    public void preloadRecentTasksList() {
+        if (DEBUG) Log.d(TAG, "preloading recents");
+        Intent intent = new Intent(RecentsActivity.PRELOAD_INTENT);
+        intent.setClassName("com.android.systemui",
+                "com.android.systemui.recent.RecentsPreloadReceiver");
+        mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+
+        RecentTasksLoader.getInstance(mContext).preloadFirstTask();
+    }
+
+    @Override
+    public void cancelPreloadingRecentTasksList() {
+        if (DEBUG) Log.d(TAG, "cancel preloading recents");
+        Intent intent = new Intent(RecentsActivity.CANCEL_PRELOAD_INTENT);
+        intent.setClassName("com.android.systemui",
+                "com.android.systemui.recent.RecentsPreloadReceiver");
+        mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+
+        RecentTasksLoader.getInstance(mContext).cancelPreloadingFirstTask();
+    }
+
+    @Override
+    public void closeRecents() {
+        if (DEBUG) Log.d(TAG, "closing recents panel");
+        Intent intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT);
+        intent.setPackage("com.android.systemui");
+        mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index bf82466..3583081 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (C) 2010 The Android Open Source Project
  *
@@ -19,11 +18,9 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
-import android.app.ActivityOptions;
 import android.app.KeyguardManager;
 import android.app.PendingIntent;
 import android.app.TaskStackBuilder;
-import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -31,10 +28,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Configuration;
-import android.content.res.Resources;
 import android.database.ContentObserver;
-import android.graphics.Bitmap;
-import android.graphics.Paint;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Build;
@@ -47,7 +41,6 @@
 import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
-import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.Display;
 import android.view.IWindowManager;
@@ -70,11 +63,9 @@
 import com.android.internal.statusbar.StatusBarIconList;
 import com.android.internal.widget.SizeAdaptiveLayout;
 import com.android.systemui.R;
+import com.android.systemui.RecentsComponent;
 import com.android.systemui.SearchPanelView;
 import com.android.systemui.SystemUI;
-import com.android.systemui.recent.RecentTasksLoader;
-import com.android.systemui.recent.RecentsActivity;
-import com.android.systemui.recent.TaskDescription;
 import com.android.systemui.statusbar.policy.NotificationRowLayout;
 
 import java.util.ArrayList;
@@ -142,6 +133,8 @@
 
     private boolean mDeviceProvisioned = false;
 
+    private RecentsComponent mRecents;
+
     public IStatusBarService getStatusBarService() {
         return mBarService;
     }
@@ -219,6 +212,8 @@
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
 
+        mRecents = getComponent(RecentsComponent.class);
+
         mLocale = mContext.getResources().getConfiguration().locale;
         mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale);
 
@@ -442,9 +437,6 @@
         mHandler.sendEmptyMessage(msg);
     }
 
-    protected abstract WindowManager.LayoutParams getRecentsLayoutParams(
-            LayoutParams layoutParams);
-
     protected abstract WindowManager.LayoutParams getSearchLayoutParams(
             LayoutParams layoutParams);
 
@@ -488,140 +480,6 @@
 
     protected abstract View getStatusBarView();
 
-    protected void toggleRecentsActivity() {
-        try {
-
-            TaskDescription firstTask = RecentTasksLoader.getInstance(mContext).getFirstTask();
-
-            Intent intent = new Intent(RecentsActivity.TOGGLE_RECENTS_INTENT);
-            intent.setClassName("com.android.systemui",
-                    "com.android.systemui.recent.RecentsActivity");
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-
-            if (firstTask == null) {
-                if (RecentsActivity.forceOpaqueBackground(mContext)) {
-                    ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
-                            R.anim.recents_launch_from_launcher_enter,
-                            R.anim.recents_launch_from_launcher_exit);
-                    mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
-                            UserHandle.USER_CURRENT));
-                } else {
-                    // The correct window animation will be applied via the activity's style
-                    mContext.startActivityAsUser(intent, new UserHandle(
-                            UserHandle.USER_CURRENT));
-                }
-
-            } else {
-                Bitmap first = firstTask.getThumbnail();
-                final Resources res = mContext.getResources();
-
-                float thumbWidth = res
-                        .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_width);
-                float thumbHeight = res
-                        .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_height);
-                if (first == null) {
-                    throw new RuntimeException("Recents thumbnail is null");
-                }
-                if (first.getWidth() != thumbWidth || first.getHeight() != thumbHeight) {
-                    first = Bitmap.createScaledBitmap(first, (int) thumbWidth, (int) thumbHeight,
-                            true);
-                    if (first == null) {
-                        throw new RuntimeException("Recents thumbnail is null");
-                    }
-                }
-
-
-                DisplayMetrics dm = new DisplayMetrics();
-                mDisplay.getMetrics(dm);
-                // calculate it here, but consider moving it elsewhere
-                // first, determine which orientation you're in.
-                final Configuration config = res.getConfiguration();
-                int x, y;
-
-                if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
-                    float appLabelLeftMargin = res
-                            .getDimensionPixelSize(R.dimen.status_bar_recents_app_label_left_margin);
-                    float appLabelWidth = res
-                            .getDimensionPixelSize(R.dimen.status_bar_recents_app_label_width);
-                    float thumbLeftMargin = res
-                            .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_left_margin);
-                    float thumbBgPadding = res
-                            .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_bg_padding);
-
-                    float width = appLabelLeftMargin +
-                            +appLabelWidth
-                            + thumbLeftMargin
-                            + thumbWidth
-                            + 2 * thumbBgPadding;
-
-                    x = (int) ((dm.widthPixels - width) / 2f + appLabelLeftMargin + appLabelWidth
-                            + thumbBgPadding + thumbLeftMargin);
-                    y = (int) (dm.heightPixels
-                            - res.getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_height) - thumbBgPadding);
-                    if (mLayoutDirection == View.LAYOUT_DIRECTION_RTL) {
-                        x = dm.widthPixels - x - res
-                                .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_width);
-                    }
-
-                } else { // if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
-                    float thumbTopMargin = res
-                            .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_top_margin);
-                    float thumbBgPadding = res
-                            .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_bg_padding);
-                    float textPadding = res
-                            .getDimensionPixelSize(R.dimen.status_bar_recents_text_description_padding);
-                    float labelTextSize = res
-                            .getDimensionPixelSize(R.dimen.status_bar_recents_app_label_text_size);
-                    Paint p = new Paint();
-                    p.setTextSize(labelTextSize);
-                    float labelTextHeight = p.getFontMetricsInt().bottom
-                            - p.getFontMetricsInt().top;
-                    float descriptionTextSize = res
-                            .getDimensionPixelSize(R.dimen.status_bar_recents_app_description_text_size);
-                    p.setTextSize(descriptionTextSize);
-                    float descriptionTextHeight = p.getFontMetricsInt().bottom
-                            - p.getFontMetricsInt().top;
-
-                    float statusBarHeight = res
-                            .getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
-                    float recentsItemTopPadding = statusBarHeight;
-
-                    float height = thumbTopMargin
-                            + thumbHeight
-                            + 2 * thumbBgPadding + textPadding + labelTextHeight
-                            + recentsItemTopPadding + textPadding + descriptionTextHeight;
-                    float recentsItemRightPadding = res
-                            .getDimensionPixelSize(R.dimen.status_bar_recents_item_padding);
-                    float recentsScrollViewRightPadding = res
-                            .getDimensionPixelSize(R.dimen.status_bar_recents_right_glow_margin);
-                    x = (int) (dm.widthPixels - res
-                            .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_width)
-                            - thumbBgPadding - recentsItemRightPadding - recentsScrollViewRightPadding);
-                    y = (int) ((dm.heightPixels - statusBarHeight - height) / 2f + thumbTopMargin
-                            + recentsItemTopPadding + thumbBgPadding + statusBarHeight);
-                }
-
-                ActivityOptions opts = ActivityOptions.makeThumbnailScaleDownAnimation(
-                        getStatusBarView(),
-                        first, x, y,
-                        new ActivityOptions.OnAnimationStartedListener() {
-                            public void onAnimationStarted() {
-                                Intent intent = new Intent(RecentsActivity.WINDOW_ANIMATION_START_INTENT);
-                                intent.setPackage("com.android.systemui");
-                                mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
-                            }
-                        });
-                intent.putExtra(RecentsActivity.WAITING_FOR_WINDOW_ANIMATION_PARAM, true);
-                mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
-                        UserHandle.USER_CURRENT));
-            }
-            return;
-        } catch (ActivityNotFoundException e) {
-            Log.e(TAG, "Failed to launch RecentAppsIntent", e);
-        }
-    }
-
     protected View.OnTouchListener mRecentsPreloadOnTouchListener = new View.OnTouchListener() {
         // additional optimization when we have software system buttons - start loading the recent
         // tasks on touch down
@@ -642,24 +500,28 @@
         }
     };
 
-    protected void preloadRecentTasksList() {
-        if (DEBUG) Log.d(TAG, "preloading recents");
-        Intent intent = new Intent(RecentsActivity.PRELOAD_INTENT);
-        intent.setClassName("com.android.systemui",
-                "com.android.systemui.recent.RecentsPreloadReceiver");
-        mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+    protected void toggleRecentsActivity() {
+        if (mRecents != null) {
+            mRecents.toggleRecents(mDisplay, mLayoutDirection, getStatusBarView());
+        }
+    }
 
-        RecentTasksLoader.getInstance(mContext).preloadFirstTask();
+    protected void preloadRecentTasksList() {
+        if (mRecents != null) {
+            mRecents.preloadRecentTasksList();
+        }
     }
 
     protected void cancelPreloadingRecentTasksList() {
-        if (DEBUG) Log.d(TAG, "cancel preloading recents");
-        Intent intent = new Intent(RecentsActivity.CANCEL_PRELOAD_INTENT);
-        intent.setClassName("com.android.systemui",
-                "com.android.systemui.recent.RecentsPreloadReceiver");
-        mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+        if (mRecents != null) {
+            mRecents.cancelPreloadingRecentTasksList();
+        }
+    }
 
-        RecentTasksLoader.getInstance(mContext).cancelPreloadingFirstTask();
+    protected void closeRecents() {
+        if (mRecents != null) {
+            mRecents.closeRecents();
+        }
     }
 
     protected class H extends Handler {
@@ -667,14 +529,10 @@
             Intent intent;
             switch (m.what) {
              case MSG_TOGGLE_RECENTS_PANEL:
-                 if (DEBUG) Log.d(TAG, "toggle recents panel");
                  toggleRecentsActivity();
                  break;
              case MSG_CLOSE_RECENTS_PANEL:
-                 if (DEBUG) Log.d(TAG, "closing recents panel");
-                 intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT);
-                 intent.setPackage("com.android.systemui");
-                 mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+                 closeRecents();
                  break;
              case MSG_PRELOAD_RECENT_APPS:
                   preloadRecentTasksList();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java
index f763f03..aea9ec6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java
@@ -98,6 +98,11 @@
 
         public void onChange(boolean selfChange, Uri uri) {
             if (mDebug) Log.d(mTag, "onChange selfChange=" + selfChange + " uri=" + uri);
+            ComponentName cn = getComponentNameFromSetting();
+            if (cn == null && mServiceName == null || cn != null && cn.equals(mServiceName)) {
+                if (mDebug) Log.d(mTag, "skipping no-op restart");
+                return;
+            }
             if (mBound) {
                 mHandler.sendEmptyMessage(MSG_STOP_SERVICE);
             }
@@ -178,6 +183,12 @@
         mHandler.sendEmptyMessage(MSG_START_SERVICE);
     }
 
+    private ComponentName getComponentNameFromSetting() {
+        String cn = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+                mSettingKey, UserHandle.USER_CURRENT);
+        return cn == null ? null : ComponentName.unflattenFromString(cn);
+    }
+
     // everything below is called on the handler
 
     private void packageIntent(Intent intent) {
@@ -210,9 +221,7 @@
     }
 
     private void startService() {
-        String cn = Settings.Secure.getStringForUser(mContext.getContentResolver(),
-                mSettingKey, UserHandle.USER_CURRENT);
-        mServiceName = cn == null ? null : ComponentName.unflattenFromString(cn);
+        mServiceName = getComponentNameFromSetting();
         if (mDebug) Log.d(mTag, "startService mServiceName=" + mServiceName);
         if (mServiceName == null) {
             mBound = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java b/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java
index 847bf96..05282fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java
@@ -84,6 +84,7 @@
             throw andLog("Error creating status bar component: " + clsName, t);
         }
         mStatusBar.mContext = mContext;
+        mStatusBar.mComponents = mComponents;
         mStatusBar.start();
         if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
     }
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 dca8c97e..ee94cc8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -670,31 +670,6 @@
     }
 
     @Override
-    protected WindowManager.LayoutParams getRecentsLayoutParams(LayoutParams layoutParams) {
-        boolean opaque = false;
-        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                layoutParams.width,
-                layoutParams.height,
-                WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
-                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
-                | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
-                (opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
-        if (ActivityManager.isHighEndGfx()) {
-            lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-        } else {
-            lp.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
-            lp.dimAmount = 0.75f;
-        }
-        lp.gravity = Gravity.BOTTOM | Gravity.START;
-        lp.setTitle("RecentsPanel");
-        lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications;
-        lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
-        | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
-        return lp;
-    }
-
-    @Override
     protected WindowManager.LayoutParams getSearchLayoutParams(LayoutParams layoutParams) {
         boolean opaque = false;
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 57ec0e5..4ee2a4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -24,7 +24,6 @@
 import android.content.IntentFilter;
 import android.media.AudioManager;
 import android.os.Handler;
-import android.os.storage.StorageManager;
 import android.util.Log;
 
 import com.android.internal.telephony.IccCardConstants;
@@ -57,10 +56,6 @@
     private final StatusBarManager mService;
     private final Handler mHandler = new Handler();
 
-    // storage
-    private StorageManager mStorageManager;
-
-
     // Assume it's all good unless we hear otherwise.  We don't always seem
     // to get broadcasts that it *is* there.
     IccCardConstants.State mSimState = IccCardConstants.State.READY;
@@ -136,11 +131,6 @@
         filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
         mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
 
-        // storage
-        mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
-        mStorageManager.registerListener(
-                new com.android.systemui.usb.StorageNotification(context));
-
         // TTY status
         mService.setIcon("tty",  R.drawable.stat_sys_tty_mode, 0, null);
         mService.setIconVisibility("tty", false);
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 0e40140..fb2348e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -27,11 +27,9 @@
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.net.wimax.WimaxManagerConstants;
-import android.os.Binder;
 import android.os.Handler;
 import android.os.Message;
 import android.os.Messenger;
-import android.os.RemoteException;
 import android.provider.Settings;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
@@ -42,12 +40,10 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
-import com.android.internal.app.IBatteryStats;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.cdma.EriInfo;
 import com.android.internal.util.AsyncChannel;
-import com.android.server.am.BatteryStatsService;
 import com.android.systemui.R;
 
 import java.io.FileDescriptor;
@@ -166,9 +162,6 @@
 
     boolean mDataAndWifiStacked = false;
 
-    // yuck -- stop doing this here and put it in the framework
-    IBatteryStats mBatteryStats;
-
     public interface SignalCluster {
         void setWifiIndicators(boolean visible, int strengthIcon, int activityIcon,
                 String contentDescription);
@@ -253,9 +246,6 @@
         // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
         updateAirplaneMode();
 
-        // yuck
-        mBatteryStats = BatteryStatsService.getService();
-
         mLastLocale = mContext.getResources().getConfiguration().locale;
     }
 
@@ -792,15 +782,6 @@
             }
         }
 
-        // yuck - this should NOT be done by the status bar
-        long ident = Binder.clearCallingIdentity();
-        try {
-            mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
-        } catch (RemoteException e) {
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-
         mDataDirectionIconId = iconId;
         mDataConnected = visible;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 18b9e26..cf909f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -97,12 +97,6 @@
     }
 
     @Override
-    protected WindowManager.LayoutParams getRecentsLayoutParams(
-            LayoutParams layoutParams) {
-        return null;
-    }
-
-    @Override
     protected WindowManager.LayoutParams getSearchLayoutParams(
             LayoutParams layoutParams) {
         return null;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index a3eeb47..b75f8b3 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -31,18 +31,15 @@
 import android.provider.Settings;
 import android.util.Log;
 
-public class StorageNotification extends StorageEventListener {
+import com.android.systemui.SystemUI;
+
+public class StorageNotification extends SystemUI {
     private static final String TAG = "StorageNotification";
     private static final boolean DEBUG = false;
 
     private static final boolean POP_UMS_ACTIVITY_ON_CONNECT = true;
 
     /**
-     * Binder context for this service
-     */
-    private Context mContext;
-    
-    /**
      * The notification that is shown when a USB mass storage host
      * is connected. 
      * <p>
@@ -66,32 +63,40 @@
 
     private Handler        mAsyncEventHandler;
 
-    public StorageNotification(Context context) {
-        mContext = context;
+    private class StorageNotificationEventListener extends StorageEventListener {
+        public void onUsbMassStorageConnectionChanged(final boolean connected) {
+            mAsyncEventHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    onUsbMassStorageConnectionChangedAsync(connected);
+                }
+            });
+        }
+        public void onStorageStateChanged(final String path,
+                final String oldState, final String newState) {
+            mAsyncEventHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    onStorageStateChangedAsync(path, oldState, newState);
+                }
+            });
+        }
+    }
 
-        mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
+    @Override
+    public void start() {
+        mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
         final boolean connected = mStorageManager.isUsbMassStorageConnected();
         if (DEBUG) Log.d(TAG, String.format( "Startup with UMS connection %s (media state %s)",
                 mUmsAvailable, Environment.getExternalStorageState()));
-        
+
         HandlerThread thr = new HandlerThread("SystemUI StorageNotification");
         thr.start();
         mAsyncEventHandler = new Handler(thr.getLooper());
 
-        onUsbMassStorageConnectionChanged(connected);
-    }
-
-    /*
-     * @override com.android.os.storage.StorageEventListener
-     */
-    @Override
-    public void onUsbMassStorageConnectionChanged(final boolean connected) {
-        mAsyncEventHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                onUsbMassStorageConnectionChangedAsync(connected);
-            }
-        });
+        StorageNotificationEventListener listener = new StorageNotificationEventListener();
+        listener.onUsbMassStorageConnectionChanged(connected);
+        mStorageManager.registerListener(listener);
     }
 
     private void onUsbMassStorageConnectionChangedAsync(boolean connected) {
@@ -115,19 +120,6 @@
         updateUsbMassStorageNotification(connected);
     }
 
-    /*
-     * @override com.android.os.storage.StorageEventListener
-     */
-    @Override
-    public void onStorageStateChanged(final String path, final String oldState, final String newState) {
-        mAsyncEventHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                onStorageStateChangedAsync(path, oldState, newState);
-            }
-        });
-    }
-
     private void onStorageStateChangedAsync(String path, String oldState, String newState) {
         if (DEBUG) Log.i(TAG, String.format(
                 "Media {%s} state changed from {%s} -> {%s}", path, oldState, newState));
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index a21b089..3ed8bd8 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -49,6 +49,7 @@
 import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Debug;
 import android.os.Handler;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -58,6 +59,7 @@
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
+import android.util.Slog;
 import android.util.SparseArray;
 import android.util.TypedValue;
 import android.view.ActionMode;
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index 32fc18e..de58496 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import android.os.BatteryStats;
 import com.android.internal.app.IBatteryStats;
 import com.android.server.am.BatteryStatsService;
 
@@ -89,7 +90,6 @@
 
     private static final int DUMP_MAX_LENGTH = 24 * 1024;
     private static final String[] DUMPSYS_ARGS = new String[] { "--checkin", "--unplugged" };
-    private static final String BATTERY_STATS_SERVICE_NAME = "batteryinfo";
 
     private static final String DUMPSYS_DATA_PATH = "/data/system/";
 
@@ -509,7 +509,7 @@
     }
 
     private void logBatteryStatsLocked() {
-        IBinder batteryInfoService = ServiceManager.getService(BATTERY_STATS_SERVICE_NAME);
+        IBinder batteryInfoService = ServiceManager.getService(BatteryStats.SERVICE_NAME);
         if (batteryInfoService == null) return;
 
         DropBoxManager db = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
@@ -519,7 +519,7 @@
         FileOutputStream dumpStream = null;
         try {
             // dump the service to a file
-            dumpFile = new File(DUMPSYS_DATA_PATH + BATTERY_STATS_SERVICE_NAME + ".dump");
+            dumpFile = new File(DUMPSYS_DATA_PATH + BatteryStats.SERVICE_NAME + ".dump");
             dumpStream = new FileOutputStream(dumpFile);
             batteryInfoService.dump(dumpStream.getFD(), DUMPSYS_ARGS);
             FileUtils.sync(dumpStream);
@@ -642,15 +642,25 @@
                         update = false;
                     }
                     if (update) {
-                        mUpdatesStopped = true;
-                        processValuesLocked();
+                        long ident = Binder.clearCallingIdentity();
+                        try {
+                            mUpdatesStopped = true;
+                            processValuesLocked();
+                        } finally {
+                            Binder.restoreCallingIdentity(ident);
+                        }
                     }
                 } catch (NumberFormatException ex) {
                     pw.println("Bad value: " + value);
                 }
             } else if (args.length == 1 && "reset".equals(args[0])) {
-                mUpdatesStopped = false;
-                updateLocked();
+                long ident = Binder.clearCallingIdentity();
+                try {
+                    mUpdatesStopped = false;
+                    updateLocked();
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
             } else {
                 pw.println("Dump current battery state, or:");
                 pw.println("  set ac|usb|wireless|status|level|invalid <value>");
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 6f8c323..54f6118 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -97,6 +97,7 @@
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.am.BatteryStatsService;
+import com.android.server.connectivity.DataConnectionStats;
 import com.android.server.connectivity.Nat464Xlat;
 import com.android.server.connectivity.Tethering;
 import com.android.server.connectivity.Vpn;
@@ -346,6 +347,8 @@
     // the set of network types that can only be enabled by system/sig apps
     List mProtectedNetworks;
 
+    private DataConnectionStats mDataConnectionStats;
+
     public ConnectivityService(Context context, INetworkManagementService netd,
             INetworkStatsService statsService, INetworkPolicyManager policyManager) {
         // Currently, omitting a NetworkFactory will create one internally
@@ -574,6 +577,9 @@
 
         mCaptivePortalTracker = CaptivePortalTracker.makeCaptivePortalTracker(mContext, this);
         loadGlobalProxy();
+
+        mDataConnectionStats = new DataConnectionStats(mContext);
+        mDataConnectionStats.startMonitoring();
     }
 
     /**
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 0ab56df..fd6b467 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -195,6 +195,9 @@
 
     private int mCurrentUserId = UserHandle.USER_OWNER;
 
+    //TODO: Remove this hack
+    private boolean mInitialized;
+
     private UserState getCurrentUserStateLocked() {
         return getUserStateLocked(mCurrentUserId);
     }
@@ -771,6 +774,10 @@
 
     private void switchUser(int userId) {
         synchronized (mLock) {
+            if (mCurrentUserId == userId && mInitialized) {
+                return;
+            }
+
             // Disconnect from services for the old user.
             UserState oldUserState = getUserStateLocked(mCurrentUserId);
             oldUserState.onSwitchToAnotherUser();
@@ -1283,6 +1290,8 @@
     }
 
     private void onUserStateChangedLocked(UserState userState) {
+        // TODO: Remove this hack
+        mInitialized = true;
         updateLegacyCapabilities(userState);
         updateServicesLocked(userState);
         updateFilterKeyEventsLocked(userState);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 6b13fc7..ad6ae432 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -33,6 +33,7 @@
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.os.ProcessStats;
 import com.android.internal.os.TransferPipe;
+import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.server.AppOpsService;
 import com.android.server.AttributeCache;
@@ -204,6 +205,7 @@
     static final boolean DEBUG_BACKGROUND_BROADCAST = DEBUG_BROADCAST || false;
     static final boolean DEBUG_CLEANUP = localLOGV || false;
     static final boolean DEBUG_CONFIGURATION = localLOGV || false;
+    static final boolean DEBUG_FOCUS = true;
     static final boolean DEBUG_IMMERSIVE = localLOGV || false;
     static final boolean DEBUG_MU = localLOGV || false;
     static final boolean DEBUG_OOM_ADJ = localLOGV || false;
@@ -1367,9 +1369,9 @@
                         StringBuilder dropBuilder = new StringBuilder(1024);
                         StringBuilder logBuilder = new StringBuilder(1024);
                         StringWriter oomSw = new StringWriter();
-                        PrintWriter oomPw = new PrintWriter(oomSw);
+                        PrintWriter oomPw = new FastPrintWriter(oomSw, false, 256);
                         StringWriter catSw = new StringWriter();
-                        PrintWriter catPw = new PrintWriter(catSw);
+                        PrintWriter catPw = new FastPrintWriter(catSw, false, 256);
                         String[] emptyArgs = new String[] { };
                         StringBuilder tag = new StringBuilder(128);
                         StringBuilder stack = new StringBuilder(128);
@@ -1379,6 +1381,7 @@
                         dropBuilder.append(stack);
                         dropBuilder.append('\n');
                         dropBuilder.append('\n');
+                        oomPw.flush();
                         String oomString = oomSw.toString();
                         dropBuilder.append(oomString);
                         dropBuilder.append('\n');
@@ -1414,6 +1417,7 @@
                             catPw.println();
                             dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null);
                         }
+                        catPw.flush();
                         dropBuilder.append(catSw.toString());
                         addErrorToDropBox("lowmem", null, "system_server", null,
                                 null, tag.toString(), dropBuilder.toString(), null, null);
@@ -1920,6 +1924,16 @@
                                             st.rel_stime-otherSTime);
                                     ps.addSpeedStepTimes(cpuSpeedTimes);
                                     pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
+                                } else if (st.uid >= Process.FIRST_APPLICATION_UID) {
+                                    BatteryStatsImpl.Uid.Proc ps = st.batteryStats;
+                                    if (ps == null) {
+                                        st.batteryStats = ps = bstats.getProcessStatsLocked(st.uid,
+                                                "(Unknown)");
+                                    }
+                                    ps.addCpuTimeLocked(st.rel_utime-otherUTime,
+                                            st.rel_stime-otherSTime);
+                                    ps.addSpeedStepTimes(cpuSpeedTimes);
+                                    pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
                                 } else {
                                     BatteryStatsImpl.Uid.Proc ps =
                                             bstats.getProcessStatsLocked(st.name, st.pid);
@@ -1981,6 +1995,7 @@
 
     final void setFocusedActivityLocked(ActivityRecord r) {
         if (mFocusedActivity != r) {
+            if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedActivitiyLocked: r=" + r);
             mFocusedActivity = r;
             mStackSupervisor.setFocusedStack(r);
             if (r != null) {
@@ -1992,6 +2007,7 @@
 
     @Override
     public void setFocusedStack(int stackId) {
+        if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: stackId=" + stackId);
         mHandler.obtainMessage(SET_FOCUSED_STACK, stackId, 0).sendToTarget();
     }
 
@@ -6367,34 +6383,55 @@
 
     @Override
     public int createStack(int taskId, int relativeStackBoxId, int position, float weight) {
+        enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+                "createStack()");
         if (DEBUG_STACK) Slog.d(TAG, "createStack: taskId=" + taskId + " relStackBoxId=" +
                 relativeStackBoxId + " position=" + position + " weight=" + weight);
         synchronized (this) {
-            int stackId = mStackSupervisor.createStack();
-            mWindowManager.createStack(stackId, relativeStackBoxId, position, weight);
-            if (taskId > 0) {
-                moveTaskToStack(taskId, stackId, true);
+            long ident = Binder.clearCallingIdentity();
+            try {
+                int stackId = mStackSupervisor.createStack();
+                mWindowManager.createStack(stackId, relativeStackBoxId, position, weight);
+                if (taskId > 0) {
+                    moveTaskToStack(taskId, stackId, true);
+                }
+                return stackId;
+            } finally {
+                Binder.restoreCallingIdentity(ident);
             }
-            return stackId;
         }
     }
 
     @Override
     public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
+        enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+                "moveTaskToStack()");
         if (stackId == HOME_STACK_ID) {
             Slog.e(TAG, "moveTaskToStack: Attempt to move task " + taskId + " to home stack",
                     new RuntimeException("here").fillInStackTrace());
         }
         synchronized (this) {
-            if (DEBUG_STACK) Slog.d(TAG, "moveTaskToStack: moving task=" + taskId + " to stackId="
-                    + stackId + " toTop=" + toTop);
-            mStackSupervisor.moveTaskToStack(taskId, stackId, toTop);
+            long ident = Binder.clearCallingIdentity();
+            try {
+                if (DEBUG_STACK) Slog.d(TAG, "moveTaskToStack: moving task=" + taskId + " to stackId="
+                        + stackId + " toTop=" + toTop);
+                mStackSupervisor.moveTaskToStack(taskId, stackId, toTop);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
         }
     }
 
     @Override
     public void resizeStackBox(int stackBoxId, float weight) {
-        mWindowManager.resizeStackBox(stackBoxId, weight);
+        enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+                "resizeStackBox()");
+        long ident = Binder.clearCallingIdentity();
+        try {
+            mWindowManager.resizeStackBox(stackBoxId, weight);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
     }
 
     private ArrayList<StackInfo> getStacks() {
@@ -6444,30 +6481,44 @@
 
     @Override
     public List<StackBoxInfo> getStackBoxes() {
-        List<StackBoxInfo> stackBoxInfos = mWindowManager.getStackBoxInfos();
-        synchronized (this) {
-            List<StackInfo> stackInfos = getStacks();
-            for (StackBoxInfo stackBoxInfo : stackBoxInfos) {
-                addStackInfoToStackBoxInfo(stackBoxInfo, stackInfos);
+        enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+                "getStackBoxes()");
+        long ident = Binder.clearCallingIdentity();
+        try {
+            List<StackBoxInfo> stackBoxInfos = mWindowManager.getStackBoxInfos();
+            synchronized (this) {
+                List<StackInfo> stackInfos = getStacks();
+                for (StackBoxInfo stackBoxInfo : stackBoxInfos) {
+                    addStackInfoToStackBoxInfo(stackBoxInfo, stackInfos);
+                }
             }
+            return stackBoxInfos;
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
-        return stackBoxInfos;
     }
 
     @Override
     public StackBoxInfo getStackBoxInfo(int stackBoxId) {
-        List<StackBoxInfo> stackBoxInfos = mWindowManager.getStackBoxInfos();
-        StackBoxInfo info = null;
-        synchronized (this) {
-            List<StackInfo> stackInfos = getStacks();
-            for (StackBoxInfo stackBoxInfo : stackBoxInfos) {
-                addStackInfoToStackBoxInfo(stackBoxInfo, stackInfos);
-                if (stackBoxInfo.stackBoxId == stackBoxId) {
-                    info = stackBoxInfo;
+        enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+                "getStackBoxInfo()");
+        long ident = Binder.clearCallingIdentity();
+        try {
+            List<StackBoxInfo> stackBoxInfos = mWindowManager.getStackBoxInfos();
+            StackBoxInfo info = null;
+            synchronized (this) {
+                List<StackInfo> stackInfos = getStacks();
+                for (StackBoxInfo stackBoxInfo : stackBoxInfos) {
+                    addStackInfoToStackBoxInfo(stackBoxInfo, stackInfos);
+                    if (stackBoxInfo.stackBoxId == stackBoxId) {
+                        info = stackBoxInfo;
+                    }
                 }
             }
+            return info;
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
-        return info;
     }
 
     @Override
@@ -7527,8 +7578,13 @@
         }
 
         synchronized(this) {
-            mLockScreenShown = shown;
-            comeOutOfSleepIfNeededLocked();
+            long ident = Binder.clearCallingIdentity();
+            try {
+                mLockScreenShown = shown;
+                comeOutOfSleepIfNeededLocked();
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
         }
     }
 
@@ -7586,33 +7642,36 @@
         enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
                 "setDebugApp()");
 
-        // Note that this is not really thread safe if there are multiple
-        // callers into it at the same time, but that's not a situation we
-        // care about.
-        if (persistent) {
-            final ContentResolver resolver = mContext.getContentResolver();
-            Settings.Global.putString(
-                resolver, Settings.Global.DEBUG_APP,
-                packageName);
-            Settings.Global.putInt(
-                resolver, Settings.Global.WAIT_FOR_DEBUGGER,
-                waitForDebugger ? 1 : 0);
-        }
+        long ident = Binder.clearCallingIdentity();
+        try {
+            // Note that this is not really thread safe if there are multiple
+            // callers into it at the same time, but that's not a situation we
+            // care about.
+            if (persistent) {
+                final ContentResolver resolver = mContext.getContentResolver();
+                Settings.Global.putString(
+                    resolver, Settings.Global.DEBUG_APP,
+                    packageName);
+                Settings.Global.putInt(
+                    resolver, Settings.Global.WAIT_FOR_DEBUGGER,
+                    waitForDebugger ? 1 : 0);
+            }
 
-        synchronized (this) {
-            if (!persistent) {
-                mOrigDebugApp = mDebugApp;
-                mOrigWaitForDebugger = mWaitForDebugger;
+            synchronized (this) {
+                if (!persistent) {
+                    mOrigDebugApp = mDebugApp;
+                    mOrigWaitForDebugger = mWaitForDebugger;
+                }
+                mDebugApp = packageName;
+                mWaitForDebugger = waitForDebugger;
+                mDebugTransient = !persistent;
+                if (packageName != null) {
+                    forceStopPackageLocked(packageName, -1, false, false, true, true,
+                            UserHandle.USER_ALL, "set debug app");
+                }
             }
-            mDebugApp = packageName;
-            mWaitForDebugger = waitForDebugger;
-            mDebugTransient = !persistent;
-            if (packageName != null) {
-                final long origId = Binder.clearCallingIdentity();
-                forceStopPackageLocked(packageName, -1, false, false, true, true,
-                        UserHandle.USER_ALL, "set debug app");
-                Binder.restoreCallingIdentity(origId);
-            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
 
@@ -7851,12 +7910,33 @@
         }
     }
 
+    @Override
     public void unregisterProcessObserver(IProcessObserver observer) {
         synchronized (this) {
             mProcessObservers.unregister(observer);
         }
     }
 
+    @Override
+    public void convertToOpaque(IBinder token) {
+        final long origId = Binder.clearCallingIdentity();
+        try {
+            synchronized (this) {
+                final ActivityRecord r = ActivityRecord.isInStackLocked(token);
+                if (r == null) {
+                    return;
+                }
+                if (r.convertToOpaque()) {
+                    mWindowManager.setAppFullscreen(token);
+                    mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    @Override
     public void setImmersive(IBinder token, boolean immersive) {
         synchronized(this) {
             final ActivityRecord r = ActivityRecord.isInStackLocked(token);
@@ -7875,6 +7955,7 @@
         }
     }
 
+    @Override
     public boolean isImmersive(IBinder token) {
         synchronized (this) {
             ActivityRecord r = ActivityRecord.isInStackLocked(token);
@@ -7947,7 +8028,7 @@
         String reason = (pReason == null) ? "Unknown" : pReason;
         // XXX Note: don't acquire main activity lock here, because the window
         // manager calls in with its locks held.
-        
+
         boolean killed = false;
         synchronized (mPidsSelfLocked) {
             int[] types = new int[pids.length];
@@ -7962,7 +8043,7 @@
                     }
                 }
             }
-            
+
             // If the worst oom_adj is somewhere in the cached proc LRU range,
             // then constrain it so we will kill all cached procs.
             if (worstType < ProcessList.CACHED_APP_MAX_ADJ
@@ -8129,7 +8210,7 @@
         // no need to synchronize(this) just to read & return the value
         return mSystemReady;
     }
-    
+
     private static File getCalledPreBootReceiversFile() {
         File dataDir = Environment.getDataDirectory();
         File systemDir = new File(dataDir, "system");
@@ -10930,6 +11011,10 @@
                             r.processName, myTotalPss, 0);
                     procMems.add(pssItem);
 
+                    synchronized (this) {
+                        r.baseProcessTracker.addPss(myTotalPss);
+                    }
+
                     nativePss += mi.nativePss;
                     dalvikPss += mi.dalvikPss;
                     otherPss += mi.otherPss;
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 561dd0f..f730e07 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -71,7 +71,7 @@
     final String processName; // process where this component wants to run
     final String taskAffinity; // as per ActivityInfo.taskAffinity
     final boolean stateNotNeeded; // As per ActivityInfo.flags
-    final boolean fullscreen; // covers the full screen?
+    boolean fullscreen; // covers the full screen?
     final boolean noDisplay;  // activity is not displayed?
     final boolean componentSpecified;  // did caller specifiy an explicit component?
 
@@ -503,6 +503,21 @@
         }
     }
 
+    boolean convertToOpaque() {
+        if (fullscreen) {
+            return false;
+        }
+
+        AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
+                realTheme, com.android.internal.R.styleable.Window);
+        if (ent != null && !ent.array.getBoolean(
+                com.android.internal.R.styleable.Window_windowIsFloating, false)) {
+            fullscreen = true;
+            ++task.numFullscreen;
+        }
+        return fullscreen;
+    }
+
     void putInHistory() {
         if (!inHistory) {
             inHistory = true;
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 5e6bdb1..8e8bb55 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -69,6 +69,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -120,6 +121,10 @@
     // is being started.
     static final boolean SHOW_APP_STARTING_PREVIEW = true;
 
+    // For debugging to make sure the caller when acquiring/releasing our
+    // wake lock is the system process.
+    static final boolean VALIDATE_WAKE_LOCK_CALLER = true;
+
     enum ActivityState {
         INITIALIZING,
         RESUMED,
@@ -288,6 +293,10 @@
                     synchronized (mService) {
                         if (mLaunchingActivity.isHeld()) {
                             Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
+                            if (VALIDATE_WAKE_LOCK_CALLER
+                                    && Binder.getCallingUid() != Process.myUid()) {
+                                throw new IllegalStateException("Calling must be system uid");
+                            }
                             mLaunchingActivity.release();
                         }
                     }
@@ -328,6 +337,9 @@
         mStackSupervisor = service.mStackSupervisor;
         mContext = context;
         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
+            throw new IllegalStateException("Calling must be system uid");
+        }
         mLaunchingActivity =
                 pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
         mLaunchingActivity.setReferenceCounted(false);
@@ -595,6 +607,9 @@
 
     void stopIfSleepingLocked() {
         if (mLaunchingActivity.isHeld()) {
+            if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
+                throw new IllegalStateException("Calling must be system uid");
+            }
             mLaunchingActivity.release();
             mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
         }
@@ -722,6 +737,9 @@
         // If we are not going to sleep, we want to ensure the device is
         // awake until the next activity is started.
         if (!mService.isSleepingOrShuttingDown()) {
+            if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
+                throw new IllegalStateException("Calling must be system uid");
+            }
             mLaunchingActivity.acquire();
             if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
                 // To be safe, don't allow the wake lock to be held for too long.
@@ -1070,11 +1088,25 @@
                         r.visible = false;
                         try {
                             mWindowManager.setAppVisibility(r.appToken, false);
-                            if ((r.state == ActivityState.STOPPING
-                                    || r.state == ActivityState.STOPPED)
-                                    && r.app != null && r.app.thread != null) {
-                                if (DEBUG_VISBILITY) Slog.v(TAG, "Scheduling invisibility: " + r);
-                                r.app.thread.scheduleWindowVisibility(r.appToken, false);
+                            switch (r.state) {
+                                case STOPPING:
+                                case STOPPED:
+                                    if (r.app != null && r.app.thread != null) {
+                                        if (DEBUG_VISBILITY) Slog.v(
+                                                TAG, "Scheduling invisibility: " + r);
+                                        r.app.thread.scheduleWindowVisibility(r.appToken, false);
+                                    }
+                                    break;
+
+                                case INITIALIZING:
+                                case RESUMED:
+                                case PAUSING:
+                                case PAUSED:
+                                    stopActivityLocked(r);
+                                    break;
+
+                                default:
+                                    break;
                             }
                         } catch (Exception e) {
                             // Just skip on any failure; we'll make it
@@ -2092,6 +2124,9 @@
             // No longer need to keep the device awake.
             if (mResumedActivity == res && mLaunchingActivity.isHeld()) {
                 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
+                if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
+                    throw new IllegalStateException("Calling must be system uid");
+                }
                 mLaunchingActivity.release();
             }
 
@@ -3298,13 +3333,16 @@
         if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
             mLastPausedActivity = null;
         }
+        final ActivityRecord top = topRunningActivityLocked(null);
+        final boolean launchHomeTaskNext =
+                top != null && top.app == app && top.mLaunchHomeTaskNext;
 
         // Remove this application's activities from active lists.
         boolean hasVisibleActivities = removeHistoryRecordsForAppLocked(app);
 
         if (!restarting) {
             ActivityStack stack = mStackSupervisor.getFocusedStack();
-            if (stack == null) {
+            if (stack == null || launchHomeTaskNext) {
                 mStackSupervisor.resumeHomeActivity(null);
             } else if (!mStackSupervisor.resumeTopActivitiesLocked(stack, null, null)) {
                 // If there was nothing to resume, and we are not already
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index a4fd7ad..8d98109 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -22,6 +22,7 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static com.android.server.am.ActivityManagerService.localLOGV;
 import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION;
+import static com.android.server.am.ActivityManagerService.DEBUG_FOCUS;
 import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
 import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
 import static com.android.server.am.ActivityManagerService.DEBUG_STACK;
@@ -1198,9 +1199,13 @@
                 // Time to create the first app stack for this user.
                 int stackId = mService.createStack(-1, HOME_STACK_ID,
                         StackBox.TASK_STACK_GOES_OVER, 1.0f);
+                if (DEBUG_FOCUS) Slog.d(TAG, "getCorrectStack: New stack r=" + r + " stackId="
+                        + stackId);
                 mFocusedStack = getStack(stackId);
             }
             if (task != null) {
+                if (DEBUG_FOCUS) Slog.d(TAG, "getCorrectStack: Setting focused stack to r=" +
+                        r + " task=" + task);
                 mFocusedStack = task.stack;
             }
             return mFocusedStack;
@@ -1214,13 +1219,15 @@
         }
         if (!r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask())) {
             if (mStackState != STACK_STATE_HOME_IN_FRONT) {
-                if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
+                if (DEBUG_STACK || DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: mStackState old=" +
                         stackStateToString(mStackState) + " new=" +
                         stackStateToString(STACK_STATE_HOME_TO_FRONT) +
                         " Callers=" + Debug.getCallers(3));
                 mStackState = STACK_STATE_HOME_TO_FRONT;
             }
         } else {
+            if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: Setting focused stack to r=" +
+                    r + " task=" + r.task + " Callers=" + Debug.getCallers(3));
             mFocusedStack = r.task.stack;
             if (mStackState != STACK_STATE_HOME_IN_BACK) {
                 if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
@@ -2170,29 +2177,31 @@
         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
             final ActivityStack stack = mStacks.get(stackNdx);
             final ActivityRecord r = stack.topRunningActivityLocked(null);
+            final ActivityState state = r == null ? ActivityState.DESTROYED : r.state;
             if (isFrontStack(stack)) {
                 if (r == null) {
                     Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
                 } else {
-                    if (stack.mPausingActivity != null) {
+                    final ActivityRecord pausing = stack.mPausingActivity;
+                    if (pausing != null && pausing == r) {
                         Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
-                            " state=" + r.state);
+                            " state=" + state);
                     }
-                    if (r.state != ActivityState.INITIALIZING &&
-                            r.state != ActivityState.RESUMED) {
+                    if (state != ActivityState.INITIALIZING && state != ActivityState.RESUMED) {
                         Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
-                                " state=" + r.state);
+                                " state=" + state);
                     }
                 }
             } else {
-                if (stack.mResumedActivity != null) {
+                final ActivityRecord resumed = stack.mResumedActivity;
+                if (resumed != null && resumed == r) {
                     Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
-                        " state=" + r.state);
+                        " state=" + state);
                 }
-                if (r != null && (r.state == ActivityState.INITIALIZING
-                        || r.state == ActivityState.RESUMED)) {
+                if (r != null && (state == ActivityState.INITIALIZING
+                        || state == ActivityState.RESUMED)) {
                     Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
-                            " state=" + r.state);
+                            " state=" + state);
                 }
             }
         }
diff --git a/services/java/com/android/server/am/ProcessTracker.java b/services/java/com/android/server/am/ProcessTracker.java
index 8a83412..30470f1 100644
--- a/services/java/com/android/server/am/ProcessTracker.java
+++ b/services/java/com/android/server/am/ProcessTracker.java
@@ -24,6 +24,7 @@
 import android.util.ArraySet;
 import android.util.SparseArray;
 import android.util.TimeUtils;
+import com.android.internal.util.ArrayUtils;
 import com.android.server.ProcessMap;
 
 import java.io.FileDescriptor;
@@ -47,6 +48,12 @@
     public static final int STATE_CACHED = 9;
     public static final int STATE_COUNT = STATE_CACHED+1;
 
+    public static final int PSS_SAMPLE_COUNT = 0;
+    public static final int PSS_MINIMUM = 1;
+    public static final int PSS_AVERAGE = 2;
+    public static final int PSS_MAXIMUM = 3;
+    public static final int PSS_COUNT = PSS_MAXIMUM+1;
+
     public static final int ADJ_NOTHING = -1;
     public static final int ADJ_MEM_FACTOR_NORMAL = 0;
     public static final int ADJ_MEM_FACTOR_MODERATE = 1;
@@ -58,6 +65,23 @@
     public static final int ADJ_SCREEN_ON = ADJ_SCREEN_MOD;
     public static final int ADJ_COUNT = ADJ_SCREEN_ON*2;
 
+    // Most data is kept in a sparse data structure: an integer array which integer
+    // holds the type of the entry, and the identifier for a long array that data
+    // exists in and the offset into the array to find it.  The constants below
+    // define the encoding of that data in an integer.
+
+    // Where the "type"/"state" part of the data appears in an offset integer.
+    static int OFFSET_TYPE_SHIFT = 0;
+    static int OFFSET_TYPE_MASK = 0xff;
+
+    // Where the "which array" part of the data appears in an offset integer.
+    static int OFFSET_ARRAY_SHIFT = 8;
+    static int OFFSET_ARRAY_MASK = 0xff;
+
+    // Where the "index into array" part of the data appears in an offset integer.
+    static int OFFSET_INDEX_SHIFT = 16;
+    static int OFFSET_INDEX_MASK = 0xffff;
+
     static final String[] STATE_NAMES = new String[] {
             "Persistent ", "Top        ", "Foreground ", "Visible    ", "Perceptible",
             "Backup     ", "Service    ", "Home       ", "Previous   ", "Cached     "
@@ -76,6 +100,19 @@
             "backup", "service", "home", "prev", "cached"
     };
 
+    static final String[] ADJ_SCREEN_TAGS = new String[] {
+            "0", "1"
+    };
+
+    static final String[] ADJ_MEM_TAGS = new String[] {
+            "n", "m",  "l", "c"
+    };
+
+    static final String[] STATE_TAGS = new String[] {
+            "p", "t", "f", "v", "t",
+            "b", "s", "h", "v", "c"
+    };
+
     static final String CSV_SEP = "\t";
 
     final Context mContext;
@@ -88,10 +125,16 @@
         final int mUid;
         final String mName;
 
-        final long[] mDurations = new long[STATE_COUNT*ADJ_COUNT];
+        int[] mDurationsTable;
+        int mDurationsTableSize;
+
+        //final long[] mDurations = new long[STATE_COUNT*ADJ_COUNT];
         int mCurState = STATE_NOTHING;
         long mStartTime;
 
+        int[] mPssTable;
+        int mPssTableSize;
+
         boolean mMultiPackage;
 
         long mTmpTotalTime;
@@ -126,7 +169,36 @@
 
         ProcessState clone(String pkg, long now) {
             ProcessState pnew = new ProcessState(this, pkg, mUid, mName, now);
-            pnew.add(this, now);
+            if (mDurationsTable != null) {
+                mState.mFindTable = new int[mDurationsTable.length];
+                mState.mFindTableSize = 0;
+                for (int i=0; i<mDurationsTableSize; i++) {
+                    int origEnt = mDurationsTable[i];
+                    int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
+                    int newOff = mState.addLongData(i, type, 1);
+                    mState.mFindTable[i] = newOff | type;
+                    mState.setLong(newOff, 0, mState.getLong(origEnt, 0));
+                }
+                pnew.mDurationsTable = mState.mFindTable;
+                pnew.mDurationsTableSize = mState.mFindTableSize;
+            }
+            /*
+            if (mPssTable != null) {
+                mState.mFindTable = new int[mPssTable.length];
+                mState.mFindTableSize = 0;
+                for (int i=0; i<mPssTableSize; i++) {
+                    int origEnt = mPssTable[i];
+                    int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
+                    int newOff = mState.addLongData(i, type, PSS_COUNT);
+                    mState.mFindTable[i] = newOff | type;
+                    for (int j=0; j<PSS_COUNT; j++) {
+                        mState.setLong(newOff, j, mState.getLong(origEnt, j));
+                    }
+                }
+                pnew.mPssTable = mState.mFindTable;
+                pnew.mPssTableSize = mState.mFindTableSize;
+            }
+            */
             return pnew;
         }
 
@@ -167,21 +239,87 @@
             if (mCurState != state) {
                 if (mCurState != STATE_NOTHING) {
                     long dur = now - mStartTime;
-                    mDurations[mCurState] += dur;
+                    int idx = State.binarySearch(mDurationsTable, mDurationsTableSize, mCurState);
+                    int off;
+                    if (idx >= 0) {
+                        off = mDurationsTable[idx];
+                    } else {
+                        mState.mFindTable = mDurationsTable;
+                        mState.mFindTableSize = mDurationsTableSize;
+                        off = mState.addLongData(~idx, mCurState, 1);
+                        mDurationsTable = mState.mFindTable;
+                        mDurationsTableSize = mState.mFindTableSize;
+                    }
+                    long[] longs = mState.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
+                    longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += dur;
                 }
                 mCurState = state;
                 mStartTime = now;
             }
         }
 
-        void add(ProcessState other, long now) {
-            for (int i=0; i<(STATE_COUNT*ADJ_COUNT); i++) {
-                mDurations[i] += other.mDurations[i];
-                if (other.mCurState == i) {
-                    mDurations[i] += now - other.mStartTime;
+        public void addPss(long pss) {
+            if (mCurState != STATE_NOTHING) {
+                int idx = State.binarySearch(mPssTable, mPssTableSize, mCurState);
+                int off;
+                if (idx >= 0) {
+                    off = mPssTable[idx];
+                } else {
+                    mState.mFindTable = mPssTable;
+                    mState.mFindTableSize = mPssTableSize;
+                    off = mState.addLongData(~idx, mCurState, PSS_COUNT);
+                    mPssTable = mState.mFindTable;
+                    mPssTableSize = mState.mFindTableSize;
+                }
+                long[] longs = mState.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
+                idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
+                long count = longs[idx+PSS_SAMPLE_COUNT];
+                if (count == 0) {
+                    longs[idx+PSS_SAMPLE_COUNT] = 1;
+                    longs[idx+PSS_MINIMUM] = pss;
+                    longs[idx+PSS_AVERAGE] = pss;
+                    longs[idx+PSS_MAXIMUM] = pss;
+                } else {
+                    longs[idx+PSS_SAMPLE_COUNT] = count+1;
+                    if (longs[idx+PSS_MINIMUM] > pss) {
+                        longs[idx+PSS_MINIMUM] = pss;
+                    }
+                    longs[idx+PSS_AVERAGE] = ((longs[idx+PSS_AVERAGE]*count)+pss)/(count+1);
+                    if (longs[idx+PSS_MAXIMUM] < pss) {
+                        longs[idx+PSS_MAXIMUM] = pss;
+                    }
                 }
             }
         }
+
+        long getDuration(int state, long now) {
+            int idx = State.binarySearch(mDurationsTable, mDurationsTableSize, state);
+            long time = idx >= 0 ? mState.getLong(mDurationsTable[idx], 0) : 0;
+            if (mCurState == state) {
+                time += now - mStartTime;
+            }
+            return time;
+        }
+
+        long getPssSampleCount(int state) {
+            int idx = State.binarySearch(mPssTable, mPssTableSize, state);
+            return idx >= 0 ? mState.getLong(mPssTable[idx], PSS_SAMPLE_COUNT) : 0;
+        }
+
+        long getPssMinimum(int state) {
+            int idx = State.binarySearch(mPssTable, mPssTableSize, state);
+            return idx >= 0 ? mState.getLong(mPssTable[idx], PSS_MINIMUM) : 0;
+        }
+
+        long getPssAverage(int state) {
+            int idx = State.binarySearch(mPssTable, mPssTableSize, state);
+            return idx >= 0 ? mState.getLong(mPssTable[idx], PSS_AVERAGE) : 0;
+        }
+
+        long getPssMaximum(int state) {
+            int idx = State.binarySearch(mPssTable, mPssTableSize, state);
+            return idx >= 0 ? mState.getLong(mPssTable[idx], PSS_MAXIMUM) : 0;
+        }
     }
 
     public static final class ServiceState {
@@ -257,6 +395,76 @@
         int mMemFactor = STATE_NOTHING;
         long mStartTime;
 
+        static final int LONGS_SIZE = 4096;
+        final ArrayList<long[]> mLongs = new ArrayList<long[]>();
+        int mNextLong;
+
+        int[] mFindTable;
+        int mFindTableSize;
+
+        int addLongData(int index, int type, int num) {
+            int tableLen = mFindTable != null ? mFindTable.length : 0;
+            if (mFindTableSize >= tableLen) {
+                int newSize = ArrayUtils.idealIntArraySize(tableLen + 1);
+                int[] newTable = new int[newSize];
+                if (tableLen > 0) {
+                    System.arraycopy(mFindTable, 0, newTable, 0, tableLen);
+                }
+                mFindTable = newTable;
+            }
+            if (mFindTableSize > 0 && mFindTableSize - index != 0) {
+                System.arraycopy(mFindTable, index, mFindTable, index + 1,
+                        mFindTableSize - index);
+            }
+            int off = allocLongData(num);
+            mFindTable[index] = type | off;
+            mFindTableSize++;
+            return off;
+        }
+
+        int allocLongData(int num) {
+            int whichLongs = mLongs.size()-1;
+            long[] longs = mLongs.get(whichLongs);
+            if (mNextLong + num > longs.length) {
+                longs = new long[LONGS_SIZE];
+                mLongs.add(longs);
+                whichLongs++;
+                mNextLong = 0;
+            }
+            int off = (whichLongs<<OFFSET_ARRAY_SHIFT) | (mNextLong<<OFFSET_INDEX_SHIFT);
+            mNextLong += num;
+            return off;
+        }
+
+        void setLong(int off, int index, long value) {
+            long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
+            longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)] = value;
+        }
+
+        long getLong(int off, int index) {
+            long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
+            return longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)];
+        }
+
+        static int binarySearch(int[] array, int size, int value) {
+            int lo = 0;
+            int hi = size - 1;
+
+            while (lo <= hi) {
+                int mid = (lo + hi) >>> 1;
+                int midVal = (array[mid] >> OFFSET_TYPE_SHIFT) & OFFSET_TYPE_MASK;
+
+                if (midVal < value) {
+                    lo = mid + 1;
+                } else if (midVal > value) {
+                    hi = mid - 1;
+                } else {
+                    return mid;  // value found
+                }
+            }
+            return ~lo;  // value not present
+        }
+
         PackageState getPackageStateLocked(String packageName, int uid) {
             PackageState as = mPackages.get(packageName, uid);
             if (as != null) {
@@ -305,9 +513,16 @@
             return ps;
         }
 
+        State() {
+            reset();
+        }
+
         void reset() {
             mPackages.getMap().clear();
             mProcesses.getMap().clear();
+            mLongs.clear();
+            mLongs.add(new long[LONGS_SIZE]);
+            mNextLong = 0;
             Arrays.fill(mMemFactorDurations, 0);
             mMemFactor = STATE_NOTHING;
             mStartTime = 0;
@@ -480,11 +695,7 @@
                     time += now - curStartTime;
                 }
                 pw.print(sep);
-                if (time != 0) {
-                    pw.print(time);
-                } else {
-                    pw.print("0");
-                }
+                pw.print(time);
             }
         }
     }
@@ -510,15 +721,21 @@
     long computeProcessTimeLocked(ProcessState proc, int[] screenStates, int[] memStates,
                 int[] procStates, long now) {
         long totalTime = 0;
+        /*
+        for (int i=0; i<proc.mDurationsTableSize; i++) {
+            int val = proc.mDurationsTable[i];
+            totalTime += proc.mState.getLong(val, 0);
+            if ((val&0xff) == proc.mCurState) {
+                totalTime += now - proc.mStartTime;
+            }
+        }
+        */
         for (int is=0; is<screenStates.length; is++) {
             for (int im=0; im<memStates.length; im++) {
                 for (int ip=0; ip<procStates.length; ip++) {
                     int bucket = ((screenStates[is]+ memStates[im]) * STATE_COUNT)
                             + procStates[ip];
-                    totalTime += proc.mDurations[bucket];
-                    if (proc.mCurState == bucket) {
-                        totalTime += now - proc.mStartTime;
-                    }
+                    totalTime += proc.getDuration(bucket, now);
                 }
             }
         }
@@ -579,10 +796,9 @@
                     final int iscreen = screenStates[is];
                     final int imem = memStates[im];
                     final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
-                    long time = proc.mDurations[bucket];
+                    long time = proc.getDuration(bucket, now);
                     String running = "";
                     if (proc.mCurState == bucket) {
-                        time += now - proc.mStartTime;
                         running = " (running)";
                     }
                     if (time != 0) {
@@ -617,6 +833,52 @@
         }
     }
 
+    void dumpProcessPss(PrintWriter pw, String prefix, ProcessState proc, int[] screenStates,
+            int[] memStates, int[] procStates) {
+        boolean printedHeader = false;
+        int printedScreen = -1;
+        for (int is=0; is<screenStates.length; is++) {
+            int printedMem = -1;
+            for (int im=0; im<memStates.length; im++) {
+                for (int ip=0; ip<procStates.length; ip++) {
+                    final int iscreen = screenStates[is];
+                    final int imem = memStates[im];
+                    final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
+                    long count = proc.getPssSampleCount(bucket);
+                    if (count > 0) {
+                        if (!printedHeader) {
+                            pw.print(prefix);
+                            pw.print("PSS (");
+                            pw.print(proc.mPssTableSize);
+                            pw.println(" entries):");
+                            printedHeader = true;
+                        }
+                        pw.print(prefix);
+                        pw.print("  ");
+                        if (screenStates.length > 1) {
+                            printScreenLabel(pw, printedScreen != iscreen
+                                    ? iscreen : STATE_NOTHING);
+                            printedScreen = iscreen;
+                        }
+                        if (memStates.length > 1) {
+                            printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
+                            printedMem = imem;
+                        }
+                        pw.print(STATE_NAMES[procStates[ip]]); pw.print(": ");
+                        pw.print(count);
+                        pw.print(" samples ");
+                        pw.print(proc.getPssMinimum(bucket));
+                        pw.print("kB ");
+                        pw.print(proc.getPssAverage(bucket));
+                        pw.print("kB ");
+                        pw.print(proc.getPssMaximum(bucket));
+                        pw.println("kB");
+                    }
+                }
+            }
+        }
+    }
+
     void dumpStateHeadersCsv(PrintWriter pw, String sep, int[] screenStates,
             int[] memStates, int[] procStates) {
         final int NS = screenStates != null ? screenStates.length : 1;
@@ -673,19 +935,12 @@
                                 final int vaproc = sepProcStates ? 0 : procStates[ipa];
                                 final int bucket = ((vsscreen + vascreen + vsmem + vamem)
                                         * STATE_COUNT) + vsproc + vaproc;
-                                totalTime += proc.mDurations[bucket];
-                                if (proc.mCurState == bucket) {
-                                    totalTime += now - proc.mStartTime;
-                                }
+                                totalTime += proc.getDuration(bucket, now);
                             }
                         }
                     }
                     pw.print(CSV_SEP);
-                    if (totalTime != 0) {
-                        pw.print(totalTime);
-                    } else {
-                        pw.print("0");
-                    }
+                    pw.print(totalTime);
                 }
             }
         }
@@ -700,8 +955,14 @@
             pw.print(proc.mName);
             pw.print(" / ");
             UserHandle.formatUid(pw, proc.mUid);
+            pw.print(" (");
+            pw.print(proc.mDurationsTableSize);
+            pw.print(" entries)");
             pw.println(":");
             dumpProcessState(pw, innerPrefix, proc, screenStates, memStates, procStates, now);
+            if (proc.mPssTableSize > 0) {
+                dumpProcessPss(pw, innerPrefix, proc, screenStates, memStates, procStates);
+            }
         }
     }
 
@@ -753,8 +1014,7 @@
         return false;
     }
 
-    void dumpAllProcessState(PrintWriter pw, String prefix, boolean isCheckin,
-            ProcessState proc, long now) {
+    void dumpAllProcessState(PrintWriter pw, String prefix, ProcessState proc, long now) {
         long totalTime = 0;
         int printedScreen = -1;
         for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
@@ -762,50 +1022,97 @@
             for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
                 for (int is=0; is<STATE_NAMES.length; is++) {
                     int bucket = is+(STATE_COUNT*(imem+iscreen));
-                    long time = proc.mDurations[bucket];
+                    long time = proc.getDuration(bucket, now);
                     String running = "";
                     if (proc.mCurState == bucket) {
-                        time += now - proc.mStartTime;
                         running = " (running)";
                     }
-                    if (!isCheckin) {
-                        if (time != 0) {
-                            pw.print(prefix);
-                            printScreenLabel(pw, printedScreen != iscreen
-                                    ? iscreen : STATE_NOTHING);
-                            printedScreen = iscreen;
-                            printMemLabel(pw, printedMem != imem
-                                    ? imem : STATE_NOTHING);
-                            printedMem = imem;
-                            pw.print(STATE_NAMES[is]); pw.print(": ");
-                            TimeUtils.formatDuration(time, pw); pw.println(running);
-                            totalTime += time;
-                        }
-                    } else {
-                        pw.print(",");
-                        if (time != 0) {
-                            pw.print(time);
-                        } else {
-                            pw.print("0");
-                        }
+                    if (time != 0) {
+                        pw.print(prefix);
+                        printScreenLabel(pw, printedScreen != iscreen
+                                ? iscreen : STATE_NOTHING);
+                        printedScreen = iscreen;
+                        printMemLabel(pw, printedMem != imem
+                                ? imem : STATE_NOTHING);
+                        printedMem = imem;
+                        pw.print(STATE_NAMES[is]); pw.print(": ");
+                        TimeUtils.formatDuration(time, pw); pw.println(running);
+                        totalTime += time;
                     }
                 }
             }
         }
-        if (!isCheckin) {
-            if (totalTime != 0) {
-                pw.print(prefix);
-                printScreenLabel(pw, STATE_NOTHING);
-                printMemLabel(pw, STATE_NOTHING);
-                pw.print("TOTAL      : ");
-                TimeUtils.formatDuration(totalTime, pw);
-                pw.println();
-            }
-        } else {
+        if (totalTime != 0) {
+            pw.print(prefix);
+            printScreenLabel(pw, STATE_NOTHING);
+            printMemLabel(pw, STATE_NOTHING);
+            pw.print("TOTAL      : ");
+            TimeUtils.formatDuration(totalTime, pw);
             pw.println();
         }
     }
 
+    static int printArrayEntry(PrintWriter pw, String[] array, int value, int mod) {
+        int index = value/mod;
+        if (index >= 0 && index < array.length) {
+            pw.print(array[index]);
+        } else {
+            pw.print('?');
+        }
+        return value - index*mod;
+    }
+
+    void printProcStateTag(PrintWriter pw, int state) {
+        state = printArrayEntry(pw, ADJ_SCREEN_TAGS,  state, ADJ_SCREEN_MOD*STATE_COUNT);
+        state = printArrayEntry(pw, ADJ_MEM_TAGS,  state, STATE_COUNT);
+        printArrayEntry(pw, STATE_TAGS,  state, 1);
+    }
+
+    void printProcStateTagAndValue(PrintWriter pw, int state, long value) {
+        pw.print(',');
+        printProcStateTag(pw, state);
+        pw.print(':');
+        pw.print(value);
+    }
+
+    void dumpAllProcessStateCheckin(PrintWriter pw, ProcessState proc, long now) {
+        boolean didCurState = false;
+        for (int i=0; i<proc.mDurationsTableSize; i++) {
+            int off = proc.mDurationsTable[i];
+            int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
+            long time = proc.mState.getLong(off, 0);
+            if (proc.mCurState == type) {
+                didCurState = true;
+                time += now - proc.mStartTime;
+            }
+            printProcStateTagAndValue(pw, type, time);
+        }
+        if (!didCurState) {
+            printProcStateTagAndValue(pw, proc.mCurState, now - proc.mStartTime);
+        }
+    }
+
+    void dumpAllProcessPssCheckin(PrintWriter pw, ProcessState proc, long now) {
+        for (int i=0; i<proc.mPssTableSize; i++) {
+            int off = proc.mPssTable[i];
+            int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
+            long count = proc.mState.getLong(off, PSS_SAMPLE_COUNT);
+            long min = proc.mState.getLong(off, PSS_MINIMUM);
+            long avg = proc.mState.getLong(off, PSS_AVERAGE);
+            long max = proc.mState.getLong(off, PSS_MAXIMUM);
+            pw.print(',');
+            printProcStateTag(pw, type);
+            pw.print(':');
+            pw.print(count);
+            pw.print(':');
+            pw.print(min);
+            pw.print(':');
+            pw.print(avg);
+            pw.print(':');
+            pw.print(max);
+        }
+    }
+
     static int[] parseStateList(String[] states, int mult, String arg, boolean[] outSep,
             String[] outError) {
         ArrayList<Integer> res = new ArrayList<Integer>();
@@ -1025,6 +1332,8 @@
                     if (NPROCS > 0 || NSRVS > 0) {
                         if (!printedHeader) {
                             pw.println("Per-Package Process Stats:");
+                            pw.print("  Num long arrays: "); pw.println(mState.mLongs.size());
+                            pw.print("  Next long entry: "); pw.println(mState.mNextLong);
                             printedHeader = true;
                         }
                         pw.print("  * "); pw.print(pkgName); pw.print(" / ");
@@ -1032,10 +1341,15 @@
                     }
                 }
                 for (int iproc=0; iproc<NPROCS; iproc++) {
+                    ProcessState proc = state.mProcesses.valueAt(iproc);
                     if (!isCheckin) {
                         pw.print("      Process ");
                         pw.print(state.mProcesses.keyAt(iproc));
+                        pw.print(" (");
+                        pw.print(proc.mDurationsTableSize);
+                        pw.print(" entries)");
                         pw.println(":");
+                        dumpAllProcessState(pw, "        ", proc, now);
                     } else {
                         pw.print("pkgproc,");
                         pw.print(pkgName);
@@ -1043,9 +1357,9 @@
                         pw.print(uid);
                         pw.print(",");
                         pw.print(state.mProcesses.keyAt(iproc));
+                        dumpAllProcessStateCheckin(pw, proc, now);
+                        pw.println();
                     }
-                    dumpAllProcessState(pw, "        ", isCheckin,
-                            state.mProcesses.valueAt(iproc), now);
                 }
                 for (int isvc=0; isvc<NSRVS; isvc++) {
                     if (!isCheckin) {
@@ -1125,14 +1439,25 @@
                 for (int iu=0; iu<uids.size(); iu++) {
                     int uid = uids.keyAt(iu);
                     ProcessState state = uids.valueAt(iu);
-                    pw.print("proc,");
-                    pw.print(procName);
-                    pw.print(",");
-                    pw.print(uid);
-                    dumpAllProcessState(pw, "        ", isCheckin, state, now);
+                    if (state.mDurationsTableSize > 0) {
+                        pw.print("proc,");
+                        pw.print(procName);
+                        pw.print(",");
+                        pw.print(uid);
+                        dumpAllProcessStateCheckin(pw, state, now);
+                        pw.println();
+                    }
+                    if (state.mPssTableSize > 0) {
+                        pw.print("pss,");
+                        pw.print(procName);
+                        pw.print(",");
+                        pw.print(uid);
+                        dumpAllProcessPssCheckin(pw, state, now);
+                        pw.println();
+                    }
                 }
             }
-            pw.print("total,");
+            pw.print("total");
             dumpSingleTimeCsv(pw, ",", mState.mMemFactorDurations, mState.mMemFactor,
                     mState.mStartTime, now);
             pw.println();
diff --git a/services/java/com/android/server/connectivity/DataConnectionStats.java b/services/java/com/android/server/connectivity/DataConnectionStats.java
new file mode 100644
index 0000000..227ab23
--- /dev/null
+++ b/services/java/com/android/server/connectivity/DataConnectionStats.java
@@ -0,0 +1,154 @@
+/*
+ * 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.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.os.RemoteException;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.server.am.BatteryStatsService;
+
+public class DataConnectionStats extends BroadcastReceiver {
+    private static final String TAG = "DataConnectionStats";
+    private static final boolean DEBUG = false;
+
+    private final Context mContext;
+    private final IBatteryStats mBatteryStats;
+
+    private IccCardConstants.State mSimState = IccCardConstants.State.READY;
+    private SignalStrength mSignalStrength;
+    private ServiceState mServiceState;
+    private int mDataState = TelephonyManager.DATA_DISCONNECTED;
+
+    public DataConnectionStats(Context context) {
+        mContext = context;
+        mBatteryStats = BatteryStatsService.getService();
+    }
+
+    public void startMonitoring() {
+        TelephonyManager phone =
+                (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
+        phone.listen(mPhoneStateListener,
+                PhoneStateListener.LISTEN_SERVICE_STATE
+              | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
+              | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
+              | PhoneStateListener.LISTEN_DATA_ACTIVITY);
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+        filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
+        mContext.registerReceiver(this, filter);
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final String action = intent.getAction();
+        if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
+            updateSimState(intent);
+            notePhoneDataConnectionState();
+        } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
+                action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
+            notePhoneDataConnectionState();
+       }
+    }
+
+    private void notePhoneDataConnectionState() {
+        if (mServiceState == null) {
+            return;
+        }
+        boolean simReadyOrUnknown = mSimState == IccCardConstants.State.READY
+                || mSimState == IccCardConstants.State.UNKNOWN;
+        boolean visible = (simReadyOrUnknown || isCdma()) // we only check the sim state for GSM
+                && hasService()
+                && mDataState == TelephonyManager.DATA_CONNECTED;
+        int networkType = mServiceState.getDataNetworkType();
+        if (DEBUG) Log.d(TAG, String.format("Noting data connection for network type %s: %svisible",
+                networkType, visible ? "" : "not "));
+        try {
+            mBatteryStats.notePhoneDataConnectionState(networkType, visible);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Error noting data connection state", e);
+        }
+    }
+
+    private final void updateSimState(Intent intent) {
+        String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
+        if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
+            mSimState = IccCardConstants.State.ABSENT;
+        } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
+            mSimState = IccCardConstants.State.READY;
+        } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
+            final String lockedReason =
+                    intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
+            if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
+                mSimState = IccCardConstants.State.PIN_REQUIRED;
+            } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
+                mSimState = IccCardConstants.State.PUK_REQUIRED;
+            } else {
+                mSimState = IccCardConstants.State.NETWORK_LOCKED;
+            }
+        } else {
+            mSimState = IccCardConstants.State.UNKNOWN;
+        }
+    }
+
+    private boolean isCdma() {
+        return mSignalStrength != null && !mSignalStrength.isGsm();
+    }
+
+    private boolean hasService() {
+        return mServiceState != null
+                && mServiceState.getState() != ServiceState.STATE_OUT_OF_SERVICE
+                && mServiceState.getState() != ServiceState.STATE_POWER_OFF;
+    }
+
+    private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+        @Override
+        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+            mSignalStrength = signalStrength;
+        }
+
+        @Override
+        public void onServiceStateChanged(ServiceState state) {
+            mServiceState = state;
+            notePhoneDataConnectionState();
+        }
+
+        @Override
+        public void onDataConnectionStateChanged(int state, int networkType) {
+            mDataState = state;
+            notePhoneDataConnectionState();
+        }
+
+        @Override
+        public void onDataActivity(int direction) {
+            notePhoneDataConnectionState();
+        }
+    };
+}
diff --git a/services/java/com/android/server/content/SyncManager.java b/services/java/com/android/server/content/SyncManager.java
index 80c7d88..9e2e841 100644
--- a/services/java/com/android/server/content/SyncManager.java
+++ b/services/java/com/android/server/content/SyncManager.java
@@ -75,6 +75,7 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.accounts.AccountManagerService;
+import com.android.server.content.SyncStorageEngine.AuthorityInfo;
 import com.android.server.content.SyncStorageEngine.OnSyncRequestListener;
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
@@ -112,7 +113,7 @@
     private static final long MAX_TIME_PER_SYNC;
 
     static {
-        final boolean isLargeRAM = ActivityManager.isLargeRAM();
+        final boolean isLargeRAM = !ActivityManager.isLowRamDeviceStatic();
         int defaultMaxInitSyncs = isLargeRAM ? 5 : 2;
         int defaultMaxRegularSyncs = isLargeRAM ? 2 : 1;
         MAX_SIMULTANEOUS_INITIALIZATION_SYNCS =
@@ -1248,10 +1249,11 @@
                     continue;
                 }
                 int row = table.getNumRows();
-                SyncStorageEngine.AuthorityInfo settings =
-                        mSyncStorageEngine.getOrCreateAuthority(
+                Pair<AuthorityInfo, SyncStatusInfo> syncAuthoritySyncStatus = 
+                        mSyncStorageEngine.getCopyOfAuthorityWithSyncStatus(
                                 account.account, account.userId, syncAdapterType.type.authority);
-                SyncStatusInfo status = mSyncStorageEngine.getOrCreateSyncStatus(settings);
+                SyncStorageEngine.AuthorityInfo settings = syncAuthoritySyncStatus.first;
+                SyncStatusInfo status = syncAuthoritySyncStatus.second;
 
                 String authority = settings.authority;
                 if (authority.length() > 50) {
@@ -1269,10 +1271,10 @@
 
 
                 for (int i = 0; i < settings.periodicSyncs.size(); i++) {
-                    final Pair<Bundle, Long> pair = settings.periodicSyncs.get(0);
+                    final Pair<Bundle, Long> pair = settings.periodicSyncs.get(i);
                     final String period = String.valueOf(pair.second);
                     final String extras = pair.first.size() > 0 ? pair.first.toString() : "";
-                    final String next = formatTime(status.getPeriodicSyncTime(0)
+                    final String next = formatTime(status.getPeriodicSyncTime(i)
                             + pair.second * 1000);
                     table.set(row + i * 2, 12, period + extras);
                     table.set(row + i * 2 + 1, 12, next);
@@ -1758,7 +1760,8 @@
             final Pair<Account, String> wakeLockKey = Pair.create(account, authority);
             PowerManager.WakeLock wakeLock = mWakeLocks.get(wakeLockKey);
             if (wakeLock == null) {
-                final String name = SYNC_WAKE_LOCK_PREFIX + "_" + authority + "_" + account;
+                final String name = SYNC_WAKE_LOCK_PREFIX + "/" + authority + "/" + account.type
+                        + "/" + account.name;
                 wakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name);
                 wakeLock.setReferenceCounted(false);
                 mWakeLocks.put(wakeLockKey, wakeLock);
@@ -1942,30 +1945,36 @@
 
             final long nowAbsolute = System.currentTimeMillis();
             final long shiftedNowAbsolute = (0 < nowAbsolute - mSyncRandomOffsetMillis)
-                                               ? (nowAbsolute  - mSyncRandomOffsetMillis) : 0;
+                    ? (nowAbsolute - mSyncRandomOffsetMillis) : 0;
 
-            ArrayList<SyncStorageEngine.AuthorityInfo> infos = mSyncStorageEngine.getAuthorities();
-            for (SyncStorageEngine.AuthorityInfo info : infos) {
-                // skip the sync if the account of this operation no longer exists
-                if (!containsAccountAndUser(accounts, info.account, info.userId)) {
+            ArrayList<Pair<AuthorityInfo, SyncStatusInfo>> infos = mSyncStorageEngine
+                    .getCopyOfAllAuthoritiesWithSyncStatus();
+            for (Pair<AuthorityInfo, SyncStatusInfo> info : infos) {
+                final AuthorityInfo authorityInfo = info.first;
+                final SyncStatusInfo status = info.second;
+                // skip the sync if the account of this operation no longer
+                // exists
+                if (!containsAccountAndUser(
+                        accounts, authorityInfo.account, authorityInfo.userId)) {
                     continue;
                 }
 
-                if (!mSyncStorageEngine.getMasterSyncAutomatically(info.userId)
-                        || !mSyncStorageEngine.getSyncAutomatically(info.account, info.userId,
-                                info.authority)) {
+                if (!mSyncStorageEngine.getMasterSyncAutomatically(authorityInfo.userId)
+                        || !mSyncStorageEngine.getSyncAutomatically(
+                                authorityInfo.account, authorityInfo.userId,
+                                authorityInfo.authority)) {
                     continue;
                 }
 
-                if (getIsSyncable(info.account, info.userId, info.authority)
+                if (getIsSyncable(
+                        authorityInfo.account, authorityInfo.userId, authorityInfo.authority)
                         == 0) {
                     continue;
                 }
 
-                SyncStatusInfo status = mSyncStorageEngine.getOrCreateSyncStatus(info);
-                for (int i = 0, N = info.periodicSyncs.size(); i < N; i++) {
-                    final Bundle extras = info.periodicSyncs.get(i).first;
-                    final Long periodInMillis = info.periodicSyncs.get(i).second * 1000;
+                for (int i = 0, N = authorityInfo.periodicSyncs.size(); i < N; i++) {
+                    final Bundle extras = authorityInfo.periodicSyncs.get(i).first;
+                    final Long periodInMillis = authorityInfo.periodicSyncs.get(i).second * 1000;
                     // Skip if the period is invalid
                     if (periodInMillis <= 0) {
                         continue;
@@ -1974,51 +1983,56 @@
                     final long lastPollTimeAbsolute = status.getPeriodicSyncTime(i);
 
                     long remainingMillis
-                            = periodInMillis - (shiftedNowAbsolute % periodInMillis);
+                    = periodInMillis - (shiftedNowAbsolute % periodInMillis);
 
                     /*
-                     * Sync scheduling strategy:
-                     *    Set the next periodic sync based on a random offset (in seconds).
-                     *
-                     *    Also sync right now if any of the following cases hold
-                     *    and mark it as having been scheduled
-                     *
-                     * Case 1:  This sync is ready to run now.
-                     * Case 2:  If the lastPollTimeAbsolute is in the future,
-                     *          sync now and reinitialize. This can happen for
-                     *          example if the user changed the time, synced and
-                     *          changed back.
-                     * Case 3:  If we failed to sync at the last scheduled time
+                     * Sync scheduling strategy: Set the next periodic sync
+                     * based on a random offset (in seconds). Also sync right
+                     * now if any of the following cases hold and mark it as
+                     * having been scheduled
+                     * Case 1: This sync is ready to run
+                     * now.
+                     * Case 2: If the lastPollTimeAbsolute is in the
+                     * future, sync now and reinitialize. This can happen for
+                     * example if the user changed the time, synced and changed
+                     * back.
+                     * Case 3: If we failed to sync at the last scheduled
+                     * time
                      */
-                    if (remainingMillis == periodInMillis  // Case 1
+                    if (remainingMillis == periodInMillis // Case 1
                             || lastPollTimeAbsolute > nowAbsolute // Case 2
                             || (nowAbsolute - lastPollTimeAbsolute
                                     >= periodInMillis)) { // Case 3
                         // Sync now
                         final Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(
-                                info.account, info.userId, info.authority);
+                                authorityInfo.account, authorityInfo.userId,
+                                authorityInfo.authority);
                         final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
                         syncAdapterInfo = mSyncAdapters.getServiceInfo(
-                                SyncAdapterType.newKey(info.authority, info.account.type),
-                                info.userId);
+                                SyncAdapterType.newKey(
+                                        authorityInfo.authority, authorityInfo.account.type),
+                                authorityInfo.userId);
                         if (syncAdapterInfo == null) {
                             continue;
                         }
                         scheduleSyncOperation(
-                                new SyncOperation(info.account, info.userId,
+                                new SyncOperation(authorityInfo.account, authorityInfo.userId,
                                         SyncOperation.REASON_PERIODIC,
                                         SyncStorageEngine.SOURCE_PERIODIC,
-                                        info.authority, extras, 0 /* delay */,
-                                        backoff != null ? backoff.first : 0,
+                                        authorityInfo.authority, extras, 0 /* delay */,
+                                                backoff != null ? backoff.first : 0,
                                         mSyncStorageEngine.getDelayUntilTime(
-                                                info.account, info.userId, info.authority),
+                                                authorityInfo.account, authorityInfo.userId,
+                                                authorityInfo.authority),
                                         syncAdapterInfo.type.allowParallelSyncs()));
-                        status.setPeriodicSyncTime(i, nowAbsolute);
+                        mSyncStorageEngine.setPeriodicSyncTime(authorityInfo.ident,
+                                authorityInfo.periodicSyncs.get(i), nowAbsolute);
                     }
                     // Compute when this periodic sync should next run
                     final long nextPollTimeAbsolute = nowAbsolute + remainingMillis;
 
-                    // remember this time if it is earlier than earliestFuturePollTime
+                    // remember this time if it is earlier than
+                    // earliestFuturePollTime
                     if (nextPollTimeAbsolute < earliestFuturePollTime) {
                         earliestFuturePollTime = nextPollTimeAbsolute;
                     }
@@ -2032,8 +2046,8 @@
             // convert absolute time to elapsed time
             return SystemClock.elapsedRealtime()
                     + ((earliestFuturePollTime < nowAbsolute)
-                      ? 0
-                      : (earliestFuturePollTime - nowAbsolute));
+                            ? 0
+                            : (earliestFuturePollTime - nowAbsolute));
         }
 
         private long maybeStartNextSyncLocked() {
diff --git a/services/java/com/android/server/content/SyncStorageEngine.java b/services/java/com/android/server/content/SyncStorageEngine.java
index 5b8d26f..863def3 100644
--- a/services/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/java/com/android/server/content/SyncStorageEngine.java
@@ -44,6 +44,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastXmlSerializer;
+import com.android.server.content.SyncStorageEngine.AuthorityInfo;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -813,14 +814,6 @@
         }
     }
 
-    public AuthorityInfo getOrCreateAuthority(Account account, int userId, String authority) {
-        synchronized (mAuthorities) {
-            return getOrCreateAuthorityLocked(account, userId, authority,
-                    -1 /* assign a new identifier if creating a new authority */,
-                    true /* write to storage if this results in a change */);
-        }
-    }
-
     public void removeAuthority(Account account, int userId, String authority) {
         synchronized (mAuthorities) {
             removeAuthorityLocked(account, userId, authority, true /* doWrite */);
@@ -1238,17 +1231,27 @@
     }
 
     /**
-     * Return an array of the current authorities. Note
-     * that the objects inside the array are the real, live objects,
-     * so be careful what you do with them.
+     * Return a copy of the specified authority with the corresponding sync status
      */
-    public ArrayList<AuthorityInfo> getAuthorities() {
+    public Pair<AuthorityInfo, SyncStatusInfo> getCopyOfAuthorityWithSyncStatus(
+            Account account, int userId, String authority) {
         synchronized (mAuthorities) {
-            final int N = mAuthorities.size();
-            ArrayList<AuthorityInfo> infos = new ArrayList<AuthorityInfo>(N);
-            for (int i=0; i<N; i++) {
-                // Make deep copy because AuthorityInfo syncs are liable to change.
-                infos.add(new AuthorityInfo(mAuthorities.valueAt(i)));
+            AuthorityInfo authorityInfo = getOrCreateAuthorityLocked(account, userId, authority,
+                    -1 /* assign a new identifier if creating a new authority */,
+                    true /* write to storage if this results in a change */);
+            return createCopyPairOfAuthorityWithSyncStatusLocked(authorityInfo);
+        }
+    }
+
+    /**
+     * Return a copy of all authorities with their corresponding sync status
+     */
+    public ArrayList<Pair<AuthorityInfo, SyncStatusInfo>> getCopyOfAllAuthoritiesWithSyncStatus() {
+        synchronized (mAuthorities) {
+            ArrayList<Pair<AuthorityInfo, SyncStatusInfo>> infos =
+                    new ArrayList<Pair<AuthorityInfo, SyncStatusInfo>>(mAuthorities.size());
+            for (int i = 0; i < mAuthorities.size(); i++) {
+                infos.add(createCopyPairOfAuthorityWithSyncStatusLocked(mAuthorities.valueAt(i)));
             }
             return infos;
         }
@@ -1337,6 +1340,12 @@
         }
     }
 
+    private Pair<AuthorityInfo, SyncStatusInfo> createCopyPairOfAuthorityWithSyncStatusLocked(
+            AuthorityInfo authorityInfo) {
+        SyncStatusInfo syncStatusInfo = getOrCreateSyncStatusLocked(authorityInfo.ident);
+        return Pair.create(new AuthorityInfo(authorityInfo), new SyncStatusInfo(syncStatusInfo));
+    }
+
     private int getCurrentDayLocked() {
         mCal.setTimeInMillis(System.currentTimeMillis());
         final int dayOfYear = mCal.get(Calendar.DAY_OF_YEAR);
@@ -1427,9 +1436,22 @@
         }
     }
 
-    public SyncStatusInfo getOrCreateSyncStatus(AuthorityInfo authority) {
+    /**
+     * Updates (in a synchronized way) the periodic sync time of the specified
+     * authority id and target periodic sync
+     */
+    public void setPeriodicSyncTime(
+            int authorityId, Pair<Bundle, Long> targetPeriodicSync, long when) {
         synchronized (mAuthorities) {
-            return getOrCreateSyncStatusLocked(authority.ident);
+            final AuthorityInfo authority = mAuthorities.get(authorityId);
+            for (int i = 0; i < authority.periodicSyncs.size(); i++) {
+                Pair<Bundle, Long> periodicSync = authority.periodicSyncs.get(i);
+                if (periodicSync.first == targetPeriodicSync.first
+                        && periodicSync.second == targetPeriodicSync.second) {
+                    mSyncStatus.get(authorityId).setPeriodicSyncTime(i, when);
+                    break;
+                }
+            }
         }
     }
 
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
old mode 100644
new mode 100755
index 9ea4262..8fde010
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -35,6 +35,7 @@
 import com.android.internal.app.ResolverActivity;
 import com.android.internal.content.NativeLibraryHelper;
 import com.android.internal.content.PackageHelper;
+import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
 import com.android.server.DeviceStorageMonitorService;
@@ -1932,8 +1933,6 @@
                         getDataPathForPackage(packageName, 0).getPath();
                 pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
             }
-            // pkg.mSetEnabled = ps.getEnabled(userId);
-            // pkg.mSetStopped = ps.getStopped(userId);
             return generatePackageInfo(pkg, flags, userId);
         }
         return null;
@@ -3363,7 +3362,7 @@
         try {
             File fname = getSettingsProblemFile();
             FileOutputStream out = new FileOutputStream(fname, true);
-            PrintWriter pw = new PrintWriter(out);
+            PrintWriter pw = new FastPrintWriter(out);
             SimpleDateFormat formatter = new SimpleDateFormat();
             String dateString = formatter.format(new Date(System.currentTimeMillis()));
             pw.println(dateString + ": " + msg);
@@ -3553,10 +3552,13 @@
         }
 
         // The apk is forward locked (not public) if its code and resources
-        // are kept in different files.
+        // are kept in different files. (except for app in either system or
+        // vendor path).
         // TODO grab this value from PackageSettings
-        if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
-            parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
+        if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+            if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
+                parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
+            }
         }
 
         String codePath = null;
@@ -6148,6 +6150,120 @@
         mHandler.sendMessage(msg);
     }
 
+    private void sendPackageAddedForUser(String packageName, PackageSetting pkgSetting, int userId) {
+        Bundle extras = new Bundle(1);
+        extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userId, pkgSetting.appId));
+
+        sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
+                packageName, extras, null, null, new int[] {userId});
+        try {
+            IActivityManager am = ActivityManagerNative.getDefault();
+            final boolean isSystem =
+                    isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting);
+            if (isSystem && am.isUserRunning(userId, false)) {
+                // The just-installed/enabled app is bundled on the system, so presumed
+                // to be able to run automatically without needing an explicit launch.
+                // Send it a BOOT_COMPLETED if it would ordinarily have gotten one.
+                Intent bcIntent = new Intent(Intent.ACTION_BOOT_COMPLETED)
+                        .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
+                        .setPackage(packageName);
+                am.broadcastIntent(null, bcIntent, null, null, 0, null, null, null,
+                        android.app.AppOpsManager.OP_NONE, false, false, userId);
+            }
+        } catch (RemoteException e) {
+            // shouldn't happen
+            Slog.w(TAG, "Unable to bootstrap installed package", e);
+        }
+    }
+
+    @Override
+    public boolean setApplicationBlockedSettingAsUser(String packageName, boolean blocked,
+            int userId) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
+        PackageSetting pkgSetting;
+        final int uid = Binder.getCallingUid();
+        if (UserHandle.getUserId(uid) != userId) {
+            mContext.enforceCallingPermission(
+                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    "setApplicationBlocked for user " + userId);
+        }
+
+        if (blocked && isPackageDeviceAdmin(packageName, userId)) {
+            Slog.w(TAG, "Not blocking package " + packageName + ": has active device admin");
+            return false;
+        }
+
+        long callingId = Binder.clearCallingIdentity();
+        try {
+            boolean sendAdded = false;
+            boolean sendRemoved = false;
+            // writer
+            synchronized (mPackages) {
+                pkgSetting = mSettings.mPackages.get(packageName);
+                if (pkgSetting == null) {
+                    return false;
+                }
+                if (pkgSetting.getBlocked(userId) != blocked) {
+                    pkgSetting.setBlocked(blocked, userId);
+                    mSettings.writePackageRestrictionsLPr(userId);
+                    if (blocked) {
+                        sendRemoved = true;
+                    } else {
+                        sendAdded = true;
+                    }
+                }
+            }
+            if (sendAdded) {
+                sendPackageAddedForUser(packageName, pkgSetting, userId);
+                return true;
+            }
+            if (sendRemoved) {
+                sendPackageBlockedForUser(packageName, pkgSetting, userId);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingId);
+        }
+        return false;
+    }
+
+    private void sendPackageBlockedForUser(String packageName, PackageSetting pkgSetting,
+            int userId) {
+        final PackageRemovedInfo info = new PackageRemovedInfo();
+        info.removedPackage = packageName;
+        info.removedUsers = new int[] {userId};
+        info.uid = UserHandle.getUid(userId, pkgSetting.appId);
+        info.sendBroadcast(false, false, false);
+    }
+
+    /**
+     * Returns true if application is not found or there was an error. Otherwise it returns
+     * the blocked state of the package for the given user.
+     */
+    @Override
+    public boolean getApplicationBlockedSettingAsUser(String packageName, int userId) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
+        PackageSetting pkgSetting;
+        final int uid = Binder.getCallingUid();
+        if (UserHandle.getUserId(uid) != userId) {
+            mContext.enforceCallingPermission(
+                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    "getApplicationBlocked for user " + userId);
+        }
+        long callingId = Binder.clearCallingIdentity();
+        try {
+            // writer
+            synchronized (mPackages) {
+                pkgSetting = mSettings.mPackages.get(packageName);
+                if (pkgSetting == null) {
+                    return true;
+                }
+                return pkgSetting.getBlocked(userId);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingId);
+        }
+    }
+
     /**
      * @hide
      */
@@ -6179,33 +6295,14 @@
                 }
                 if (!pkgSetting.getInstalled(userId)) {
                     pkgSetting.setInstalled(true, userId);
+                    pkgSetting.setBlocked(false, userId);
                     mSettings.writePackageRestrictionsLPr(userId);
-                    extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userId, pkgSetting.appId));
                     sendAdded = true;
                 }
             }
 
             if (sendAdded) {
-                sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
-                        packageName, extras, null, null, new int[] {userId});
-                try {
-                    IActivityManager am = ActivityManagerNative.getDefault();
-                    final boolean isSystem =
-                            isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting);
-                    if (isSystem && am.isUserRunning(userId, false)) {
-                        // The just-installed/enabled app is bundled on the system, so presumed
-                        // to be able to run automatically without needing an explicit launch.
-                        // Send it a BOOT_COMPLETED if it would ordinarily have gotten one.
-                        Intent bcIntent = new Intent(Intent.ACTION_BOOT_COMPLETED)
-                                .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
-                                .setPackage(packageName);
-                        am.broadcastIntent(null, bcIntent, null, null, 0, null, null, null,
-                                android.app.AppOpsManager.OP_NONE, false, false, userId);
-                    }
-                } catch (RemoteException e) {
-                    // shouldn't happen
-                    Slog.w(TAG, "Unable to bootstrap installed package", e);
-                }
+                sendPackageAddedForUser(packageName, pkgSetting, userId);
             }
         } finally {
             Binder.restoreCallingIdentity(callingId);
@@ -8272,6 +8369,9 @@
         boolean updatedSettings = false;
         parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
                 PackageParser.PARSE_IS_SYSTEM;
+        if ((deletedPackage.applicationInfo.flags&ApplicationInfo.FLAG_PRIVILEGED) != 0) {
+            parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
+        }
         String packageName = deletedPackage.packageName;
         res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
         if (packageName == null) {
@@ -8696,6 +8796,19 @@
         });
     }
 
+    private boolean isPackageDeviceAdmin(String packageName, int userId) {
+        IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
+                ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
+        try {
+            if (dpm != null && (dpm.packageHasActiveAdmins(packageName, userId)
+                    || dpm.isDeviceOwner(packageName))) {
+                return true;
+            }
+        } catch (RemoteException e) {
+        }
+        return false;
+    }
+
     /**
      *  This method is an internal method that could be get invoked either
      *  to delete an installed package or to clean up a failed installation.
@@ -8714,15 +8827,9 @@
         final PackageRemovedInfo info = new PackageRemovedInfo();
         final boolean res;
 
-        IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
-                ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
-        try {
-            if (dpm != null && (dpm.packageHasActiveAdmins(packageName, userId)
-                    || dpm.isDeviceOwner(packageName))) {
-                Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
-                return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
-            }
-        } catch (RemoteException e) {
+        if (isPackageDeviceAdmin(packageName, userId)) {
+            Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
+            return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
         }
 
         boolean removedForAllUsers = false;
@@ -9038,6 +9145,7 @@
                         false, //installed
                         true,  //stopped
                         true,  //notLaunched
+                        false, //blocked
                         null, null, null);
                 if (!isSystemApp(ps)) {
                     if (ps.isAnyInstalled(sUserManager.getUserIds())) {
diff --git a/services/java/com/android/server/pm/PackageSettingBase.java b/services/java/com/android/server/pm/PackageSettingBase.java
index b3fd60c..7747c8f 100644
--- a/services/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/java/com/android/server/pm/PackageSettingBase.java
@@ -260,14 +260,24 @@
         modifyUserState(userId).notLaunched = stop;
     }
 
+    boolean getBlocked(int userId) {
+        return readUserState(userId).blocked;
+    }
+
+    void setBlocked(boolean blocked, int userId) {
+        modifyUserState(userId).blocked = blocked;
+    }
+
     void setUserState(int userId, int enabled, boolean installed, boolean stopped,
-            boolean notLaunched, String lastDisableAppCaller, HashSet<String> enabledComponents,
+            boolean notLaunched, boolean blocked,
+            String lastDisableAppCaller, HashSet<String> enabledComponents,
             HashSet<String> disabledComponents) {
         PackageUserState state = modifyUserState(userId);
         state.enabled = enabled;
         state.installed = installed;
         state.stopped = stopped;
         state.notLaunched = notLaunched;
+        state.blocked = blocked;
         state.lastDisableAppCaller = lastDisableAppCaller;
         state.enabledComponents = enabledComponents;
         state.disabledComponents = disabledComponents;
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 0cae5d65..2d7d8a0 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -109,6 +109,7 @@
     private static final String ATTR_ENABLED = "enabled";
     private static final String ATTR_ENABLED_CALLER = "enabledCaller";
     private static final String ATTR_STOPPED = "stopped";
+    private static final String ATTR_BLOCKED = "blocked";
     private static final String ATTR_INSTALLED = "inst";
 
     private final File mSettingsFilename;
@@ -462,6 +463,7 @@
                                     installed,
                                     true, // stopped,
                                     true, // notLaunched
+                                    false, // blocked
                                     null, null, null);
                             writePackageRestrictionsLPr(user.id);
                         }
@@ -860,6 +862,7 @@
                                 true,   // installed
                                 false,  // stopped
                                 false,  // notLaunched
+                                false,  // blocked
                                 null, null, null);
                     }
                     return;
@@ -913,6 +916,9 @@
                     final String stoppedStr = parser.getAttributeValue(null, ATTR_STOPPED);
                     final boolean stopped = stoppedStr == null
                             ? false : Boolean.parseBoolean(stoppedStr);
+                    final String blockedStr = parser.getAttributeValue(null, ATTR_BLOCKED);
+                    final boolean blocked = blockedStr == null
+                            ? false : Boolean.parseBoolean(blockedStr);
                     final String notLaunchedStr = parser.getAttributeValue(null, ATTR_NOT_LAUNCHED);
                     final boolean notLaunched = stoppedStr == null
                             ? false : Boolean.parseBoolean(notLaunchedStr);
@@ -936,7 +942,7 @@
                         }
                     }
 
-                    ps.setUserState(userId, enabled, installed, stopped, notLaunched,
+                    ps.setUserState(userId, enabled, installed, stopped, notLaunched, blocked,
                             enabledCaller, enabledComponents, disabledComponents);
                 } else if (tagName.equals("preferred-activities")) {
                     readPreferredActivitiesLPw(parser, userId);
@@ -1044,6 +1050,7 @@
                 PackageUserState ustate = pkg.readUserState(userId);
                 if (ustate.stopped || ustate.notLaunched || !ustate.installed
                         || ustate.enabled != COMPONENT_ENABLED_STATE_DEFAULT
+                        || ustate.blocked
                         || (ustate.enabledComponents != null
                                 && ustate.enabledComponents.size() > 0)
                         || (ustate.disabledComponents != null
@@ -1061,6 +1068,9 @@
                     if (ustate.notLaunched) {
                         serializer.attribute(null, ATTR_NOT_LAUNCHED, "true");
                     }
+                    if (ustate.blocked) {
+                        serializer.attribute(null, ATTR_BLOCKED, "true");
+                    }
                     if (ustate.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
                         serializer.attribute(null, ATTR_ENABLED,
                                 Integer.toString(ustate.enabled));
@@ -2847,6 +2857,8 @@
             pw.print(prefix); pw.print("  User "); pw.print(user.id); pw.print(": ");
             pw.print(" installed=");
             pw.print(ps.getInstalled(user.id));
+            pw.print(" blocked=");
+            pw.print(ps.getBlocked(user.id));
             pw.print(" stopped=");
             pw.print(ps.getStopped(user.id));
             pw.print(" notLaunched=");
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index 1323c93..d86f2c7 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -39,12 +39,15 @@
 import android.os.IUserManager;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.AtomicFile;
+import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
+import android.util.SparseLongArray;
 import android.util.TimeUtils;
 import android.util.Xml;
 
@@ -63,6 +66,9 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -78,6 +84,10 @@
     private static final String ATTR_ID = "id";
     private static final String ATTR_CREATION_TIME = "created";
     private static final String ATTR_LAST_LOGGED_IN_TIME = "lastLoggedIn";
+    private static final String ATTR_SALT = "salt";
+    private static final String ATTR_PIN_HASH = "pinHash";
+    private static final String ATTR_FAILED_ATTEMPTS = "failedAttempts";
+    private static final String ATTR_LAST_RETRY_MS = "lastAttemptMs";
     private static final String ATTR_SERIAL_NO = "serialNumber";
     private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
     private static final String ATTR_PARTIAL = "partial";
@@ -107,6 +117,13 @@
 
     private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
 
+    // Number of attempts before jumping to the next BACKOFF_TIMES slot
+    private static final int BACKOFF_INC_INTERVAL = 5;
+
+    // Amount of time to force the user to wait before entering the PIN again, after failing
+    // BACKOFF_INC_INTERVAL times.
+    private static final int[] BACKOFF_TIMES = { 0, 30*1000, 60*1000, 5*60*1000, 30*60*1000 };
+
     private final Context mContext;
     private final PackageManagerService mPm;
     private final Object mInstallLock;
@@ -121,6 +138,16 @@
     private final SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>();
     private final SparseArray<Bundle> mUserRestrictions = new SparseArray<Bundle>();
 
+    class RestrictionsPinState {
+        long salt;
+        String pinHash;
+        int failedAttempts;
+        long lastAttemptTime;
+    }
+
+    private final SparseArray<RestrictionsPinState> mRestrictionsPinStates =
+            new SparseArray<RestrictionsPinState>();
+
     /**
      * Set of user IDs being actively removed. Removed IDs linger in this set
      * for several seconds to work around a VFS caching issue.
@@ -604,6 +631,21 @@
             serializer.attribute(null, ATTR_CREATION_TIME, Long.toString(userInfo.creationTime));
             serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME,
                     Long.toString(userInfo.lastLoggedInTime));
+            RestrictionsPinState pinState = mRestrictionsPinStates.get(userInfo.id);
+            if (pinState != null) {
+                if (pinState.salt != 0) {
+                    serializer.attribute(null, ATTR_SALT, Long.toString(pinState.salt));
+                }
+                if (pinState.pinHash != null) {
+                    serializer.attribute(null, ATTR_PIN_HASH, pinState.pinHash);
+                }
+                if (pinState.failedAttempts != 0) {
+                    serializer.attribute(null, ATTR_FAILED_ATTEMPTS,
+                            Integer.toString(pinState.failedAttempts));
+                    serializer.attribute(null, ATTR_LAST_RETRY_MS,
+                            Long.toString(pinState.lastAttemptTime));
+                }
+            }
             if (userInfo.iconPath != null) {
                 serializer.attribute(null,  ATTR_ICON_PATH, userInfo.iconPath);
             }
@@ -690,6 +732,10 @@
         String iconPath = null;
         long creationTime = 0L;
         long lastLoggedInTime = 0L;
+        long salt = 0L;
+        String pinHash = null;
+        int failedAttempts = 0;
+        long lastAttemptTime = 0L;
         boolean partial = false;
         Bundle restrictions = new Bundle();
 
@@ -722,6 +768,10 @@
                 iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
                 creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0);
                 lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_TIME, 0);
+                salt = readLongAttribute(parser, ATTR_SALT, 0L);
+                pinHash = parser.getAttributeValue(null, ATTR_PIN_HASH);
+                failedAttempts = readIntAttribute(parser, ATTR_FAILED_ATTEMPTS, 0);
+                lastAttemptTime = readLongAttribute(parser, ATTR_LAST_RETRY_MS, 0L);
                 String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
                 if ("true".equals(valueString)) {
                     partial = true;
@@ -761,6 +811,17 @@
             userInfo.lastLoggedInTime = lastLoggedInTime;
             userInfo.partial = partial;
             mUserRestrictions.append(id, restrictions);
+            if (salt != 0L) {
+                RestrictionsPinState pinState = mRestrictionsPinStates.get(id);
+                if (pinState == null) {
+                    pinState = new RestrictionsPinState();
+                    mRestrictionsPinStates.put(id, pinState);
+                }
+                pinState.salt = salt;
+                pinState.pinHash = pinHash;
+                pinState.failedAttempts = failedAttempts;
+                pinState.lastAttemptTime = lastAttemptTime;
+            }
             return userInfo;
 
         } catch (IOException ioe) {
@@ -949,6 +1010,7 @@
             }
         }, MINUTE_IN_MILLIS);
 
+        mRestrictionsPinStates.remove(userHandle);
         // Remove user file
         AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + ".xml"));
         userFile.delete();
@@ -999,6 +1061,123 @@
         }
     }
 
+    @Override
+    public boolean changeRestrictionsPin(String newPin) {
+        checkManageUsersPermission("Only system can modify the restrictions pin");
+        int userId = UserHandle.getCallingUserId();
+        synchronized (mPackagesLock) {
+            RestrictionsPinState pinState = mRestrictionsPinStates.get(userId);
+            if (pinState == null) {
+                pinState = new RestrictionsPinState();
+            }
+            if (newPin == null) {
+                pinState.salt = 0;
+                pinState.pinHash = null;
+            } else {
+                try {
+                    pinState.salt = SecureRandom.getInstance("SHA1PRNG").nextLong();
+                } catch (NoSuchAlgorithmException e) {
+                    pinState.salt = (long) (Math.random() * Long.MAX_VALUE);
+                }
+                pinState.pinHash = passwordToHash(newPin, pinState.salt);
+                pinState.failedAttempts = 0;
+            }
+            mRestrictionsPinStates.put(userId, pinState);
+            writeUserLocked(mUsers.get(userId));
+        }
+        return true;
+    }
+
+    @Override
+    public int checkRestrictionsPin(String pin) {
+        checkManageUsersPermission("Only system can verify the restrictions pin");
+        int userId = UserHandle.getCallingUserId();
+        synchronized (mPackagesLock) {
+            RestrictionsPinState pinState = mRestrictionsPinStates.get(userId);
+            // If there's no pin set, return error code
+            if (pinState == null || pinState.salt == 0 || pinState.pinHash == null) {
+                return UserManager.PIN_VERIFICATION_FAILED_NOT_SET;
+            } else if (pin == null) {
+                // If just checking if user can be prompted, return remaining time
+                int waitTime = getRemainingTimeForPinAttempt(pinState);
+                Slog.d(LOG_TAG, "Remaining waittime peek=" + waitTime);
+                return waitTime;
+            } else {
+                int waitTime = getRemainingTimeForPinAttempt(pinState);
+                Slog.d(LOG_TAG, "Remaining waittime=" + waitTime);
+                if (waitTime > 0) {
+                    return waitTime;
+                }
+                if (passwordToHash(pin, pinState.salt).equals(pinState.pinHash)) {
+                    pinState.failedAttempts = 0;
+                    writeUserLocked(mUsers.get(userId));
+                    return UserManager.PIN_VERIFICATION_SUCCESS;
+                } else {
+                    pinState.failedAttempts++;
+                    pinState.lastAttemptTime = System.currentTimeMillis();
+                    writeUserLocked(mUsers.get(userId));
+                    return waitTime;
+                }
+            }
+        }
+    }
+
+    private int getRemainingTimeForPinAttempt(RestrictionsPinState pinState) {
+        int backoffIndex = Math.min(pinState.failedAttempts / BACKOFF_INC_INTERVAL,
+                BACKOFF_TIMES.length - 1);
+        int backoffTime = (pinState.failedAttempts % BACKOFF_INC_INTERVAL) == 0 ?
+                BACKOFF_TIMES[backoffIndex] : 0;
+        return (int) Math.max(backoffTime + pinState.lastAttemptTime - System.currentTimeMillis(),
+                0);
+    }
+
+    @Override
+    public boolean hasRestrictionsPin() {
+        int userId = UserHandle.getCallingUserId();
+        synchronized (mPackagesLock) {
+            RestrictionsPinState pinState = mRestrictionsPinStates.get(userId);
+            if (pinState == null || pinState.salt == 0 || pinState.pinHash == null) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /*
+     * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash.
+     * Not the most secure, but it is at least a second level of protection. First level is that
+     * the file is in a location only readable by the system process.
+     * @param password the password.
+     * @param salt the randomly generated salt
+     * @return the hash of the pattern in a String.
+     */
+    private String passwordToHash(String password, long salt) {
+        if (password == null) {
+            return null;
+        }
+        String algo = null;
+        String hashed = salt + password;
+        try {
+            byte[] saltedPassword = (password + salt).getBytes();
+            byte[] sha1 = MessageDigest.getInstance(algo = "SHA-1").digest(saltedPassword);
+            byte[] md5 = MessageDigest.getInstance(algo = "MD5").digest(saltedPassword);
+            hashed = toHex(sha1) + toHex(md5);
+        } catch (NoSuchAlgorithmException e) {
+            Log.w(LOG_TAG, "Failed to encode string because of missing algorithm: " + algo);
+        }
+        return hashed;
+    }
+
+    private static String toHex(byte[] ary) {
+        final String hex = "0123456789ABCDEF";
+        String ret = "";
+        for (int i = 0; i < ary.length; i++) {
+            ret += hex.charAt((ary[i] >> 4) & 0xf);
+            ret += hex.charAt(ary[i] & 0xf);
+        }
+        return ret;
+    }
+
     private int getUidForPackage(String packageName) {
         long ident = Binder.clearCallingIdentity();
         try {
diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/java/com/android/server/wifi/WifiService.java
index 66ef978..a70978e 100644
--- a/services/java/com/android/server/wifi/WifiService.java
+++ b/services/java/com/android/server/wifi/WifiService.java
@@ -114,10 +114,6 @@
     /* Tracks the persisted states for wi-fi & airplane mode */
     final WifiSettingsStore mSettingsStore;
 
-    /* The work source (UID) that triggered the current WIFI scan, synchronized
-     * on this */
-    private WorkSource mScanWorkSource;
-
     /**
      * Asynchronous channel to WifiStateMachine
      */
@@ -255,17 +251,6 @@
                 },
                 new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
 
-        mContext.registerReceiver(
-                new BroadcastReceiver() {
-                    @Override
-                    public void onReceive(Context context, Intent intent) {
-                        if (intent.getAction().equals(
-                                WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
-                            noteScanEnd();
-                        }
-                    }
-                }, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
-
         // Adding optimizations of only receiving broadcasts when wifi is enabled
         // can result in race conditions when apps toggle wifi in the background
         // without active user involvement. Always receive broadcasts.
@@ -274,44 +259,6 @@
 
     private WifiController mWifiController;
 
-    /** Tell battery stats about a new WIFI scan */
-    private void noteScanStart() {
-        WorkSource scanWorkSource = null;
-        synchronized (WifiService.this) {
-            if (mScanWorkSource != null) {
-                // Scan already in progress, don't add this one to battery stats
-                return;
-            }
-            scanWorkSource = new WorkSource(Binder.getCallingUid());
-            mScanWorkSource = scanWorkSource;
-        }
-
-        long id = Binder.clearCallingIdentity();
-        try {
-            mBatteryStats.noteWifiScanStartedFromSource(scanWorkSource);
-        } catch (RemoteException e) {
-            Log.w(TAG, e);
-        } finally {
-            Binder.restoreCallingIdentity(id);
-        }
-    }
-
-    /** Tell battery stats that the current WIFI scan has completed */
-    private void noteScanEnd() {
-        WorkSource scanWorkSource = null;
-        synchronized (WifiService.this) {
-            scanWorkSource = mScanWorkSource;
-            mScanWorkSource = null;
-        }
-        if (scanWorkSource != null) {
-            try {
-                mBatteryStats.noteWifiScanStoppedFromSource(scanWorkSource);
-            } catch (RemoteException e) {
-                Log.w(TAG, e);
-            }
-        }
-    }
-
     /**
      * Check if Wi-Fi needs to be enabled and start
      * if needed
@@ -352,8 +299,7 @@
      */
     public void startScan() {
         enforceChangePermission();
-        mWifiStateMachine.startScan();
-        noteScanStart();
+        mWifiStateMachine.startScan(Binder.getCallingUid());
     }
 
     private void enforceAccessPermission() {
diff --git a/services/java/com/android/server/wm/TaskStack.java b/services/java/com/android/server/wm/TaskStack.java
index 827958d..b43a7a1 100644
--- a/services/java/com/android/server/wm/TaskStack.java
+++ b/services/java/com/android/server/wm/TaskStack.java
@@ -16,7 +16,12 @@
 
 package com.android.server.wm;
 
+import static com.android.server.wm.WindowManagerService.DEBUG_TASK_MOVEMENT;
+import static com.android.server.wm.WindowManagerService.TAG;
+
 import android.graphics.Rect;
+import android.os.Debug;
+import android.util.Slog;
 import android.util.TypedValue;
 
 import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
@@ -88,6 +93,7 @@
      * @param toTop Whether to add it to the top or bottom.
      */
     boolean addTask(Task task, boolean toTop) {
+        if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "addTask: task=" + task + " toTop=" + toTop);
         mStackBox.makeDirty();
         mTasks.add(toTop ? mTasks.size() : 0, task);
         task.mStack = this;
@@ -95,11 +101,14 @@
     }
 
     boolean moveTaskToTop(Task task) {
+        if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "moveTaskToTop: task=" + task + " Callers="
+                + Debug.getCallers(6));
         mTasks.remove(task);
         return addTask(task, true);
     }
 
     boolean moveTaskToBottom(Task task) {
+        if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "moveTaskToBottom: task=" + task);
         mTasks.remove(task);
         return addTask(task, false);
     }
@@ -110,6 +119,7 @@
      * @param task The Task to delete.
      */
     void removeTask(Task task) {
+        if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "removeTask: task=" + task);
         mStackBox.makeDirty();
         mTasks.remove(task);
     }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index fd06535..ee2ef37 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -28,6 +28,7 @@
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.policy.PolicyManager;
 import com.android.internal.policy.impl.PhoneWindowManager;
+import com.android.internal.util.FastPrintWriter;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodClient;
 import com.android.internal.view.IInputMethodManager;
@@ -3776,7 +3777,6 @@
                 }
                 changed = mFocusedApp != newFocus;
                 mFocusedApp = newFocus;
-                moveTaskToTop(newFocus.groupId);
                 if (DEBUG_FOCUS) Slog.v(TAG, "Set focused app to: " + mFocusedApp
                         + " moveFocusNow=" + moveFocusNow);
                 if (changed) {
@@ -4117,6 +4117,13 @@
         }
     }
 
+    public void setAppFullscreen(IBinder token) {
+        AppWindowToken atoken = findAppWindowToken(token);
+        if (atoken != null) {
+            atoken.appFullscreen = true;
+        }
+    }
+
     boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
             boolean visible, int transit, boolean performLayout) {
         boolean delayed = false;
@@ -5318,8 +5325,9 @@
             if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
             if (false) {
                 StringWriter sw = new StringWriter();
-                PrintWriter pw = new PrintWriter(sw);
+                PrintWriter pw = new FastPrintWriter(sw, false, 1024);
                 this.dump(null, pw, null);
+                pw.flush();
                 Slog.i(TAG, sw.toString());
             }
             try {
@@ -6609,8 +6617,9 @@
             displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
             displayInfo.appWidth = appWidth;
             displayInfo.appHeight = appHeight;
-            displayInfo.getLogicalMetrics(mRealDisplayMetrics, null);
-            displayInfo.getAppMetrics(mDisplayMetrics, null);
+            displayInfo.getLogicalMetrics(mRealDisplayMetrics,
+                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+            displayInfo.getAppMetrics(mDisplayMetrics);
             mDisplayManagerService.setDisplayInfoOverrideFromWindowManager(
                     displayContent.getDisplayId(), displayInfo);
         }
@@ -7897,7 +7906,7 @@
                 WindowState ws = mRebuildTmp[i];
                 if (ws.mRebuilding) {
                     StringWriter sw = new StringWriter();
-                    PrintWriter pw = new PrintWriter(sw);
+                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
                     ws.dump(pw, "", true);
                     pw.flush();
                     Slog.w(TAG, "This window was lost: " + ws);
@@ -10472,7 +10481,7 @@
      */
     public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState) {
         StringWriter sw = new StringWriter();
-        PrintWriter pw = new PrintWriter(sw);
+        PrintWriter pw = new FastPrintWriter(sw, false, 1024);
         pw.println("  ANR time: " + DateFormat.getInstance().format(new Date()));
         if (appWindowToken != null) {
             pw.println("  Application at fault: " + appWindowToken.stringName);
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 29d6e4d..44077ae 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -39,7 +39,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.UserHandle;
-import android.view.CompatibilityInfoHolder;
+import android.view.DisplayAdjustments;
 import android.view.Display;
 
 import java.io.File;
@@ -574,7 +574,7 @@
 
     /** @hide */
     @Override
-    public CompatibilityInfoHolder getCompatibilityInfo(int displayId) {
+    public DisplayAdjustments getDisplayAdjustments(int displayId) {
         throw new UnsupportedOperationException();
     }
 }
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 20a26ab..4683534 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -45,6 +45,8 @@
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.Binder;
+import android.os.UserHandle;
 
 import java.util.List;
 
@@ -585,6 +587,23 @@
      * @hide
      */
     @Override
+    public boolean setApplicationBlockedSettingAsUser(String packageName, boolean blocked,
+            UserHandle user) {
+        return false;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public boolean getApplicationBlockedSettingAsUser(String packageName, UserHandle user) {
+        return false;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
     public int installExistingPackage(String packageName)
             throws NameNotFoundException {
         throw new UnsupportedOperationException();
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index 61180a0..3b49819 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -86,15 +86,17 @@
 LOCAL_CFLAGS += -DSTATIC_ANDROIDFW_FOR_TOOLS
 LOCAL_CFLAGS += -Wno-non-virtual-dtor
 
+LOCAL_SHARED_LIBRARIES := \
+        libpng \
+        libz
+
 LOCAL_STATIC_LIBRARIES := \
         libstlport_static \
         libandroidfw \
         libutils \
         libcutils \
         libexpat_static \
-        libpng \
-        liblog \
-        libz
+        liblog
 
 include $(BUILD_EXECUTABLE)
 endif
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 21bef1c..98a32a5 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -67,8 +67,8 @@
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
 import android.view.BridgeInflater;
-import android.view.CompatibilityInfoHolder;
 import android.view.Display;
+import android.view.DisplayAdjustments;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
@@ -1394,7 +1394,7 @@
     }
 
     @Override
-    public CompatibilityInfoHolder getCompatibilityInfo(int displayId) {
+    public DisplayAdjustments getDisplayAdjustments(int displayId) {
         // pass
         return null;
     }
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index ec76a8b..a3c172a 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -70,6 +70,18 @@
     public static final int ERROR_AUTHENTICATING = 1;
 
     /**
+     * Broadcast intent action indicating whether Wi-Fi scanning is allowed currently
+     * @hide
+     */
+    public static final String WIFI_SCAN_AVAILABLE = "wifi_scan_available";
+
+    /**
+     * Extra int indicating scan availability, WIFI_STATE_ENABLED and WIFI_STATE_DISABLED
+     * @hide
+     */
+     public static final String EXTRA_SCAN_AVAILABLE = "scan_enabled";
+
+    /**
      * Broadcast intent action indicating that Wi-Fi has been enabled, disabled,
      * enabling, disabling, or unknown. One extra provides this state as an int.
      * Another extra provides the previous state, if available.
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 1040ab19..1f51b2a 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -142,6 +142,8 @@
     */
     private int mOperationalMode = CONNECT_MODE;
     private boolean mScanResultIsPending = false;
+    private WorkSource mScanWorkSource = null;
+    private static final int UNKNOWN_SCAN_SOURCE = -1;
     /* Tracks if state machine has received any screen state change broadcast yet.
      * We can miss one of these at boot.
      */
@@ -603,7 +605,7 @@
                 new BroadcastReceiver() {
                     @Override
                     public void onReceive(Context context, Intent intent) {
-                        startScan();
+                        startScan(UNKNOWN_SCAN_SOURCE);
                     }
                 },
                 new IntentFilter(ACTION_START_SCAN));
@@ -696,6 +698,11 @@
 
         //start the state machine
         start();
+
+        final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     /*********************************************************
@@ -718,8 +725,31 @@
     /**
      * TODO: doc
      */
-    public void startScan() {
-        sendMessage(CMD_START_SCAN);
+    public void startScan(int callingUid) {
+        sendMessage(CMD_START_SCAN, callingUid);
+    }
+
+    private void noteScanStart(int callingUid) {
+        if (mScanWorkSource == null && callingUid != UNKNOWN_SCAN_SOURCE) {
+            mScanWorkSource = new WorkSource(callingUid);
+            try {
+                mBatteryStats.noteWifiScanStartedFromSource(mScanWorkSource);
+            } catch (RemoteException e) {
+                log(e.toString());
+            }
+        }
+    }
+
+    private void noteScanEnd() {
+        if (mScanWorkSource != null) {
+            try {
+                mBatteryStats.noteWifiScanStoppedFromSource(mScanWorkSource);
+            } catch (RemoteException e) {
+                log(e.toString());
+            } finally {
+                mScanWorkSource = null;
+            }
+        }
     }
 
     private void startScanNative(int type) {
@@ -1577,6 +1607,7 @@
     }
 
     private void sendScanResultsAvailableBroadcast() {
+        noteScanEnd();
         Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
@@ -1921,6 +1952,7 @@
                     }
                     break;
                     /* Discard */
+                case CMD_START_SCAN:
                 case CMD_START_SUPPLICANT:
                 case CMD_STOP_SUPPLICANT:
                 case CMD_STOP_SUPPLICANT_FAILED:
@@ -1935,7 +1967,6 @@
                 case CMD_STOP_AP:
                 case CMD_TETHER_STATE_CHANGE:
                 case CMD_TETHER_NOTIFICATION_TIMED_OUT:
-                case CMD_START_SCAN:
                 case CMD_DISCONNECT:
                 case CMD_RECONNECT:
                 case CMD_REASSOCIATE:
@@ -2440,11 +2471,18 @@
             mWifiNative.setPowerSave(true);
 
             if (mP2pSupported) mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P);
+
+            final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
+            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+            intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_ENABLED);
+            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
         }
+
         @Override
         public boolean processMessage(Message message) {
             switch(message.what) {
                 case CMD_START_SCAN:
+                    noteScanStart(message.arg1);
                     startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP);
                     break;
                 case CMD_SET_COUNTRY_CODE:
@@ -2565,6 +2603,12 @@
             mIsRunning = false;
             updateBatteryWorkSource(null);
             mScanResults = new ArrayList<ScanResult>();
+
+            final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
+            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+            intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED);
+            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+            noteScanEnd(); // wrap up any pending request.
         }
     }
 
@@ -2715,6 +2759,7 @@
                 // Handle scan. All the connection related commands are
                 // handled only in ConnectModeState
                 case CMD_START_SCAN:
+                    noteScanStart(message.arg1);
                     startScanNative(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP);
                     break;
                 default:
@@ -2981,6 +3026,7 @@
                     break;
                 case CMD_START_SCAN:
                     /* Do not attempt to connect when we are already connected */
+                    noteScanStart(message.arg1);
                     startScanNative(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP);
                     break;
                     /* Ignore connection to same network */
@@ -3298,7 +3344,7 @@
                     if (mP2pConnected.get()) break;
                     if (message.arg1 == mPeriodicScanToken &&
                             mWifiConfigStore.getConfiguredNetworks().size() == 0) {
-                        sendMessage(CMD_START_SCAN);
+                        sendMessage(CMD_START_SCAN, UNKNOWN_SCAN_SOURCE);
                         sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
                                     ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
                     }