Merge "bufferpool2.0 tests: add read/write verification"
diff --git a/media/libstagefright/bqhelper/Conversion.cpp b/media/libstagefright/bqhelper/Conversion.cpp
index ffed005..91d7c74 100644
--- a/media/libstagefright/bqhelper/Conversion.cpp
+++ b/media/libstagefright/bqhelper/Conversion.cpp
@@ -98,6 +98,17 @@
  */
 
 /**
+ * \brief Convert `Return<void>` to `status_t`. This is for legacy binder calls.
+ *
+ * \param[in] t The source `Return<void>`.
+ * \return The corresponding `status_t`.
+ */
+// convert: Return<void> -> status_t
+status_t toStatusT(Return<void> const& t) {
+    return t.isOk() ? OK : (t.isDeadObject() ? DEAD_OBJECT : UNKNOWN_ERROR);
+}
+
+/**
  * \brief Convert `Return<void>` to `binder::Status`.
  *
  * \param[in] t The source `Return<void>`.
@@ -107,22 +118,11 @@
 ::android::binder::Status toBinderStatus(
         Return<void> const& t) {
     return ::android::binder::Status::fromExceptionCode(
-            t.isOk() ? OK : UNKNOWN_ERROR,
+            toStatusT(t),
             t.description().c_str());
 }
 
 /**
- * \brief Convert `Return<void>` to `status_t`. This is for legacy binder calls.
- *
- * \param[in] t The source `Return<void>`.
- * \return The corresponding `status_t`.
- */
-// convert: Return<void> -> status_t
-status_t toStatusT(Return<void> const& t) {
-    return t.isOk() ? OK : UNKNOWN_ERROR;
-}
-
-/**
  * \brief Wrap `native_handle_t*` in `hidl_handle`.
  *
  * \param[in] nh The source `native_handle_t*`.
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/1.0/Conversion.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Conversion.h
index a9fce55..0f229f7 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/1.0/Conversion.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Conversion.h
@@ -190,7 +190,12 @@
  */
 // convert: Status -> status_t
 inline status_t toStatusT(Return<Status> const& t) {
-    return t.isOk() ? toStatusT(static_cast<Status>(t)) : UNKNOWN_ERROR;
+    if (t.isOk()) {
+        return toStatusT(static_cast<Status>(t));
+    } else if (t.isDeadObject()) {
+        return DEAD_OBJECT;
+    }
+    return UNKNOWN_ERROR;
 }
 
 /**
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index 8c1ac59..c66cd50 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -84,8 +84,17 @@
 
 EXPORT
 media_status_t AMediaExtractor_setDataSource(AMediaExtractor *mData, const char *location) {
-    ALOGV("setDataSource(%s)", location);
-    // TODO: add header support
+    return AMediaExtractor_setDataSourceWithHeaders(mData, location, 0, NULL, NULL);
+}
+
+EXPORT
+media_status_t AMediaExtractor_setDataSourceWithHeaders(AMediaExtractor *mData,
+        const char *uri,
+        int numheaders,
+        const char * const *keys,
+        const char * const *values) {
+
+    ALOGV("setDataSource(%s)", uri);
 
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jobject service = NULL;
@@ -109,7 +118,7 @@
         return AMEDIA_ERROR_UNSUPPORTED;
     }
 
-    jstring jloc = env->NewStringUTF(location);
+    jstring jloc = env->NewStringUTF(uri);
 
     service = env->CallStaticObjectMethod(mediahttpclass, mediaHttpCreateMethod, jloc);
     env->DeleteLocalRef(jloc);
@@ -120,7 +129,15 @@
         httpService = interface_cast<IMediaHTTPService>(binder);
     }
 
-    status_t err = mData->mImpl->setDataSource(httpService, location, NULL);
+    KeyedVector<String8, String8> headers;
+    for (int i = 0; i < numheaders; ++i) {
+        String8 key8(keys[i]);
+        String8 value8(values[i]);
+        headers.add(key8, value8);
+    }
+
+    status_t err;
+    err = mData->mImpl->setDataSource(httpService, uri, numheaders > 0 ? &headers : NULL);
     env->ExceptionClear();
     return translate_error(err);
 }
diff --git a/media/ndk/include/media/NdkMediaExtractor.h b/media/ndk/include/media/NdkMediaExtractor.h
index 6a1796f..413bc1a 100644
--- a/media/ndk/include/media/NdkMediaExtractor.h
+++ b/media/ndk/include/media/NdkMediaExtractor.h
@@ -72,7 +72,27 @@
  */
 media_status_t AMediaExtractor_setDataSource(AMediaExtractor*,
         const char *location) __INTRODUCED_IN(21);
-        // TODO support headers
+
+#if __ANDROID_API__ >= 29
+/**
+ * Set the |uri| from which the extractor will read,
+ * plus additional http headers when initiating the request.
+ *
+ * Headers will contain corresponding items from |keys| & |values|
+ * from indices 0 (inclusive) to numheaders-1 (inclusive):
+ *
+ * keys[0]:values[0]
+ * ...
+ * keys[numheaders - 1]:values[numheaders - 1]
+ *
+ */
+media_status_t AMediaExtractor_setDataSourceWithHeaders(AMediaExtractor*,
+        const char *uri,
+        int numheaders,
+        const char * const *keys,
+        const char * const *values) __INTRODUCED_IN(29);
+
+#endif /* __ANDROID_API__ >= 29 */
 
 #if __ANDROID_API__ >= 28
 
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index 0751a55..1fd69a2 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -184,6 +184,7 @@
     AMediaExtractor_setDataSource;
     AMediaExtractor_setDataSourceCustom; # introduced=28
     AMediaExtractor_setDataSourceFd;
+    AMediaExtractor_setDataSourceWithHeaders; # introduced=29
     AMediaExtractor_unselectTrack;
     AMediaFormat_clear; # introduced=29
     AMediaFormat_copy; # introduced=29
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index c4c742e..6cab441 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1157,7 +1157,8 @@
 {
     sp<ThreadBase> thread = mThread.promote();
     if (thread != 0 &&
-        (thread->type() == ThreadBase::OFFLOAD || thread->type() == ThreadBase::DIRECT)) {
+        (thread->type() == ThreadBase::OFFLOAD || thread->type() == ThreadBase::DIRECT) &&
+        !isNonOffloadableEnabled_l()) {
         PlaybackThread *t = (PlaybackThread *)thread.get();
         float vol_l = (float)left / (1 << 24);
         float vol_r = (float)right / (1 << 24);
@@ -2552,6 +2553,11 @@
 bool AudioFlinger::EffectChain::isNonOffloadableEnabled()
 {
     Mutex::Autolock _l(mLock);
+    return isNonOffloadableEnabled_l();
+}
+
+bool AudioFlinger::EffectChain::isNonOffloadableEnabled_l()
+{
     size_t size = mEffects.size();
     for (size_t i = 0; i < size; i++) {
         if (mEffects[i]->isEnabled() && !mEffects[i]->isOffloadable()) {
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index e04ee8e..15a26ea 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -378,6 +378,7 @@
 
     // At least one non offloadable effect in the chain is enabled
     bool isNonOffloadableEnabled();
+    bool isNonOffloadableEnabled_l();
 
     void syncHalEffectsState();
 
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 2a8b397..e4f3cf1 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2811,12 +2811,9 @@
     }
 
     // Check if offload has been disabled
-    char propValue[PROPERTY_VALUE_MAX];
-    if (property_get("audio.offload.disable", propValue, "0")) {
-        if (atoi(propValue) != 0) {
-            ALOGV("offload disabled by audio.offload.disable=%s", propValue );
-            return false;
-        }
+    if (property_get_bool("audio.offload.disable", false /* default_value */)) {
+        ALOGV("offload disabled by audio.offload.disable");
+        return false;
     }
 
     // Check if stream type is music, then only allow offload as of now.
@@ -2835,9 +2832,12 @@
     }
 
     //If duration is less than minimum value defined in property, return false
-    if (property_get("audio.offload.min.duration.secs", propValue, NULL)) {
-        if (offloadInfo.duration_us < (atoi(propValue) * 1000000 )) {
-            ALOGV("Offload denied by duration < audio.offload.min.duration.secs(=%s)", propValue);
+    const int min_duration_secs = property_get_int32(
+            "audio.offload.min.duration.secs", -1 /* default_value */);
+    if (min_duration_secs >= 0) {
+        if (offloadInfo.duration_us < min_duration_secs * 1000000LL) {
+            ALOGV("Offload denied by duration < audio.offload.min.duration.secs(=%d)",
+                    min_duration_secs);
             return false;
         }
     } else if (offloadInfo.duration_us < OFFLOAD_DEFAULT_MIN_DURATION_SECS * 1000000) {
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 8476711..ecbcf76 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -237,12 +237,14 @@
     /**
      * Return buffer back to ANativeWindow
      */
-    if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR || mDropBuffers) {
+    if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR || mDropBuffers || timestamp == 0) {
         // Cancel buffer
         if (mDropBuffers) {
             ALOGV("%s: Dropping a frame for stream %d.", __FUNCTION__, mId);
-        } else {
+        } else if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
             ALOGW("%s: A frame is dropped for stream %d due to buffer error.", __FUNCTION__, mId);
+        } else {
+            ALOGE("%s: Stream %d: timestamp shouldn't be 0", __FUNCTION__, mId);
         }
 
         res = currentConsumer->cancelBuffer(currentConsumer.get(),
@@ -268,10 +270,6 @@
             mTraceFirstBuffer = false;
         }
 
-        if (timestamp == 0) {
-            ALOGW("%s: Stream %d: timestamp shouldn't be 0", __FUNCTION__, mId);
-        }
-
         /* Certain consumers (such as AudioSource or HardwareComposer) use
          * MONOTONIC time, causing time misalignment if camera timestamp is
          * in BOOTTIME. Do the conversion if necessary. */
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index b208d9f..9238590 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -662,9 +662,12 @@
 
     removeOutstandingBuffer(buffer);
 
+    // Buffer status may be changed, so make a copy of the stream_buffer struct.
+    camera3_stream_buffer b = buffer;
     if (timestampIncreasing && timestamp != 0 && timestamp <= mLastTimestamp) {
-        ALOGW("%s: Stream %d: timestamp %" PRId64 " is not increasing. Prev timestamp %" PRId64,
+        ALOGE("%s: Stream %d: timestamp %" PRId64 " is not increasing. Prev timestamp %" PRId64,
                 __FUNCTION__, mId, timestamp, mLastTimestamp);
+        b.status = CAMERA3_BUFFER_STATUS_ERROR;
     }
     mLastTimestamp = timestamp;
 
@@ -676,9 +679,9 @@
      *
      * Do this for getBuffer as well.
      */
-    status_t res = returnBufferLocked(buffer, timestamp);
+    status_t res = returnBufferLocked(b, timestamp);
     if (res == OK) {
-        fireBufferListenersLocked(buffer, /*acquired*/false, /*output*/true);
+        fireBufferListenersLocked(b, /*acquired*/false, /*output*/true);
     }
 
     // Even if returning the buffer failed, we still want to signal whoever is waiting for the