Merge "Make MediaSession2.CommandGroup updatable"
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 7ab0bcd..b5c1ddf 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -44,6 +44,8 @@
 using drm::V1_0::KeyValue;
 using drm::V1_1::HdcpLevel;;
 using drm::V1_0::SecureStop;
+using drm::V1_1::SecureStopRelease;
+using drm::V1_0::SecureStopId;
 using drm::V1_1::SecurityLevel;
 using drm::V1_0::Status;
 using ::android::hardware::hidl_array;
@@ -165,6 +167,15 @@
     return secureStops;
 }
 
+static List<Vector<uint8_t>> toSecureStopIds(const hidl_vec<SecureStopId>&
+        hSecureStopIds) {
+    List<Vector<uint8_t>> secureStopIds;
+    for (size_t i = 0; i < hSecureStopIds.size(); i++) {
+        secureStopIds.push_back(toVector(hSecureStopIds[i]));
+    }
+    return secureStopIds;
+}
+
 static status_t toStatusT(Status status) {
     switch (status) {
     case Status::OK:
@@ -797,6 +808,32 @@
 }
 
 
+status_t DrmHal::getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    if (mPluginV1_1 == NULL) {
+        return ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    status_t err = UNKNOWN_ERROR;
+
+    Return<void> hResult = mPluginV1_1->getSecureStopIds(
+            [&](Status status, const hidl_vec<SecureStopId>& hSecureStopIds) {
+                if (status == Status::OK) {
+                    secureStopIds = toSecureStopIds(hSecureStopIds);
+                }
+                err = toStatusT(status);
+            }
+    );
+
+    return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+
 status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
@@ -819,13 +856,36 @@
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
+    if (mPluginV1_1 != NULL) {
+        SecureStopRelease secureStopRelease;
+        secureStopRelease.opaqueData = toHidlVec(ssRelease);
+        return toStatusT(mPluginV1_1->releaseSecureStops(secureStopRelease));
+    }
+
     return toStatusT(mPlugin->releaseSecureStop(toHidlVec(ssRelease)));
 }
 
-status_t DrmHal::releaseAllSecureStops() {
+status_t DrmHal::removeSecureStop(Vector<uint8_t> const &ssid) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    if (mPluginV1_1 == NULL) {
+        return ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    return toStatusT(mPluginV1_1->removeSecureStop(toHidlVec(ssid)));
+}
+
+status_t DrmHal::removeAllSecureStops() {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
+    if (mPluginV1_1 != NULL) {
+        return toStatusT(mPluginV1_1->removeAllSecureStops());
+    }
     return toStatusT(mPlugin->releaseAllSecureStops());
 }
 
diff --git a/drm/libmediadrm/IDrm.cpp b/drm/libmediadrm/IDrm.cpp
index e7417cc..63a9562 100644
--- a/drm/libmediadrm/IDrm.cpp
+++ b/drm/libmediadrm/IDrm.cpp
@@ -56,11 +56,13 @@
     VERIFY,
     SET_LISTENER,
     GET_SECURE_STOP,
-    RELEASE_ALL_SECURE_STOPS,
+    REMOVE_ALL_SECURE_STOPS,
     GET_HDCP_LEVELS,
     GET_NUMBER_OF_SESSIONS,
     GET_SECURITY_LEVEL,
     SET_SECURITY_LEVEL,
+    REMOVE_SECURE_STOP,
+    GET_SECURE_STOP_IDS
 };
 
 struct BpDrm : public BpInterface<IDrm> {
@@ -302,6 +304,25 @@
         return reply.readInt32();
     }
 
+    virtual status_t getSecureStopIds(List<Vector<uint8_t> > &secureStopIds) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
+
+        status_t status = remote()->transact(GET_SECURE_STOP_IDS, data, &reply);
+        if (status != OK) {
+            return status;
+        }
+
+        secureStopIds.clear();
+        uint32_t count = reply.readInt32();
+        for (size_t i = 0; i < count; i++) {
+            Vector<uint8_t> secureStopId;
+            readVector(reply, secureStopId);
+            secureStopIds.push_back(secureStopId);
+        }
+        return reply.readInt32();
+    }
+
     virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
         Parcel data, reply;
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
@@ -329,11 +350,24 @@
         return reply.readInt32();
     }
 
-    virtual status_t releaseAllSecureStops() {
+    virtual status_t removeSecureStop(Vector<uint8_t> const &ssid) {
         Parcel data, reply;
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
 
-        status_t status = remote()->transact(RELEASE_ALL_SECURE_STOPS, data, &reply);
+        writeVector(data, ssid);
+        status_t status = remote()->transact(REMOVE_SECURE_STOP, data, &reply);
+        if (status != OK) {
+            return status;
+        }
+
+        return reply.readInt32();
+    }
+
+    virtual status_t removeAllSecureStops() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
+
+        status_t status = remote()->transact(REMOVE_ALL_SECURE_STOPS, data, &reply);
         if (status != OK) {
             return status;
         }
@@ -854,6 +888,24 @@
             return OK;
         }
 
+        case GET_SECURE_STOP_IDS:
+        {
+            CHECK_INTERFACE(IDrm, data, reply);
+            List<Vector<uint8_t> > secureStopIds;
+            status_t result = getSecureStopIds(secureStopIds);
+            size_t count = secureStopIds.size();
+            reply->writeInt32(count);
+            List<Vector<uint8_t> >::iterator iter = secureStopIds.begin();
+            while(iter != secureStopIds.end()) {
+                size_t size = iter->size();
+                reply->writeInt32(size);
+                reply->write(iter->array(), iter->size());
+                iter++;
+            }
+            reply->writeInt32(result);
+            return OK;
+        }
+
         case GET_SECURE_STOP:
         {
             CHECK_INTERFACE(IDrm, data, reply);
@@ -874,10 +926,19 @@
             return OK;
         }
 
-        case RELEASE_ALL_SECURE_STOPS:
+        case REMOVE_SECURE_STOP:
         {
             CHECK_INTERFACE(IDrm, data, reply);
-            reply->writeInt32(releaseAllSecureStops());
+            Vector<uint8_t> ssid;
+            readVector(data, ssid);
+            reply->writeInt32(removeSecureStop(ssid));
+            return OK;
+        }
+
+        case REMOVE_ALL_SECURE_STOPS:
+        {
+            CHECK_INTERFACE(IDrm, data, reply);
+            reply->writeInt32(removeAllSecureStops());
             return OK;
         }
 
diff --git a/media/libmedia/include/media/DrmHal.h b/media/libmedia/include/media/DrmHal.h
index c18d845..ec3a9b3 100644
--- a/media/libmedia/include/media/DrmHal.h
+++ b/media/libmedia/include/media/DrmHal.h
@@ -97,10 +97,12 @@
                                               Vector<uint8_t> &wrappedKey);
 
     virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops);
+    virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
     virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
 
     virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
-    virtual status_t releaseAllSecureStops();
+    virtual status_t removeSecureStop(Vector<uint8_t> const &ssid);
+    virtual status_t removeAllSecureStops();
 
     virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
             DrmPlugin::HdcpLevel *maxLevel) const;
diff --git a/media/libmedia/include/media/IDrm.h b/media/libmedia/include/media/IDrm.h
index 9266f99..994cade 100644
--- a/media/libmedia/include/media/IDrm.h
+++ b/media/libmedia/include/media/IDrm.h
@@ -74,10 +74,12 @@
                                               Vector<uint8_t> &wrappedKey) = 0;
 
     virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops) = 0;
+    virtual status_t getSecureStopIds(List<Vector<uint8_t> > &secureStopIds) = 0;
     virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) = 0;
 
     virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) = 0;
-    virtual status_t releaseAllSecureStops() = 0;
+    virtual status_t removeSecureStop(Vector<uint8_t> const &ssid) = 0;
+    virtual status_t removeAllSecureStops() = 0;
 
     virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
             DrmPlugin::HdcpLevel *maxLevel)
diff --git a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
index 688aadc..b4aaa79 100644
--- a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
@@ -56,7 +56,6 @@
 
     private static final int MAX_PROGRESS = 1000;
     private static final int DEFAULT_PROGRESS_UPDATE_TIME_MS = 1000;
-    private static final int DEFAULT_TIMEOUT_MS = 2000;
 
     private static final int REWIND_TIME_MS = 10000;
     private static final int FORWARD_TIME_MS = 30000;
@@ -72,6 +71,8 @@
     private TextView mTitleView;
     private int mDuration;
     private int mPrevState;
+    private int mCurrentVisibility;
+    private long mTimeout;
     private long mPlaybackActions;
     private boolean mShowing;
     private boolean mDragging;
@@ -115,6 +116,9 @@
         // Inflate MediaControlView2 from XML
         View root = makeControllerView();
         mInstance.addView(root);
+
+        // Set default timeout
+        mTimeout = 2000;
     }
 
     @Override
@@ -134,50 +138,8 @@
     }
 
     @Override
-    public void show_impl() {
-        mInstance.show(DEFAULT_TIMEOUT_MS);
-    }
-
-    @Override
-    public void show_impl(long timeout) {
-        if (!mShowing) {
-            setProgress();
-            if (mPlayPauseButton != null) {
-                mPlayPauseButton.requestFocus();
-            }
-            disableUnsupportedButtons();
-            mInstance.setVisibility(View.VISIBLE);
-            mShowing = true;
-        }
-        // cause the progress bar to be updated even if mShowing
-        // was already true.  This happens, for example, if we're
-        // paused with the progress bar showing the user hits play.
-        mInstance.post(mShowProgress);
-
-        if (timeout != 0 && !mAccessibilityManager.isTouchExplorationEnabled()) {
-            mInstance.removeCallbacks(mFadeOut);
-            mInstance.postDelayed(mFadeOut, timeout);
-        }
-    }
-
-    @Override
     public boolean isShowing_impl() {
-        return mShowing;
-    }
-
-    @Override
-    public void hide_impl() {
-        if (mShowing) {
-            try {
-                mInstance.removeCallbacks(mShowProgress);
-                // Remove existing call to mFadeOut to avoid from being called later.
-                mInstance.removeCallbacks(mFadeOut);
-                mInstance.setVisibility(View.GONE);
-            } catch (IllegalArgumentException ex) {
-                Log.w(TAG, "already removed");
-            }
-            mShowing = false;
-        }
+        return (mInstance.getVisibility() == View.VISIBLE) ? true : false;
     }
 
     @Override
@@ -248,6 +210,46 @@
     }
 
     @Override
+    public void requestPlayButtonFocus_impl() {
+        if (mPlayPauseButton != null) {
+            mPlayPauseButton.requestFocus();
+        }
+    }
+
+    @Override
+    public void setTimeout_impl(long timeout) {
+        mTimeout = timeout;
+    }
+
+    @Override
+    public long getTimeout_impl() {
+        return mTimeout;
+    }
+
+    @Override
+    public void onVisibilityAggregated_impl(boolean invisible) {
+        int visibility = mInstance.getVisibility();
+        if (mCurrentVisibility != visibility) {
+            mInstance.setVisibility(visibility);
+            mCurrentVisibility = visibility;
+
+            if (visibility == View.VISIBLE) {
+                setProgress();
+                disableUnsupportedButtons();
+                // cause the progress bar to be updated even if mShowing
+                // was already true.  This happens, for example, if we're
+                // paused with the progress bar showing the user hits play.
+                mInstance.post(mShowProgress);
+                resetFadeOutRunnable();
+            } else if (visibility == View.GONE) {
+                mInstance.removeCallbacks(mShowProgress);
+                // Remove existing call to mFadeOut to avoid from being called later.
+                mInstance.removeCallbacks(mFadeOut);
+            }
+        }
+    }
+
+    @Override
     public void onAttachedToWindow_impl() {
         mSuperProvider.onAttachedToWindow_impl();
     }
@@ -270,7 +272,7 @@
     // TODO: Should this function be removed?
     @Override
     public boolean onTrackballEvent_impl(MotionEvent ev) {
-        mInstance.show(DEFAULT_TIMEOUT_MS);
+        resetFadeOutRunnable();
         return false;
     }
 
@@ -483,7 +485,7 @@
         @Override
         public void run() {
             if (isPlaying()) {
-                mInstance.hide();
+                mInstance.setVisibility(View.GONE);
             }
         }
     };
@@ -499,6 +501,13 @@
         }
     };
 
+    private void resetFadeOutRunnable() {
+        if (mTimeout != 0 && !mAccessibilityManager.isTouchExplorationEnabled()) {
+            mInstance.removeCallbacks(mFadeOut);
+            mInstance.postDelayed(mFadeOut, mTimeout);
+        }
+    }
+
     private String stringForTime(int timeMs) {
         int totalSeconds = timeMs / 1000;
 
@@ -572,9 +581,9 @@
             if (!mSeekAvailable) {
                 return;
             }
-            mInstance.show(3600000);
 
             mDragging = true;
+            mInstance.removeCallbacks(mFadeOut);
 
             // By removing these pending progress messages we make sure
             // that a) we won't update the progress while the user adjusts
@@ -622,7 +631,8 @@
             mDragging = false;
 
             setProgress();
-            mInstance.show(DEFAULT_TIMEOUT_MS);
+
+            resetFadeOutRunnable();
 
             // Ensure that progress is properly updated in the future,
             // the call to show() does not guarantee this because it is a
@@ -635,7 +645,7 @@
         @Override
         public void onClick(View v) {
             togglePausePlayState();
-            mInstance.show(DEFAULT_TIMEOUT_MS);
+            resetFadeOutRunnable();
         }
     };
 
@@ -646,7 +656,7 @@
             mControls.seekTo(pos);
             setProgress();
 
-            mInstance.show(DEFAULT_TIMEOUT_MS);
+            resetFadeOutRunnable();
         }
     };
 
@@ -657,7 +667,7 @@
             mControls.seekTo(pos);
             setProgress();
 
-            mInstance.show(DEFAULT_TIMEOUT_MS);
+            resetFadeOutRunnable();
         }
     };
 
@@ -665,7 +675,7 @@
         @Override
         public void onClick(View v) {
             mControls.skipToNext();
-            mInstance.show(DEFAULT_TIMEOUT_MS);
+            resetFadeOutRunnable();
         }
     };
 
@@ -673,7 +683,7 @@
         @Override
         public void onClick(View v) {
             mControls.skipToPrevious();
-            mInstance.show(DEFAULT_TIMEOUT_MS);
+            resetFadeOutRunnable();
         }
     };
 
@@ -693,7 +703,7 @@
                 mController.sendCommand(MediaControlView2.COMMAND_HIDE_SUBTITLE, null, null);
                 mSubtitleIsEnabled = false;
             }
-            mInstance.show(DEFAULT_TIMEOUT_MS);
+            resetFadeOutRunnable();
         }
     };
 
@@ -715,7 +725,7 @@
             mController.sendCommand(MediaControlView2.COMMAND_SET_FULLSCREEN, args, null);
 
             mIsFullScreen = isEnteringFullScreen;
-            mInstance.show(DEFAULT_TIMEOUT_MS);
+            resetFadeOutRunnable();
         }
     };
 
@@ -724,7 +734,7 @@
         public void onClick(View v) {
             mBasicControls.setVisibility(View.GONE);
             mExtraControls.setVisibility(View.VISIBLE);
-            mInstance.show(DEFAULT_TIMEOUT_MS);
+            resetFadeOutRunnable();
         }
     };
 
@@ -733,6 +743,7 @@
         public void onClick(View v) {
             mBasicControls.setVisibility(View.VISIBLE);
             mExtraControls.setVisibility(View.GONE);
+            resetFadeOutRunnable();
         }
     };
 
@@ -830,7 +841,7 @@
                             // TODO: Currently, we are just sending extras that came from session.
                             // Is it the right behavior?
                             mControls.sendCustomAction(actionString, action.getExtras());
-                            mInstance.show(DEFAULT_TIMEOUT_MS);
+                            mInstance.setVisibility(View.VISIBLE);
                         }
                     });
                     mCustomButtons.addView(button);
diff --git a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
index 38ade41..a8864fc 100644
--- a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
@@ -452,7 +452,7 @@
                     + ", mTargetState=" + mTargetState + ", " + view.toString());
         }
         if (mMediaControlView != null) {
-            mMediaControlView.hide();
+            mMediaControlView.setVisibility(View.GONE);
         }
     }
 
@@ -674,9 +674,9 @@
 
     private void toggleMediaControlViewVisibility() {
         if (mMediaControlView.isShowing()) {
-            mMediaControlView.hide();
+            mMediaControlView.setVisibility(View.GONE);
         } else {
-            mMediaControlView.show();
+            mMediaControlView.setVisibility(View.VISIBLE);
         }
     }
 
@@ -763,14 +763,17 @@
                 if (needToStart()) {
                     mMediaController.getTransportControls().play();
                     if (mMediaControlView != null) {
-                        mMediaControlView.show();
+                        mMediaControlView.setVisibility(View.VISIBLE);
                     }
                 } else if (!(isInPlaybackState() && mMediaPlayer.isPlaying())
                         && (seekToPosition != 0 || mMediaPlayer.getCurrentPosition() > 0)) {
                     if (mMediaControlView != null) {
                         // Show the media controls when we're paused into a video and
                         // make them stick.
-                        mMediaControlView.show(0);
+                        long currTimeout = mMediaControlView.getTimeout();
+                        mMediaControlView.setTimeout(0L);
+                        mMediaControlView.setVisibility(View.VISIBLE);
+                        mMediaControlView.setTimeout(currTimeout);
                     }
                 }
             } else {
@@ -834,7 +837,7 @@
                     updatePlaybackState();
 
                     if (mMediaControlView != null) {
-                        mMediaControlView.hide();
+                        mMediaControlView.setVisibility(View.GONE);
                     }
 
                     /* If an error handler has been supplied, use it and finish. */
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index b868fa6..f149f8a 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2400,6 +2400,8 @@
 
     Vector<camera3_stream_t*> streams;
     streams.setCapacity(config.num_streams);
+    std::vector<uint32_t> outBufSizes(mOutputStreams.size(), 0);
+
 
     if (mInputStream != NULL) {
         camera3_stream_t *inputStream;
@@ -2430,6 +2432,12 @@
             return INVALID_OPERATION;
         }
         streams.add(outputStream);
+
+        if (outputStream->format == HAL_PIXEL_FORMAT_BLOB &&
+                outputStream->data_space == HAL_DATASPACE_V0_JFIF) {
+            outBufSizes[i] = static_cast<uint32_t>(
+                    getJpegBufferSize(outputStream->width, outputStream->height));
+        }
     }
 
     config.streams = streams.editArray();
@@ -2438,7 +2446,7 @@
     // max_buffers, usage, priv fields.
 
     const camera_metadata_t *sessionBuffer = sessionParams.getAndLock();
-    res = mInterface->configureStreams(sessionBuffer, &config);
+    res = mInterface->configureStreams(sessionBuffer, &config, outBufSizes);
     sessionParams.unlock(sessionBuffer);
 
     if (res == BAD_VALUE) {
@@ -3494,7 +3502,7 @@
 }
 
 status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t *sessionParams,
-        camera3_stream_configuration *config) {
+        camera3_stream_configuration *config, const std::vector<uint32_t>& outputBufferSizes) {
     ATRACE_NAME("CameraHal::configureStreams");
     if (!valid()) return INVALID_OPERATION;
     status_t res = OK;
@@ -3535,6 +3543,7 @@
         dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
         dst3_2.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
         dst3_4.v3_2 = dst3_2;
+        dst3_4.bufferSize = outputBufferSizes[i];
         if (src->physical_camera_id != nullptr) {
             dst3_4.physicalCameraId = src->physical_camera_id;
         }
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index bc97510..ccd9d7a 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -282,7 +282,8 @@
         status_t constructDefaultRequestSettings(camera3_request_template_t templateId,
                 /*out*/ camera_metadata_t **requestTemplate);
         status_t configureStreams(const camera_metadata_t *sessionParams,
-                /*inout*/ camera3_stream_configuration *config);
+                /*inout*/ camera3_stream_configuration *config,
+                const std::vector<uint32_t>& outputBufferSizes);
         status_t processCaptureRequest(camera3_capture_request_t *request);
         status_t processBatchCaptureRequests(
                 std::vector<camera3_capture_request_t*>& requests,