Merge "Fixed bad merge conflict resolution" into mnc-dev
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index 46cafad..46ffe36 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -138,6 +138,45 @@
      */
     public abstract void prepare(@NonNull Surface surface) throws CameraAccessException;
 
+
+    /**
+     * <p>Free all buffers allocated for an output Surface.</p>
+     *
+     * <p>Normally, once allocated, the image buffers for a given output Surface remain allocated
+     * for the lifetime of the capture session, to minimize latency of captures and to reduce
+     * memory allocation overhead.</p>
+     *
+     * <p>However, in some cases, it may be desirable for allocated buffers to be freed to reduce
+     * the application's memory consumption, if the particular output Surface will not be used by
+     * the application for some time.</p>
+     *
+     * <p>The tearDown() method can be used to perform this operation. After the call finishes, all
+     * unfilled image buffers will have been freed. Any future use of the target Surface may require
+     * allocation of additional buffers, as if the session had just been created.  Buffers being
+     * held by the application (either explicitly as Image objects from ImageReader, or implicitly
+     * as the current texture in a SurfaceTexture or the current contents of a RS Allocation, will
+     * remain valid and allocated even when tearDown is invoked.</p>
+     *
+     * <p>A Surface that has had tearDown() called on it is eligible to have prepare() invoked on it
+     * again even if it was used as a request target before the tearDown() call, as long as it
+     * doesn't get used as a target of a request between the tearDown() and prepare() calls.</p>
+     *
+     * @param surface the output Surface for which buffers should be freed. Must be one of the
+     * the output Surfaces used to create this session.
+     *
+     * @throws CameraAccessException if the camera device is no longer connected or has
+     *                               encountered a fatal error.
+     * @throws IllegalStateException if this session is no longer active, either because the session
+     *                               was explicitly closed, a new session has been created
+     *                               or the camera device has been closed.
+     * @throws IllegalArgumentException if the Surface is invalid, not part of this Session, or has
+     *                                  already been used as a target of a CaptureRequest in this
+     *                                  session or immediately prior sessions.
+     *
+     * @hide
+     */
+    public abstract void tearDown(@NonNull Surface surface) throws CameraAccessException;
+
     /**
      * <p>Submit a request for an image to be captured by the camera device.</p>
      *
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index c36683b..af1367c 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -1994,8 +1994,9 @@
     public static final int EDGE_MODE_OFF = 0;
 
     /**
-     * <p>Apply edge enhancement at a quality level that does not slow down frame rate relative to sensor
-     * output</p>
+     * <p>Apply edge enhancement at a quality level that does not slow down frame rate
+     * relative to sensor output. It may be the same as OFF if edge enhancement will
+     * slow down frame rate relative to sensor.</p>
      * @see CaptureRequest#EDGE_MODE
      */
     public static final int EDGE_MODE_FAST = 1;
@@ -2117,7 +2118,8 @@
 
     /**
      * <p>Noise reduction is applied without reducing frame rate relative to sensor
-     * output.</p>
+     * output. It may be the same as OFF if noise reduction will reduce frame rate
+     * relative to sensor.</p>
      * @see CaptureRequest#NOISE_REDUCTION_MODE
      */
     public static final int NOISE_REDUCTION_MODE_FAST = 1;
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index a136d0f..e965d65 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1584,8 +1584,9 @@
      * will be applied. HIGH_QUALITY mode indicates that the
      * camera device will use the highest-quality enhancement algorithms,
      * even if it slows down capture rate. FAST means the camera device will
-     * not slow down capture rate when applying edge enhancement. Every output stream will
-     * have a similar amount of enhancement applied.</p>
+     * not slow down capture rate when applying edge enhancement. FAST may be the same as OFF if
+     * edge enhancement will slow down capture rate. Every output stream will have a similar
+     * amount of enhancement applied.</p>
      * <p>ZERO_SHUTTER_LAG is meant to be used by applications that maintain a continuous circular
      * buffer of high-resolution images during preview and reprocess image(s) from that buffer
      * into a final capture when triggered by the user. In this mode, the camera device applies
@@ -1594,7 +1595,7 @@
      * since those will be reprocessed later if necessary.</p>
      * <p>For YUV_REPROCESSING, these FAST/HIGH_QUALITY modes both mean that the camera
      * device will apply FAST/HIGH_QUALITY YUV-domain edge enhancement, respectively.
-     * The camera device may adjust its internal noise reduction parameters for best
+     * The camera device may adjust its internal edge enhancement parameters for best
      * image quality based on the {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor}, if it is set.</p>
      * <p><b>Possible values:</b>
      * <ul>
@@ -2003,8 +2004,9 @@
      * will be applied. HIGH_QUALITY mode indicates that the camera device
      * will use the highest-quality noise filtering algorithms,
      * even if it slows down capture rate. FAST means the camera device will not
-     * slow down capture rate when applying noise filtering. Every output stream will
-     * have a similar amount of enhancement applied.</p>
+     * slow down capture rate when applying noise filtering. FAST may be the same as MINIMAL if
+     * MINIMAL is listed, or the same as OFF if any noise filtering will slow down capture rate.
+     * Every output stream will have a similar amount of enhancement applied.</p>
      * <p>ZERO_SHUTTER_LAG is meant to be used by applications that maintain a continuous circular
      * buffer of high-resolution images during preview and reprocess image(s) from that buffer
      * into a final capture when triggered by the user. In this mode, the camera device applies
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index f7cf1850..d5511c1 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2095,8 +2095,9 @@
      * will be applied. HIGH_QUALITY mode indicates that the
      * camera device will use the highest-quality enhancement algorithms,
      * even if it slows down capture rate. FAST means the camera device will
-     * not slow down capture rate when applying edge enhancement. Every output stream will
-     * have a similar amount of enhancement applied.</p>
+     * not slow down capture rate when applying edge enhancement. FAST may be the same as OFF if
+     * edge enhancement will slow down capture rate. Every output stream will have a similar
+     * amount of enhancement applied.</p>
      * <p>ZERO_SHUTTER_LAG is meant to be used by applications that maintain a continuous circular
      * buffer of high-resolution images during preview and reprocess image(s) from that buffer
      * into a final capture when triggered by the user. In this mode, the camera device applies
@@ -2105,7 +2106,7 @@
      * since those will be reprocessed later if necessary.</p>
      * <p>For YUV_REPROCESSING, these FAST/HIGH_QUALITY modes both mean that the camera
      * device will apply FAST/HIGH_QUALITY YUV-domain edge enhancement, respectively.
-     * The camera device may adjust its internal noise reduction parameters for best
+     * The camera device may adjust its internal edge enhancement parameters for best
      * image quality based on the {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor}, if it is set.</p>
      * <p><b>Possible values:</b>
      * <ul>
@@ -2786,8 +2787,9 @@
      * will be applied. HIGH_QUALITY mode indicates that the camera device
      * will use the highest-quality noise filtering algorithms,
      * even if it slows down capture rate. FAST means the camera device will not
-     * slow down capture rate when applying noise filtering. Every output stream will
-     * have a similar amount of enhancement applied.</p>
+     * slow down capture rate when applying noise filtering. FAST may be the same as MINIMAL if
+     * MINIMAL is listed, or the same as OFF if any noise filtering will slow down capture rate.
+     * Every output stream will have a similar amount of enhancement applied.</p>
      * <p>ZERO_SHUTTER_LAG is meant to be used by applications that maintain a continuous circular
      * buffer of high-resolution images during preview and reprocess image(s) from that buffer
      * into a final capture when triggered by the user. In this mode, the camera device applies
diff --git a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
index 1574f93..7cb3673 100644
--- a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -100,4 +100,6 @@
     int flush(out LongParcelable lastFrameNumber);
 
     int prepare(int streamId);
+
+    int tearDown(int streamId);
 }
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index 3c19cd2..d325c77 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -146,6 +146,11 @@
     }
 
     @Override
+    public void tearDown(Surface surface) throws CameraAccessException {
+        mDeviceImpl.tearDown(surface);
+    }
+
+    @Override
     public synchronized int capture(CaptureRequest request, CaptureCallback callback,
             Handler handler) throws CameraAccessException {
         if (request == null) {
diff --git a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java
index d732535..a920e2b 100644
--- a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java
@@ -169,6 +169,11 @@
     }
 
     @Override
+    public void tearDown(Surface surface) throws CameraAccessException {
+        mSessionImpl.tearDown(surface);
+    }
+
+    @Override
     public int capture(CaptureRequest request, CaptureCallback listener, Handler handler)
             throws CameraAccessException {
         throw new UnsupportedOperationException("Constrained high speed session doesn't support"
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index c594228..91d623e 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -679,6 +679,31 @@
         }
     }
 
+    public void tearDown(Surface surface) throws CameraAccessException {
+        if (surface == null) throw new IllegalArgumentException("Surface is null");
+
+        synchronized(mInterfaceLock) {
+            int streamId = -1;
+            for (int i = 0; i < mConfiguredOutputs.size(); i++) {
+                if (surface == mConfiguredOutputs.valueAt(i).getSurface()) {
+                    streamId = mConfiguredOutputs.keyAt(i);
+                    break;
+                }
+            }
+            if (streamId == -1) {
+                throw new IllegalArgumentException("Surface is not part of this session");
+            }
+            try {
+                mRemoteDevice.tearDown(streamId);
+            } catch (CameraRuntimeException e) {
+                throw e.asChecked();
+            } catch (RemoteException e) {
+                // impossible
+                return;
+            }
+        }
+    }
+
     public int capture(CaptureRequest request, CaptureCallback callback, Handler handler)
             throws CameraAccessException {
         if (DEBUG) {
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index f5314da..e20eaa7 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -636,6 +636,20 @@
         return CameraBinderDecorator.NO_ERROR;
     }
 
+    public int tearDown(int streamId) {
+        if (DEBUG) {
+            Log.d(TAG, "tearDown called.");
+        }
+        if (mLegacyDevice.isClosed()) {
+            Log.e(TAG, "Cannot tear down stream, device has been closed.");
+            return CameraBinderDecorator.ENODEV;
+        }
+
+        // LEGACY doesn't support actual teardown, so just a no-op
+
+        return CameraBinderDecorator.NO_ERROR;
+    }
+
     @Override
     public IBinder asBinder() {
         // This is solely intended to be used for in-process binding.
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index d547a60..8ce1cbf 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -5957,9 +5957,7 @@
              */
             public static final CharSequence getTypeLabel(Resources res, int type,
                     CharSequence label) {
-                if (type == TYPE_CUSTOM) {
-                    return (label != null ? label : "");
-                } else if (type == TYPE_ASSISTANT && !TextUtils.isEmpty(label)) {
+                if ((type == TYPE_CUSTOM || type == TYPE_ASSISTANT) && !TextUtils.isEmpty(label)) {
                     return label;
                 } else {
                     final int labelRes = getTypeLabelResource(type);
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index e1b5a6d..76eaea9 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -314,11 +314,16 @@
             contentValues.put(Voicemails.IS_READ, voicemail.isRead() ? 1 : 0);
 
             PhoneAccountHandle phoneAccount = voicemail.getPhoneAccount();
-            if (voicemail.getPhoneAccount() != null) {
+            if (phoneAccount != null) {
                 contentValues.put(Voicemails.PHONE_ACCOUNT_COMPONENT_NAME,
                         phoneAccount.getComponentName().flattenToString());
                 contentValues.put(Voicemails.PHONE_ACCOUNT_ID, phoneAccount.getId());
             }
+
+            if (voicemail.getTranscription() != null) {
+                contentValues.put(Voicemails.TRANSCRIPTION, voicemail.getTranscription());
+            }
+
             return contentValues;
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 094b9b5..10191ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -773,14 +773,7 @@
                 && mQsExpansionEnabled) {
             mTwoFingerQsExpandPossible = true;
         }
-        final int pointerCount = event.getPointerCount();
-        final boolean twoFingerDrag = action == MotionEvent.ACTION_POINTER_DOWN
-                && pointerCount == 2;
-        final boolean stylusClickDrag = action == MotionEvent.ACTION_DOWN
-                && pointerCount == 1 && event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS
-                && (event.isButtonPressed(MotionEvent.BUTTON_SECONDARY)
-                        || event.isButtonPressed(MotionEvent.BUTTON_TERTIARY));
-        if (mTwoFingerQsExpandPossible && (twoFingerDrag || stylusClickDrag)
+        if (mTwoFingerQsExpandPossible && isOpenQsEvent(event)
                 && event.getY(event.getActionIndex()) < mStatusBarMinHeight) {
             MetricsLogger.count(mContext, COUNTER_PANEL_OPEN_QS, 1);
             mQsExpandImmediate = true;
@@ -799,6 +792,24 @@
                 || y <= mQsContainer.getY() + mQsContainer.getHeight());
     }
 
+    private boolean isOpenQsEvent(MotionEvent event) {
+        final int pointerCount = event.getPointerCount();
+        final int action = event.getActionMasked();
+
+        final boolean twoFingerDrag = action == MotionEvent.ACTION_POINTER_DOWN
+                && pointerCount == 2;
+
+        final boolean stylusButtonClickDrag = action == MotionEvent.ACTION_DOWN
+                && (event.isButtonPressed(MotionEvent.BUTTON_STYLUS_PRIMARY)
+                        || event.isButtonPressed(MotionEvent.BUTTON_STYLUS_SECONDARY));
+
+        final boolean mouseButtonClickDrag = action == MotionEvent.ACTION_DOWN
+                && (event.isButtonPressed(MotionEvent.BUTTON_SECONDARY)
+                        || event.isButtonPressed(MotionEvent.BUTTON_TERTIARY));
+
+        return twoFingerDrag || stylusButtonClickDrag || mouseButtonClickDrag;
+    }
+
     private void handleQsDown(MotionEvent event) {
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN
                 && shouldQuickSettingsIntercept(event.getX(), event.getY(), -1)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index 04c626b..61986ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -232,7 +232,13 @@
             } else if (hhmm != null && hhmm.length() == 4) {
                 int hh = Integer.parseInt(hhmm.substring(0, 2));
                 int mm = Integer.parseInt(hhmm.substring(2));
-                mCalendar.set(Calendar.HOUR, hh);
+                boolean is24 = DateFormat.is24HourFormat(
+                        getContext(), ActivityManager.getCurrentUser());
+                if (is24) {
+                    mCalendar.set(Calendar.HOUR_OF_DAY, hh);
+                } else {
+                    mCalendar.set(Calendar.HOUR, hh);
+                }
                 mCalendar.set(Calendar.MINUTE, mm);
             }
             setText(getSmallTime());
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f041d50..d3f7795 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -6172,12 +6172,16 @@
                 return false;
             }
         }
-
-        synchronized (mInstallLock) {
-            final String[] instructionSets = new String[] { targetInstructionSet };
-            int result = mPackageDexOptimizer.performDexOpt(p, instructionSets,
-                    false /* forceDex */, false /* defer */, true /* inclDependencies */);
-            return result == PackageDexOptimizer.DEX_OPT_PERFORMED;
+        long callingId = Binder.clearCallingIdentity();
+        try {
+            synchronized (mInstallLock) {
+                final String[] instructionSets = new String[] { targetInstructionSet };
+                int result = mPackageDexOptimizer.performDexOpt(p, instructionSets,
+                        false /* forceDex */, false /* defer */, true /* inclDependencies */);
+                return result == PackageDexOptimizer.DEX_OPT_PERFORMED;
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingId);
         }
     }
 
diff --git a/telecomm/java/android/telecom/Voicemail.java b/telecomm/java/android/telecom/Voicemail.java
index 151917e..ca235bf 100644
--- a/telecomm/java/android/telecom/Voicemail.java
+++ b/telecomm/java/android/telecom/Voicemail.java
@@ -36,10 +36,11 @@
     private final Uri mUri;
     private final Boolean mIsRead;
     private final Boolean mHasContent;
+    private final String mTranscription;
 
     private Voicemail(Long timestamp, String number, PhoneAccountHandle phoneAccountHandle, Long id,
             Long duration, String source, String providerData, Uri uri, Boolean isRead,
-            Boolean hasContent) {
+            Boolean hasContent, String transcription) {
         mTimestamp = timestamp;
         mNumber = number;
         mPhoneAccount = phoneAccountHandle;
@@ -50,6 +51,7 @@
         mUri = uri;
         mIsRead = isRead;
         mHasContent = hasContent;
+        mTranscription = transcription;
     }
 
     /**
@@ -88,6 +90,7 @@
         private Uri mBuilderUri;
         private Boolean mBuilderIsRead;
         private boolean mBuilderHasContent;
+        private String mBuilderTranscription;
 
         /** You should use the correct factory method to construct a builder. */
         private Builder() {
@@ -143,6 +146,11 @@
             return this;
         }
 
+        public Builder setTranscription(String transcription) {
+            mBuilderTranscription = transcription;
+            return this;
+        }
+
         public Voicemail build() {
             mBuilderId = mBuilderId == null ? -1 : mBuilderId;
             mBuilderTimestamp = mBuilderTimestamp == null ? 0 : mBuilderTimestamp;
@@ -150,7 +158,7 @@
             mBuilderIsRead = mBuilderIsRead == null ? false : mBuilderIsRead;
             return new Voicemail(mBuilderTimestamp, mBuilderNumber, mBuilderPhoneAccount,
                     mBuilderId, mBuilderDuration, mBuilderSourcePackage, mBuilderSourceData,
-                    mBuilderUri, mBuilderIsRead, mBuilderHasContent);
+                    mBuilderUri, mBuilderIsRead, mBuilderHasContent, mBuilderTranscription);
         }
     }
 
@@ -230,6 +238,13 @@
         return mHasContent;
     }
 
+    /**
+     * Returns the text transcription of this voicemail, or null if this field is not set.
+     */
+    public String getTranscription() {
+        return mTranscription;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -265,6 +280,7 @@
         } else {
             dest.writeInt(0);
         }
+        dest.writeCharSequence(mTranscription);
     }
 
     public static final Creator<Voicemail> CREATOR
@@ -299,5 +315,6 @@
         }
         mIsRead = in.readInt() > 0 ? true : false;
         mHasContent = in.readInt() > 0 ? true : false;
+        mTranscription = (String) in.readCharSequence();
     }
 }