Merge "Fix to only do pre boot receivers on upgrade." into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index 29fc7b1..5126123 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4019,10 +4019,12 @@
     ctor public AssistContent();
     method public android.content.ClipData getClipData();
     method public android.os.Bundle getExtras();
+    method public java.lang.String getStructuredData();
     method public android.net.Uri getWebUri();
     method public boolean isAppProvidedIntent();
     method public void setClipData(android.content.ClipData);
     method public void setIntent(android.content.Intent);
+    method public void setStructuredData(java.lang.String);
     method public void setWebUri(android.net.Uri);
   }
 
diff --git a/api/system-current.txt b/api/system-current.txt
index 4b4a77c..d3823fc 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4114,10 +4114,12 @@
     ctor public AssistContent();
     method public android.content.ClipData getClipData();
     method public android.os.Bundle getExtras();
+    method public java.lang.String getStructuredData();
     method public android.net.Uri getWebUri();
     method public boolean isAppProvidedIntent();
     method public void setClipData(android.content.ClipData);
     method public void setIntent(android.content.Intent);
+    method public void setStructuredData(java.lang.String);
     method public void setWebUri(android.net.Uri);
   }
 
diff --git a/core/java/android/app/AssistContent.java b/core/java/android/app/AssistContent.java
index 0df9ce5..ad2ba39 100644
--- a/core/java/android/app/AssistContent.java
+++ b/core/java/android/app/AssistContent.java
@@ -33,6 +33,7 @@
 public class AssistContent {
     private boolean mIsAppProvidedIntent = false;
     private Intent mIntent;
+    private String mStructuredData;
     private ClipData mClipData;
     private Uri mUri;
     private final Bundle mExtras;
@@ -125,6 +126,22 @@
     }
 
     /**
+     * Sets optional structured data regarding the content being viewed. The provided data
+     * must be a string represented with <a href="http://json-ld.org/">JSON-LD</a> using the
+     * <a href="http://schema.org/">schema.org</a> vocabulary.
+     */
+    public void setStructuredData(String structuredData) {
+        mStructuredData = structuredData;
+    }
+
+    /**
+     * Returns the current {@link #setStructuredData}.
+     */
+    public String getStructuredData() {
+        return mStructuredData;
+    }
+
+    /**
      * Set a web URI associated with the current data being shown to the user.
      * This URI could be opened in a web browser, or in the app as an
      * {@link Intent#ACTION_VIEW} Intent, to show the same data that is currently
@@ -163,6 +180,9 @@
         if (in.readInt() != 0) {
             mUri = Uri.CREATOR.createFromParcel(in);
         }
+        if (in.readInt() != 0) {
+            mStructuredData = in.readString();
+        }
         mIsAppProvidedIntent = in.readInt() == 1;
         mExtras = in.readBundle();
     }
@@ -187,6 +207,12 @@
         } else {
             dest.writeInt(0);
         }
+        if (mStructuredData != null) {
+            dest.writeInt(1);
+            dest.writeString(mStructuredData);
+        } else {
+            dest.writeInt(0);
+        }
         dest.writeInt(mIsAppProvidedIntent ? 1 : 0);
         dest.writeBundle(mExtras);
     }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 634f116..ed20086 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -403,8 +403,9 @@
         = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
 
     /**
-     * A String extra holding the URL-safe base64 encoded SHA-1 checksum of the file at download
-     * location specified in {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}.
+     * A String extra holding the URL-safe base64 encoded SHA-256 or SHA-1 hash (see notes below) of
+     * the file at download location specified in
+     * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}.
      *
      * <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM} should be
      * present. The provided checksum should match the checksum of the file at the download
@@ -413,12 +414,17 @@
      *
      * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
      * provisioning via an NFC bump.
+     *
+     * <p><strong>Note:</strong> for devices running {@link android.os.Build.VERSION_CODES#LOLLIPOP}
+     * and {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} only SHA-1 hash is supported.
+     * Starting from {@link android.os.Build.VERSION_CODES#MNC}, this parameter accepts SHA-256 in
+     * addition to SHA-1. Support for SHA-1 is likely to be removed in future OS releases.
      */
     public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM
         = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
 
     /**
-     * A String extra holding the URL-safe base64 encoded SHA-1 checksum of any signature of the
+     * A String extra holding the URL-safe base64 encoded SHA-256 checksum of any signature of the
      * android package archive at the download location specified in {@link
      * #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}.
      *
@@ -510,7 +516,7 @@
         = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER";
 
     /**
-     * A String extra holding the URL-safe base64 encoded SHA-1 checksum of the file at download
+     * A String extra holding the URL-safe base64 encoded SHA-256 checksum of the file at download
      * location specified in
      * {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}.
      *
@@ -526,7 +532,7 @@
         = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM";
 
     /**
-     * A String extra holding the URL-safe base64 encoded SHA-1 checksum of any signature of the
+     * A String extra holding the URL-safe base64 encoded SHA-256 checksum of any signature of the
      * android package archive at the download location specified in {@link
      * #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}.
      *
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 152bc22..27d14b3 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1093,14 +1093,28 @@
      * <p>so <code>[x_s, y_s]</code> is the pixel coordinates of the world
      * point, <code>z_s = 1</code>, and <code>w_s</code> is a measurement of disparity
      * (depth) in pixel coordinates.</p>
+     * <p>Note that the coordinate system for this transform is the
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} system,
+     * where <code>(0,0)</code> is the top-left of the
+     * preCorrectionActiveArraySize rectangle. Once the pose and
+     * intrinsic calibration transforms have been applied to a
+     * world point, then the android.lens.radialDistortion
+     * transform needs to be applied, and the result adjusted to
+     * be in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate
+     * system (where <code>(0, 0)</code> is the top-left of the
+     * activeArraySize rectangle), to determine the final pixel
+     * coordinate of the world point for processed (non-RAW)
+     * output buffers.</p>
      * <p><b>Units</b>:
-     * Pixels in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate
-     * system.</p>
+     * Pixels in the
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
+     * coordinate system.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
      * @see CameraCharacteristics#LENS_POSE_ROTATION
      * @see CameraCharacteristics#LENS_POSE_TRANSLATION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
     @PublicKey
     public static final Key<float[]> LENS_INTRINSIC_CALIBRATION =
@@ -2006,19 +2020,19 @@
      * {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}:</p>
      * <ol>
      * <li>Choose a pixel (x', y') within the active array region of the raw buffer given in
-     * android.sensor.info.preCorrectedActiveArraySize, otherwise this pixel is considered
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, otherwise this pixel is considered
      * to be outside of the FOV, and will not be shown in the processed output image.</li>
      * <li>Apply geometric distortion correction to get the post-distortion pixel coordinate,
      * (x_i, y_i). When applying geometric correction metadata, note that metadata for raw
      * buffers is defined relative to the top, left of the
-     * android.sensor.info.preCorrectedActiveArraySize rectangle.</li>
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} rectangle.</li>
      * <li>If the resulting corrected pixel coordinate is within the region given in
      * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, then the position of this pixel in the
      * processed output image buffer is <code>(x_i - activeArray.left, y_i - activeArray.top)</code>,
      * when the top, left coordinate of that buffer is treated as (0, 0).</li>
      * </ol>
      * <p>Thus, for pixel x',y' = (25, 25) on a sensor where {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}
-     * is (100,100), android.sensor.info.preCorrectedActiveArraySize is (10, 10, 100, 100),
+     * is (100,100), {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} is (10, 10, 100, 100),
      * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} is (20, 20, 80, 80), and the geometric distortion
      * correction doesn't change the pixel coordinate, the resulting pixel selected in
      * pixel coordinates would be x,y = (25, 25) relative to the top,left of the raw buffer
@@ -2042,6 +2056,7 @@
      *
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
     @PublicKey
     public static final Key<android.graphics.Rect> SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE =
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 479583c..da216aa 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2655,14 +2655,28 @@
      * <p>so <code>[x_s, y_s]</code> is the pixel coordinates of the world
      * point, <code>z_s = 1</code>, and <code>w_s</code> is a measurement of disparity
      * (depth) in pixel coordinates.</p>
+     * <p>Note that the coordinate system for this transform is the
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} system,
+     * where <code>(0,0)</code> is the top-left of the
+     * preCorrectionActiveArraySize rectangle. Once the pose and
+     * intrinsic calibration transforms have been applied to a
+     * world point, then the android.lens.radialDistortion
+     * transform needs to be applied, and the result adjusted to
+     * be in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate
+     * system (where <code>(0, 0)</code> is the top-left of the
+     * activeArraySize rectangle), to determine the final pixel
+     * coordinate of the world point for processed (non-RAW)
+     * output buffers.</p>
      * <p><b>Units</b>:
-     * Pixels in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate
-     * system.</p>
+     * Pixels in the
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
+     * coordinate system.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
      * @see CameraCharacteristics#LENS_POSE_ROTATION
      * @see CameraCharacteristics#LENS_POSE_TRANSLATION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
     @PublicKey
     public static final Key<float[]> LENS_INTRINSIC_CALIBRATION =
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 8ace0f3..2ea2667 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -26,7 +26,6 @@
 import android.app.ActionBar;
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -148,6 +147,9 @@
     // Clear me after use.
     private final ArrayList<View> mTempViews = new ArrayList<View>();
 
+    // Used to hold views that will be removed while we have an expanded action view.
+    private final ArrayList<View> mHiddenViews = new ArrayList<>();
+
     private final int[] mTempMargins = new int[2];
 
     private OnMenuItemClickListener mOnMenuItemClickListener;
@@ -435,12 +437,12 @@
     public void setLogo(Drawable drawable) {
         if (drawable != null) {
             ensureLogoView();
-            if (mLogoView.getParent() == null) {
-                addSystemView(mLogoView);
-                updateChildVisibilityForExpandedActionView(mLogoView);
+            if (!isChildOrHidden(mLogoView)) {
+                addSystemView(mLogoView, true);
             }
-        } else if (mLogoView != null && mLogoView.getParent() != null) {
+        } else if (mLogoView != null && isChildOrHidden(mLogoView)) {
             removeView(mLogoView);
+            mHiddenViews.remove(mLogoView);
         }
         if (mLogoView != null) {
             mLogoView.setImageDrawable(drawable);
@@ -577,12 +579,12 @@
                     mTitleTextView.setTextColor(mTitleTextColor);
                 }
             }
-            if (mTitleTextView.getParent() == null) {
-                addSystemView(mTitleTextView);
-                updateChildVisibilityForExpandedActionView(mTitleTextView);
+            if (!isChildOrHidden(mTitleTextView)) {
+                addSystemView(mTitleTextView, true);
             }
-        } else if (mTitleTextView != null && mTitleTextView.getParent() != null) {
+        } else if (mTitleTextView != null && isChildOrHidden(mTitleTextView)) {
             removeView(mTitleTextView);
+            mHiddenViews.remove(mTitleTextView);
         }
         if (mTitleTextView != null) {
             mTitleTextView.setText(title);
@@ -631,12 +633,12 @@
                     mSubtitleTextView.setTextColor(mSubtitleTextColor);
                 }
             }
-            if (mSubtitleTextView.getParent() == null) {
-                addSystemView(mSubtitleTextView);
-                updateChildVisibilityForExpandedActionView(mSubtitleTextView);
+            if (!isChildOrHidden(mSubtitleTextView)) {
+                addSystemView(mSubtitleTextView, true);
             }
-        } else if (mSubtitleTextView != null && mSubtitleTextView.getParent() != null) {
+        } else if (mSubtitleTextView != null && isChildOrHidden(mSubtitleTextView)) {
             removeView(mSubtitleTextView);
+            mHiddenViews.remove(mSubtitleTextView);
         }
         if (mSubtitleTextView != null) {
             mSubtitleTextView.setText(subtitle);
@@ -772,12 +774,12 @@
     public void setNavigationIcon(@Nullable Drawable icon) {
         if (icon != null) {
             ensureNavButtonView();
-            if (mNavButtonView.getParent() == null) {
-                addSystemView(mNavButtonView);
-                updateChildVisibilityForExpandedActionView(mNavButtonView);
+            if (!isChildOrHidden(mNavButtonView)) {
+                addSystemView(mNavButtonView, true);
             }
-        } else if (mNavButtonView != null && mNavButtonView.getParent() != null) {
+        } else if (mNavButtonView != null && isChildOrHidden(mNavButtonView)) {
             removeView(mNavButtonView);
+            mHiddenViews.remove(mNavButtonView);
         }
         if (mNavButtonView != null) {
             mNavButtonView.setImageDrawable(icon);
@@ -866,7 +868,7 @@
             final LayoutParams lp = generateDefaultLayoutParams();
             lp.gravity = Gravity.END | (mButtonGravity & Gravity.VERTICAL_GRAVITY_MASK);
             mMenuView.setLayoutParams(lp);
-            addSystemView(mMenuView);
+            addSystemView(mMenuView, false);
         }
     }
 
@@ -1041,7 +1043,7 @@
         }
     }
 
-    private void addSystemView(View v) {
+    private void addSystemView(View v, boolean allowHide) {
         final ViewGroup.LayoutParams vlp = v.getLayoutParams();
         final LayoutParams lp;
         if (vlp == null) {
@@ -1052,7 +1054,13 @@
             lp = (LayoutParams) vlp;
         }
         lp.mViewType = LayoutParams.SYSTEM;
-        addView(v, lp);
+
+        if (allowHide && mExpandedActionView != null) {
+            v.setLayoutParams(lp);
+            mHiddenViews.add(v);
+        } else {
+            addView(v, lp);
+        }
     }
 
     @Override
@@ -1741,22 +1749,30 @@
         return mWrapper;
     }
 
-    private void setChildVisibilityForExpandedActionView(boolean expand) {
+    void removeChildrenForExpandedActionView() {
         final int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
+        // Go backwards since we're removing from the list
+        for (int i = childCount - 1; i >= 0; i--) {
             final View child = getChildAt(i);
             final LayoutParams lp = (LayoutParams) child.getLayoutParams();
             if (lp.mViewType != LayoutParams.EXPANDED && child != mMenuView) {
-                child.setVisibility(expand ? GONE : VISIBLE);
+                removeViewAt(i);
+                mHiddenViews.add(child);
             }
         }
     }
 
-    private void updateChildVisibilityForExpandedActionView(View child) {
-        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-        if (lp.mViewType != LayoutParams.EXPANDED && child != mMenuView) {
-            child.setVisibility(mExpandedActionView != null ? GONE : VISIBLE);
+    void addChildrenForExpandedActionView() {
+        final int count = mHiddenViews.size();
+        // Re-add in reverse order since we removed in reverse order
+        for (int i = count - 1; i >= 0; i--) {
+            addView(mHiddenViews.get(i));
         }
+        mHiddenViews.clear();
+    }
+
+    private boolean isChildOrHidden(View child) {
+        return child.getParent() == this || mHiddenViews.contains(child);
     }
 
     /**
@@ -1971,7 +1987,7 @@
                 addView(mExpandedActionView);
             }
 
-            setChildVisibilityForExpandedActionView(true);
+            removeChildrenForExpandedActionView();
             requestLayout();
             item.setActionViewExpanded(true);
 
@@ -1994,7 +2010,7 @@
             removeView(mCollapseButtonView);
             mExpandedActionView = null;
 
-            setChildVisibilityForExpandedActionView(false);
+            addChildrenForExpandedActionView();
             mCurrentExpandedItem = null;
             requestLayout();
             item.setActionViewExpanded(false);
diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java
index 34b9dcb..2b162af 100644
--- a/core/java/com/android/internal/app/ToolbarActionBar.java
+++ b/core/java/com/android/internal/app/ToolbarActionBar.java
@@ -83,7 +83,9 @@
 
     @Override
     public void setCustomView(View view, LayoutParams layoutParams) {
-        view.setLayoutParams(layoutParams);
+        if (view != null) {
+            view.setLayoutParams(layoutParams);
+        }
         mDecorToolbar.setCustomView(view);
     }
 
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index 2229071..304de8c 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -371,8 +371,8 @@
         realCount = count;
     }
 
-    jobject chainingBuf = mEnv->CallObjectMethod(mInBuf, gInputByteBufferClassInfo.mGetMethod, mByteArray, 0,
-            realCount);
+    jobject chainingBuf = mEnv->CallObjectMethod(mInBuf, gInputByteBufferClassInfo.mGetMethod,
+            mByteArray, 0, realCount);
     mEnv->DeleteLocalRef(chainingBuf);
 
     if (mEnv->ExceptionCheck()) {
@@ -630,8 +630,10 @@
     bool hasThumbnail = writer->hasIfd(TIFF_IFD_SUB1);
 
     // TODO: handle lens shading map, etc. conversions for other raw buffer sizes.
-    uint32_t metadataWidth = *(writer->getEntry(TAG_IMAGEWIDTH, (hasThumbnail) ? TIFF_IFD_SUB1 : TIFF_IFD_0)->getData<uint32_t>());
-    uint32_t metadataHeight = *(writer->getEntry(TAG_IMAGELENGTH, (hasThumbnail) ? TIFF_IFD_SUB1 : TIFF_IFD_0)->getData<uint32_t>());
+    uint32_t metadataWidth = *(writer->getEntry(TAG_IMAGEWIDTH, (hasThumbnail) ? TIFF_IFD_SUB1 :
+            TIFF_IFD_0)->getData<uint32_t>());
+    uint32_t metadataHeight = *(writer->getEntry(TAG_IMAGELENGTH, (hasThumbnail) ? TIFF_IFD_SUB1 :
+            TIFF_IFD_0)->getData<uint32_t>());
 
     if (width < 0 || metadataWidth != static_cast<uint32_t>(width)) {
         jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", \
@@ -641,7 +643,8 @@
 
     if (height < 0 || metadataHeight != static_cast<uint32_t>(height)) {
         jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", \
-                        "Metadata height %d doesn't match image height %d", metadataHeight, height);
+                        "Metadata height %d doesn't match image height %d",
+                        metadataHeight, height);
         return false;
     }
 
@@ -1428,7 +1431,11 @@
     }
 
     {
-        // Setup opcode List 2
+        // Set up opcode List 2
+        OpcodeListBuilder builder;
+        status_t err = OK;
+
+        // Set up lens shading map
         camera_metadata_entry entry1 =
                 characteristics.find(ANDROID_LENS_INFO_SHADING_MAP_SIZE);
 
@@ -1444,34 +1451,52 @@
                 results.find(ANDROID_STATISTICS_LENS_SHADING_MAP);
 
         if (entry2.count > 0 && entry2.count == lsmWidth * lsmHeight * 4) {
-
-            OpcodeListBuilder builder;
-            status_t err = builder.addGainMapsForMetadata(lsmWidth,
-                                                          lsmHeight,
-                                                          0,
-                                                          0,
-                                                          imageHeight,
-                                                          imageWidth,
-                                                          opcodeCfaLayout,
-                                                          entry2.data.f);
-            if (err == OK) {
-                size_t listSize = builder.getSize();
-                uint8_t opcodeListBuf[listSize];
-                err = builder.buildOpList(opcodeListBuf);
-                if (err == OK) {
-                    BAIL_IF_INVALID(writer->addEntry(TAG_OPCODELIST2, listSize, opcodeListBuf,
-                            TIFF_IFD_0), env, TAG_OPCODELIST2, writer);
-                } else {
-                    ALOGE("%s: Could not build Lens shading map opcode.", __FUNCTION__);
-                    jniThrowRuntimeException(env, "failed to construct lens shading map opcode.");
-                }
-            } else {
+            err = builder.addGainMapsForMetadata(lsmWidth,
+                                                 lsmHeight,
+                                                 0,
+                                                 0,
+                                                 imageHeight,
+                                                 imageWidth,
+                                                 opcodeCfaLayout,
+                                                 entry2.data.f);
+            if (err != OK) {
                 ALOGE("%s: Could not add Lens shading map.", __FUNCTION__);
                 jniThrowRuntimeException(env, "failed to add lens shading map.");
+                return;
             }
+        }
+
+        // Set up rectilinear distortion correction
+        camera_metadata_entry entry3 =
+                results.find(ANDROID_LENS_RADIAL_DISTORTION);
+        camera_metadata_entry entry4 =
+                results.find(ANDROID_LENS_INTRINSIC_CALIBRATION);
+
+        if (entry3.count == 6 && entry4.count == 5) {
+            float cx = entry4.data.f[/*c_x*/2];
+            float cy = entry4.data.f[/*c_y*/3];
+            err = builder.addWarpRectilinearForMetadata(entry3.data.f, imageWidth, imageHeight, cx,
+                    cy);
+            if (err != OK) {
+                ALOGE("%s: Could not add distortion correction.", __FUNCTION__);
+                jniThrowRuntimeException(env, "failed to add distortion correction.");
+                return;
+            }
+        }
+
+
+        size_t listSize = builder.getSize();
+        uint8_t opcodeListBuf[listSize];
+        err = builder.buildOpList(opcodeListBuf);
+        if (err == OK) {
+            BAIL_IF_INVALID(writer->addEntry(TAG_OPCODELIST2, listSize, opcodeListBuf,
+                    TIFF_IFD_0), env, TAG_OPCODELIST2, writer);
         } else {
-            ALOGW("%s: No lens shading map found in result metadata. Image quality may be reduced.",
-                    __FUNCTION__);
+            ALOGE("%s: Could not build list of opcodes for distortion correction and lens shading"
+                    "map.", __FUNCTION__);
+            jniThrowRuntimeException(env, "failed to construct opcode list for distortion"
+                    " correction and lens shading map");
+            return;
         }
     }
 
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 4c0631f..8d4bfcd 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -70,6 +70,8 @@
  * <p>NOTE: The key material of the generated symmetric and private keys is not accessible. The key
  * material of the public keys is accessible.
  *
+ * <p>Instances of this class are immutable.
+ *
  * <p><h3>Example: Asymmetric key pair</h3>
  * The following example illustrates how to generate an EC key pair in the Android KeyStore system
  * under alias {@code key1} authorized to be used only for signing using SHA-256, SHA-384,
@@ -79,11 +81,12 @@
  *         KeyProperties.KEY_ALGORITHM_EC,
  *         "AndroidKeyStore");
  * keyPairGenerator.initialize(
- *         new KeyGenParameterSpec.Builder("key1",
+ *         new KeyGenParameterSpec.Builder(
+ *                 "key1",
  *                 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
- *                 .setDigests(KeyProperties.DIGEST_SHA256
- *                         | KeyProperties.DIGEST_SHA384
- *                         | KeyProperties.DIGEST_SHA512)
+ *                 .setDigests(KeyProperties.DIGEST_SHA256,
+ *                         KeyProperties.DIGEST_SHA384,
+ *                         KeyProperties.DIGEST_SHA512)
  *                 // Only permit this key to be used if the user authenticated
  *                 // within the last five minutes.
  *                 .setUserAuthenticationRequired(true)
@@ -100,16 +103,17 @@
  *
  * <p><h3>Example: Symmetric key</h3>
  * The following example illustrates how to generate an AES key in the Android KeyStore system under
- * alias {@code key2} authorized to be used only for encryption/decryption in CTR mode.
+ * alias {@code key2} authorized to be used only for encryption/decryption in CBC mode with PKCS#7
+ * padding.
  * <pre> {@code
  * KeyGenerator keyGenerator = KeyGenerator.getInstance(
- *         KeyProperties.KEY_ALGORITHM_HMAC_SHA256,
+ *         KeyProperties.KEY_ALGORITHM_AES,
  *         "AndroidKeyStore");
  * keyGenerator.initialize(
  *         new KeyGenParameterSpec.Builder("key2",
  *                 KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
- *                 .setBlockModes(KeyProperties.BLOCK_MODE_CTR)
- *                 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+ *                 .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
+ *                 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
  *                 .build());
  * SecretKey key = keyGenerator.generateKey();
  *
@@ -169,10 +173,6 @@
             int userAuthenticationValidityDurationSeconds) {
         if (TextUtils.isEmpty(keyStoreAlias)) {
             throw new IllegalArgumentException("keyStoreAlias must not be empty");
-        } else if ((userAuthenticationValidityDurationSeconds < 0)
-                && (userAuthenticationValidityDurationSeconds != -1)) {
-            throw new IllegalArgumentException(
-                    "userAuthenticationValidityDurationSeconds must not be negative");
         }
 
         if (certificateSubject == null) {
@@ -197,11 +197,11 @@
         mSpec = spec;
         mCertificateSubject = certificateSubject;
         mCertificateSerialNumber = certificateSerialNumber;
-        mCertificateNotBefore = certificateNotBefore;
-        mCertificateNotAfter = certificateNotAfter;
-        mKeyValidityStart = keyValidityStart;
-        mKeyValidityForOriginationEnd = keyValidityForOriginationEnd;
-        mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd;
+        mCertificateNotBefore = Utils.cloneIfNotNull(certificateNotBefore);
+        mCertificateNotAfter = Utils.cloneIfNotNull(certificateNotAfter);
+        mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
+        mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
+        mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
         mPurposes = purposes;
         mDigests = ArrayUtils.cloneIfNotEmpty(digests);
         mEncryptionPaddings =
@@ -217,6 +217,7 @@
      * Returns the alias that will be used in the {@code java.security.KeyStore}
      * in conjunction with the {@code AndroidKeyStore}.
      */
+    @NonNull
     public String getKeystoreAlias() {
         return mKeystoreAlias;
     }
@@ -231,10 +232,10 @@
     }
 
     /**
-     * Returns the {@link AlgorithmParameterSpec} that will be used for creation
-     * of the key pair.
+     * Returns the key algorithm-specific {@link AlgorithmParameterSpec} that will be used for
+     * creation of the key or {@code null} if algorithm-specific defaults should be used.
      */
-    @NonNull
+    @Nullable
     public AlgorithmParameterSpec getAlgorithmParameterSpec() {
         return mSpec;
     }
@@ -263,7 +264,7 @@
      */
     @NonNull
     public Date getCertificateNotBefore() {
-        return mCertificateNotBefore;
+        return Utils.cloneIfNotNull(mCertificateNotBefore);
     }
 
     /**
@@ -272,7 +273,7 @@
      */
     @NonNull
     public Date getCertificateNotAfter() {
-        return mCertificateNotAfter;
+        return Utils.cloneIfNotNull(mCertificateNotAfter);
     }
 
     /**
@@ -281,7 +282,7 @@
      */
     @Nullable
     public Date getKeyValidityStart() {
-        return mKeyValidityStart;
+        return Utils.cloneIfNotNull(mKeyValidityStart);
     }
 
     /**
@@ -290,7 +291,7 @@
      */
     @Nullable
     public Date getKeyValidityForConsumptionEnd() {
-        return mKeyValidityForConsumptionEnd;
+        return Utils.cloneIfNotNull(mKeyValidityForConsumptionEnd);
     }
 
     /**
@@ -299,7 +300,7 @@
      */
     @Nullable
     public Date getKeyValidityForOriginationEnd() {
-        return mKeyValidityForOriginationEnd;
+        return Utils.cloneIfNotNull(mKeyValidityForOriginationEnd);
     }
 
     /**
@@ -411,7 +412,7 @@
      * restricted.
      *
      * @return duration in seconds or {@code -1} if authentication is required for every use of the
-     *         key.
+     * key.
      *
      * @see #isUserAuthenticationRequired()
      */
@@ -447,7 +448,7 @@
          * Creates a new instance of the {@code Builder}.
          *
          * @param keystoreAlias alias of the entry in which the generated key will appear in
-         *        Android KeyStore.
+         *        Android KeyStore. Must not be empty.
          * @param purposes set of purposes (e.g., encrypt, decrypt, sign) for which the key can be
          *        used. Attempts to use the key for any other purpose will be rejected.
          *
@@ -462,6 +463,8 @@
         public Builder(@NonNull String keystoreAlias, @KeyProperties.PurposeEnum int purposes) {
             if (keystoreAlias == null) {
                 throw new NullPointerException("keystoreAlias == null");
+            } else if (keystoreAlias.isEmpty()) {
+                throw new IllegalArgumentException("keystoreAlias must not be empty");
             }
             mKeystoreAlias = keystoreAlias;
             mPurposes = purposes;
@@ -488,7 +491,11 @@
 
         /**
          * Sets the algorithm-specific key generation parameters. For example, for RSA keys this may
-         * be an instance of {@link java.security.spec.RSAKeyGenParameterSpec}.
+         * be an instance of {@link java.security.spec.RSAKeyGenParameterSpec} whereas for EC keys
+         * this may be an instance of {@link java.security.spec.ECGenParameterSpec}.
+         *
+         * <p>These key generation parameters must match other explicitly set parameters (if any),
+         * such as key size.
          */
         public Builder setAlgorithmParameterSpec(@NonNull AlgorithmParameterSpec spec) {
             if (spec == null) {
@@ -537,7 +544,7 @@
             if (date == null) {
                 throw new NullPointerException("date == null");
             }
-            mCertificateNotBefore = date;
+            mCertificateNotBefore = Utils.cloneIfNotNull(date);
             return this;
         }
 
@@ -552,7 +559,7 @@
             if (date == null) {
                 throw new NullPointerException("date == null");
             }
-            mCertificateNotAfter = date;
+            mCertificateNotAfter = Utils.cloneIfNotNull(date);
             return this;
         }
 
@@ -565,7 +572,7 @@
          */
         @NonNull
         public Builder setKeyValidityStart(Date startDate) {
-            mKeyValidityStart = startDate;
+            mKeyValidityStart = Utils.cloneIfNotNull(startDate);
             return this;
         }
 
@@ -594,7 +601,7 @@
          */
         @NonNull
         public Builder setKeyValidityForOriginationEnd(Date endDate) {
-            mKeyValidityForOriginationEnd = endDate;
+            mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(endDate);
             return this;
         }
 
@@ -608,7 +615,7 @@
          */
         @NonNull
         public Builder setKeyValidityForConsumptionEnd(Date endDate) {
-            mKeyValidityForConsumptionEnd = endDate;
+            mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(endDate);
             return this;
         }
 
@@ -768,14 +775,15 @@
         @NonNull
         public Builder setUserAuthenticationValidityDurationSeconds(
                 @IntRange(from = -1) int seconds) {
+            if (seconds < -1) {
+                throw new IllegalArgumentException("seconds must be -1 or larger");
+            }
             mUserAuthenticationValidityDurationSeconds = seconds;
             return this;
         }
 
         /**
          * Builds an instance of {@code KeyGenParameterSpec}.
-         *
-         * @throws IllegalArgumentException if a required field is missing
          */
         @NonNull
         public KeyGenParameterSpec build() {
diff --git a/keystore/java/android/security/keystore/KeyInfo.java b/keystore/java/android/security/keystore/KeyInfo.java
index e4f921e..03b4100 100644
--- a/keystore/java/android/security/keystore/KeyInfo.java
+++ b/keystore/java/android/security/keystore/KeyInfo.java
@@ -33,6 +33,8 @@
  * is authorized for (e.g., only in {@code CBC} mode, or signing only), whether the key should be
  * encrypted at rest, the key's and validity start and end dates.
  *
+ * <p>Instances of this class are immutable.
+ *
  * <p><h3>Example: Symmetric Key</h3>
  * The following example illustrates how to obtain a {@code KeyInfo} describing the provided Android
  * Keystore {@link SecretKey}.
@@ -102,9 +104,9 @@
         mInsideSecureHardware = insideSecureHardware;
         mOrigin = origin;
         mKeySize = keySize;
-        mKeyValidityStart = keyValidityStart;
-        mKeyValidityForOriginationEnd = keyValidityForOriginationEnd;
-        mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd;
+        mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
+        mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
+        mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
         mPurposes = purposes;
         mEncryptionPaddings =
                 ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(encryptionPaddings));
@@ -155,7 +157,7 @@
      */
     @Nullable
     public Date getKeyValidityStart() {
-        return mKeyValidityStart;
+        return Utils.cloneIfNotNull(mKeyValidityStart);
     }
 
     /**
@@ -165,7 +167,7 @@
      */
     @Nullable
     public Date getKeyValidityForConsumptionEnd() {
-        return mKeyValidityForConsumptionEnd;
+        return Utils.cloneIfNotNull(mKeyValidityForConsumptionEnd);
     }
 
     /**
@@ -175,7 +177,7 @@
      */
     @Nullable
     public Date getKeyValidityForOriginationEnd() {
-        return mKeyValidityForOriginationEnd;
+        return Utils.cloneIfNotNull(mKeyValidityForOriginationEnd);
     }
 
     /**
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 432fc12..1e0611c 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -47,6 +47,8 @@
  *
  * <p>NOTE: The key material of keys stored in the Android KeyStore is not accessible.
  *
+ * <p>Instances of this class are immutable.
+ *
  * <p><h3>Example: Symmetric Key</h3>
  * The following example illustrates how to import an AES key into the Android KeyStore under alias
  * {@code key1} authorized to be used only for encryption/decryption in CBC mode with PKCS#7
@@ -122,15 +124,9 @@
             boolean randomizedEncryptionRequired,
             boolean userAuthenticationRequired,
             int userAuthenticationValidityDurationSeconds) {
-        if ((userAuthenticationValidityDurationSeconds < 0)
-                && (userAuthenticationValidityDurationSeconds != -1)) {
-            throw new IllegalArgumentException(
-                    "userAuthenticationValidityDurationSeconds must not be negative");
-        }
-
-        mKeyValidityStart = keyValidityStart;
-        mKeyValidityForOriginationEnd = keyValidityForOriginationEnd;
-        mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd;
+        mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
+        mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
+        mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
         mPurposes = purposes;
         mEncryptionPaddings =
                 ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(encryptionPaddings));
@@ -150,7 +146,7 @@
      */
     @Nullable
     public Date getKeyValidityStart() {
-        return mKeyValidityStart;
+        return Utils.cloneIfNotNull(mKeyValidityStart);
     }
 
     /**
@@ -160,7 +156,7 @@
      */
     @Nullable
     public Date getKeyValidityForConsumptionEnd() {
-        return mKeyValidityForConsumptionEnd;
+        return Utils.cloneIfNotNull(mKeyValidityForConsumptionEnd);
     }
 
     /**
@@ -170,7 +166,7 @@
      */
     @Nullable
     public Date getKeyValidityForOriginationEnd() {
-        return mKeyValidityForOriginationEnd;
+        return Utils.cloneIfNotNull(mKeyValidityForOriginationEnd);
     }
 
     /**
@@ -320,7 +316,7 @@
          */
         @NonNull
         public Builder setKeyValidityStart(Date startDate) {
-            mKeyValidityStart = startDate;
+            mKeyValidityStart = Utils.cloneIfNotNull(startDate);
             return this;
         }
 
@@ -349,7 +345,7 @@
          */
         @NonNull
         public Builder setKeyValidityForOriginationEnd(Date endDate) {
-            mKeyValidityForOriginationEnd = endDate;
+            mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(endDate);
             return this;
         }
 
@@ -363,7 +359,7 @@
          */
         @NonNull
         public Builder setKeyValidityForConsumptionEnd(Date endDate) {
-            mKeyValidityForConsumptionEnd = endDate;
+            mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(endDate);
             return this;
         }
 
@@ -517,6 +513,9 @@
         @NonNull
         public Builder setUserAuthenticationValidityDurationSeconds(
                 @IntRange(from = -1) int seconds) {
+            if (seconds < -1) {
+                throw new IllegalArgumentException("seconds must be -1 or larger");
+            }
             mUserAuthenticationValidityDurationSeconds = seconds;
             return this;
         }
diff --git a/keystore/java/android/security/keystore/Utils.java b/keystore/java/android/security/keystore/Utils.java
new file mode 100644
index 0000000..9bec682
--- /dev/null
+++ b/keystore/java/android/security/keystore/Utils.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 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.security.keystore;
+
+import java.util.Date;
+
+/**
+ * Assorted utility methods.
+ *
+ * @hide
+ */
+abstract class Utils {
+    private Utils() {}
+
+    static Date cloneIfNotNull(Date value) {
+        return (value != null) ? (Date) value.clone() : null;
+    }
+}
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index b4cbc36..fc18491 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -241,8 +241,12 @@
         animatorDirtyMask = mAnimatorManager.animate(info);
     }
 
-    bool willHaveFunctor = info.mode == TreeInfo::MODE_FULL && mStagingDisplayListData
-            ? !mStagingDisplayListData->functors.isEmpty() : !mDisplayListData->functors.isEmpty();
+    bool willHaveFunctor = false;
+    if (info.mode == TreeInfo::MODE_FULL && mStagingDisplayListData) {
+        willHaveFunctor = !mStagingDisplayListData->functors.isEmpty();
+    } else if (mDisplayListData) {
+        willHaveFunctor = !mDisplayListData->functors.isEmpty();
+    }
     bool childFunctorsNeedLayer = mProperties.prepareForFunctorPresence(
             willHaveFunctor, functorsNeedLayer);
 
diff --git a/packages/Shell/src/com/android/shell/BugreportReceiver.java b/packages/Shell/src/com/android/shell/BugreportReceiver.java
index e1bfc43..13747ed 100644
--- a/packages/Shell/src/com/android/shell/BugreportReceiver.java
+++ b/packages/Shell/src/com/android/shell/BugreportReceiver.java
@@ -33,11 +33,23 @@
 import android.os.SystemProperties;
 import android.support.v4.content.FileProvider;
 import android.text.format.DateUtils;
+import android.util.Log;
 import android.util.Patterns;
 
 import com.google.android.collect.Lists;
+import libcore.io.Streams;
 
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
 import java.util.ArrayList;
 
 /**
@@ -73,30 +85,14 @@
         final Uri bugreportUri = FileProvider.getUriForFile(context, AUTHORITY, bugreportFile);
         final Uri screenshotUri = FileProvider.getUriForFile(context, AUTHORITY, screenshotFile);
 
-        Intent sendIntent = buildSendIntent(context, bugreportUri, screenshotUri);
-        Intent notifIntent;
-
-        // Send through warning dialog by default
-        if (getWarningState(context, STATE_SHOW) == STATE_SHOW) {
-            notifIntent = buildWarningIntent(context, sendIntent);
+        boolean isPlainText = bugreportFile.getName().toLowerCase().endsWith(".txt");
+        if (!isPlainText) {
+            // Already zipped, send it right away.
+            sendBugreportNotification(context, bugreportFile, screenshotFile);
         } else {
-            notifIntent = sendIntent;
+            // Asynchronously zip the file first, then send it.
+            sendZippedBugreportNotification(context, bugreportFile, screenshotFile);
         }
-        notifIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        final Notification.Builder builder = new Notification.Builder(context)
-                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
-                .setContentTitle(context.getString(R.string.bugreport_finished_title))
-                .setTicker(context.getString(R.string.bugreport_finished_title))
-                .setContentText(context.getString(R.string.bugreport_finished_text))
-                .setContentIntent(PendingIntent.getActivity(
-                        context, 0, notifIntent, PendingIntent.FLAG_CANCEL_CURRENT))
-                .setAutoCancel(true)
-                .setLocalOnly(true)
-                .setColor(context.getColor(
-                        com.android.internal.R.color.system_notification_accent_color));
-
-        NotificationManager.from(context).notify(TAG, 0, builder.build());
 
         // Clean up older bugreports in background
         final PendingResult result = goAsync();
@@ -141,6 +137,88 @@
     }
 
     /**
+     * Sends a bugreport notitication.
+     */
+    private static void sendBugreportNotification(Context context, File bugreportFile,
+            File screenshotFile) {
+        // Files are kept on private storage, so turn into Uris that we can
+        // grant temporary permissions for.
+        final Uri bugreportUri = FileProvider.getUriForFile(context, AUTHORITY, bugreportFile);
+        final Uri screenshotUri = FileProvider.getUriForFile(context, AUTHORITY, screenshotFile);
+
+        Intent sendIntent = buildSendIntent(context, bugreportUri, screenshotUri);
+        Intent notifIntent;
+
+        // Send through warning dialog by default
+        if (getWarningState(context, STATE_SHOW) == STATE_SHOW) {
+            notifIntent = buildWarningIntent(context, sendIntent);
+        } else {
+            notifIntent = sendIntent;
+        }
+        notifIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        final Notification.Builder builder = new Notification.Builder(context)
+                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+                .setContentTitle(context.getString(R.string.bugreport_finished_title))
+                .setTicker(context.getString(R.string.bugreport_finished_title))
+                .setContentText(context.getString(R.string.bugreport_finished_text))
+                .setContentIntent(PendingIntent.getActivity(
+                        context, 0, notifIntent, PendingIntent.FLAG_CANCEL_CURRENT))
+                .setAutoCancel(true)
+                .setLocalOnly(true)
+                .setColor(context.getColor(
+                        com.android.internal.R.color.system_notification_accent_color));
+
+        NotificationManager.from(context).notify(TAG, 0, builder.build());
+    }
+
+    /**
+     * Sends a zipped bugreport notification.
+     */
+    private static void sendZippedBugreportNotification(final Context context,
+            final File bugreportFile, final File screenshotFile) {
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                File zippedFile = zipBugreport(bugreportFile);
+                sendBugreportNotification(context, zippedFile, screenshotFile);
+                return null;
+            }
+        }.execute();
+    }
+
+    /**
+     * Zips a bugreport file, returning the path to the new file (or to the
+     * original in case of failure).
+     */
+    private static File zipBugreport(File bugreportFile) {
+        String bugreportPath = bugreportFile.getAbsolutePath();
+        String zippedPath = bugreportPath.replace(".txt", ".zip");
+        Log.v(TAG, "zipping " + bugreportPath + " as " + zippedPath);
+        File bugreportZippedFile = new File(zippedPath);
+        try (InputStream is = new FileInputStream(bugreportFile);
+            ZipOutputStream zos = new ZipOutputStream(
+                new BufferedOutputStream(new FileOutputStream(bugreportZippedFile)))) {
+            ZipEntry entry = new ZipEntry("bugreport.txt");
+            zos.putNextEntry(entry);
+            int totalBytes = Streams.copy(is, zos);
+            Log.v(TAG, "size of original bugreport: " + totalBytes + " bytes");
+            zos.closeEntry();
+            // Delete old file;
+            boolean deleted = bugreportFile.delete();
+            if (deleted) {
+                Log.v(TAG, "deleted original bugreport (" + bugreportPath + ")");
+            } else {
+                Log.e(TAG, "could not delete original bugreport (" + bugreportPath + ")");
+            }
+            return bugreportZippedFile;
+        } catch (IOException e) {
+          Log.e(TAG, "exception zipping file " + zippedPath, e);
+          return bugreportFile;  // Return original.
+        }
+    }
+
+    /**
      * Find the best matching {@link Account} based on build properties.
      */
     private static Account findSendToAccount(Context context) {
diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
index 10f1696..4af7d4e 100644
--- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
+++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
@@ -51,7 +51,7 @@
 public class ValidateNotificationPeople implements NotificationSignalExtractor {
     // Using a shorter log tag since setprop has a limit of 32chars on variable name.
     private static final String TAG = "ValidateNoPeople";
-    private static final boolean INFO = true;
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);;
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final boolean ENABLE_PEOPLE_VALIDATOR = true;
@@ -100,7 +100,7 @@
                 public void onChange(boolean selfChange, Uri uri, int userId) {
                     super.onChange(selfChange, uri, userId);
                     if (DEBUG || mEvictionCount % 100 == 0) {
-                        if (INFO) Slog.i(TAG, "mEvictionCount: " + mEvictionCount);
+                        if (VERBOSE) Slog.i(TAG, "mEvictionCount: " + mEvictionCount);
                     }
                     mPeopleCache.evictAll();
                     mEvictionCount++;
@@ -113,20 +113,20 @@
 
     public RankingReconsideration process(NotificationRecord record) {
         if (!mEnabled) {
-            if (INFO) Slog.i(TAG, "disabled");
+            if (VERBOSE) Slog.i(TAG, "disabled");
             return null;
         }
         if (record == null || record.getNotification() == null) {
-            if (INFO) Slog.i(TAG, "skipping empty notification");
+            if (VERBOSE) Slog.i(TAG, "skipping empty notification");
             return null;
         }
         if (record.getUserId() == UserHandle.USER_ALL) {
-            if (INFO) Slog.i(TAG, "skipping global notification");
+            if (VERBOSE) Slog.i(TAG, "skipping global notification");
             return null;
         }
         Context context = getContextAsUser(record.getUser());
         if (context == null) {
-            if (INFO) Slog.i(TAG, "skipping notification that lacks a context");
+            if (VERBOSE) Slog.i(TAG, "skipping notification that lacks a context");
             return null;
         }
         return validatePeople(context, record);
@@ -220,7 +220,7 @@
             return null;
         }
 
-        if (INFO) Slog.i(TAG, "Validating: " + key + " for " + context.getUserId());
+        if (VERBOSE) Slog.i(TAG, "Validating: " + key + " for " + context.getUserId());
         final LinkedList<String> pendingLookups = new LinkedList<String>();
         for (int personIdx = 0; personIdx < people.length && personIdx < MAX_PEOPLE; personIdx++) {
             final String handle = people[personIdx];
@@ -244,7 +244,7 @@
         affinityOut[0] = affinity;
 
         if (pendingLookups.isEmpty()) {
-            if (INFO) Slog.i(TAG, "final affinity: " + affinity);
+            if (VERBOSE) Slog.i(TAG, "final affinity: " + affinity);
             if (affinity != NONE) MetricsLogger.count(mBaseContext, "note_with_people", 1);
             return null;
         }
@@ -422,7 +422,7 @@
 
         @Override
         public void work() {
-            if (INFO) Slog.i(TAG, "Executing: validation for: " + mKey);
+            if (VERBOSE) Slog.i(TAG, "Executing: validation for: " + mKey);
             long timeStartMs = System.currentTimeMillis();
             for (final String handle: mPendingLookups) {
                 LookupResult lookupResult = null;
@@ -463,7 +463,7 @@
         public void applyChangesLocked(NotificationRecord operand) {
             float affinityBound = operand.getContactAffinity();
             operand.setContactAffinity(Math.max(mContactAffinity, affinityBound));
-            if (INFO) Slog.i(TAG, "final affinity: " + operand.getContactAffinity());
+            if (VERBOSE) Slog.i(TAG, "final affinity: " + operand.getContactAffinity());
         }
 
         public float getContactAffinity() {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 1cc275d..8291a30 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -667,7 +667,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getDeviceSvnUsingSubId(subId[0]);
+            return info.getDeviceSvnUsingSubId(subId[0], mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -744,7 +744,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getImeiForSubscriber(subId[0]);
+            return info.getImeiForSubscriber(subId[0], mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -773,7 +773,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            String nai = info.getNaiForSubscriber(subId[0]);
+            String nai = info.getNaiForSubscriber(subId[0], mContext.getOpPackageName());
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
                 Rlog.v(TAG, "Nai = " + nai);
             }
@@ -1856,7 +1856,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getIccSerialNumberForSubscriber(subId);
+            return info.getIccSerialNumberForSubscriber(subId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -1938,7 +1938,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getSubscriberIdForSubscriber(subId);
+            return info.getSubscriberIdForSubscriber(subId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -1959,7 +1959,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getGroupIdLevel1();
+            return info.getGroupIdLevel1(mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -1983,7 +1983,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getGroupIdLevel1ForSubscriber(subId);
+            return info.getGroupIdLevel1ForSubscriber(subId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -2029,7 +2029,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getLine1NumberForSubscriber(subId);
+            return info.getLine1NumberForSubscriber(subId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -2122,7 +2122,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getLine1AlphaTagForSubscriber(subId);
+            return info.getLine1AlphaTagForSubscriber(subId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -2178,7 +2178,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getMsisdnForSubscriber(subId);
+            return info.getMsisdnForSubscriber(subId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -2211,7 +2211,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getVoiceMailNumberForSubscriber(subId);
+            return info.getVoiceMailNumberForSubscriber(subId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -2350,7 +2350,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getVoiceMailAlphaTagForSubscriber(subId);
+            return info.getVoiceMailAlphaTagForSubscriber(subId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index c91a59c..ed85392 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -25,12 +25,12 @@
     /**
      * Retrieves the unique device ID, e.g., IMEI for GSM phones.
      */
-    String getDeviceId();
+    String getDeviceId(String callingPackage);
 
      /**
      * Retrieves the unique Network Access ID
      */
-    String getNaiForSubscriber(int subId);
+    String getNaiForSubscriber(int subId, String callingPackage);
 
     /**
      * Retrieves the unique device ID of a phone for the device, e.g., IMEI
@@ -41,91 +41,91 @@
     /**
      * Retrieves the IMEI.
      */
-    String getImeiForSubscriber(int subId);
+    String getImeiForSubscriber(int subId, String callingPackage);
 
     /**
      * Retrieves the software version number for the device, e.g., IMEI/SV
      * for GSM phones.
      */
-    String getDeviceSvn();
+    String getDeviceSvn(String callingPackage);
 
     /**
      * Retrieves the software version number of a subId for the device, e.g., IMEI/SV
      * for GSM phones.
      */
-    String getDeviceSvnUsingSubId(int subId);
+    String getDeviceSvnUsingSubId(int subId, String callingPackage);
 
     /**
      * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones.
      */
-    String getSubscriberId();
+    String getSubscriberId(String callingPackage);
 
     /**
      * Retrieves the unique subscriber ID of a given subId, e.g., IMSI for GSM phones.
      */
-    String getSubscriberIdForSubscriber(int subId);
+    String getSubscriberIdForSubscriber(int subId, String callingPackage);
 
     /**
      * Retrieves the Group Identifier Level1 for GSM phones.
      */
-    String getGroupIdLevel1();
+    String getGroupIdLevel1(String callingPackage);
 
     /**
      * Retrieves the Group Identifier Level1 for GSM phones of a subId.
      */
-    String getGroupIdLevel1ForSubscriber(int subId);
+    String getGroupIdLevel1ForSubscriber(int subId, String callingPackage);
 
     /**
      * Retrieves the serial number of the ICC, if applicable.
      */
-    String getIccSerialNumber();
+    String getIccSerialNumber(String callingPackage);
 
     /**
      * Retrieves the serial number of a given subId.
      */
-    String getIccSerialNumberForSubscriber(int subId);
+    String getIccSerialNumberForSubscriber(int subId, String callingPackage);
 
     /**
      * Retrieves the phone number string for line 1.
      */
-    String getLine1Number();
+    String getLine1Number(String callingPackage);
 
     /**
      * Retrieves the phone number string for line 1 of a subcription.
      */
-    String getLine1NumberForSubscriber(int subId);
+    String getLine1NumberForSubscriber(int subId, String callingPackage);
 
 
     /**
      * Retrieves the alpha identifier for line 1.
      */
-    String getLine1AlphaTag();
+    String getLine1AlphaTag(String callingPackage);
 
     /**
      * Retrieves the alpha identifier for line 1 of a subId.
      */
-    String getLine1AlphaTagForSubscriber(int subId);
+    String getLine1AlphaTagForSubscriber(int subId, String callingPackage);
 
 
     /**
      * Retrieves MSISDN Number.
      */
-    String getMsisdn();
+    String getMsisdn(String callingPackage);
 
     /**
      * Retrieves the Msisdn of a subId.
      */
-    String getMsisdnForSubscriber(int subId);
+    String getMsisdnForSubscriber(int subId, String callingPackage);
 
     /**
      * Retrieves the voice mail number.
      */
-    String getVoiceMailNumber();
+    String getVoiceMailNumber(String callingPackage);
 
     /**
      * Retrieves the voice mail number of a given subId.
      */
-    String getVoiceMailNumberForSubscriber(int subId);
+    String getVoiceMailNumberForSubscriber(int subId, String callingPackage);
 
     /**
      * Retrieves the complete voice mail number.
@@ -140,13 +140,13 @@
     /**
      * Retrieves the alpha identifier associated with the voice mail number.
      */
-    String getVoiceMailAlphaTag();
+    String getVoiceMailAlphaTag(String callingPackage);
 
     /**
      * Retrieves the alpha identifier associated with the voice mail number
      * of a subId.
      */
-    String getVoiceMailAlphaTagForSubscriber(int subId);
+    String getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage);
 
     /**
      * Returns the IMS private user identity (IMPI) that was loaded from the ISIM.