Merge "audio policy: fix enforced audible playback"
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index 10d8b13..1f24413 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -16,6 +16,7 @@
 	libhwbinder \
 	libmedia \
 	libmedialogservice \
+	libmediautils \
 	libnbaio \
 	libnblog \
 	libsoundtriggerservice \
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index 4200a46..7239302 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -1557,6 +1557,21 @@
                 } else if (!strcmp("A_FLAC", codecID)) {
                     AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_FLAC);
                     err = addFlacMetadata(meta, codecPrivate, codecPrivateSize);
+                } else if ((!strcmp("A_MS/ACM", codecID))) {
+                    if ((NULL == codecPrivate) || (codecPrivateSize < 30)) {
+                        ALOGW("unsupported audio: A_MS/ACM has no valid private data: %s, size: %zu",
+                               codecPrivate == NULL ? "null" : "non-null", codecPrivateSize);
+                        continue;
+                    } else {
+                        uint16_t ID = *(uint16_t *)codecPrivate;
+                        if (ID == 0x0055) {
+                            AMediaFormat_setString(meta,
+                                    AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG);
+                        } else {
+                            ALOGW("A_MS/ACM unsupported type , continue");
+                            continue;
+                        }
+                    }
                 } else {
                     ALOGW("%s is not supported.", codecID);
                     continue;
diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
index 82a0631..4302aee 100644
--- a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
@@ -423,6 +423,11 @@
             CHECK_LE(offset + (mOtherDataLenBits / 8), buffer->size());
             offset += mOtherDataLenBits / 8;
         }
+
+        if (i < mNumSubFrames && offset >= buffer->size()) {
+            ALOGW("Skip subframes after %d, total %d", (int)i, (int)mNumSubFrames);
+            break;
+        }
     }
 
     if (offset < buffer->size()) {
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index b010aa9..bcc7ff3 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -25,7 +25,7 @@
 #include <cutils/atomic.h>
 #include <utils/Log.h>
 #include <android_media_Utils.h>
-#include <android_runtime/android_view_Surface.h>
+#include <ui/PublicFormat.h>
 #include <private/android/AHardwareBufferHelpers.h>
 #include <grallocusage/GrallocUsageConversion.h>
 #include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
@@ -272,8 +272,8 @@
 media_status_t
 AImageReader::init() {
     PublicFormat publicFormat = static_cast<PublicFormat>(mFormat);
-    mHalFormat = android_view_Surface_mapPublicFormatToHalFormat(publicFormat);
-    mHalDataSpace = android_view_Surface_mapPublicFormatToHalDataspace(publicFormat);
+    mHalFormat = mapPublicFormatToHalFormat(publicFormat);
+    mHalDataSpace = mapPublicFormatToHalDataspace(publicFormat);
     mHalUsage = AHardwareBuffer_convertToGrallocUsageBits(mUsage);
 
     sp<IGraphicBufferProducer> gbProducer;
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 599c446..2fb24f5 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -22,6 +22,9 @@
 #include <binder/PermissionCache.h>
 #include "mediautils/ServiceUtilities.h"
 
+#include <iterator>
+#include <algorithm>
+
 /* When performing permission checks we do not use permission cache for
  * runtime permissions (protection level dangerous) as they may change at
  * runtime. All other permissions (protection level normal and dangerous)
@@ -220,4 +223,85 @@
     return NO_ERROR;
 }
 
+sp<content::pm::IPackageManagerNative> MediaPackageManager::retreivePackageManager() {
+    const sp<IServiceManager> sm = defaultServiceManager();
+    if (sm == nullptr) {
+        ALOGW("%s: failed to retrieve defaultServiceManager", __func__);
+        return nullptr;
+    }
+    sp<IBinder> packageManager = sm->checkService(String16(nativePackageManagerName));
+    if (packageManager == nullptr) {
+        ALOGW("%s: failed to retrieve native package manager", __func__);
+        return nullptr;
+    }
+    return interface_cast<content::pm::IPackageManagerNative>(packageManager);
+}
+
+std::optional<bool> MediaPackageManager::doIsAllowed(uid_t uid) {
+    if (mPackageManager == nullptr) {
+        /** Can not fetch package manager at construction it may not yet be registered. */
+        mPackageManager = retreivePackageManager();
+        if (mPackageManager == nullptr) {
+            ALOGW("%s: Playback capture is denied as package manager is not reachable", __func__);
+            return std::nullopt;
+        }
+    }
+
+    std::vector<std::string> packageNames;
+    auto status = mPackageManager->getNamesForUids({(int32_t)uid}, &packageNames);
+    if (!status.isOk()) {
+        ALOGW("%s: Playback capture is denied for uid %u as the package names could not be "
+              "retrieved from the package manager: %s", __func__, uid, status.toString8().c_str());
+        return std::nullopt;
+    }
+    if (packageNames.empty()) {
+        ALOGW("%s: Playback capture for uid %u is denied as no package name could be retrieved "
+              "from the package manager: %s", __func__, uid, status.toString8().c_str());
+        return std::nullopt;
+    }
+    std::vector<bool> isAllowed;
+    status = mPackageManager->isAudioPlaybackCaptureAllowed(packageNames, &isAllowed);
+    if (!status.isOk()) {
+        ALOGW("%s: Playback capture is denied for uid %u as the manifest property could not be "
+              "retrieved from the package manager: %s", __func__, uid, status.toString8().c_str());
+        return std::nullopt;
+    }
+    if (packageNames.size() != isAllowed.size()) {
+        ALOGW("%s: Playback capture is denied for uid %u as the package manager returned incoherent"
+              " response size: %zu != %zu", __func__, uid, packageNames.size(), isAllowed.size());
+        return std::nullopt;
+    }
+
+    // Zip together packageNames and isAllowed for debug logs
+    Packages& packages = mDebugLog[uid];
+    packages.resize(packageNames.size()); // Reuse all objects
+    std::transform(begin(packageNames), end(packageNames), begin(isAllowed),
+                   begin(packages), [] (auto& name, bool isAllowed) -> Package {
+                       return {std::move(name), isAllowed};
+                   });
+
+    // Only allow playback record if all packages in this UID allow it
+    bool playbackCaptureAllowed = std::all_of(begin(isAllowed), end(isAllowed),
+                                                  [](bool b) { return b; });
+
+    return playbackCaptureAllowed;
+}
+
+void MediaPackageManager::dump(int fd, int spaces) const {
+    dprintf(fd, "%*sAllow playback capture log:\n", spaces, "");
+    if (mPackageManager == nullptr) {
+        dprintf(fd, "%*sNo package manager\n", spaces + 2, "");
+    }
+    dprintf(fd, "%*sPackage manager errors: %u\n", spaces + 2, "", mPackageManagerErrors);
+
+    for (const auto& uidCache : mDebugLog) {
+        for (const auto& package : std::get<Packages>(uidCache)) {
+            dprintf(fd, "%*s- uid=%5u, allowPlaybackCapture=%s, packageName=%s\n", spaces + 2, "",
+                    std::get<const uid_t>(uidCache),
+                    package.playbackCaptureAllowed ? "true " : "false",
+                    package.name.c_str());
+        }
+    }
+}
+
 } // namespace android
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 98f54c2..94370ee 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -14,13 +14,22 @@
  * limitations under the License.
  */
 
+#ifndef ANDROID_MEDIAUTILS_SERVICEUTILITIES_H
+#define ANDROID_MEDIAUTILS_SERVICEUTILITIES_H
+
 #include <unistd.h>
 
+#include <android/content/pm/IPackageManagerNative.h>
 #include <binder/IMemory.h>
 #include <binder/PermissionController.h>
 #include <cutils/multiuser.h>
 #include <private/android_filesystem_config.h>
 
+#include <map>
+#include <optional>
+#include <string>
+#include <vector>
+
 namespace android {
 
 // Audio permission utilities
@@ -72,4 +81,31 @@
 bool dumpAllowed();
 bool modifyPhoneStateAllowed(pid_t pid, uid_t uid);
 status_t checkIMemory(const sp<IMemory>& iMemory);
+
+class MediaPackageManager {
+public:
+    /** Query the PackageManager to check if all apps of an UID allow playback capture. */
+    bool allowPlaybackCapture(uid_t uid) {
+        auto result = doIsAllowed(uid);
+        if (!result) {
+            mPackageManagerErrors++;
+        }
+        return result.value_or(false);
+    }
+    void dump(int fd, int spaces = 0) const;
+private:
+    static constexpr const char* nativePackageManagerName = "package_native";
+    std::optional<bool> doIsAllowed(uid_t uid);
+    sp<content::pm::IPackageManagerNative> retreivePackageManager();
+    sp<content::pm::IPackageManagerNative> mPackageManager; // To check apps manifest
+    uint_t mPackageManagerErrors = 0;
+    struct Package {
+        std::string name;
+        bool playbackCaptureAllowed = false;
+    };
+    using Packages = std::vector<Package>;
+    std::map<uid_t, Packages> mDebugLog;
+};
 }
+
+#endif // ANDROID_MEDIAUTILS_SERVICEUTILITIES_H
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8a45fc2..8f181a4 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -842,6 +842,12 @@
                 mIoJitterMs.toString().c_str());
     }
 
+    if (mLatencyMs.getN() > 0) {
+        dprintf(fd, "  Threadloop %s latency stats: %s\n",
+                isOutput() ? "write" : "read",
+                mLatencyMs.toString().c_str());
+    }
+
     if (locked) {
         mLock.unlock();
     }
@@ -3380,6 +3386,14 @@
                     }
                 }
             }
+
+            if (audio_has_proportional_frames(mFormat)) {
+                const double latencyMs = mTimestamp.getOutputServerLatencyMs(mSampleRate);
+                if (latencyMs != 0.) { // note 0. means timestamp is empty.
+                    mLatencyMs.add(latencyMs);
+                }
+            }
+
             } // if (mType ... ) { // no indentation
 #if 0
             // logFormat example
@@ -5296,13 +5310,6 @@
     dprintf(fd, "  Master balance: %f (%s)\n", mMasterBalance.load(),
             (hasFastMixer() ? std::to_string(mFastMixer->getMasterBalance())
                             : mBalance.toString()).c_str());
-    const double latencyMs = mTimestamp.getOutputServerLatencyMs(mSampleRate);
-    if (latencyMs != 0.) {
-        dprintf(fd, "  NormalMixer latency ms: %.2lf\n", latencyMs);
-    } else {
-        dprintf(fd, "  NormalMixer latency ms: unavail\n");
-    }
-
     if (hasFastMixer()) {
         dprintf(fd, "  FastMixer thread %p tid=%d", mFastMixer.get(), mFastMixer->getTid());
 
@@ -7042,6 +7049,15 @@
                 mTimestampVerifier.error();
             }
         }
+
+        // From the timestamp, input read latency is negative output write latency.
+        const audio_input_flags_t flags = mInput != NULL ? mInput->flags : AUDIO_INPUT_FLAG_NONE;
+        const double latencyMs = RecordTrack::checkServerLatencySupported(mFormat, flags)
+                ? - mTimestamp.getOutputServerLatencyMs(mSampleRate) : 0.;
+        if (latencyMs != 0.) { // note 0. means timestamp is empty.
+            mLatencyMs.add(latencyMs);
+        }
+
         // Use this to track timestamp information
         // ALOGD("%s", mTimestamp.toString().c_str());
 
@@ -7734,14 +7750,6 @@
         (void)input->stream->dump(fd);
     }
 
-    const double latencyMs = RecordTrack::checkServerLatencySupported(mFormat, flags)
-            ? - mTimestamp.getOutputServerLatencyMs(mSampleRate) : 0.;
-    if (latencyMs != 0.) {
-        dprintf(fd, "  NormalRecord latency ms: %.2lf\n", latencyMs);
-    } else {
-        dprintf(fd, "  NormalRecord latency ms: unavail\n");
-    }
-
     dprintf(fd, "  Fast capture thread: %s\n", hasFastCapture() ? "yes" : "no");
     dprintf(fd, "  Fast track available: %s\n", mFastTrackAvail ? "yes" : "no");
 
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 4968829..1afea08 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -520,6 +520,7 @@
                 // This should be read under ThreadBase lock (if not on the threadLoop thread).
                 audio_utils::Statistics<double> mIoJitterMs{0.995 /* alpha */};
                 audio_utils::Statistics<double> mProcessTimeMs{0.995 /* alpha */};
+                audio_utils::Statistics<double> mLatencyMs{0.995 /* alpha */};
 
                 bool                    mIsMsdDevice = false;
                 // A condition that must be evaluated by the thread loop has changed and
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 65f799e..ad78a45 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -700,8 +700,13 @@
         const AudioBufferProvider::Buffer& sourceBuffer) {
     auto start = std::chrono::steady_clock::now();
     const size_t frameCount = sourceBuffer.frameCount;
-    for (auto& sink : mTeePatches) {
-        RecordThread::PatchRecord* patchRecord = sink.patchRecord.get();
+    if (frameCount == 0) {
+        return;  // No audio to intercept.
+        // Additionally PatchProxyBufferProvider::obtainBuffer (called by PathTrack::getNextBuffer)
+        // does not allow 0 frame size request contrary to getNextBuffer
+    }
+    for (auto& teePatch : mTeePatches) {
+        RecordThread::PatchRecord* patchRecord = teePatch.patchRecord.get();
 
         size_t framesWritten = writeFrames(patchRecord, sourceBuffer.i8, frameCount);
         // On buffer wrap, the buffer frame count will be less than requested,
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index f72f44a..9e4eebc 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -90,7 +90,7 @@
 LOCAL_SHARED_LIBRARIES += libmedia_helper
 LOCAL_SHARED_LIBRARIES += libmediametrics
 
-LOCAL_SHARED_LIBRARIES += libhidlbase libxml2
+LOCAL_SHARED_LIBRARIES += libbinder libhidlbase libxml2
 
 ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
 LOCAL_CFLAGS += -DUSE_XML_AUDIO_POLICY_CONF
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index d61188f..acbfc9e 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -58,10 +58,12 @@
     typedef enum {
         API_INPUT_INVALID = -1,
         API_INPUT_LEGACY  = 0,// e.g. audio recording from a microphone
-        API_INPUT_MIX_CAPTURE,// used for "remote submix", capture of the media to play it remotely
+        API_INPUT_MIX_CAPTURE,// used for "remote submix" legacy mode (no DAP),
+                              // capture of the media to play it remotely
         API_INPUT_MIX_EXT_POLICY_REROUTE,// used for platform audio rerouting, where mixes are
                                          // handled by external and dynamically installed
                                          // policies which reroute audio mixes
+        API_INPUT_MIX_PUBLIC_CAPTURE_PLAYBACK,  // used for playback capture with a MediaProjection
         API_INPUT_TELEPHONY_RX, // used for capture from telephony RX path
     } input_type_t;
 
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioGain.h b/services/audiopolicy/common/managerdefinitions/include/AudioGain.h
index 996347b..4af93e1 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioGain.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioGain.h
@@ -20,6 +20,7 @@
 #include <utils/RefBase.h>
 #include <utils/String8.h>
 #include <system/audio.h>
+#include <vector>
 
 namespace android {
 
@@ -59,12 +60,36 @@
     void getDefaultConfig(struct audio_gain_config *config);
     status_t checkConfig(const struct audio_gain_config *config);
 
+    void setUseForVolume(bool canUseForVolume) { mUseForVolume = canUseForVolume; }
+    bool canUseForVolume() const { return mUseForVolume; }
+
     const struct audio_gain &getGain() const { return mGain; }
 
 private:
     int               mIndex;
     struct audio_gain mGain;
     bool              mUseInChannelMask;
+    bool              mUseForVolume = false;
+};
+
+class AudioGains : public std::vector<sp<AudioGain> >
+{
+public:
+    bool canUseForVolume() const
+    {
+        for (const auto &gain: *this) {
+            if (gain->canUseForVolume()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    int32_t add(const sp<AudioGain> gain)
+    {
+        push_back(gain);
+        return 0;
+    }
 };
 
 } // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index cf9519b..704f404 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -98,7 +98,7 @@
         ActivityTracking::dump(dst, spaces);
         dst->appendFormat(", Volume: %.03f, MuteCount: %02d\n", mCurVolumeDb, mMuteCount);
     }
-    void setVolume(float volume) { mCurVolumeDb = volume; }
+    void setVolume(float volumeDb) { mCurVolumeDb = volumeDb; }
     float getVolume() const { return mCurVolumeDb; }
 
 private:
@@ -156,7 +156,7 @@
     virtual bool isDuplicated() const { return false; }
     virtual uint32_t latency() { return 0; }
     virtual bool isFixedVolume(audio_devices_t device);
-    virtual bool setVolume(float volume,
+    virtual bool setVolume(float volumeDb,
                            audio_stream_type_t stream,
                            audio_devices_t device,
                            uint32_t delayMs,
@@ -219,10 +219,10 @@
     {
         return mVolumeActivities[vs].decMuteCount();
     }
-    void setCurVolume(VolumeSource vs, float volume)
+    void setCurVolume(VolumeSource vs, float volumeDb)
     {
         // Even if not activity for this group registered, need to create anyway
-        mVolumeActivities[vs].setVolume(volume);
+        mVolumeActivities[vs].setVolume(volumeDb);
     }
     float getCurVolume(VolumeSource vs) const
     {
@@ -327,7 +327,7 @@
             setClientActive(client, false);
         }
     }
-    virtual bool setVolume(float volume,
+    virtual bool setVolume(float volumeDb,
                            audio_stream_type_t stream,
                            audio_devices_t device,
                            uint32_t delayMs,
@@ -401,7 +401,7 @@
 
             void dump(String8 *dst) const override;
 
-    virtual bool setVolume(float volume,
+    virtual bool setVolume(float volumeDb,
                            audio_stream_type_t stream,
                            audio_devices_t device,
                            uint32_t delayMs,
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index 1b5a2d6..2d182bd 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -18,6 +18,7 @@
 
 #include "AudioCollections.h"
 #include "AudioProfile.h"
+#include "AudioGain.h"
 #include "HandleGenerator.h"
 #include <utils/String8.h>
 #include <utils/Vector.h>
@@ -29,9 +30,7 @@
 namespace android {
 
 class HwModule;
-class AudioGain;
 class AudioRoute;
-typedef Vector<sp<AudioGain> > AudioGainCollection;
 
 class AudioPort : public virtual RefBase, private HandleGenerator<audio_port_handle_t>
 {
@@ -49,8 +48,8 @@
 
     virtual const String8 getTagName() const = 0;
 
-    void setGains(const AudioGainCollection &gains) { mGains = gains; }
-    const AudioGainCollection &getGains() const { return mGains; }
+    void setGains(const AudioGains &gains) { mGains = gains; }
+    const AudioGains &getGains() const { return mGains; }
 
     virtual void setFlags(uint32_t flags)
     {
@@ -138,7 +137,7 @@
 
     void log(const char* indent) const;
 
-    AudioGainCollection mGains; // gain controllers
+    AudioGains mGains; // gain controllers
 
 private:
     void pickChannelMask(audio_channel_mask_t &channelMask, const ChannelsVector &channelMasks) const;
@@ -165,6 +164,8 @@
         return (other != 0) && (other->getAudioPort() != 0) && (getAudioPort() != 0) &&
                 (other->getAudioPort()->getModuleHandle() == getAudioPort()->getModuleHandle());
     }
+    bool hasGainController(bool canUseForVolume = false) const;
+
     unsigned int mSamplingRate = 0u;
     audio_format_t mFormat = AUDIO_FORMAT_INVALID;
     audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 7293bc4..fd33649 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -149,7 +149,7 @@
     return false;
 }
 
-bool AudioOutputDescriptor::setVolume(float volume,
+bool AudioOutputDescriptor::setVolume(float volumeDb,
                                       audio_stream_type_t stream,
                                       audio_devices_t device __unused,
                                       uint32_t delayMs,
@@ -158,9 +158,9 @@
     // We actually change the volume if:
     // - the float value returned by computeVolume() changed
     // - the force flag is set
-    if (volume != getCurVolume(static_cast<VolumeSource>(stream)) || force) {
-        ALOGV("setVolume() for stream %d, volume %f, delay %d", stream, volume, delayMs);
-        setCurVolume(static_cast<VolumeSource>(stream), volume);
+    if (volumeDb != getCurVolume(static_cast<VolumeSource>(stream)) || force) {
+        ALOGV("setVolume() for stream %d, volume %f, delay %d", stream, volumeDb, delayMs);
+        setCurVolume(static_cast<VolumeSource>(stream), volumeDb);
         return true;
     }
     return false;
@@ -388,15 +388,39 @@
             mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL;
 }
 
-bool SwAudioOutputDescriptor::setVolume(float volume,
+bool SwAudioOutputDescriptor::setVolume(float volumeDb,
                                         audio_stream_type_t stream,
                                         audio_devices_t device,
                                         uint32_t delayMs,
                                         bool force)
 {
-    if (!AudioOutputDescriptor::setVolume(volume, stream, device, delayMs, force)) {
+    if (!AudioOutputDescriptor::setVolume(volumeDb, stream, device, delayMs, force)) {
         return false;
     }
+    if (!devices().isEmpty()) {
+        // Assume first device to check upon Gain Crontroller availability
+        const auto &devicePort = devices().itemAt(0);
+        ALOGV("%s: device %s hasGC %d", __FUNCTION__,
+            devicePort->toString().c_str(), devices().itemAt(0)->hasGainController(true));
+        if (devicePort->hasGainController(true)) {
+            // @todo: default stream volume to max (0) when using HW Port gain?
+            float volumeAmpl = Volume::DbToAmpl(0);
+            mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
+
+            AudioGains gains = devicePort->getGains();
+            int gainMinValueInMb = gains[0]->getMinValueInMb();
+            int gainMaxValueInMb = gains[0]->getMaxValueInMb();
+            int gainStepValueInMb = gains[0]->getStepValueInMb();
+            int gainValueMb = ((volumeDb * 100)/ gainStepValueInMb) * gainStepValueInMb;
+            gainValueMb = std::max(gainMinValueInMb, std::min(gainValueMb, gainMaxValueInMb));
+
+            audio_port_config config = {};
+            devicePort->toAudioPortConfig(&config);
+            config.config_mask = AUDIO_PORT_CONFIG_GAIN;
+            config.gain.values[0] = gainValueMb;
+            return mClientInterface->setAudioPortConfig(&config, 0) == NO_ERROR;
+        }
+    }
     // Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is enabled
     float volumeAmpl = Volume::DbToAmpl(getCurVolume(static_cast<VolumeSource>(stream)));
     if (stream == AUDIO_STREAM_BLUETOOTH_SCO) {
@@ -591,13 +615,13 @@
 }
 
 
-bool HwAudioOutputDescriptor::setVolume(float volume,
+bool HwAudioOutputDescriptor::setVolume(float volumeDb,
                                         audio_stream_type_t stream,
                                         audio_devices_t device,
                                         uint32_t delayMs,
                                         bool force)
 {
-    bool changed = AudioOutputDescriptor::setVolume(volume, stream, device, delayMs, force);
+    bool changed = AudioOutputDescriptor::setVolume(volumeDb, stream, device, delayMs, force);
 
     if (changed) {
       // TODO: use gain controller on source device if any to adjust volume
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
index 9fcf5e7..a66c695 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
@@ -479,4 +479,14 @@
             dstConfig, srcConfig, AUDIO_PORT_CONFIG_FLAGS, { AUDIO_INPUT_FLAG_NONE });
 }
 
+bool AudioPortConfig::hasGainController(bool canUseForVolume) const
+{
+    sp<AudioPort> audioport = getAudioPort();
+    if (audioport == nullptr) {
+        return false;
+    }
+    return canUseForVolume ? audioport->getGains().canUseForVolume()
+                           : audioport->getGains().size() > 0;
+}
+
 } // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 81d3968..5f820c2 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -64,7 +64,7 @@
     }
 };
 
-struct AudioGainTraits : public AndroidCollectionTraits<AudioGain, AudioGainCollection>
+struct AudioGainTraits : public AndroidCollectionTraits<AudioGain, AudioGains>
 {
     static constexpr const char *tag = "gain";
     static constexpr const char *collectionTag = "gains";
@@ -84,6 +84,9 @@
         static constexpr const char *minRampMs = "minRampMs";
         /** needed if mode AUDIO_GAIN_MODE_RAMP. */
         static constexpr const char *maxRampMs = "maxRampMs";
+        /** needed to allow use setPortGain instead of setStreamVolume. */
+        static constexpr const char *useForVolume = "useForVolume";
+
     };
 
     static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
@@ -375,9 +378,14 @@
     if (!maxRampMsLiteral.empty() && convertTo(maxRampMsLiteral, maxRampMs)) {
         gain->setMaxRampInMs(maxRampMs);
     }
-    ALOGV("%s: adding new gain mode %08x channel mask %08x min mB %d max mB %d", __func__,
-          gain->getMode(), gain->getChannelMask(), gain->getMinValueInMb(),
-          gain->getMaxValueInMb());
+    std::string useForVolumeLiteral = getXmlAttribute(cur, Attributes::useForVolume);
+    bool useForVolume = false;
+    if (!useForVolumeLiteral.empty() && convertTo(useForVolumeLiteral, useForVolume)) {
+        gain->setUseForVolume(useForVolume);
+    }
+    ALOGV("%s: adding new gain mode %08x channel mask %08x min mB %d max mB %d UseForVolume: %d",
+          __func__, gain->getMode(), gain->getChannelMask(), gain->getMinValueInMb(),
+          gain->getMaxValueInMb(), useForVolume);
 
     if (gain->getMode() != 0) {
         return gain;
diff --git a/services/audiopolicy/config/a2dp_in_audio_policy_configuration.xml b/services/audiopolicy/config/a2dp_in_audio_policy_configuration.xml
new file mode 100644
index 0000000..57bd4f8
--- /dev/null
+++ b/services/audiopolicy/config/a2dp_in_audio_policy_configuration.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Bluetooth Input Audio HAL Audio Policy Configuration file -->
+<module name="a2dp" halVersion="2.0">
+    <mixPorts>
+        <mixPort name="a2dp input" role="sink">
+            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                     samplingRates="44100,48000"
+                     channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+        </mixPort>
+    </mixPorts>
+    <devicePorts>
+        <devicePort tagName="BT A2DP In" type="AUDIO_DEVICE_IN_BLUETOOTH_A2DP" role="source">
+            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                     samplingRates="44100,48000"
+                     channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+        </devicePort>
+    </devicePorts>
+    <routes>
+        <route type="mix" sink="a2dp input"
+               sources="BT A2DP In"/>
+    </routes>
+</module>
diff --git a/services/audiopolicy/config/audio_policy_configuration.xml b/services/audiopolicy/config/audio_policy_configuration.xml
index b4cc1d3..b28381b 100644
--- a/services/audiopolicy/config/audio_policy_configuration.xml
+++ b/services/audiopolicy/config/audio_policy_configuration.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!-- Copyright (C) 2019 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.
@@ -173,8 +173,8 @@
 
         </module>
 
-        <!-- A2dp Audio HAL -->
-        <xi:include href="a2dp_audio_policy_configuration.xml"/>
+        <!-- A2dp Input Audio HAL -->
+        <xi:include href="a2dp_in_audio_policy_configuration.xml"/>
 
         <!-- Usb Audio HAL -->
         <xi:include href="usb_audio_policy_configuration.xml"/>
@@ -182,8 +182,8 @@
         <!-- Remote Submix Audio HAL -->
         <xi:include href="r_submix_audio_policy_configuration.xml"/>
 
-        <!-- Hearing aid Audio HAL -->
-        <xi:include href="hearing_aid_audio_policy_configuration.xml"/>
+        <!-- Bluetooth Audio HAL -->
+        <xi:include href="bluetooth_audio_policy_configuration.xml"/>
 
         <!-- MSD Audio HAL (optional) -->
         <xi:include href="msd_audio_policy_configuration.xml"/>
diff --git a/services/audiopolicy/config/audio_policy_configuration_bluetooth_legacy_hal.xml b/services/audiopolicy/config/audio_policy_configuration_bluetooth_legacy_hal.xml
new file mode 100644
index 0000000..b4cc1d3
--- /dev/null
+++ b/services/audiopolicy/config/audio_policy_configuration_bluetooth_legacy_hal.xml
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <!-- version section contains a “version” tag in the form “major.minor” e.g version=”1.0” -->
+
+    <!-- Global configuration Decalaration -->
+    <globalConfiguration speaker_drc_enabled="true"/>
+
+
+    <!-- Modules section:
+        There is one section per audio HW module present on the platform.
+        Each module section will contains two mandatory tags for audio HAL “halVersion” and “name”.
+        The module names are the same as in current .conf file:
+                “primary”, “A2DP”, “remote_submix”, “USB”
+        Each module will contain the following sections:
+        “devicePorts”: a list of device descriptors for all input and output devices accessible via this
+        module.
+        This contains both permanently attached devices and removable devices.
+        “mixPorts”: listing all output and input streams exposed by the audio HAL
+        “routes”: list of possible connections between input and output devices or between stream and
+        devices.
+            "route": is defined by an attribute:
+                -"type": <mux|mix> means all sources are mutual exclusive (mux) or can be mixed (mix)
+                -"sink": the sink involved in this route
+                -"sources": all the sources than can be connected to the sink via vis route
+        “attachedDevices”: permanently attached devices.
+        The attachedDevices section is a list of devices names. The names correspond to device names
+        defined in <devicePorts> section.
+        “defaultOutputDevice”: device to be used by default when no policy rule applies
+    -->
+    <modules>
+        <!-- Primary Audio HAL -->
+        <module name="primary" halVersion="3.0">
+            <attachedDevices>
+                <item>Speaker</item>
+                <item>Built-In Mic</item>
+                <item>Built-In Back Mic</item>
+            </attachedDevices>
+            <defaultOutputDevice>Speaker</defaultOutputDevice>
+            <mixPorts>
+                <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="deep_buffer" role="source"
+                        flags="AUDIO_OUTPUT_FLAG_DEEP_BUFFER">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="compressed_offload" role="source"
+                         flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">
+                    <profile name="" format="AUDIO_FORMAT_MP3"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_AAC"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+                    <profile name="" format="AUDIO_FORMAT_AAC_LC"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+                </mixPort>
+                <mixPort name="voice_tx" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </mixPort>
+                <mixPort name="primary input" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </mixPort>
+                <mixPort name="voice_rx" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </mixPort>
+            </mixPorts>
+            <devicePorts>
+                <!-- Output devices declaration, i.e. Sink DEVICE PORT -->
+                <devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">
+                   <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                            samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </devicePort>
+                <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address="">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                    <gains>
+                        <gain name="gain_1" mode="AUDIO_GAIN_MODE_JOINT"
+                              minValueMB="-8400"
+                              maxValueMB="4000"
+                              defaultValueMB="0"
+                              stepValueMB="100"/>
+                    </gains>
+                </devicePort>
+                <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </devicePort>
+                <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+                <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+                <devicePort tagName="BT SCO Car Kit" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+                <devicePort tagName="Telephony Tx" type="AUDIO_DEVICE_OUT_TELEPHONY_TX" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+                </devicePort>
+
+                <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+                </devicePort>
+                <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </devicePort>
+                <devicePort tagName="Telephony Rx" type="AUDIO_DEVICE_IN_TELEPHONY_RX" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+                </devicePort>
+            </devicePorts>
+            <!-- route declaration, i.e. list all available sources for a given sink -->
+            <routes>
+                <route type="mix" sink="Earpiece"
+                       sources="primary output,deep_buffer,BT SCO Headset Mic"/>
+                <route type="mix" sink="Speaker"
+                       sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/>
+                <route type="mix" sink="Wired Headset"
+                       sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/>
+                <route type="mix" sink="Wired Headphones"
+                       sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/>
+                <route type="mix" sink="primary input"
+                       sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic"/>
+                <route type="mix" sink="Telephony Tx"
+                       sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic, voice_tx"/>
+                <route type="mix" sink="voice_rx"
+                       sources="Telephony Rx"/>
+            </routes>
+
+        </module>
+
+        <!-- A2dp Audio HAL -->
+        <xi:include href="a2dp_audio_policy_configuration.xml"/>
+
+        <!-- Usb Audio HAL -->
+        <xi:include href="usb_audio_policy_configuration.xml"/>
+
+        <!-- Remote Submix Audio HAL -->
+        <xi:include href="r_submix_audio_policy_configuration.xml"/>
+
+        <!-- Hearing aid Audio HAL -->
+        <xi:include href="hearing_aid_audio_policy_configuration.xml"/>
+
+        <!-- MSD Audio HAL (optional) -->
+        <xi:include href="msd_audio_policy_configuration.xml"/>
+
+    </modules>
+    <!-- End of Modules section -->
+
+    <!-- Volume section:
+        IMPORTANT NOTE: Volume tables have been moved to engine configuration.
+                        Keep it here for legacy.
+                        Engine will fallback on these files if none are provided by engine.
+     -->
+
+    <xi:include href="audio_policy_volumes.xml"/>
+    <xi:include href="default_volume_tables.xml"/>
+
+    <!-- End of Volume section -->
+
+    <!-- Surround Sound configuration -->
+
+    <xi:include href="surround_sound_configuration_5_0.xml"/>
+
+    <!-- End of Surround Sound configuration -->
+
+</audioPolicyConfiguration>
diff --git a/services/audiopolicy/config/bluetooth_audio_policy_configuration.xml b/services/audiopolicy/config/bluetooth_audio_policy_configuration.xml
new file mode 100644
index 0000000..ce78eb0
--- /dev/null
+++ b/services/audiopolicy/config/bluetooth_audio_policy_configuration.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Bluetooth Audio HAL Audio Policy Configuration file -->
+<module name="bluetooth" halVersion="2.0">
+    <mixPorts>
+        <!-- A2DP Audio Ports -->
+        <mixPort name="a2dp output" role="source"/>
+        <!-- Hearing AIDs Audio Ports -->
+        <mixPort name="hearing aid output" role="source">
+            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                     samplingRates="24000,16000"
+                     channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+        </mixPort>
+    </mixPorts>
+    <devicePorts>
+        <!-- A2DP Audio Ports -->
+        <devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink">
+            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                     samplingRates="44100,48000,88200,96000"
+                     channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+        </devicePort>
+        <devicePort tagName="BT A2DP Headphones" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES" role="sink">
+            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                     samplingRates="44100,48000,88200,96000"
+                     channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+        </devicePort>
+        <devicePort tagName="BT A2DP Speaker" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER" role="sink">
+            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                     samplingRates="44100,48000,88200,96000"
+                     channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+        </devicePort>
+        <!-- Hearing AIDs Audio Ports -->
+        <devicePort tagName="BT Hearing Aid Out" type="AUDIO_DEVICE_OUT_HEARING_AID" role="sink"/>
+    </devicePorts>
+    <routes>
+        <route type="mix" sink="BT A2DP Out"
+               sources="a2dp output"/>
+        <route type="mix" sink="BT A2DP Headphones"
+               sources="a2dp output"/>
+        <route type="mix" sink="BT A2DP Speaker"
+               sources="a2dp output"/>
+        <route type="mix" sink="BT Hearing Aid Out"
+               sources="hearing aid output"/>
+    </routes>
+</module>
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index e546e2d..c969af3 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -33,8 +33,8 @@
 #define AUDIO_POLICY_XML_CONFIG_FILE_NAME "audio_policy_configuration.xml"
 #define AUDIO_POLICY_A2DP_OFFLOAD_DISABLED_XML_CONFIG_FILE_NAME \
         "audio_policy_configuration_a2dp_offload_disabled.xml"
-#define AUDIO_POLICY_BLUETOOTH_HAL_ENABLED_XML_CONFIG_FILE_NAME \
-        "audio_policy_configuration_bluetooth_hal_enabled.xml"
+#define AUDIO_POLICY_BLUETOOTH_LEGACY_HAL_XML_CONFIG_FILE_NAME \
+        "audio_policy_configuration_bluetooth_legacy_hal.xml"
 
 #include <inttypes.h>
 #include <math.h>
@@ -479,36 +479,16 @@
                                     std::vector<audio_format_t> *formats)
 {
     ALOGV("getHwOffloadEncodingFormatsSupportedForA2DP()");
-    char *tok = NULL, *saveptr;
     status_t status = NO_ERROR;
-    char encoding_formats_list[PROPERTY_VALUE_MAX];
-    audio_format_t format = AUDIO_FORMAT_DEFAULT;
-    // FIXME This list should not come from a property but the supported encoded
-    // formats of declared A2DP devices in primary module
-    property_get("persist.bluetooth.a2dp_offload.cap", encoding_formats_list, "");
-    tok = strtok_r(encoding_formats_list, "-", &saveptr);
-    for (;tok != NULL; tok = strtok_r(NULL, "-", &saveptr)) {
-        if (strcmp(tok, "sbc") == 0) {
-            ALOGV("%s: SBC offload supported\n",__func__);
-            format = AUDIO_FORMAT_SBC;
-        } else if (strcmp(tok, "aptx") == 0) {
-            ALOGV("%s: APTX offload supported\n",__func__);
-            format = AUDIO_FORMAT_APTX;
-        } else if (strcmp(tok, "aptxhd") == 0) {
-            ALOGV("%s: APTX HD offload supported\n",__func__);
-            format = AUDIO_FORMAT_APTX_HD;
-        } else if (strcmp(tok, "ldac") == 0) {
-            ALOGV("%s: LDAC offload supported\n",__func__);
-            format = AUDIO_FORMAT_LDAC;
-        } else if (strcmp(tok, "aac") == 0) {
-            ALOGV("%s: AAC offload supported\n",__func__);
-            format = AUDIO_FORMAT_AAC;
-        } else {
-            ALOGE("%s: undefined token - %s\n",__func__, tok);
-            continue;
-        }
-        formats->push_back(format);
+    std::unordered_set<audio_format_t> formatSet;
+    sp<HwModule> primaryModule =
+            mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY);
+    DeviceVector declaredDevices = primaryModule->getDeclaredDevices().getDevicesFromTypeMask(
+            AUDIO_DEVICE_OUT_ALL_A2DP);
+    for (const auto& device : declaredDevices) {
+        formatSet.insert(device->encodedFormats().begin(), device->encodedFormats().end());
     }
+    formats->assign(formatSet.begin(), formatSet.end());
     return status;
 }
 
@@ -1986,7 +1966,11 @@
         if (status != NO_ERROR) {
             goto error;
         }
-        *inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
+        if (is_mix_loopback_render(policyMix->mRouteFlags)) {
+            *inputType = API_INPUT_MIX_PUBLIC_CAPTURE_PLAYBACK;
+        } else {
+            *inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
+        }
         device = mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
                                                   String8(attr->tags + strlen("addr=")),
                                                   AUDIO_FORMAT_DEFAULT);
@@ -4178,17 +4162,17 @@
     status_t ret;
 
     if (property_get_bool("ro.bluetooth.a2dp_offload.supported", false)) {
-        if (property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) {
+        if (property_get_bool("persist.bluetooth.bluetooth_audio_hal.disabled", false) &&
+            property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) {
+            // Both BluetoothAudio@2.0 and BluetoothA2dp@1.0 (Offlaod) are disabled, and uses
+            // the legacy hardware module for A2DP and hearing aid.
+            fileNames.push_back(AUDIO_POLICY_BLUETOOTH_LEGACY_HAL_XML_CONFIG_FILE_NAME);
+        } else if (property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) {
+            // A2DP offload supported but disabled: try to use special XML file
             fileNames.push_back(AUDIO_POLICY_A2DP_OFFLOAD_DISABLED_XML_CONFIG_FILE_NAME);
-        } else if (property_get_bool("persist.bluetooth.bluetooth_audio_hal.enabled", false)) {
-            // This property persist.bluetooth.bluetooth_audio_hal.enabled is temporary only.
-            // xml files AUDIO_POLICY_BLUETOOTH_HAL_ENABLED_XML_CONFIG_FILE_NAME, although having
-            // the same name, must be different in offload and non offload cases in device
-            // specific configuration file.
-            fileNames.push_back(AUDIO_POLICY_BLUETOOTH_HAL_ENABLED_XML_CONFIG_FILE_NAME);
         }
-    } else if (property_get_bool("persist.bluetooth.bluetooth_audio_hal.enabled", false)) {
-        fileNames.push_back(AUDIO_POLICY_BLUETOOTH_HAL_ENABLED_XML_CONFIG_FILE_NAME);
+    } else if (property_get_bool("persist.bluetooth.bluetooth_audio_hal.disabled", false)) {
+        fileNames.push_back(AUDIO_POLICY_BLUETOOTH_LEGACY_HAL_XML_CONFIG_FILE_NAME);
     }
     fileNames.push_back(AUDIO_POLICY_XML_CONFIG_FILE_NAME);
 
@@ -5628,7 +5612,7 @@
                                         audio_devices_t device)
 {
     auto &curves = getVolumeCurves(stream);
-    float volumeDB = curves.volIndexToDb(Volume::getDeviceCategory(device), index);
+    float volumeDb = curves.volIndexToDb(Volume::getDeviceCategory(device), index);
 
     // handle the case of accessibility active while a ringtone is playing: if the ringtone is much
     // louder than the accessibility prompt, the prompt cannot be heard, thus masking the touch
@@ -5638,7 +5622,7 @@
             && (AUDIO_MODE_RINGTONE == mEngine->getPhoneState())
             && isStreamActive(AUDIO_STREAM_RING, 0)) {
         const float ringVolumeDB = computeVolume(AUDIO_STREAM_RING, index, device);
-        return ringVolumeDB - 4 > volumeDB ? ringVolumeDB - 4 : volumeDB;
+        return ringVolumeDB - 4 > volumeDb ? ringVolumeDB - 4 : volumeDb;
     }
 
     // in-call: always cap volume by voice volume + some low headroom
@@ -5657,10 +5641,10 @@
             const float maxVoiceVolDb =
                 computeVolume(AUDIO_STREAM_VOICE_CALL, voiceVolumeIndex, device)
                 + IN_CALL_EARPIECE_HEADROOM_DB;
-            if (volumeDB > maxVoiceVolDb) {
+            if (volumeDb > maxVoiceVolDb) {
                 ALOGV("computeVolume() stream %d at vol=%f overriden by stream %d at vol=%f",
-                        stream, volumeDB, AUDIO_STREAM_VOICE_CALL, maxVoiceVolDb);
-                volumeDB = maxVoiceVolDb;
+                        stream, volumeDb, AUDIO_STREAM_VOICE_CALL, maxVoiceVolDb);
+                volumeDb = maxVoiceVolDb;
             }
             } break;
         default:
@@ -5693,7 +5677,7 @@
         // just stopped
         if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY) ||
                 mLimitRingtoneVolume) {
-            volumeDB += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
+            volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
             audio_devices_t musicDevice =
                     mEngine->getOutputDevicesForAttributes(attributes_initializer(AUDIO_USAGE_MEDIA),
                                                            nullptr, true /*fromCache*/).types();
@@ -5702,29 +5686,29 @@
                                    musicDevice);
             float minVolDB = (musicVolDB > SONIFICATION_HEADSET_VOLUME_MIN_DB) ?
                     musicVolDB : SONIFICATION_HEADSET_VOLUME_MIN_DB;
-            if (volumeDB > minVolDB) {
-                volumeDB = minVolDB;
+            if (volumeDb > minVolDB) {
+                volumeDb = minVolDB;
                 ALOGV("computeVolume limiting volume to %f musicVol %f", minVolDB, musicVolDB);
             }
             if (device & (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
                     AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES)) {
                 // on A2DP, also ensure notification volume is not too low compared to media when
                 // intended to be played
-                if ((volumeDB > -96.0f) &&
-                        (musicVolDB - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB > volumeDB)) {
+                if ((volumeDb > -96.0f) &&
+                        (musicVolDB - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB > volumeDb)) {
                     ALOGV("computeVolume increasing volume for stream=%d device=0x%X from %f to %f",
                             stream, device,
-                            volumeDB, musicVolDB - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB);
-                    volumeDB = musicVolDB - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB;
+                            volumeDb, musicVolDB - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB);
+                    volumeDb = musicVolDB - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB;
                 }
             }
         } else if ((Volume::getDeviceForVolume(device) != AUDIO_DEVICE_OUT_SPEAKER) ||
                 (stream != AUDIO_STREAM_ALARM && stream != AUDIO_STREAM_RING)) {
-            volumeDB += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
+            volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
         }
     }
 
-    return volumeDB;
+    return volumeDb;
 }
 
 int AudioPolicyManager::rescaleVolumeIndex(int srcIndex,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index a1b6b0f..a672521 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -20,7 +20,6 @@
 #include "AudioPolicyService.h"
 #include "TypeConverter.h"
 #include <media/MediaAnalyticsItem.h>
-#include <mediautils/ServiceUtilities.h>
 #include <media/AudioPolicy.h>
 #include <utils/Log.h>
 
@@ -167,7 +166,7 @@
     return mAudioPolicyManager->getOutput(stream);
 }
 
-status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
+status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *originalAttr,
                                               audio_io_handle_t *output,
                                               audio_session_t session,
                                               audio_stream_type_t *stream,
@@ -191,9 +190,13 @@
                 "%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid, uid);
         uid = callingUid;
     }
+    audio_attributes_t attr = *originalAttr;
+    if (!mPackageManager.allowPlaybackCapture(uid)) {
+        attr.flags |= AUDIO_FLAG_NO_CAPTURE;
+    }
     audio_output_flags_t originalFlags = flags;
     AutoCallerClear acc;
-    status_t result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
+    status_t result = mAudioPolicyManager->getOutputForAttr(&attr, output, session, stream, uid,
                                                  config,
                                                  &flags, selectedDeviceId, portId,
                                                  secondaryOutputs);
@@ -209,14 +212,14 @@
         *selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
         *portId = AUDIO_PORT_HANDLE_NONE;
         secondaryOutputs->clear();
-        result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid, config,
+        result = mAudioPolicyManager->getOutputForAttr(&attr, output, session, stream, uid, config,
                                                        &flags, selectedDeviceId, portId,
                                                        secondaryOutputs);
     }
 
     if (result == NO_ERROR) {
         sp <AudioPlaybackClient> client =
-            new AudioPlaybackClient(*attr, *output, uid, pid, session, *selectedDeviceId, *stream);
+            new AudioPlaybackClient(attr, *output, uid, pid, session, *selectedDeviceId, *stream);
         mAudioPlaybackClients.add(*portId, client);
     }
     return result;
@@ -404,6 +407,9 @@
         if (status == NO_ERROR) {
             // enforce permission (if any) required for each type of input
             switch (inputType) {
+            case AudioPolicyInterface::API_INPUT_MIX_PUBLIC_CAPTURE_PLAYBACK:
+                // this use case has been validated in audio service with a MediaProjection token,
+                // and doesn't rely on regular permissions
             case AudioPolicyInterface::API_INPUT_LEGACY:
                 break;
             case AudioPolicyInterface::API_INPUT_TELEPHONY_RX:
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index cf9cf71..d9514f6 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -591,6 +591,8 @@
             mAudioPolicyManager->dump(fd);
         }
 
+        mPackageManager.dump(fd);
+
         if (locked) mLock.unlock();
     }
     return NO_ERROR;
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 5888841..aaace0c 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -31,6 +31,7 @@
 #include <media/ToneGenerator.h>
 #include <media/AudioEffect.h>
 #include <media/AudioPolicy.h>
+#include <mediautils/ServiceUtilities.h>
 #include "AudioPolicyEffects.h"
 #include "managerdefault/AudioPolicyManager.h"
 #include <android/hardware/BnSensorPrivacyListener.h>
@@ -819,6 +820,8 @@
 
     DefaultKeyedVector< audio_port_handle_t, sp<AudioRecordClient> >   mAudioRecordClients;
     DefaultKeyedVector< audio_port_handle_t, sp<AudioPlaybackClient> >   mAudioPlaybackClients;
+
+    MediaPackageManager mPackageManager; // To check allowPlaybackCapture
 };
 
 } // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 923d17a..dfbff18 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2847,12 +2847,19 @@
         }
         streams.add(outputStream);
 
-        if (outputStream->format == HAL_PIXEL_FORMAT_BLOB &&
-                outputStream->data_space == HAL_DATASPACE_V0_JFIF) {
+        if (outputStream->format == HAL_PIXEL_FORMAT_BLOB) {
             size_t k = i + ((mInputStream != nullptr) ? 1 : 0); // Input stream if present should
                                                                 // always occupy the initial entry.
-            bufferSizes[k] = static_cast<uint32_t>(
-                    getJpegBufferSize(outputStream->width, outputStream->height));
+            if (outputStream->data_space == HAL_DATASPACE_V0_JFIF) {
+                bufferSizes[k] = static_cast<uint32_t>(
+                        getJpegBufferSize(outputStream->width, outputStream->height));
+            } else if (outputStream->data_space ==
+                    static_cast<android_dataspace>(HAL_DATASPACE_JPEG_APP_SEGMENTS)) {
+                bufferSizes[k] = outputStream->width * outputStream->height;
+            } else {
+                ALOGW("%s: Blob dataSpace %d not supported",
+                        __FUNCTION__, outputStream->data_space);
+            }
         }
     }