Merge "RESTRICT AUTOMERGE CCodec: make config consistent before/after flush" into qt-qpr1-dev
diff --git a/camera/aidl/android/hardware/ICameraServiceListener.aidl b/camera/aidl/android/hardware/ICameraServiceListener.aidl
index e9dcbdb..47580f8 100644
--- a/camera/aidl/android/hardware/ICameraServiceListener.aidl
+++ b/camera/aidl/android/hardware/ICameraServiceListener.aidl
@@ -83,4 +83,12 @@
      * can retry after receiving this callback.
      */
     oneway void onCameraAccessPrioritiesChanged();
+
+    /**
+     * Notify registered clients about cameras being opened/closed.
+     * Only clients with android.permission.CAMERA_OPEN_CLOSE_LISTENER permission
+     * will receive such callbacks.
+     */
+    oneway void onCameraOpened(String cameraId, String clientPackageId);
+    oneway void onCameraClosed(String cameraId);
 }
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
index 8c1da36..28fec82 100644
--- a/camera/ndk/impl/ACameraManager.h
+++ b/camera/ndk/impl/ACameraManager.h
@@ -92,6 +92,12 @@
         }
 
         virtual binder::Status onCameraAccessPrioritiesChanged();
+        virtual binder::Status onCameraOpened(const String16&, const String16&) {
+            return binder::Status::ok();
+        }
+        virtual binder::Status onCameraClosed(const String16&) {
+            return binder::Status::ok();
+        }
 
       private:
         const wp<CameraManagerGlobal> mCameraManager;
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index 8fe029a..dc5afc5 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -95,6 +95,17 @@
         return binder::Status::ok();
     }
 
+    virtual binder::Status onCameraOpened(const String16& /*cameraId*/,
+            const String16& /*clientPackageName*/) {
+        // No op
+        return binder::Status::ok();
+    }
+
+    virtual binder::Status onCameraClosed(const String16& /*cameraId*/) {
+        // No op
+        return binder::Status::ok();
+    }
+
     bool waitForNumCameras(size_t num) const {
         Mutex::Autolock l(mLock);
 
diff --git a/drm/libmediadrm/ICrypto.cpp b/drm/libmediadrm/ICrypto.cpp
index a2594aa..8d8d088 100644
--- a/drm/libmediadrm/ICrypto.cpp
+++ b/drm/libmediadrm/ICrypto.cpp
@@ -264,8 +264,12 @@
         {
             CHECK_INTERFACE(ICrypto, data, reply);
 
-            uint8_t uuid[16];
-            data.read(uuid, sizeof(uuid));
+            uint8_t uuid[16] = {0};
+            if (data.read(uuid, sizeof(uuid)) != NO_ERROR) {
+                android_errorWriteLog(0x534e4554, "144767096");
+                reply->writeInt32(BAD_VALUE);
+                return OK;
+            }
 
             size_t opaqueSize = data.readInt32();
             void *opaqueData = NULL;
@@ -280,7 +284,11 @@
                 return NO_MEMORY;
             }
 
-            data.read(opaqueData, opaqueSize);
+            if (data.read(opaqueData, opaqueSize) != NO_ERROR) {
+                android_errorWriteLog(0x534e4554, "144767096");
+                reply->writeInt32(BAD_VALUE);
+                return OK;
+            }
             reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize));
 
             free(opaqueData);
diff --git a/drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp
index caff393..121a4e2 100644
--- a/drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp
+++ b/drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp
@@ -76,10 +76,21 @@
 
 android::status_t InitDataParser::parsePssh(const Vector<uint8_t>& initData,
         Vector<const uint8_t*>* keyIds) {
+    // Description of PSSH format:
+    // https://w3c.github.io/encrypted-media/format-registry/initdata/cenc.html
     size_t readPosition = 0;
 
-    // Validate size field
     uint32_t expectedSize = initData.size();
+    const char psshIdentifier[4] = {'p', 's', 's', 'h'};
+    const uint8_t psshVersion1[4] = {1, 0, 0, 0};
+    uint32_t keyIdCount = 0;
+    size_t headerSize = sizeof(expectedSize) + sizeof(psshIdentifier) +
+                        sizeof(psshVersion1) + kSystemIdSize + sizeof(keyIdCount);
+    if (initData.size() < headerSize) {
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    // Validate size field
     expectedSize = htonl(expectedSize);
     if (memcmp(&initData[readPosition], &expectedSize,
                sizeof(expectedSize)) != 0) {
@@ -88,7 +99,6 @@
     readPosition += sizeof(expectedSize);
 
     // Validate PSSH box identifier
-    const char psshIdentifier[4] = {'p', 's', 's', 'h'};
     if (memcmp(&initData[readPosition], psshIdentifier,
                sizeof(psshIdentifier)) != 0) {
         return android::ERROR_DRM_CANNOT_HANDLE;
@@ -96,7 +106,6 @@
     readPosition += sizeof(psshIdentifier);
 
     // Validate EME version number
-    const uint8_t psshVersion1[4] = {1, 0, 0, 0};
     if (memcmp(&initData[readPosition], psshVersion1,
                sizeof(psshVersion1)) != 0) {
         return android::ERROR_DRM_CANNOT_HANDLE;
@@ -110,12 +119,14 @@
     readPosition += kSystemIdSize;
 
     // Read key ID count
-    uint32_t keyIdCount;
     memcpy(&keyIdCount, &initData[readPosition], sizeof(keyIdCount));
     keyIdCount = ntohl(keyIdCount);
     readPosition += sizeof(keyIdCount);
-    if (readPosition + ((uint64_t)keyIdCount * kKeyIdSize) !=
-            initData.size() - sizeof(uint32_t)) {
+
+    uint64_t psshSize = 0;
+    if (__builtin_mul_overflow(keyIdCount, kKeyIdSize, &psshSize) ||
+        __builtin_add_overflow(readPosition, psshSize, &psshSize) ||
+        psshSize != initData.size() - sizeof(uint32_t) /* DataSize(0) */) {
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
 
diff --git a/media/codec2/sfplugin/C2OMXNode.cpp b/media/codec2/sfplugin/C2OMXNode.cpp
index 78d221e..c7588e9 100644
--- a/media/codec2/sfplugin/C2OMXNode.cpp
+++ b/media/codec2/sfplugin/C2OMXNode.cpp
@@ -62,7 +62,7 @@
             android::base::unique_fd &&fd0,
             android::base::unique_fd &&fd1) {
         Mutexed<Jobs>::Locked jobs(mJobs);
-        auto it = jobs->queues.try_emplace(comp, comp, systemTime()).first;
+        auto it = jobs->queues.try_emplace(comp, comp).first;
         it->second.workList.emplace_back(
                 std::move(work), fenceFd, std::move(fd0), std::move(fd1));
         jobs->cond.broadcast();
@@ -79,7 +79,8 @@
             for (auto it = jobs->queues.begin(); it != jobs->queues.end(); ) {
                 Queue &queue = it->second;
                 if (queue.workList.empty()
-                        || nowNs - queue.lastQueuedTimestampNs < kIntervalNs) {
+                        || (queue.lastQueuedTimestampNs != 0 &&
+                            nowNs - queue.lastQueuedTimestampNs < kIntervalNs)) {
                     ++it;
                     continue;
                 }
@@ -104,6 +105,7 @@
                     sp<Fence> fence(new Fence(fenceFd));
                     fence->waitForever(LOG_TAG);
                 }
+                queue.lastQueuedTimestampNs = nowNs;
                 comp->queue(&items);
                 for (android::base::unique_fd &ufd : uniqueFds) {
                     (void)ufd.release();
@@ -143,8 +145,8 @@
         android::base::unique_fd fd1;
     };
     struct Queue {
-        Queue(const std::shared_ptr<Codec2Client::Component> &comp, nsecs_t timestamp)
-            : component(comp), lastQueuedTimestampNs(timestamp) {}
+        Queue(const std::shared_ptr<Codec2Client::Component> &comp)
+            : component(comp), lastQueuedTimestampNs(0) {}
         Queue(const Queue &) = delete;
         Queue &operator =(const Queue &) = delete;
 
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 64f0aca..2fb9491 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -1346,7 +1346,8 @@
         case GET_OFFLOAD_FORMATS_A2DP:
         case LIST_AUDIO_VOLUME_GROUPS:
         case GET_VOLUME_GROUP_FOR_ATTRIBUTES:
-        case SET_RTT_ENABLED: {
+        case SET_RTT_ENABLED:
+        case SET_ALLOWED_CAPTURE_POLICY: {
             if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
                 ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
                       __func__, code, IPCThreadState::self()->getCallingPid(),
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index c048de3..a984b10 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -5535,7 +5535,10 @@
             patchBuilder.addSink(filteredDevice);
         }
 
-        installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(), delayMs);
+        // Add half reported latency to delayMs when muteWaitMs is null in order
+        // to avoid disordered sequence of muting volume and changing devices.
+        installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(),
+                muteWaitMs == 0 ? (delayMs + (outputDesc->latency() / 2)) : delayMs);
     }
 
     // update stream volumes according to new device
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index fa8da89..20e1c9e 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -976,11 +976,6 @@
         ALOGV("%s() mAudioPolicyManager == NULL", __func__);
         return NO_INIT;
     }
-    uint_t callingUid = IPCThreadState::self()->getCallingUid();
-    if (uid != callingUid) {
-        ALOGD("%s() uid invalid %d != %d", __func__, uid, callingUid);
-        return PERMISSION_DENIED;
-    }
     return mAudioPolicyManager->setAllowedCapturePolicy(uid, capturePolicy);
 }
 
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index b20c9a4..670e026 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -118,6 +118,8 @@
 // ----------------------------------------------------------------------------
 
 static const String16 sManageCameraPermission("android.permission.MANAGE_CAMERA");
+static const String16 sCameraOpenCloseListenerPermission(
+        "android.permission.CAMERA_OPEN_CLOSE_LISTENER");
 
 // Matches with PERCEPTIBLE_APP_ADJ in ProcessList.java
 static constexpr int32_t kVendorClientScore = 200;
@@ -1811,7 +1813,11 @@
         }
 
         auto clientUid = CameraThreadState::getCallingUid();
-        sp<ServiceListener> serviceListener = new ServiceListener(this, listener, clientUid);
+        auto clientPid = CameraThreadState::getCallingPid();
+        bool openCloseCallbackAllowed = checkPermission(sCameraOpenCloseListenerPermission,
+                clientPid, clientUid);
+        sp<ServiceListener> serviceListener = new ServiceListener(this, listener,
+                clientUid, clientPid, openCloseCallbackAllowed);
         auto ret = serviceListener->initialize();
         if (ret != NO_ERROR) {
             String8 msg = String8::format("Failed to initialize service listener: %s (%d)",
@@ -2515,6 +2521,9 @@
 
     sCameraService->mUidPolicy->registerMonitorUid(mClientUid);
 
+    // Notify listeners of camera open/close status
+    sCameraService->updateOpenCloseStatus(mCameraIdStr, true/*open*/, mClientPackageName);
+
     return OK;
 }
 
@@ -2555,6 +2564,9 @@
 
     sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid);
 
+    // Notify listeners of camera open/close status
+    sCameraService->updateOpenCloseStatus(mCameraIdStr, false/*open*/, mClientPackageName);
+
     return OK;
 }
 
@@ -3311,6 +3323,29 @@
         });
 }
 
+void CameraService::updateOpenCloseStatus(const String8& cameraId, bool open,
+        const String16& clientPackageName) {
+    Mutex::Autolock lock(mStatusListenerLock);
+
+    for (const auto& it : mListenerList) {
+        if (!it.second->isOpenCloseCallbackAllowed()) {
+            continue;
+        }
+
+        binder::Status ret;
+        String16 cameraId64(cameraId);
+        if (open) {
+            ret = it.second->getListener()->onCameraOpened(cameraId64, clientPackageName);
+        } else {
+            ret = it.second->getListener()->onCameraClosed(cameraId64);
+        }
+        if (!ret.isOk()) {
+            ALOGE("%s: Failed to trigger onCameraOpened/onCameraClosed callback: %d", __FUNCTION__,
+                    ret.exceptionCode());
+        }
+    }
+}
+
 template<class Func>
 void CameraService::CameraState::updateStatus(StatusInternal status,
         const String8& cameraId,
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 22842a1..bcaca9f 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -817,7 +817,9 @@
     class ServiceListener : public virtual IBinder::DeathRecipient {
         public:
             ServiceListener(sp<CameraService> parent, sp<hardware::ICameraServiceListener> listener,
-                    int uid) : mParent(parent), mListener(listener), mListenerUid(uid) {}
+                    int uid, int pid, bool openCloseCallbackAllowed) : mParent(parent),
+                    mListener(listener), mListenerUid(uid), mListenerPid(pid),
+                    mOpenCloseCallbackAllowed(openCloseCallbackAllowed) {}
 
             status_t initialize() {
                 return IInterface::asBinder(mListener)->linkToDeath(this);
@@ -831,12 +833,16 @@
             }
 
             int getListenerUid() { return mListenerUid; }
+            int getListenerPid() { return mListenerPid; }
             sp<hardware::ICameraServiceListener> getListener() { return mListener; }
+            bool isOpenCloseCallbackAllowed() { return mOpenCloseCallbackAllowed; }
 
         private:
             wp<CameraService> mParent;
             sp<hardware::ICameraServiceListener> mListener;
             int mListenerUid;
+            int mListenerPid;
+            bool mOpenCloseCallbackAllowed = false;
     };
 
     // Guarded by mStatusListenerMutex
@@ -859,6 +865,13 @@
     void updateStatus(StatusInternal status,
             const String8& cameraId);
 
+    /**
+     * Update the opened/closed status of the given camera id.
+     *
+     * This method acqiures mStatusListenerLock.
+     */
+    void updateOpenCloseStatus(const String8& cameraId, bool open, const String16& packageName);
+
     // flashlight control
     sp<CameraFlashlight> mFlashlight;
     // guard mTorchStatusMap
diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
index 0f6be79..b9e5857 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
+++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
@@ -54,6 +54,15 @@
         // TODO: no implementation yet.
         return binder::Status::ok();
     }
+    virtual binder::Status onCameraOpened(const ::android::String16& /*cameraId*/,
+            const ::android::String16& /*clientPackageId*/) {
+        // empty implementation
+        return binder::Status::ok();
+    }
+    virtual binder::Status onCameraClosed(const ::android::String16& /*cameraId*/) {
+        // empty implementation
+        return binder::Status::ok();
+    }
 };
 
 } // implementation
diff --git a/services/camera/libcameraservice/utils/ExifUtils.cpp b/services/camera/libcameraservice/utils/ExifUtils.cpp
index c0afdc1..8a0303a 100644
--- a/services/camera/libcameraservice/utils/ExifUtils.cpp
+++ b/services/camera/libcameraservice/utils/ExifUtils.cpp
@@ -603,13 +603,13 @@
 }
 
 bool ExifUtilsImpl::setImageHeight(uint32_t length) {
-    SET_LONG(EXIF_IFD_0, EXIF_TAG_IMAGE_LENGTH, length);
+    SET_SHORT(EXIF_IFD_0, EXIF_TAG_IMAGE_LENGTH, length);
     SET_LONG(EXIF_IFD_EXIF, EXIF_TAG_PIXEL_Y_DIMENSION, length);
     return true;
 }
 
 bool ExifUtilsImpl::setImageWidth(uint32_t width) {
-    SET_LONG(EXIF_IFD_0, EXIF_TAG_IMAGE_WIDTH, width);
+    SET_SHORT(EXIF_IFD_0, EXIF_TAG_IMAGE_WIDTH, width);
     SET_LONG(EXIF_IFD_EXIF, EXIF_TAG_PIXEL_X_DIMENSION, width);
     return true;
 }