Merge "MediaMetrics: Garbage collection fixes" into rvc-dev
diff --git a/media/extractors/aac/AACExtractor.cpp b/media/extractors/aac/AACExtractor.cpp
index 5d00d94..8f60f6b 100644
--- a/media/extractors/aac/AACExtractor.cpp
+++ b/media/extractors/aac/AACExtractor.cpp
@@ -181,6 +181,8 @@
 }
 
 AACExtractor::~AACExtractor() {
+    mOffsetVector.clear();
+    delete mDataSource;
     if (mMeta != nullptr) {
         AMediaFormat_delete(mMeta);
     }
diff --git a/media/extractors/mp4/AC4Parser.cpp b/media/extractors/mp4/AC4Parser.cpp
index 13d60c8..25fc4cd 100644
--- a/media/extractors/mp4/AC4Parser.cpp
+++ b/media/extractors/mp4/AC4Parser.cpp
@@ -600,6 +600,10 @@
         if (ac4_dsi_version == 1) {
             uint64_t end = (mDSISize - mBitReader.numBitsLeft()) / 8;
             uint64_t presentation_bytes = end - start;
+            if (pres_bytes < presentation_bytes) {
+                ALOGE("pres_bytes is smaller than presentation_bytes.");
+                return false;
+            }
             uint64_t skip_bytes = pres_bytes - presentation_bytes;
             ALOGV("skipping = %" PRIu64 " bytes", skip_bytes);
             CHECK_BITS_LEFT(skip_bytes * 8);
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 3638d2c..65afc8d 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -51,6 +51,7 @@
         // AIDL files for audioclient interfaces
         // The headers for these interfaces will be available to any modules that
         // include libaudioclient, at the path "aidl/package/path/BnFoo.h"
+        ":libaudioclient_aidl_callback",
         ":libaudioclient_aidl_private",
         ":libaudioclient_aidl",
 
@@ -138,3 +139,12 @@
     ],
     path: "aidl",
 }
+
+// AIDL interface for audio track callback
+filegroup {
+    name: "libaudioclient_aidl_callback",
+    srcs: [
+        "aidl/android/media/IAudioTrackCallback.aidl",
+    ],
+    path: "aidl",
+}
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index d5690fb..2f95886 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -217,7 +217,8 @@
       mPreviousSchedulingGroup(SP_DEFAULT),
       mPausedPosition(0),
       mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
-      mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE)
+      mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
+      mAudioTrackCallback(new AudioTrackCallback())
 {
     mAttributes.content_type = AUDIO_CONTENT_TYPE_UNKNOWN;
     mAttributes.usage = AUDIO_USAGE_UNKNOWN;
@@ -248,7 +249,8 @@
       mState(STATE_STOPPED),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
       mPreviousSchedulingGroup(SP_DEFAULT),
-      mPausedPosition(0)
+      mPausedPosition(0),
+      mAudioTrackCallback(new AudioTrackCallback())
 {
     mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
 
@@ -281,7 +283,8 @@
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
       mPreviousSchedulingGroup(SP_DEFAULT),
       mPausedPosition(0),
-      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE)
+      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
+      mAudioTrackCallback(new AudioTrackCallback())
 {
     mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
 
@@ -1527,6 +1530,7 @@
     input.notificationFrameCount = mNotificationFramesReq;
     input.selectedDeviceId = mSelectedDeviceId;
     input.sessionId = mSessionId;
+    input.audioTrackCallback = mAudioTrackCallback;
 
     IAudioFlinger::CreateTrackOutput output;
 
@@ -3376,4 +3380,23 @@
     mPausedNs = ns;
 }
 
+binder::Status AudioTrack::AudioTrackCallback::onCodecFormatChanged(
+        const std::vector<uint8_t>& audioMetadata)
+{
+    AutoMutex _l(mAudioTrackCbLock);
+    sp<media::IAudioTrackCallback> callback = mCallback.promote();
+    if (callback.get() != nullptr) {
+        callback->onCodecFormatChanged(audioMetadata);
+    } else {
+        mCallback.clear();
+    }
+    return binder::Status::ok();
+}
+
+void AudioTrack::AudioTrackCallback::setAudioTrackCallback(
+        const sp<media::IAudioTrackCallback> &callback) {
+    AutoMutex lock(mAudioTrackCbLock);
+    mCallback = callback;
+}
+
 } // namespace android
diff --git a/media/libaudioclient/aidl/android/media/IAudioTrackCallback.aidl b/media/libaudioclient/aidl/android/media/IAudioTrackCallback.aidl
new file mode 100644
index 0000000..21553b5
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/IAudioTrackCallback.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * @hide
+ */
+interface IAudioTrackCallback {
+    oneway void onCodecFormatChanged(in byte[] audioMetadata);
+}
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 95cad0a..4adaaea 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -26,6 +26,9 @@
 #include <media/Modulo.h>
 #include <utils/threads.h>
 
+#include "android/media/BnAudioTrackCallback.h"
+#include "android/media/IAudioTrackCallback.h"
+
 namespace android {
 
 // ----------------------------------------------------------------------------
@@ -885,8 +888,6 @@
             virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
                                              audio_port_handle_t deviceId);
 
-
-
     /* Obtain the pending duration in milliseconds for playback of pure PCM
      * (mixable without embedded timing) data remaining in AudioTrack.
      *
@@ -933,6 +934,10 @@
      */
             audio_port_handle_t getPortId() const { return mPortId; };
 
+            void setAudioTrackCallback(const sp<media::IAudioTrackCallback>& callback) {
+                mAudioTrackCallback->setAudioTrackCallback(callback);
+            }
+
  protected:
     /* copying audio tracks is not allowed */
                         AudioTrack(const AudioTrack& other);
@@ -1254,6 +1259,18 @@
     };
     MediaMetrics mMediaMetrics;
     std::string mMetricsId;  // GUARDED_BY(mLock), could change in createTrack_l().
+
+private:
+    class AudioTrackCallback : public media::BnAudioTrackCallback {
+    public:
+        binder::Status onCodecFormatChanged(const std::vector<uint8_t>& audioMetadata) override;
+
+        void setAudioTrackCallback(const sp<media::IAudioTrackCallback>& callback);
+    private:
+        Mutex mAudioTrackCbLock;
+        wp<media::IAudioTrackCallback> mCallback;
+    };
+    sp<AudioTrackCallback> mAudioTrackCallback;
 };
 
 }; // namespace android
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 8658cfa..f4ce5d7 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -40,6 +40,7 @@
 #include <vector>
 
 #include "android/media/IAudioRecord.h"
+#include "android/media/IAudioTrackCallback.h"
 
 namespace android {
 
@@ -83,6 +84,8 @@
             }
             notificationsPerBuffer = parcel->readInt32();
             speed = parcel->readFloat();
+            audioTrackCallback = interface_cast<media::IAudioTrackCallback>(
+                    parcel->readStrongBinder());
 
             /* input/output arguments*/
             (void)parcel->read(&flags, sizeof(audio_output_flags_t));
@@ -107,6 +110,7 @@
             }
             (void)parcel->writeInt32(notificationsPerBuffer);
             (void)parcel->writeFloat(speed);
+            (void)parcel->writeStrongBinder(IInterface::asBinder(audioTrackCallback));
 
             /* input/output arguments*/
             (void)parcel->write(&flags, sizeof(audio_output_flags_t));
@@ -125,6 +129,7 @@
         sp<IMemory> sharedBuffer;
         uint32_t notificationsPerBuffer;
         float speed;
+        sp<media::IAudioTrackCallback> audioTrackCallback;
 
         /* input/output */
         audio_output_flags_t flags;
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index c08dddb..2726e36 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -299,10 +299,17 @@
         if (mCallback.unsafe_get()) {
             processReturn("clearCallback", mStream->clearCallback());
         }
+#if MAJOR_VERSION >= 6
+        if (mEventCallback.unsafe_get() != nullptr) {
+            processReturn("setEventCallback",
+                    mStream->setEventCallback(nullptr));
+        }
+#endif
         processReturn("close", mStream->close());
         mStream.clear();
     }
     mCallback.clear();
+    mEventCallback.clear();
     hardware::IPCThreadState::self()->flushCommands();
     if (mEfGroup) {
         EventFlag::deleteEventFlag(&mEfGroup);
@@ -614,6 +621,50 @@
 }
 #endif
 
+#if MAJOR_VERSION < 6
+status_t StreamOutHalHidl::setEventCallback(
+        const sp<StreamOutHalInterfaceEventCallback>& callback __unused) {
+    // Codec format callback is supported starting from audio HAL V6.0
+    return INVALID_OPERATION;
+}
+#else
+
+#include PATH(android/hardware/audio/FILE_VERSION/IStreamOutEventCallback.h)
+
+namespace {
+
+struct StreamOutEventCallback : public IStreamOutEventCallback {
+    StreamOutEventCallback(const wp<StreamOutHalHidl>& stream) : mStream(stream) {}
+
+    // IStreamOutEventCallback implementation
+    Return<void> onCodecFormatChanged(
+            const android::hardware::hidl_vec<uint8_t>& audioMetadata)  override {
+        sp<StreamOutHalHidl> stream = mStream.promote();
+        if (stream != nullptr) {
+            std::basic_string<uint8_t> metadataBs(audioMetadata.begin(), audioMetadata.end());
+            stream->onCodecFormatChanged(metadataBs);
+        }
+        return Void();
+    }
+
+  private:
+    wp<StreamOutHalHidl> mStream;
+};
+
+}  // namespace
+
+status_t StreamOutHalHidl::setEventCallback(
+        const sp<StreamOutHalInterfaceEventCallback>& callback) {
+    if (mStream == nullptr) return NO_INIT;
+    mEventCallback = callback;
+    status_t status = processReturn(
+            "setEventCallback",
+            mStream->setEventCallback(
+                    callback.get() == nullptr ? nullptr : new StreamOutEventCallback(this)));
+    return status;
+}
+#endif
+
 void StreamOutHalHidl::onWriteReady() {
     sp<StreamOutHalInterfaceCallback> callback = mCallback.promote();
     if (callback == 0) return;
@@ -635,6 +686,13 @@
     callback->onError();
 }
 
+void StreamOutHalHidl::onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs) {
+    sp<StreamOutHalInterfaceEventCallback> callback = mEventCallback.promote();
+    if (callback == nullptr) return;
+    ALOGV("asyncCodecFormatCallback %s", __func__);
+    callback->onCodecFormatChanged(metadataBs);
+}
+
 
 StreamInHalHidl::StreamInHalHidl(const sp<IStreamIn>& stream)
         : StreamHalHidl(stream.get()), mStream(stream), mReaderClient(0), mEfGroup(nullptr) {
diff --git a/media/libaudiohal/impl/StreamHalHidl.h b/media/libaudiohal/impl/StreamHalHidl.h
index f587889..88f8587 100644
--- a/media/libaudiohal/impl/StreamHalHidl.h
+++ b/media/libaudiohal/impl/StreamHalHidl.h
@@ -173,6 +173,11 @@
     void onDrainReady();
     void onError();
 
+    status_t setEventCallback(const sp<StreamOutHalInterfaceEventCallback>& callback) override;
+
+    // Methods used by StreamCodecFormatCallback (HIDL).
+    void onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs);
+
   private:
     friend class DeviceHalHidl;
     typedef MessageQueue<WriteCommand, hardware::kSynchronizedReadWrite> CommandMQ;
@@ -180,6 +185,7 @@
     typedef MessageQueue<WriteStatus, hardware::kSynchronizedReadWrite> StatusMQ;
 
     wp<StreamOutHalInterfaceCallback> mCallback;
+    wp<StreamOutHalInterfaceEventCallback> mEventCallback;
     sp<IStreamOut> mStream;
     std::unique_ptr<CommandMQ> mCommandMQ;
     std::unique_ptr<DataMQ> mDataMQ;
diff --git a/media/libaudiohal/impl/StreamHalLocal.cpp b/media/libaudiohal/impl/StreamHalLocal.cpp
index 4818fd8..69be303 100644
--- a/media/libaudiohal/impl/StreamHalLocal.cpp
+++ b/media/libaudiohal/impl/StreamHalLocal.cpp
@@ -275,6 +275,43 @@
     return mStream->get_mmap_position(mStream, position);
 }
 
+status_t StreamOutHalLocal::setEventCallback(
+        const sp<StreamOutHalInterfaceEventCallback>& callback) {
+    if (mStream->set_event_callback == nullptr) {
+        return INVALID_OPERATION;
+    }
+    stream_event_callback_t asyncCallback =
+            callback == nullptr ? nullptr : StreamOutHalLocal::asyncEventCallback;
+    status_t result = mStream->set_event_callback(mStream, asyncCallback, this);
+    if (result == OK) {
+        mEventCallback = callback;
+    }
+    return result;
+}
+
+// static
+int StreamOutHalLocal::asyncEventCallback(
+        stream_event_callback_type_t event, void *param, void *cookie) {
+    // We act as if we gave a wp<StreamOutHalLocal> to HAL. This way we should handle
+    // correctly the case when the callback is invoked while StreamOutHalLocal's destructor is
+    // already running, because the destructor is invoked after the refcount has been atomically
+    // decremented.
+    wp<StreamOutHalLocal> weakSelf(static_cast<StreamOutHalLocal*>(cookie));
+    sp<StreamOutHalLocal> self = weakSelf.promote();
+    if (self == nullptr) return 0;
+    sp<StreamOutHalInterfaceEventCallback> callback = self->mEventCallback.promote();
+    if (callback.get() == nullptr) return 0;
+    switch (event) {
+        case STREAM_EVENT_CBK_TYPE_CODEC_FORMAT_CHANGED:
+            callback->onCodecFormatChanged(std::basic_string<uint8_t>((uint8_t*)param));
+            break;
+        default:
+            ALOGW("%s unknown event %d", __func__, event);
+            break;
+    }
+    return 0;
+}
+
 StreamInHalLocal::StreamInHalLocal(audio_stream_in_t *stream, sp<DeviceHalLocal> device)
         : StreamHalLocal(&stream->common, device), mStream(stream) {
 }
diff --git a/media/libaudiohal/impl/StreamHalLocal.h b/media/libaudiohal/impl/StreamHalLocal.h
index 34f2bd8..d17f9f3 100644
--- a/media/libaudiohal/impl/StreamHalLocal.h
+++ b/media/libaudiohal/impl/StreamHalLocal.h
@@ -156,9 +156,12 @@
     // Called when the metadata of the stream's source has been changed.
     status_t updateSourceMetadata(const SourceMetadata& sourceMetadata) override;
 
+    status_t setEventCallback(const sp<StreamOutHalInterfaceEventCallback>& callback) override;
+
   private:
     audio_stream_out_t *mStream;
     wp<StreamOutHalInterfaceCallback> mCallback;
+    wp<StreamOutHalInterfaceEventCallback> mEventCallback;
 
     friend class DeviceHalLocal;
 
@@ -168,6 +171,8 @@
     virtual ~StreamOutHalLocal();
 
     static int asyncCallback(stream_callback_event_t event, void *param, void *cookie);
+
+    static int asyncEventCallback(stream_event_callback_type_t event, void *param, void *cookie);
 };
 
 class StreamInHalLocal : public StreamInHalInterface, public StreamHalLocal {
diff --git a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
index 6c3b21c..e30cb72 100644
--- a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
@@ -101,6 +101,15 @@
     virtual ~StreamOutHalInterfaceCallback() {}
 };
 
+class StreamOutHalInterfaceEventCallback : public virtual RefBase {
+public:
+    virtual void onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs) = 0;
+
+protected:
+    StreamOutHalInterfaceEventCallback() {}
+    virtual ~StreamOutHalInterfaceEventCallback() {}
+};
+
 class StreamOutHalInterface : public virtual StreamHalInterface {
   public:
     // Return the audio hardware driver estimated latency in milliseconds.
@@ -157,6 +166,8 @@
      */
     virtual status_t updateSourceMetadata(const SourceMetadata& sourceMetadata) = 0;
 
+    virtual status_t setEventCallback(const sp<StreamOutHalInterfaceEventCallback>& callback) = 0;
+
   protected:
     virtual ~StreamOutHalInterface() {}
 };
diff --git a/media/libstagefright/webm/WebmFrameThread.cpp b/media/libstagefright/webm/WebmFrameThread.cpp
index 631a2ab..59ce8db 100644
--- a/media/libstagefright/webm/WebmFrameThread.cpp
+++ b/media/libstagefright/webm/WebmFrameThread.cpp
@@ -321,6 +321,7 @@
 status_t WebmFrameMediaSourceThread::pause() {
     if (mStarted) {
         mPaused = true;
+        mResumed = false;
     }
     return OK;
 }
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index e5a6e27..4adbad2 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -833,7 +833,7 @@
                                       input.notificationsPerBuffer, input.speed,
                                       input.sharedBuffer, sessionId, &output.flags,
                                       callingPid, input.clientInfo.clientTid, clientUid,
-                                      &lStatus, portId);
+                                      &lStatus, portId, input.audioTrackCallback);
         LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0));
         // we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless
 
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index a16fa94..d69b49d 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -33,6 +33,7 @@
 #include <sys/types.h>
 #include <limits.h>
 
+#include <android/media/IAudioTrackCallback.h>
 #include <android/os/BnExternalVibrationController.h>
 #include <android-base/macros.h>
 
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 2833525..f24dcd7 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -42,6 +42,7 @@
 #include <private/media/AudioTrackShared.h>
 #include <private/android_filesystem_config.h>
 #include <audio_utils/Balance.h>
+#include <audio_utils/Metadata.h>
 #include <audio_utils/channels.h>
 #include <audio_utils/mono_blend.h>
 #include <audio_utils/primitives.h>
@@ -1921,6 +1922,16 @@
 
 void AudioFlinger::PlaybackThread::onFirstRef()
 {
+    if (mOutput == nullptr || mOutput->stream == nullptr) {
+        ALOGE("The stream is not open yet"); // This should not happen.
+    } else {
+        // setEventCallback will need a strong pointer as a parameter. Calling it
+        // here instead of constructor of PlaybackThread so that the onFirstRef
+        // callback would not be made on an incompletely constructed object.
+        if (mOutput->stream->setEventCallback(this) != OK) {
+            ALOGE("Failed to add event callback");
+        }
+    }
     run(mThreadName, ANDROID_PRIORITY_URGENT_AUDIO);
 }
 
@@ -2050,7 +2061,8 @@
         pid_t tid,
         uid_t uid,
         status_t *status,
-        audio_port_handle_t portId)
+        audio_port_handle_t portId,
+        const sp<media::IAudioTrackCallback>& callback)
 {
     size_t frameCount = *pFrameCount;
     size_t notificationFrameCount = *pNotificationFrameCount;
@@ -2340,6 +2352,12 @@
             goto Exit;
         }
         mTracks.add(track);
+        {
+            Mutex::Autolock _atCbL(mAudioTrackCbLock);
+            if (callback.get() != nullptr) {
+                mAudioTrackCallbacks.emplace(callback);
+            }
+        }
 
         sp<EffectChain> chain = getEffectChain_l(sessionId);
         if (chain != 0) {
@@ -2642,6 +2660,29 @@
     mCallbackThread->setAsyncError();
 }
 
+void AudioFlinger::PlaybackThread::onCodecFormatChanged(
+        const std::basic_string<uint8_t>& metadataBs)
+{
+    std::thread([this, metadataBs]() {
+            audio_utils::metadata::Data metadata =
+                    audio_utils::metadata::dataFromByteString(metadataBs);
+            if (metadata.empty()) {
+                ALOGW("Can not transform the buffer to audio metadata, %s, %d",
+                      reinterpret_cast<char*>(const_cast<uint8_t*>(metadataBs.data())),
+                      (int)metadataBs.size());
+                return;
+            }
+
+            audio_utils::metadata::ByteString metaDataStr =
+                    audio_utils::metadata::byteStringFromData(metadata);
+            std::vector metadataVec(metaDataStr.begin(), metaDataStr.end());
+            Mutex::Autolock _l(mAudioTrackCbLock);
+            for (const auto& callback : mAudioTrackCallbacks) {
+                callback->onCodecFormatChanged(metadataVec);
+            }
+    }).detach();
+}
+
 void AudioFlinger::PlaybackThread::resetWriteBlocked(uint32_t sequence)
 {
     Mutex::Autolock _l(mLock);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index b0eb75d..153cf7c 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -720,7 +720,7 @@
 
 // --- PlaybackThread ---
 class PlaybackThread : public ThreadBase, public StreamOutHalInterfaceCallback,
-    public VolumeInterface {
+                       public VolumeInterface, public StreamOutHalInterfaceEventCallback {
 public:
 
 #include "PlaybackTracks.h"
@@ -796,6 +796,10 @@
     virtual     void        onAddNewTrack_l();
                 void        onAsyncError(); // error reported by AsyncCallbackThread
 
+    // StreamHalInterfaceCodecFormatCallback implementation
+                void        onCodecFormatChanged(
+                                const std::basic_string<uint8_t>& metadataBs) override;
+
     // ThreadBase virtuals
     virtual     void        preExit();
 
@@ -845,7 +849,8 @@
                                 pid_t tid,
                                 uid_t uid,
                                 status_t *status /*non-NULL*/,
-                                audio_port_handle_t portId);
+                                audio_port_handle_t portId,
+                                const sp<media::IAudioTrackCallback>& callback);
 
                 AudioStreamOut* getOutput() const;
                 AudioStreamOut* clearOutput();
@@ -1168,6 +1173,10 @@
     uint32_t                        mDrainSequence;
     sp<AsyncCallbackThread>         mCallbackThread;
 
+    Mutex                                    mAudioTrackCbLock;
+    // Record of IAudioTrackCallback
+    std::set<sp<media::IAudioTrackCallback>> mAudioTrackCallbacks;
+
 private:
     // The HAL output sink is treated as non-blocking, but current implementation is blocking
     sp<NBAIO_Sink>          mOutputSink;
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 99cec5a..1b8c202 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -446,17 +446,19 @@
 
     sp<AudioRecordClient> topActive;
     sp<AudioRecordClient> latestActive;
+    sp<AudioRecordClient> topSensitiveActive;
     sp<AudioRecordClient> latestSensitiveActive;
 
     nsecs_t topStartNs = 0;
     nsecs_t latestStartNs = 0;
+    nsecs_t topSensitiveStartNs = 0;
     nsecs_t latestSensitiveStartNs = 0;
     bool isA11yOnTop = mUidPolicy->isA11yOnTop();
     bool isAssistantOnTop = false;
     bool isSensitiveActive = false;
     bool isInCall = mPhoneState == AUDIO_MODE_IN_CALL;
-    bool rttCallActive =
-            (mPhoneState == AUDIO_MODE_IN_CALL || mPhoneState == AUDIO_MODE_IN_COMMUNICATION)
+    bool isInCommunication = mPhoneState == AUDIO_MODE_IN_COMMUNICATION;
+    bool rttCallActive = (isInCall || isInCommunication)
             && mUidPolicy->isRttEnabled();
     bool onlyHotwordActive = true;
 
@@ -479,33 +481,47 @@
             continue;
         }
 
-        bool isAssistant = mUidPolicy->isAssistantUid(current->uid);
         bool isAccessibility = mUidPolicy->isA11yUid(current->uid);
-        if (appState == APP_STATE_TOP && !isAccessibility) {
-            if (current->startTimeNs > topStartNs) {
-                topActive = current;
-                topStartNs = current->startTimeNs;
+        // Clients capturing for Accessibility services are not considered
+        // for top or latest active to avoid masking regular clients started before
+        if (!isAccessibility) {
+            bool isAssistant = mUidPolicy->isAssistantUid(current->uid);
+            bool isPrivacySensitive =
+                    (current->attributes.flags & AUDIO_FLAG_CAPTURE_PRIVATE) != 0;
+            if (appState == APP_STATE_TOP) {
+                if (isPrivacySensitive) {
+                    if (current->startTimeNs > topSensitiveStartNs) {
+                        topSensitiveActive = current;
+                        topSensitiveStartNs = current->startTimeNs;
+                    }
+                } else {
+                    if (current->startTimeNs > topStartNs) {
+                        topActive = current;
+                        topStartNs = current->startTimeNs;
+                    }
+                }
+                if (isAssistant) {
+                    isAssistantOnTop = true;
+                }
             }
-            if (isAssistant) {
-                isAssistantOnTop = true;
+            // Clients capturing for HOTWORD are not considered
+            // for latest active to avoid masking regular clients started before
+            if (!(current->attributes.source == AUDIO_SOURCE_HOTWORD
+                    || ((isA11yOnTop || rttCallActive) && isAssistant))) {
+                if (isPrivacySensitive) {
+                    if (current->startTimeNs > latestSensitiveStartNs) {
+                        latestSensitiveActive = current;
+                        latestSensitiveStartNs = current->startTimeNs;
+                    }
+                    isSensitiveActive = true;
+                } else {
+                    if (current->startTimeNs > latestStartNs) {
+                        latestActive = current;
+                        latestStartNs = current->startTimeNs;
+                    }
+                }
             }
         }
-        // Client capturing for HOTWORD or Accessibility services not considered
-        // for latest active to avoid masking regular clients started before
-        if (current->startTimeNs > latestStartNs
-                && !(current->attributes.source == AUDIO_SOURCE_HOTWORD
-                        || ((isA11yOnTop || rttCallActive) && isAssistant))
-                && !isAccessibility) {
-            latestActive = current;
-            latestStartNs = current->startTimeNs;
-        }
-        if ((current->attributes.flags & AUDIO_FLAG_CAPTURE_PRIVATE) != 0) {
-            if (current->startTimeNs > latestSensitiveStartNs) {
-                latestSensitiveActive = current;
-                latestSensitiveStartNs = current->startTimeNs;
-            }
-            isSensitiveActive = true;
-        }
         if (current->attributes.source != AUDIO_SOURCE_HOTWORD) {
             onlyHotwordActive = false;
         }
@@ -514,6 +530,21 @@
     // if no active client with UI on Top, consider latest active as top
     if (topActive == nullptr) {
         topActive = latestActive;
+        topStartNs = latestStartNs;
+    }
+    if (topSensitiveActive == nullptr) {
+        topSensitiveActive = latestSensitiveActive;
+        topSensitiveStartNs = latestSensitiveStartNs;
+    }
+
+    // If both privacy sensitive and regular capture are active:
+    //  if the regular capture is privileged
+    //    allow concurrency
+    //  else
+    //    favor the privacy sensitive case
+    if (topActive != nullptr && topSensitiveActive != nullptr
+            && !topActive->canCaptureCallOrOutput) {
+        topActive = nullptr;
     }
 
     for (size_t i =0; i < mAudioRecordClients.size(); i++) {
@@ -524,8 +555,17 @@
 
         audio_source_t source = current->attributes.source;
         bool isTopOrLatestActive = topActive == nullptr ? false : current->uid == topActive->uid;
-        bool isLatestSensitive = latestSensitiveActive == nullptr ?
-                                 false : current->uid == latestSensitiveActive->uid;
+        bool isTopOrLatestSensitive = topSensitiveActive == nullptr ?
+                                 false : current->uid == topSensitiveActive->uid;
+
+        auto canCaptureIfInCallOrCommunication = [&](const auto &recordClient) {
+            bool canCaptureCall = recordClient->canCaptureCallOrOutput;
+            bool canCaptureCommunication = recordClient->canCaptureCallOrOutput
+                || recordClient->uid == mPhoneStateOwnerUid
+                || isServiceUid(mPhoneStateOwnerUid);
+            return !(isInCall && !canCaptureCall)
+                && !(isInCommunication && !canCaptureCommunication);
+        };
 
         // By default allow capture if:
         //     The assistant is not on TOP
@@ -533,9 +573,10 @@
         //     AND there is no active privacy sensitive capture or call
         //             OR client has CAPTURE_AUDIO_OUTPUT privileged permission
         bool allowCapture = !isAssistantOnTop
-                && ((isTopOrLatestActive && !isLatestSensitive) || isLatestSensitive)
-                && !(isSensitiveActive && !(isLatestSensitive || current->canCaptureCallOrOutput))
-                && !(isInCall && !current->canCaptureCallOrOutput);
+                && (isTopOrLatestActive || isTopOrLatestSensitive)
+                && !(isSensitiveActive
+                    && !(isTopOrLatestSensitive || current->canCaptureCallOrOutput))
+                && canCaptureIfInCallOrCommunication(current);
 
         if (isVirtualSource(source)) {
             // Allow capture for virtual (remote submix, call audio TX or RX...) sources
@@ -554,8 +595,9 @@
                 }
             } else {
                 if (((isAssistantOnTop && source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
-                        source == AUDIO_SOURCE_HOTWORD) &&
-                        (!(isSensitiveActive || isInCall) || current->canCaptureCallOrOutput)) {
+                        source == AUDIO_SOURCE_HOTWORD)
+                        && !(isSensitiveActive && !current->canCaptureCallOrOutput)
+                        && canCaptureIfInCallOrCommunication(current)) {
                     allowCapture = true;
                 }
             }
@@ -567,7 +609,8 @@
             //     OR
             //         Is on TOP AND the source is VOICE_RECOGNITION or HOTWORD
             if (!isAssistantOnTop
-                    && (!(isSensitiveActive || isInCall) || current->canCaptureCallOrOutput)) {
+                    && !(isSensitiveActive && !current->canCaptureCallOrOutput)
+                    && canCaptureIfInCallOrCommunication(current)) {
                 allowCapture = true;
             }
             if (isA11yOnTop) {
@@ -580,7 +623,8 @@
             //     All active clients are using HOTWORD source
             //     AND no call is active
             //         OR client has CAPTURE_AUDIO_OUTPUT privileged permission
-            if (onlyHotwordActive && !(isInCall && !current->canCaptureCallOrOutput)) {
+            if (onlyHotwordActive
+                    && canCaptureIfInCallOrCommunication(current)) {
                 allowCapture = true;
             }
         }
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;
 }