Merge "audiopolicy: clean delayMs to 0 before reevaluate all outputs routing when call state changes" into pi-dev
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index b53c741..5d0f68e 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -253,7 +253,7 @@
 
     int32_t seqNum = mHeapSeqNum++;
     sp<HidlMemory> hidlMemory = fromHeap(heap);
-    mHeapBases.add(seqNum, mNextBufferId);
+    mHeapBases.add(seqNum, HeapBase(mNextBufferId, heap->getSize()));
     Return<void> hResult = mPlugin->setSharedBufferBase(*hidlMemory, mNextBufferId++);
     ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
     return seqNum;
@@ -278,10 +278,26 @@
         return UNEXPECTED_NULL;
     }
 
-    // memory must be in the declared heap
-    CHECK(mHeapBases.indexOfKey(seqNum) >= 0);
+    // memory must be in one of the heaps that have been set
+    if (mHeapBases.indexOfKey(seqNum) < 0) {
+        return UNKNOWN_ERROR;
+    }
 
-    buffer->bufferId = mHeapBases.valueFor(seqNum);
+    // heap must be the same size as the one that was set in setHeapBase
+    if (mHeapBases.valueFor(seqNum).getSize() != heap->getSize()) {
+        android_errorWriteLog(0x534e4554, "76221123");
+        return UNKNOWN_ERROR;
+     }
+
+    // memory must be within the address space of the heap
+    if (memory->pointer() != static_cast<uint8_t *>(heap->getBase()) + memory->offset()  ||
+            heap->getSize() < memory->offset() + memory->size() ||
+            SIZE_MAX - memory->offset() < memory->size()) {
+        android_errorWriteLog(0x534e4554, "76221123");
+        return UNKNOWN_ERROR;
+    }
+
+    buffer->bufferId = mHeapBases.valueFor(seqNum).getBufferId();
     buffer->offset = offset >= 0 ? offset : 0;
     buffer->size = size;
     return OK;
diff --git a/drm/libmediadrm/DrmMetrics.cpp b/drm/libmediadrm/DrmMetrics.cpp
index fce1717..4fed707 100644
--- a/drm/libmediadrm/DrmMetrics.cpp
+++ b/drm/libmediadrm/DrmMetrics.cpp
@@ -29,6 +29,7 @@
 using ::android::String16;
 using ::android::String8;
 using ::android::drm_metrics::DrmFrameworkMetrics;
+using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
 using ::android::hardware::drm::V1_0::EventType;
 using ::android::hardware::drm::V1_0::KeyStatusType;
@@ -192,6 +193,13 @@
     }
 }
 
+inline String16 MakeIndexString(unsigned int index) {
+  std::string str("[");
+  str.append(std::to_string(index));
+  str.append("]");
+  return String16(str.c_str());
+}
+
 } // namespace
 
 namespace android {
@@ -370,9 +378,11 @@
     }
 
     int groupIndex = 0;
+    std::map<String16, int> indexMap;
     for (const auto &hidlMetricGroup : hidlMetricGroups) {
         PersistableBundle bundleMetricGroup;
         for (const auto &hidlMetric : hidlMetricGroup.metrics) {
+            String16 metricName(hidlMetric.name.c_str());
             PersistableBundle bundleMetric;
             // Add metric component values.
             for (const auto &value : hidlMetric.values) {
@@ -388,14 +398,22 @@
             // Add attributes to the bundle metric.
             bundleMetric.putPersistableBundle(String16("attributes"),
                                               bundleMetricAttributes);
+            // Add one layer of indirection, allowing for repeated metric names.
+            PersistableBundle repeatedMetrics;
+            bundleMetricGroup.getPersistableBundle(metricName,
+                                                   &repeatedMetrics);
+            int index = indexMap[metricName];
+            repeatedMetrics.putPersistableBundle(MakeIndexString(index),
+                                                 bundleMetric);
+            indexMap[metricName] = ++index;
+
             // Add the bundle metric to the group of metrics.
-            bundleMetricGroup.putPersistableBundle(
-                String16(hidlMetric.name.c_str()), bundleMetric);
+            bundleMetricGroup.putPersistableBundle(metricName,
+                                                   repeatedMetrics);
         }
         // Add the bundle metric group to the collection of groups.
-        bundleMetricGroups->putPersistableBundle(
-            String16(std::to_string(groupIndex).c_str()), bundleMetricGroup);
-        groupIndex++;
+        bundleMetricGroups->putPersistableBundle(MakeIndexString(groupIndex++),
+                                                 bundleMetricGroup);
     }
 
     return OK;
diff --git a/drm/libmediadrm/tests/DrmMetrics_test.cpp b/drm/libmediadrm/tests/DrmMetrics_test.cpp
index 1a20342..64aa9d0 100644
--- a/drm/libmediadrm/tests/DrmMetrics_test.cpp
+++ b/drm/libmediadrm/tests/DrmMetrics_test.cpp
@@ -429,7 +429,8 @@
   DrmMetricGroup hidlMetricGroup =
       { { {
               "open_session_ok",
-              { { "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, "" } },
+              { { "status", DrmMetricGroup::ValueType::INT64_TYPE,
+                  (int64_t) Status::OK, 0.0, "" } },
               { { "count", DrmMetricGroup::ValueType::INT64_TYPE, 3, 0.0, "" } }
           },
           {
@@ -444,25 +445,28 @@
                                                      &bundleMetricGroups));
   ASSERT_EQ(1U, bundleMetricGroups.size());
   PersistableBundle bundleMetricGroup;
-  ASSERT_TRUE(bundleMetricGroups.getPersistableBundle(String16("0"), &bundleMetricGroup));
+  ASSERT_TRUE(bundleMetricGroups.getPersistableBundle(String16("[0]"), &bundleMetricGroup));
   ASSERT_EQ(2U, bundleMetricGroup.size());
 
   // Verify each metric.
   PersistableBundle metric;
   ASSERT_TRUE(bundleMetricGroup.getPersistableBundle(String16("open_session_ok"), &metric));
+  PersistableBundle metricInstance;
+  ASSERT_TRUE(metric.getPersistableBundle(String16("[0]"), &metricInstance));
   int64_t value = 0;
-  ASSERT_TRUE(metric.getLong(String16("count"), &value));
+  ASSERT_TRUE(metricInstance.getLong(String16("count"), &value));
   ASSERT_EQ(3, value);
   PersistableBundle attributeBundle;
-  ASSERT_TRUE(metric.getPersistableBundle(String16("attributes"), &attributeBundle));
+  ASSERT_TRUE(metricInstance.getPersistableBundle(String16("attributes"), &attributeBundle));
   ASSERT_TRUE(attributeBundle.getLong(String16("status"), &value));
   ASSERT_EQ((int64_t) Status::OK, value);
 
   ASSERT_TRUE(bundleMetricGroup.getPersistableBundle(String16("close_session_not_opened"),
                                                      &metric));
-  ASSERT_TRUE(metric.getLong(String16("count"), &value));
+  ASSERT_TRUE(metric.getPersistableBundle(String16("[0]"), &metricInstance));
+  ASSERT_TRUE(metricInstance.getLong(String16("count"), &value));
   ASSERT_EQ(7, value);
-  ASSERT_TRUE(metric.getPersistableBundle(String16("attributes"), &attributeBundle));
+  ASSERT_TRUE(metricInstance.getPersistableBundle(String16("attributes"), &attributeBundle));
   value = 0;
   ASSERT_TRUE(attributeBundle.getLong(String16("status"), &value));
   ASSERT_EQ((int64_t) Status::ERROR_DRM_SESSION_NOT_OPENED, value);
diff --git a/media/extractors/mp4/ItemTable.cpp b/media/extractors/mp4/ItemTable.cpp
index a1f6e9a..b6787af 100644
--- a/media/extractors/mp4/ItemTable.cpp
+++ b/media/extractors/mp4/ItemTable.cpp
@@ -1397,7 +1397,8 @@
         ALOGV("adding %s: itemId %d", image.isGrid() ? "grid" : "image", info.itemId);
 
         if (image.isGrid()) {
-            if (size > 12) {
+            // ImageGrid struct is at least 8-byte, at most 12-byte (if flags&1)
+            if (size < 8 || size > 12) {
                 return ERROR_MALFORMED;
             }
             uint8_t buf[12];
diff --git a/media/libmedia/include/media/CryptoHal.h b/media/libmedia/include/media/CryptoHal.h
index 4414e9d..ff8789d 100644
--- a/media/libmedia/include/media/CryptoHal.h
+++ b/media/libmedia/include/media/CryptoHal.h
@@ -81,7 +81,20 @@
      */
     status_t mInitCheck;
 
-    KeyedVector<int32_t, uint32_t> mHeapBases;
+    struct HeapBase {
+        HeapBase() : mBufferId(0), mSize(0) {}
+        HeapBase(uint32_t bufferId, size_t size) :
+            mBufferId(bufferId), mSize(size) {}
+
+        uint32_t getBufferId() const {return mBufferId;}
+        size_t getSize() const {return mSize;}
+
+    private:
+        uint32_t mBufferId;
+        size_t mSize;
+    };
+
+    KeyedVector<int32_t, HeapBase> mHeapBases;
     uint32_t mNextBufferId;
     int32_t mHeapSeqNum;
 
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index b75b234..f6d407f 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -342,6 +342,13 @@
         return PERMISSION_DENIED;
     }
 
+    if ((attr->source == AUDIO_SOURCE_VOICE_UPLINK ||
+        attr->source == AUDIO_SOURCE_VOICE_DOWNLINK ||
+        attr->source == AUDIO_SOURCE_VOICE_CALL) &&
+        !captureAudioOutputAllowed(pid, uid)) {
+        return PERMISSION_DENIED;
+    }
+
     if ((attr->source == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed(pid, uid)) {
         return BAD_VALUE;
     }
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 8d8bcab..4a58620 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -1215,6 +1215,35 @@
 
     fastInfo.maxJpegSize = getMaxSize(getAvailableJpegSizes());
 
+    isZslReprocessPresent = false;
+    camera_metadata_ro_entry_t availableCapabilities =
+        staticInfo(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+    if (0 < availableCapabilities.count) {
+        const uint8_t *caps = availableCapabilities.data.u8;
+        for (size_t i = 0; i < availableCapabilities.count; i++) {
+            if (ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING ==
+                caps[i]) {
+                isZslReprocessPresent = true;
+                break;
+            }
+        }
+    }
+    if (isZslReprocessPresent) {
+        Vector<StreamConfiguration> scs = getStreamConfigurations();
+        Size maxPrivInputSize = {0, 0};
+        for (const auto& sc : scs) {
+            if (sc.isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT &&
+                    sc.format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+                if (sc.width * sc.height > maxPrivInputSize.width * maxPrivInputSize.height) {
+                    maxPrivInputSize = {sc.width, sc.height};
+                }
+            }
+        }
+        fastInfo.maxZslSize = maxPrivInputSize;
+    } else {
+        fastInfo.maxZslSize = {0, 0};
+    }
+
     return OK;
 }
 
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h
index fe725fd..e35b7a4 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.h
+++ b/services/camera/libcameraservice/api1/client2/Parameters.h
@@ -242,6 +242,7 @@
         float minFocalLength;
         bool useFlexibleYuv;
         Size maxJpegSize;
+        Size maxZslSize;
     } fastInfo;
 
     // Quirks information; these are short-lived flags to enable workarounds for
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index 372a2c5..37e1495 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -231,63 +231,9 @@
         return INVALID_OPERATION;
     }
 
-    if ((mZslStreamId != NO_STREAM) || (mInputStreamId != NO_STREAM)) {
-        // Check if stream parameters have to change
-        CameraDeviceBase::StreamInfo streamInfo;
-        res = device->getStreamInfo(mZslStreamId, &streamInfo);
-        if (res != OK) {
-            ALOGE("%s: Camera %d: Error querying capture output stream info: "
-                    "%s (%d)", __FUNCTION__,
-                    client->getCameraId(), strerror(-res), res);
-            return res;
-        }
-        if (streamInfo.width != (uint32_t)params.fastInfo.arrayWidth ||
-                streamInfo.height != (uint32_t)params.fastInfo.arrayHeight) {
-            if (mZslStreamId != NO_STREAM) {
-                ALOGV("%s: Camera %d: Deleting stream %d since the buffer "
-                      "dimensions changed",
-                    __FUNCTION__, client->getCameraId(), mZslStreamId);
-                res = device->deleteStream(mZslStreamId);
-                if (res == -EBUSY) {
-                    ALOGV("%s: Camera %d: Device is busy, call updateStream again "
-                          " after it becomes idle", __FUNCTION__, mId);
-                    return res;
-                } else if(res != OK) {
-                    ALOGE("%s: Camera %d: Unable to delete old output stream "
-                            "for ZSL: %s (%d)", __FUNCTION__,
-                            client->getCameraId(), strerror(-res), res);
-                    return res;
-                }
-                mZslStreamId = NO_STREAM;
-            }
-
-            if (mInputStreamId != NO_STREAM) {
-                ALOGV("%s: Camera %d: Deleting stream %d since the buffer "
-                      "dimensions changed",
-                    __FUNCTION__, client->getCameraId(), mInputStreamId);
-                res = device->deleteStream(mInputStreamId);
-                if (res == -EBUSY) {
-                    ALOGV("%s: Camera %d: Device is busy, call updateStream again "
-                          " after it becomes idle", __FUNCTION__, mId);
-                    return res;
-                } else if(res != OK) {
-                    ALOGE("%s: Camera %d: Unable to delete old output stream "
-                            "for ZSL: %s (%d)", __FUNCTION__,
-                            client->getCameraId(), strerror(-res), res);
-                    return res;
-                }
-                mInputStreamId = NO_STREAM;
-            }
-            if (nullptr != mInputProducer.get()) {
-                mInputProducer->disconnect(NATIVE_WINDOW_API_CPU);
-                mInputProducer.clear();
-            }
-        }
-    }
-
     if (mInputStreamId == NO_STREAM) {
-        res = device->createInputStream(params.fastInfo.arrayWidth,
-            params.fastInfo.arrayHeight, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+        res = device->createInputStream(params.fastInfo.maxZslSize.width,
+            params.fastInfo.maxZslSize.height, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
             &mInputStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create input stream: "
@@ -309,8 +255,8 @@
         mProducer->setName(String8("Camera2-ZslRingBufferConsumer"));
         sp<Surface> outSurface = new Surface(producer);
 
-        res = device->createStream(outSurface, params.fastInfo.arrayWidth,
-            params.fastInfo.arrayHeight, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+        res = device->createStream(outSurface, params.fastInfo.maxZslSize.width,
+            params.fastInfo.maxZslSize.height, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
             HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mZslStreamId,
             String8());
         if (res != OK) {