Merge "Remove unused variable"
diff --git a/Android.bp b/Android.bp
index 37f6457..302e250 100644
--- a/Android.bp
+++ b/Android.bp
@@ -102,3 +102,27 @@
         },
     },
 }
+
+aidl_interface {
+    name: "av-audio-types-aidl",
+    unstable: true,
+    host_supported: true,
+    vendor_available: true,
+    double_loadable: true,
+    local_include_dir: "aidl",
+    srcs: [
+        "aidl/android/media/audio/IHalAdapterVendorExtension.aidl",
+    ],
+    imports: [
+        "android.hardware.audio.core-V1",
+    ],
+    backend: {
+        // The C++ backend is disabled transitively due to use of FMQ by the audio core HAL.
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+    },
+}
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 1f7083b..62cf827 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -12,3 +12,4 @@
                media/libmediatranscoding/
                services/mediatranscoding/
                media/libaudioclient/tests/
+               media/libaudiohal/tests/
diff --git a/aidl/android/media/audio/IHalAdapterVendorExtension.aidl b/aidl/android/media/audio/IHalAdapterVendorExtension.aidl
new file mode 100644
index 0000000..b7a7678
--- /dev/null
+++ b/aidl/android/media/audio/IHalAdapterVendorExtension.aidl
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2023 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.audio;
+
+import android.hardware.audio.core.VendorParameter;
+
+/**
+ * This interface is used by the HAL adapter of the Audio Server. Implementation
+ * is optional. Vendors may provide an implementation on the system_ext
+ * partition. The default instance of this interface, if provided, must be
+ * registered prior to the moment when the audio server connects to HAL modules.
+ *
+ * {@hide}
+ */
+interface IHalAdapterVendorExtension {
+    enum ParameterScope {
+        MODULE = 0,
+        STREAM = 1,
+    }
+
+    /**
+     * Parse raw parameter keys into vendor parameter ids.
+     *
+     * This method prepares arguments for a call to the 'getVendorParameters'
+     * method of an 'IModule' or an 'IStreamCommon' interface instance,
+     * depending on the provided scope.
+     *
+     * The client calls this method in order to prepare arguments for a call to
+     * the particular Core HAL interface. The result returned by the HAL is then
+     * processed using the 'processVendorParameters' method. It is not required
+     * to maintain a 1:1 correspondence between the provided raw keys and the
+     * elements of the parsed result. If the returned list is empty, the call of
+     * 'getVendorParameters' is skipped. The implementation can either ignore
+     * keys which it does not recognize, or throw an error. The latter is
+     * preferred as it can help in discovering malformed key names.
+     *
+     * @param scope The scope of all raw parameter keys.
+     * @param rawKeys Raw parameter keys, joined into a string using a semicolon
+     *                (';') as the delimiter.
+     * @return A list of vendor parameter IDs, see android.hardware.audio.core.VendorParameter.
+     * @throws EX_ILLEGAL_ARGUMENT If the implementation can not parse the raw keys
+     *                             and prefers to signal an error.
+     */
+    @utf8InCpp String[] parseVendorParameterIds(
+            ParameterScope scope, in @utf8InCpp String rawKeys);
+
+    /**
+     * Parse raw parameter key-value pairs into vendor parameters.
+     *
+     * This method prepares arguments for a call to the 'setVendorParameters'
+     * method of an 'IModule' or an 'IStreamCommon' interface instance,
+     * depending on the provided scope.
+     *
+     * The vendor parameters returned using 'syncParameters' argument is then
+     * used to call the 'setVendorParameters' method with 'async = false', and
+     * 'asyncParameters' is used in a subsequent call to the same method, but
+     * with 'async = true'. It is not required to maintain a 1:1 correspondence
+     * between the provided key-value pairs and the elements of parsed
+     * results. If any of the returned lists of vendor parameters is empty, then
+     * the corresponding call is skipped. The implementation can either ignore
+     * keys which it does not recognize, and invalid values, or throw an
+     * error. The latter is preferred as it can help in discovering malformed
+     * key names and values.
+     *
+     * @param scope The scope of all raw key-value pairs.
+     * @param rawKeys Raw key-value pairs, separated by the "equals" sign ('='),
+     *                joined into a string using a semicolon (';') as the delimiter.
+     * @param syncParameters A list of vendor parameters to be set synchronously.
+     * @param asyncParameters A list of vendor parameters to be set asynchronously.
+     * @throws EX_ILLEGAL_ARGUMENT If the implementation can not parse raw key-value
+     *                             pairs and prefers to signal an error.
+     */
+    void parseVendorParameters(
+            ParameterScope scope, in @utf8InCpp String rawKeysAndValues,
+            out VendorParameter[] syncParameters, out VendorParameter[] asyncParameters);
+
+    /**
+     * Parse raw value of the parameter for BT A2DP reconfiguration.
+     *
+     * This method may return any number of vendor parameters (including zero)
+     * which will be passed to the 'IBluetoothA2dp.reconfigureOffload' method.
+     *
+     * @param rawValue An unparsed value of the legacy parameter.
+     * @return A list of vendor parameters.
+     * @throws EX_ILLEGAL_ARGUMENT If the implementation can not parse the raw value.
+     */
+    VendorParameter[] parseBluetoothA2dpReconfigureOffload(in @utf8InCpp String rawValue);
+
+    /**
+     * Parse raw value of the parameter for BT LE reconfiguration.
+     *
+     * This method may return any number of vendor parameters (including zero)
+     * which will be passed to the 'IBluetoothLe.reconfigureOffload' method.
+     *
+     * @param rawValue An unparsed value of the legacy parameter.
+     * @return A list of vendor parameters.
+     * @throws EX_ILLEGAL_ARGUMENT If the implementation can not parse the raw value.
+     */
+    VendorParameter[] parseBluetoothLeReconfigureOffload(in @utf8InCpp String rawValue);
+
+    /**
+     * Process vendor parameters returned by the Audio Core HAL.
+     *
+     * This processes the result returned from a call to the
+     * 'getVendorParameters' method of an 'IModule' or an 'IStreamCommon'
+     * interface instance, depending on the provided scope.
+     *
+     * See 'parseVendorParameterIds' method for the flow description.  It is not
+     * required to maintain a 1:1 correspondence between the elements of the
+     * provided list and the emitted key-value pairs. The returned string with
+     * raw key-value pairs is passed back to the framework.
+     *
+     * @param scope The scope of vendor parameters.
+     * @param parameters Vendor parameters, see android.hardware.audio.core.VendorParameter.
+     * @return Key-value pairs, separated by the "equals" sign ('='),
+     *         joined into a string using a semicolon (';') as the delimiter.
+     * @throws EX_ILLEGAL_ARGUMENT If the implementation can not emit raw key-value
+     *                             pairs and prefers to signal an error.
+     */
+    @utf8InCpp String processVendorParameters(
+            ParameterScope scope, in VendorParameter[] parameters);
+}
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index da45e9c..cee44b9 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -31,7 +31,33 @@
     ],
 }
 
-cc_binary {
+prebuilt_etc {
+    name: "drmserver.zygote64_32.rc",
+    src: "drmserver.zygote64_32.rc",
+    sub_dir: "init/hw",
+}
+
+prebuilt_etc {
+    name: "drmserver.zygote64.rc",
+    src: "drmserver.zygote64.rc",
+    sub_dir: "init/hw",
+}
+
+soong_config_module_type {
+    name: "drmserver_cc_binary",
+    module_type: "cc_binary",
+    config_namespace: "ANDROID",
+    bool_variables: ["TARGET_DYNAMIC_64_32_DRMSERVER"],
+    properties: [
+        "compile_multilib",
+        "init_rc",
+        "multilib.lib32.suffix",
+        "multilib.lib64.suffix",
+        "required",
+    ],
+}
+
+drmserver_cc_binary {
     name: "drmserver",
 
     srcs: [
@@ -61,7 +87,27 @@
 
     compile_multilib: "prefer32",
 
-    init_rc: ["drmserver.rc"],
+    soong_config_variables: {
+        TARGET_DYNAMIC_64_32_DRMSERVER: {
+            compile_multilib: "both",
+            multilib: {
+                lib32: {
+                    suffix: "32",
+                },
+                lib64: {
+                    suffix: "64",
+                },
+            },
+            required: [
+                "drmserver.zygote64_32.rc",
+                "drmserver.zygote64.rc",
+            ],
+            init_rc: ["drmserver_dynamic.rc"],
+            conditions_default: {
+                init_rc: ["drmserver.rc"],
+            },
+        },
+    },
 }
 
 cc_fuzz {
diff --git a/drm/drmserver/drmserver.zygote64.rc b/drm/drmserver/drmserver.zygote64.rc
new file mode 100644
index 0000000..60cd906
--- /dev/null
+++ b/drm/drmserver/drmserver.zygote64.rc
@@ -0,0 +1,6 @@
+service drm /system/bin/drmserver64
+    disabled
+    class main
+    user drm
+    group drm system inet drmrpc readproc
+    task_profiles ProcessCapacityHigh
diff --git a/drm/drmserver/drmserver.zygote64_32.rc b/drm/drmserver/drmserver.zygote64_32.rc
new file mode 100644
index 0000000..c881acf
--- /dev/null
+++ b/drm/drmserver/drmserver.zygote64_32.rc
@@ -0,0 +1,6 @@
+service drm /system/bin/drmserver32
+    disabled
+    class main
+    user drm
+    group drm system inet drmrpc readproc
+    task_profiles ProcessCapacityHigh
diff --git a/drm/drmserver/drmserver_dynamic.rc b/drm/drmserver/drmserver_dynamic.rc
new file mode 100644
index 0000000..bfaada1
--- /dev/null
+++ b/drm/drmserver/drmserver_dynamic.rc
@@ -0,0 +1,7 @@
+import /system/etc/init/hw/drmserver.${ro.zygote}.rc
+
+on property:drm.service.enabled=true
+    start drm
+
+on property:drm.service.enabled=1
+    start drm
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index be00d1e..91a107f 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1586,7 +1586,8 @@
         watcher->inputDelay(inputDelayValue)
                 .pipelineDelay(pipelineDelayValue)
                 .outputDelay(outputDelayValue)
-                .smoothnessFactor(kSmoothnessFactor);
+                .smoothnessFactor(kSmoothnessFactor)
+                .tunneled(mTunneled);
         watcher->flush();
     }
 
diff --git a/media/codec2/sfplugin/PipelineWatcher.cpp b/media/codec2/sfplugin/PipelineWatcher.cpp
index bc9197c..fa70a28 100644
--- a/media/codec2/sfplugin/PipelineWatcher.cpp
+++ b/media/codec2/sfplugin/PipelineWatcher.cpp
@@ -45,6 +45,11 @@
     return *this;
 }
 
+PipelineWatcher &PipelineWatcher::tunneled(bool value) {
+    mTunneled = value;
+    return *this;
+}
+
 void PipelineWatcher::onWorkQueued(
         uint64_t frameIndex,
         std::vector<std::shared_ptr<C2Buffer>> &&buffers,
@@ -87,8 +92,13 @@
     ALOGV("onWorkDone(frameIndex=%llu)", (unsigned long long)frameIndex);
     auto it = mFramesInPipeline.find(frameIndex);
     if (it == mFramesInPipeline.end()) {
-        ALOGD("onWorkDone: frameIndex not found (%llu); ignored",
-              (unsigned long long)frameIndex);
+        if (!mTunneled) {
+            ALOGD("onWorkDone: frameIndex not found (%llu); ignored",
+                  (unsigned long long)frameIndex);
+        } else {
+            ALOGV("onWorkDone: frameIndex not found (%llu); ignored",
+                  (unsigned long long)frameIndex);
+        }
         return;
     }
     (void)mFramesInPipeline.erase(it);
diff --git a/media/codec2/sfplugin/PipelineWatcher.h b/media/codec2/sfplugin/PipelineWatcher.h
index 1e23147..b29c7cd 100644
--- a/media/codec2/sfplugin/PipelineWatcher.h
+++ b/media/codec2/sfplugin/PipelineWatcher.h
@@ -37,7 +37,8 @@
         : mInputDelay(0),
           mPipelineDelay(0),
           mOutputDelay(0),
-          mSmoothnessFactor(0) {}
+          mSmoothnessFactor(0),
+          mTunneled(false) {}
     ~PipelineWatcher() = default;
 
     /**
@@ -65,6 +66,12 @@
     PipelineWatcher &smoothnessFactor(uint32_t value);
 
     /**
+     * \param value the new tunneled value
+     * \return  this object
+     */
+    PipelineWatcher &tunneled(bool value);
+
+    /**
      * Client queued a work item to the component.
      *
      * \param frameIndex  input frame index of this work
@@ -122,6 +129,7 @@
     uint32_t mPipelineDelay;
     uint32_t mOutputDelay;
     uint32_t mSmoothnessFactor;
+    bool mTunneled;
 
     struct Frame {
         Frame(std::vector<std::shared_ptr<C2Buffer>> &&b,
diff --git a/media/libaudiohal/TEST_MAPPING b/media/libaudiohal/TEST_MAPPING
index 3de5a9f..78a9dbc 100644
--- a/media/libaudiohal/TEST_MAPPING
+++ b/media/libaudiohal/TEST_MAPPING
@@ -7,6 +7,9 @@
           "include-filter": "android.nativemedia.aaudio.AAudioTests#AAudioBasic.*"
         }
       ]
+    },
+    {
+      "name": "CoreAudioHalAidlTest"
     }
   ]
 }
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index 30a4bf9..fc04cb3 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -240,19 +240,47 @@
     ]
 }
 
-cc_library_shared {
-    name: "libaudiohal@aidl",
+cc_defaults {
+    name: "libaudiohal_aidl_default",
     defaults: [
-        "libaudiohal_default",
         "latest_android_hardware_audio_common_ndk_shared",
         "latest_android_hardware_audio_core_ndk_shared",
         "latest_android_hardware_audio_effect_ndk_shared",
         "latest_android_media_audio_common_types_ndk_shared",
     ],
+    shared_libs: [
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
+        "av-audio-types-aidl-ndk",
+        "libaudio_aidl_conversion_common_cpp",
+        "libaudio_aidl_conversion_common_ndk",
+        "libaudio_aidl_conversion_common_ndk_cpp",
+        "libaudio_aidl_conversion_core_ndk",
+        "libaudio_aidl_conversion_effect_ndk",
+        "libaudioaidlcommon",
+        "libbinder_ndk",
+    ],
+    header_libs: [
+        "libaudio_system_headers",
+        "libeffectsconfig_headers",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+        "-DBACKEND_CPP_NDK",
+    ],
+}
+
+cc_library_shared {
+    name: "libaudiohal@aidl",
+    defaults: [
+        "libaudiohal_default",
+        "libaudiohal_aidl_default",
+    ],
     srcs: [
-        "DeviceHalAidl.cpp",
         "DevicesFactoryHalEntry.cpp",
-        "DevicesFactoryHalAidl.cpp",
         "EffectConversionHelperAidl.cpp",
         "EffectBufferHalAidl.cpp",
         "EffectHalAidl.cpp",
@@ -274,32 +302,18 @@
         "effectsAidlConversion/AidlConversionVisualizer.cpp",
         "EffectsFactoryHalAidl.cpp",
         "EffectsFactoryHalEntry.cpp",
+        ":audio_effectproxy_src_files",
+        ":core_audio_hal_aidl_src_files",
+    ],
+}
+
+filegroup {
+    name: "core_audio_hal_aidl_src_files",
+    srcs: [
+        "ConversionHelperAidl.cpp",
+        "DeviceHalAidl.cpp",
+        "DevicesFactoryHalAidl.cpp",
         "StreamHalAidl.cpp",
-        ":audio_effectproxy_src_files"
-    ],
-    static_libs: [
-        "android.hardware.common-V2-ndk",
-        "android.hardware.common.fmq-V1-ndk",
-    ],
-    shared_libs: [
-        "libaudio_aidl_conversion_common_cpp",
-        "libaudio_aidl_conversion_common_ndk",
-        "libaudio_aidl_conversion_common_ndk_cpp",
-        "libaudio_aidl_conversion_core_ndk",
-        "libaudio_aidl_conversion_effect_ndk",
-        "libaudioaidlcommon",
-        "libbinder_ndk",
-    ],
-    header_libs: [
-        "libaudio_system_headers",
-        "libeffectsconfig_headers",
-    ],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-Wthread-safety",
-        "-DBACKEND_CPP_NDK",
     ],
 }
 
diff --git a/media/libaudiohal/impl/ConversionHelperAidl.cpp b/media/libaudiohal/impl/ConversionHelperAidl.cpp
new file mode 100644
index 0000000..7197bf2
--- /dev/null
+++ b/media/libaudiohal/impl/ConversionHelperAidl.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#define LOG_TAG "ConversionHelperAidl"
+
+#include <memory>
+
+#include <media/AidlConversionUtil.h>
+#include <utils/Log.h>
+
+#include "ConversionHelperAidl.h"
+
+using aidl::android::aidl_utils::statusTFromBinderStatus;
+using aidl::android::hardware::audio::core::VendorParameter;
+using aidl::android::media::audio::IHalAdapterVendorExtension;
+
+namespace android {
+
+status_t parseAndGetVendorParameters(
+        std::shared_ptr<IHalAdapterVendorExtension> vendorExt,
+        const VendorParametersRecipient& recipient,
+        const AudioParameter& parameterKeys,
+        String8* values) {
+    using ParameterScope = IHalAdapterVendorExtension::ParameterScope;
+    if (parameterKeys.size() == 0) return OK;
+    const String8 rawKeys = parameterKeys.keysToString();
+    if (vendorExt == nullptr) {
+        ALOGW("%s: unknown parameters, ignored: \"%s\"", __func__, rawKeys.c_str());
+        return OK;
+    }
+
+    std::vector<std::string> parameterIds;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameterIds(
+                            ParameterScope(recipient.index()),
+                            std::string(rawKeys.c_str()), &parameterIds)));
+    if (parameterIds.empty()) return OK;
+
+    std::vector<VendorParameter> parameters;
+    if (recipient.index() == static_cast<int>(ParameterScope::MODULE)) {
+        auto module = std::get<static_cast<int>(ParameterScope::MODULE)>(recipient);
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->getVendorParameters(
+                                parameterIds, &parameters)));
+    } else if (recipient.index() == static_cast<int>(ParameterScope::STREAM)) {
+        auto stream = std::get<static_cast<int>(ParameterScope::STREAM)>(recipient);
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->getVendorParameters(
+                                parameterIds, &parameters)));
+    } else {
+        LOG_ALWAYS_FATAL("%s: unexpected recipient variant index: %zu",
+                __func__, recipient.index());
+    }
+    if (!parameters.empty()) {
+        std::string vendorParameters;
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->processVendorParameters(
+                                ParameterScope(recipient.index()),
+                                parameters, &vendorParameters)));
+        // Re-parse the vendor-provided string to ensure that it is correct.
+        AudioParameter reparse(String8(vendorParameters.c_str()));
+        if (reparse.size() != 0) {
+            if (!values->empty()) {
+                values->append(";");
+            }
+            values->append(reparse.toString().c_str());
+        }
+    }
+    return OK;
+}
+
+status_t parseAndSetVendorParameters(
+        std::shared_ptr<IHalAdapterVendorExtension> vendorExt,
+        const VendorParametersRecipient& recipient,
+        const AudioParameter& parameters) {
+    using ParameterScope = IHalAdapterVendorExtension::ParameterScope;
+    if (parameters.size() == 0) return OK;
+    const String8 rawKeysAndValues = parameters.toString();
+    if (vendorExt == nullptr) {
+        ALOGW("%s: unknown parameters, ignored: \"%s\"", __func__, rawKeysAndValues.c_str());
+        return OK;
+    }
+
+    std::vector<VendorParameter> syncParameters, asyncParameters;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameters(
+                            ParameterScope(recipient.index()),
+                            std::string(rawKeysAndValues.c_str()),
+                            &syncParameters, &asyncParameters)));
+    if (recipient.index() == static_cast<int>(ParameterScope::MODULE)) {
+        auto module = std::get<static_cast<int>(ParameterScope::MODULE)>(recipient);
+        if (!syncParameters.empty()) {
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->setVendorParameters(
+                                    syncParameters, false /*async*/)));
+        }
+        if (!asyncParameters.empty()) {
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->setVendorParameters(
+                                    asyncParameters, true /*async*/)));
+        }
+    } else if (recipient.index() == static_cast<int>(ParameterScope::STREAM)) {
+        auto stream = std::get<static_cast<int>(ParameterScope::STREAM)>(recipient);
+        if (!syncParameters.empty()) {
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->setVendorParameters(
+                                    syncParameters, false /*async*/)));
+        }
+        if (!asyncParameters.empty()) {
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->setVendorParameters(
+                                    asyncParameters, true /*async*/)));
+        }
+    } else {
+        LOG_ALWAYS_FATAL("%s: unexpected recipient variant index: %zu",
+                __func__, recipient.index());
+    }
+    return OK;
+}
+
+} // namespace android
diff --git a/media/libaudiohal/impl/ConversionHelperAidl.h b/media/libaudiohal/impl/ConversionHelperAidl.h
index 5534d13..0fadd9c 100644
--- a/media/libaudiohal/impl/ConversionHelperAidl.h
+++ b/media/libaudiohal/impl/ConversionHelperAidl.h
@@ -18,8 +18,12 @@
 
 #include <string>
 #include <string_view>
+#include <variant>
 #include <vector>
 
+#include <aidl/android/hardware/audio/core/IModule.h>
+#include <aidl/android/hardware/audio/core/IStreamCommon.h>
+#include <aidl/android/media/audio/IHalAdapterVendorExtension.h>
 #include <android-base/expected.h>
 #include <error/Result.h>
 #include <media/AudioParameter.h>
@@ -74,4 +78,18 @@
     return false;
 }
 
+// Must use the same order of elements as IHalAdapterVendorExtension::ParameterScope.
+using VendorParametersRecipient = std::variant<
+        std::shared_ptr<::aidl::android::hardware::audio::core::IModule>,
+        std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>>;
+status_t parseAndGetVendorParameters(
+        std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> vendorExt,
+        const VendorParametersRecipient& recipient,
+        const AudioParameter& parameterKeys,
+        String8* values);
+status_t parseAndSetVendorParameters(
+        std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> vendorExt,
+        const VendorParametersRecipient& recipient,
+        const AudioParameter& parameters);
+
 }  // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index 922604f..e6e7c6a 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -62,6 +62,7 @@
 using aidl::android::media::audio::common::Int;
 using aidl::android::media::audio::common::MicrophoneDynamicInfo;
 using aidl::android::media::audio::common::MicrophoneInfo;
+using aidl::android::media::audio::IHalAdapterVendorExtension;
 using aidl::android::hardware::audio::common::getFrameSizeInBytes;
 using aidl::android::hardware::audio::common::isBitPositionFlagSet;
 using aidl::android::hardware::audio::common::isDefaultAudioFormat;
@@ -76,6 +77,7 @@
 using aidl::android::hardware::audio::core::ITelephony;
 using aidl::android::hardware::audio::core::ModuleDebug;
 using aidl::android::hardware::audio::core::StreamDescriptor;
+using aidl::android::hardware::audio::core::VendorParameter;
 
 namespace android {
 
@@ -125,9 +127,10 @@
 
 }  // namespace
 
-DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module)
+DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module,
+                             const std::shared_ptr<IHalAdapterVendorExtension>& vext)
         : ConversionHelperAidl("DeviceHalAidl"),
-          mInstance(instance), mModule(module),
+          mInstance(instance), mModule(module), mVendorExt(vext),
           mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
           mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
           mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
@@ -286,19 +289,24 @@
     if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
         ALOGW("%s: filtering or updating BT SCO parameters failed: %d", __func__, status);
     }
-
-    ALOGW_IF(parameters.size() != 0, "%s: unknown parameters, ignored: \"%s\"",
-            __func__, parameters.toString().c_str());
-    return OK;
+    if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) {
+        ALOGW("%s: filtering or updating screen parameters failed: %d", __func__, status);
+    }
+    return parseAndSetVendorParameters(mVendorExt, mModule, parameters);
 }
 
-status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
+status_t DeviceHalAidl::getParameters(const String8& keys, String8 *values) {
     TIME_CHECK();
-    // FIXME(b/278976019): Support keyReconfigA2dpSupported via vendor plugin
-    values->clear();
     if (!mModule) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
+    if (values == nullptr) {
+        return BAD_VALUE;
+    }
+    AudioParameter parameterKeys(keys), result;
+    if (status_t status = filterAndRetrieveBtA2dpParameters(parameterKeys, &result); status != OK) {
+        ALOGW("%s: filtering or retrieving BT A2DP parameters failed: %d", __func__, status);
+    }
+    *values = result.toString();
+    return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
 }
 
 namespace {
@@ -568,7 +576,7 @@
         return NO_INIT;
     }
     *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
-            std::move(ret.stream), this /*callbackBroker*/);
+            std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
     mStreams.insert(std::pair(*outStream, aidlPatch.id));
     void* cbCookie = (*outStream).get();
     {
@@ -629,7 +637,7 @@
         return NO_INIT;
     }
     *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
-            std::move(ret.stream), this /*micInfoProvider*/);
+            std::move(ret.stream), mVendorExt, this /*micInfoProvider*/);
     mStreams.insert(std::pair(*inStream, aidlPatch.id));
     cleanups.disarmAll();
     return OK;
@@ -1090,9 +1098,23 @@
     return OK;
 }
 
+status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
+        AudioParameter &keys, AudioParameter *result) {
+    TIME_CHECK();
+    if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
+        keys.remove(key);
+        bool supports;
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+                        mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
+        result->addInt(key, supports ? 1 : 0);
+    }
+    return OK;
+}
+
 status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter &parameters) {
     TIME_CHECK();
     std::optional<bool> a2dpEnabled;
+    std::optional<std::vector<VendorParameter>> reconfigureOffload;
     (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
                     parameters, String8(AudioParameter::keyBtA2dpSuspended),
                     [&a2dpEnabled](const String8& trueOrFalse) {
@@ -1107,10 +1129,27 @@
                                 AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
                         return BAD_VALUE;
                     }));
-    // FIXME(b/278976019): Support keyReconfigA2dp via vendor plugin
+    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+                    parameters, String8(AudioParameter::keyReconfigA2dp),
+                    [&](const String8& value) -> status_t {
+                        if (mVendorExt != nullptr) {
+                            std::vector<VendorParameter> result;
+                            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+                                    mVendorExt->parseBluetoothA2dpReconfigureOffload(
+                                            std::string(value.c_str()), &result)));
+                            reconfigureOffload = std::move(result);
+                        } else {
+                            reconfigureOffload = std::vector<VendorParameter>();
+                        }
+                        return OK;
+                    }));
     if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
         return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
     }
+    if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
+        return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
+                        reconfigureOffload.value()));
+    }
     return OK;
 }
 
@@ -1234,6 +1273,44 @@
     return OK;
 }
 
+status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter &parameters) {
+    TIME_CHECK();
+    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+                    parameters, String8(AudioParameter::keyScreenState),
+                    [&](const String8& onOrOff) -> status_t {
+                        std::optional<bool> isTurnedOn;
+                        if (onOrOff == AudioParameter::valueOn) {
+                            isTurnedOn = true;
+                        } else if (onOrOff == AudioParameter::valueOff) {
+                            isTurnedOn = false;
+                        }
+                        if (!isTurnedOn.has_value()) {
+                            ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
+                                    AudioParameter::keyScreenState, onOrOff.c_str());
+                            return BAD_VALUE;
+                        }
+                        return statusTFromBinderStatus(
+                                mModule->updateScreenState(isTurnedOn.value()));
+                    }));
+    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+                    parameters, String8(AudioParameter::keyScreenRotation),
+            [&](int rotationDegrees) -> status_t {
+                IModule::ScreenRotation rotation;
+                switch (rotationDegrees) {
+                    case 0: rotation = IModule::ScreenRotation::DEG_0; break;
+                    case 90: rotation = IModule::ScreenRotation::DEG_90; break;
+                    case 180: rotation = IModule::ScreenRotation::DEG_180; break;
+                    case 270: rotation = IModule::ScreenRotation::DEG_270; break;
+                    default:
+                        ALOGE("setParameters: parameter key \"%s\" has invalid value %d",
+                                AudioParameter::keyScreenRotation, rotationDegrees);
+                        return BAD_VALUE;
+                }
+                return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
+            }));
+    return OK;
+}
+
 status_t DeviceHalAidl::findOrCreatePatch(
         const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
     std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index e29ae79..45768a3 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -20,6 +20,7 @@
 #include <set>
 #include <vector>
 
+#include <aidl/android/media/audio/IHalAdapterVendorExtension.h>
 #include <aidl/android/hardware/audio/core/BpModule.h>
 #include <android-base/thread_annotations.h>
 #include <media/audiohal/DeviceHalInterface.h>
@@ -199,7 +200,8 @@
     // Must not be constructed directly by clients.
     DeviceHalAidl(
             const std::string& instance,
-            const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module);
+            const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module,
+            const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext);
 
     ~DeviceHalAidl() override = default;
 
@@ -210,10 +212,12 @@
     status_t createOrUpdatePortConfig(
             const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
             PortConfigs::iterator* result, bool *created);
+    status_t filterAndRetrieveBtA2dpParameters(AudioParameter &keys, AudioParameter *result);
     status_t filterAndUpdateBtA2dpParameters(AudioParameter &parameters);
     status_t filterAndUpdateBtHfpParameters(AudioParameter &parameters);
     status_t filterAndUpdateBtLeParameters(AudioParameter &parameters);
     status_t filterAndUpdateBtScoParameters(AudioParameter &parameters);
+    status_t filterAndUpdateScreenParameters(AudioParameter &parameters);
     status_t findOrCreatePatch(
         const std::set<int32_t>& sourcePortConfigIds,
         const std::set<int32_t>& sinkPortConfigIds,
@@ -287,6 +291,7 @@
 
     const std::string mInstance;
     const std::shared_ptr<::aidl::android::hardware::audio::core::IModule> mModule;
+    const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> mVendorExt;
     const std::shared_ptr<::aidl::android::hardware::audio::core::ITelephony> mTelephony;
     const std::shared_ptr<::aidl::android::hardware::audio::core::IBluetooth> mBluetooth;
     const std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothA2dp> mBluetoothA2dp;
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
index c8cce96..f00b1a0 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
@@ -34,7 +34,8 @@
 using aidl::android::hardware::audio::core::IModule;
 using aidl::android::hardware::audio::core::SurroundSoundConfig;
 using aidl::android::media::audio::common::AudioHalEngineConfig;
-using ::android::detail::AudioHalVersionInfo;
+using aidl::android::media::audio::IHalAdapterVendorExtension;
+using android::detail::AudioHalVersionInfo;
 
 namespace android {
 
@@ -92,7 +93,7 @@
         ALOGE("%s fromBinder %s failed", __func__, serviceName.c_str());
         return NO_INIT;
     }
-    *device = sp<DeviceHalAidl>::make(name, service);
+    *device = sp<DeviceHalAidl>::make(name, service, getVendorExtension());
     return OK;
 }
 
@@ -154,6 +155,20 @@
     return OK;
 }
 
+std::shared_ptr<IHalAdapterVendorExtension> DevicesFactoryHalAidl::getVendorExtension() {
+    if (!mVendorExt.has_value()) {
+        auto serviceName = std::string(IHalAdapterVendorExtension::descriptor) + "/default";
+        if (AServiceManager_isDeclared(serviceName.c_str())) {
+            mVendorExt = std::shared_ptr<IHalAdapterVendorExtension>(
+                    IHalAdapterVendorExtension::fromBinder(ndk::SpAIBinder(
+                                    AServiceManager_waitForService(serviceName.c_str()))));
+        } else {
+            mVendorExt = nullptr;
+        }
+    }
+    return mVendorExt.value();
+}
+
 // Main entry-point to the shared library.
 extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() {
     auto serviceName = std::string(IConfig::descriptor) + "/default";
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.h b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
index 21957bc..97e3796 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <aidl/android/hardware/audio/core/IConfig.h>
+#include <aidl/android/media/audio/IHalAdapterVendorExtension.h>
 #include <media/audiohal/DevicesFactoryHalInterface.h>
 #include <utils/RefBase.h>
 
@@ -46,6 +47,11 @@
 
   private:
     const std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> mConfig;
+    std::optional<std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>>
+            mVendorExt;
+
+    std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> getVendorExtension();
+
     ~DevicesFactoryHalAidl() = default;
 };
 
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index d1044dc..c84f80f 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -43,6 +43,7 @@
 using ::aidl::android::hardware::audio::core::StreamDescriptor;
 using ::aidl::android::hardware::audio::core::MmapBufferDescriptor;
 using ::aidl::android::media::audio::common::MicrophoneDynamicInfo;
+using ::aidl::android::media::audio::IHalAdapterVendorExtension;
 
 namespace android {
 
@@ -73,12 +74,14 @@
 StreamHalAidl::StreamHalAidl(
         std::string_view className, bool isInput, const audio_config& config,
         int32_t nominalLatency, StreamContextAidl&& context,
-        const std::shared_ptr<IStreamCommon>& stream)
+        const std::shared_ptr<IStreamCommon>& stream,
+        const std::shared_ptr<IHalAdapterVendorExtension>& vext)
         : ConversionHelperAidl(className),
           mIsInput(isInput),
           mConfig(configToBase(config)),
           mContext(std::move(context)),
-          mStream(stream) {
+          mStream(stream),
+          mVendorExt(vext) {
     {
         std::lock_guard l(mLock);
         mLastReply.latencyMs = nominalLatency;
@@ -125,7 +128,6 @@
 status_t StreamHalAidl::setParameters(const String8& kvPairs) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-
     AudioParameter parameters(kvPairs);
     ALOGD("%s: parameters: %s", __func__, parameters.toString().c_str());
 
@@ -134,18 +136,18 @@
             [&](int hwAvSyncId) {
                 return statusTFromBinderStatus(mStream->updateHwAvSyncId(hwAvSyncId));
             }));
-
-    ALOGW_IF(parameters.size() != 0, "%s: unknown parameters, ignored: %s",
-            __func__, parameters.toString().c_str());
-    return OK;
+    return parseAndSetVendorParameters(mVendorExt, mStream, parameters);
 }
 
 status_t StreamHalAidl::getParameters(const String8& keys __unused, String8 *values) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
     TIME_CHECK();
-    values->clear();
-    // AIDL HAL doesn't support getParameters API.
-    return INVALID_OPERATION;
+    if (!mStream) return NO_INIT;
+    if (values == nullptr) {
+        return BAD_VALUE;
+    }
+    AudioParameter parameterKeys(keys), result;
+    *values = result.toString();
+    return parseAndGetVendorParameters(mVendorExt, mStream, parameterKeys, values);
 }
 
 status_t StreamHalAidl::getFrameSize(size_t *size) {
@@ -533,9 +535,11 @@
 
 StreamOutHalAidl::StreamOutHalAidl(
         const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
-        const std::shared_ptr<IStreamOut>& stream, const sp<CallbackBroker>& callbackBroker)
+        const std::shared_ptr<IStreamOut>& stream,
+        const std::shared_ptr<IHalAdapterVendorExtension>& vext,
+        const sp<CallbackBroker>& callbackBroker)
         : StreamHalAidl("StreamOutHalAidl", false /*isInput*/, config, nominalLatency,
-                std::move(context), getStreamCommon(stream)),
+                std::move(context), getStreamCommon(stream), vext),
           mStream(stream), mCallbackBroker(callbackBroker) {
     // Initialize the offload metadata
     mOffloadMetadata.sampleRate = static_cast<int32_t>(config.sample_rate);
@@ -861,9 +865,11 @@
 
 StreamInHalAidl::StreamInHalAidl(
         const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
-        const std::shared_ptr<IStreamIn>& stream, const sp<MicrophoneInfoProvider>& micInfoProvider)
+        const std::shared_ptr<IStreamIn>& stream,
+        const std::shared_ptr<IHalAdapterVendorExtension>& vext,
+        const sp<MicrophoneInfoProvider>& micInfoProvider)
         : StreamHalAidl("StreamInHalAidl", true /*isInput*/, config, nominalLatency,
-                std::move(context), getStreamCommon(stream)),
+                std::move(context), getStreamCommon(stream), vext),
           mStream(stream), mMicInfoProvider(micInfoProvider) {}
 
 status_t StreamInHalAidl::setGain(float gain) {
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index 75a1dd9..3b369bd 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -26,9 +26,11 @@
 #include <aidl/android/hardware/audio/core/BpStreamIn.h>
 #include <aidl/android/hardware/audio/core/BpStreamOut.h>
 #include <aidl/android/hardware/audio/core/MmapBufferDescriptor.h>
+#include <aidl/android/media/audio/IHalAdapterVendorExtension.h>
 #include <fmq/AidlMessageQueue.h>
 #include <media/audiohal/EffectHalInterface.h>
 #include <media/audiohal/StreamHalInterface.h>
+#include <media/AidlConversionUtil.h>
 #include <media/AudioParameter.h>
 
 #include "ConversionHelperAidl.h"
@@ -48,7 +50,7 @@
     typedef AidlMessageQueue<int8_t,
             ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> DataMQ;
 
-    explicit StreamContextAidl(
+    StreamContextAidl(
             ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
             bool isAsynchronous)
         : mFrameSizeBytes(descriptor.frameSizeBytes),
@@ -185,6 +187,9 @@
     status_t legacyReleaseAudioPatch() override;
 
   protected:
+    // For tests.
+    friend class sp<StreamHalAidl>;
+
     template<class T>
     static std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> getStreamCommon(
             const std::shared_ptr<T>& stream);
@@ -195,7 +200,8 @@
             const audio_config& config,
             int32_t nominalLatency,
             StreamContextAidl&& context,
-            const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>& stream);
+            const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>& stream,
+            const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext);
 
     ~StreamHalAidl() override;
 
@@ -247,6 +253,7 @@
             ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
 
     const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> mStream;
+    const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> mVendorExt;
     std::mutex mLock;
     ::aidl::android::hardware::audio::core::StreamDescriptor::Reply mLastReply GUARDED_BY(mLock);
     // mStreamPowerLog is used for audio signal power logging.
@@ -349,6 +356,7 @@
     StreamOutHalAidl(
             const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
             const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut>& stream,
+            const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext,
             const sp<CallbackBroker>& callbackBroker);
 
     ~StreamOutHalAidl() override;
@@ -401,6 +409,7 @@
     StreamInHalAidl(
             const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
             const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamIn>& stream,
+            const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext,
             const sp<MicrophoneInfoProvider>& micInfoProvider);
 
     ~StreamInHalAidl() override = default;
diff --git a/media/libaudiohal/tests/Android.bp b/media/libaudiohal/tests/Android.bp
index 8210f7d..8f011c8 100644
--- a/media/libaudiohal/tests/Android.bp
+++ b/media/libaudiohal/tests/Android.bp
@@ -21,34 +21,34 @@
 }
 
 cc_defaults {
-    name: "AudioHalTestDefaults",
+    name: "libaudiohal_aidl_test_default",
     test_suites: ["device-tests"],
     defaults: [
-        "latest_android_media_audio_common_types_ndk_shared",
+        "libaudiohal_default",
+        "libaudiohal_aidl_default",
     ],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-Wthread-safety",
-        "-DBACKEND_NDK",
-    ],
-
     shared_libs: [
-        "audioclient-types-aidl-cpp",
-        "libaudio_aidl_conversion_common_ndk",
         "libaudiohal",
-        "liblog",
-        "libutils",
-        "libvibrator",
     ],
 }
 
 cc_test {
+    name: "CoreAudioHalAidlTest",
+    srcs: [
+        "CoreAudioHalAidl_test.cpp",
+        ":core_audio_hal_aidl_src_files",
+    ],
+    defaults: ["libaudiohal_aidl_test_default"],
+    header_libs: ["libaudiohalimpl_headers"],
+}
+
+cc_test {
     name: "EffectsFactoryHalInterfaceTest",
     srcs: ["EffectsFactoryHalInterface_test.cpp"],
-    defaults: ["AudioHalTestDefaults"],
-    header_libs: ["libaudiohal_headers"],
+    defaults: ["libaudiohal_aidl_test_default"],
+    shared_libs: [
+        "libvibrator",
+    ],
 }
 
 cc_test {
@@ -58,15 +58,8 @@
         ":audio_effectproxy_src_files",
     ],
     defaults: [
-        "AudioHalTestDefaults",
-        "latest_android_hardware_audio_effect_ndk_shared",
-        "libaudiohal_default",
+        "libaudiohal_aidl_test_default",
         "use_libaidlvintf_gtest_helper_static",
     ],
-    shared_libs: [
-        "android.hardware.common.fmq-V1-ndk",
-        "libbinder_ndk",
-        "libfmq",
-    ],
     header_libs: ["libaudiohalimpl_headers"],
 }
diff --git a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
new file mode 100644
index 0000000..ea20794
--- /dev/null
+++ b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
@@ -0,0 +1,607 @@
+/*
+ * Copyright 2023 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.
+ */
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#define LOG_TAG "CoreAudioHalAidlTest"
+#include <gtest/gtest.h>
+
+#include <DeviceHalAidl.h>
+#include <StreamHalAidl.h>
+#include <aidl/android/hardware/audio/core/BnModule.h>
+#include <aidl/android/hardware/audio/core/BnStreamCommon.h>
+#include <aidl/android/media/audio/BnHalAdapterVendorExtension.h>
+#include <aidl/android/media/audio/common/Int.h>
+#include <utils/Log.h>
+
+namespace {
+
+using ::aidl::android::hardware::audio::core::VendorParameter;
+
+class VendorParameterMock {
+  public:
+    const std::vector<std::string>& getRetrievedParameterIds() const { return mGetParameterIds; }
+    const std::vector<VendorParameter>& getAsyncParameters() const { return mAsyncParameters; }
+    const std::vector<VendorParameter>& getSyncParameters() const { return mSyncParameters; }
+
+  protected:
+    ndk::ScopedAStatus getVendorParametersImpl(const std::vector<std::string>& in_parameterIds) {
+        mGetParameterIds.insert(mGetParameterIds.end(), in_parameterIds.begin(),
+                                in_parameterIds.end());
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus setVendorParametersImpl(const std::vector<VendorParameter>& in_parameters,
+                                               bool async) {
+        if (async) {
+            mAsyncParameters.insert(mAsyncParameters.end(), in_parameters.begin(),
+                                    in_parameters.end());
+        } else {
+            mSyncParameters.insert(mSyncParameters.end(), in_parameters.begin(),
+                                   in_parameters.end());
+        }
+        return ndk::ScopedAStatus::ok();
+    }
+
+  private:
+    std::vector<std::string> mGetParameterIds;
+    std::vector<VendorParameter> mAsyncParameters;
+    std::vector<VendorParameter> mSyncParameters;
+};
+
+class ModuleMock : public ::aidl::android::hardware::audio::core::BnModule,
+                   public VendorParameterMock {
+  public:
+    bool isScreenTurnedOn() const { return mIsScreenTurnedOn; }
+    ScreenRotation getScreenRotation() const { return mScreenRotation; }
+
+  private:
+    ndk::ScopedAStatus setModuleDebug(
+            const ::aidl::android::hardware::audio::core::ModuleDebug&) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getTelephony(
+            std::shared_ptr<::aidl::android::hardware::audio::core::ITelephony>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getBluetooth(
+            std::shared_ptr<::aidl::android::hardware::audio::core::IBluetooth>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getBluetoothA2dp(
+            std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothA2dp>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getBluetoothLe(
+            std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothLe>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus connectExternalDevice(
+            const ::aidl::android::media::audio::common::AudioPort&,
+            ::aidl::android::media::audio::common::AudioPort*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus disconnectExternalDevice(int32_t) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getAudioPatches(
+            std::vector<::aidl::android::hardware::audio::core::AudioPatch>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getAudioPort(int32_t,
+                                    ::aidl::android::media::audio::common::AudioPort*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getAudioPortConfigs(
+            std::vector<::aidl::android::media::audio::common::AudioPortConfig>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getAudioPorts(
+            std::vector<::aidl::android::media::audio::common::AudioPort>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getAudioRoutes(
+            std::vector<::aidl::android::hardware::audio::core::AudioRoute>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getAudioRoutesForAudioPort(
+            int32_t, std::vector<::aidl::android::hardware::audio::core::AudioRoute>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus openInputStream(const OpenInputStreamArguments&,
+                                       OpenInputStreamReturn*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus openOutputStream(const OpenOutputStreamArguments&,
+                                        OpenOutputStreamReturn*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getSupportedPlaybackRateFactors(SupportedPlaybackRateFactors*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus setAudioPatch(const ::aidl::android::hardware::audio::core::AudioPatch&,
+                                     ::aidl::android::hardware::audio::core::AudioPatch*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus setAudioPortConfig(
+            const ::aidl::android::media::audio::common::AudioPortConfig&,
+            ::aidl::android::media::audio::common::AudioPortConfig*, bool*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus resetAudioPatch(int32_t) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus resetAudioPortConfig(int32_t) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus getMasterMute(bool*) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus setMasterMute(bool) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus getMasterVolume(float*) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus setMasterVolume(float) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus getMicMute(bool*) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus setMicMute(bool) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus getMicrophones(
+            std::vector<::aidl::android::media::audio::common::MicrophoneInfo>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus updateAudioMode(::aidl::android::media::audio::common::AudioMode) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus updateScreenRotation(ScreenRotation in_rotation) override {
+        mScreenRotation = in_rotation;
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus updateScreenState(bool in_isTurnedOn) override {
+        mIsScreenTurnedOn = in_isTurnedOn;
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getSoundDose(
+            std::shared_ptr<::aidl::android::hardware::audio::core::sounddose::ISoundDose>*)
+            override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus generateHwAvSyncId(int32_t*) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_parameterIds,
+                                           std::vector<VendorParameter>*) override {
+        return getVendorParametersImpl(in_parameterIds);
+    }
+    ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+                                           bool async) override {
+        return setVendorParametersImpl(in_parameters, async);
+    }
+    ndk::ScopedAStatus addDeviceEffect(
+            int32_t,
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus removeDeviceEffect(
+            int32_t,
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getMmapPolicyInfos(
+            ::aidl::android::media::audio::common::AudioMMapPolicyType,
+            std::vector<::aidl::android::media::audio::common::AudioMMapPolicyInfo>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus supportsVariableLatency(bool*) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus getAAudioMixerBurstCount(int32_t*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getAAudioHardwareBurstMinUsec(int32_t*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+
+    bool mIsScreenTurnedOn = false;
+    ScreenRotation mScreenRotation = ScreenRotation::DEG_0;
+};
+
+class StreamCommonMock : public ::aidl::android::hardware::audio::core::BnStreamCommon,
+                         public VendorParameterMock {
+    ndk::ScopedAStatus close() override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus prepareToClose() override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus updateHwAvSyncId(int32_t) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_parameterIds,
+                                           std::vector<VendorParameter>*) override {
+        return getVendorParametersImpl(in_parameterIds);
+    }
+    ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+                                           bool async) override {
+        return setVendorParametersImpl(in_parameters, async);
+    }
+    ndk::ScopedAStatus addEffect(
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus removeEffect(
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
+        return ndk::ScopedAStatus::ok();
+    }
+};
+
+VendorParameter makeVendorParameter(const std::string& id, int value) {
+    VendorParameter result{.id = id};
+    // Note: in real life, a parcelable type defined by vendor must be used,
+    // here we use Int just for test purposes.
+    ::aidl::android::media::audio::common::Int vendorValue{.value = value};
+    result.ext.setParcelable(std::move(vendorValue));
+    return result;
+}
+
+android::status_t parseVendorParameter(const VendorParameter& param, int* value) {
+    std::optional<::aidl::android::media::audio::common::Int> vendorValue;
+    RETURN_STATUS_IF_ERROR(param.ext.getParcelable(&vendorValue));
+    if (!vendorValue.has_value()) return android::BAD_VALUE;
+    *value = vendorValue.value().value;
+    return android::OK;
+}
+
+class TestHalAdapterVendorExtension
+    : public ::aidl::android::media::audio::BnHalAdapterVendorExtension {
+  public:
+    static const std::string kLegacyParameterKey;
+    static const std::string kLegacyAsyncParameterKey;
+    static const std::string kModuleVendorParameterId;
+    static const std::string kStreamVendorParameterId;
+
+  private:
+    ndk::ScopedAStatus parseVendorParameterIds(ParameterScope in_scope,
+                                               const std::string& in_rawKeys,
+                                               std::vector<std::string>* _aidl_return) override {
+        android::AudioParameter keys(android::String8(in_rawKeys.c_str()));
+        for (size_t i = 0; i < keys.size(); ++i) {
+            android::String8 key;
+            if (android::status_t status = keys.getAt(i, key); status != android::OK) {
+                return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+            }
+            switch (in_scope) {
+                case ParameterScope::MODULE:
+                    if (key == android::String8(kLegacyParameterKey.c_str()) ||
+                        key == android::String8(kLegacyAsyncParameterKey.c_str())) {
+                        _aidl_return->push_back(kModuleVendorParameterId);
+                    } else {
+                        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+                    }
+                    break;
+                case ParameterScope::STREAM:
+                    if (key == android::String8(kLegacyParameterKey.c_str()) ||
+                        key == android::String8(kLegacyAsyncParameterKey.c_str())) {
+                        _aidl_return->push_back(kStreamVendorParameterId);
+                    } else {
+                        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+                    }
+                    break;
+            }
+        }
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus parseVendorParameters(
+            ParameterScope in_scope, const std::string& in_rawKeysAndValues,
+            std::vector<VendorParameter>* out_syncParameters,
+            std::vector<VendorParameter>* out_asyncParameters) override {
+        android::AudioParameter legacy(android::String8(in_rawKeysAndValues.c_str()));
+        for (size_t i = 0; i < legacy.size(); ++i) {
+            android::String8 key;
+            if (android::status_t status = legacy.getAt(i, key); status != android::OK) {
+                return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+            }
+            int value;
+            if (android::status_t status = legacy.getInt(key, value); status != android::OK) {
+                return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+            }
+            std::string parameterId;
+            switch (in_scope) {
+                case ParameterScope::MODULE:
+                    parameterId = kModuleVendorParameterId;
+                    break;
+                case ParameterScope::STREAM:
+                    parameterId = kStreamVendorParameterId;
+                    break;
+            }
+            if (key == android::String8(kLegacyParameterKey.c_str())) {
+                out_syncParameters->push_back(makeVendorParameter(parameterId, value));
+            } else if (key == android::String8(kLegacyAsyncParameterKey.c_str())) {
+                out_asyncParameters->push_back(makeVendorParameter(parameterId, value));
+            } else {
+                return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+            }
+        }
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus parseBluetoothA2dpReconfigureOffload(
+            const std::string&, std::vector<VendorParameter>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus parseBluetoothLeReconfigureOffload(const std::string&,
+                                                          std::vector<VendorParameter>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus processVendorParameters(ParameterScope in_scope,
+                                               const std::vector<VendorParameter>& in_parameters,
+                                               std::string* _aidl_return) override {
+        android::AudioParameter legacy;
+        for (const auto& vendorParam : in_parameters) {
+            if ((in_scope == ParameterScope::MODULE &&
+                 vendorParam.id == kModuleVendorParameterId) ||
+                (in_scope == ParameterScope::STREAM &&
+                 vendorParam.id == kStreamVendorParameterId)) {
+                int value;
+                if (android::status_t status = parseVendorParameter(vendorParam, &value);
+                    status != android::OK) {
+                    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+                }
+                legacy.addInt(android::String8(kLegacyParameterKey.c_str()), value);
+            }
+        }
+        *_aidl_return = legacy.toString().c_str();
+        return ndk::ScopedAStatus::ok();
+    }
+};
+
+const std::string TestHalAdapterVendorExtension::kLegacyParameterKey = "aosp_test_param";
+const std::string TestHalAdapterVendorExtension::kLegacyAsyncParameterKey = "aosp_test_param_async";
+// Note: in real life, there is no need to explicitly separate "module" and "stream"
+// parameters, here it's done just for test purposes.
+const std::string TestHalAdapterVendorExtension::kModuleVendorParameterId =
+        "aosp.test.module.parameter";
+const std::string TestHalAdapterVendorExtension::kStreamVendorParameterId =
+        "aosp.test.stream.parameter";
+
+android::String8 createParameterString(const std::string& key, const std::string& value) {
+    android::AudioParameter params;
+    params.add(android::String8(key.c_str()), android::String8(value.c_str()));
+    return params.toString();
+}
+
+android::String8 createParameterString(const std::string& key, int value) {
+    android::AudioParameter params;
+    params.addInt(android::String8(key.c_str()), value);
+    return params.toString();
+}
+
+template <typename>
+struct mf_traits {};
+template <class T, class U>
+struct mf_traits<U T::*> {
+    using member_type = U;
+};
+
+}  // namespace
+
+// Provide value printers for types generated from AIDL
+// They need to be in the same namespace as the types we intend to print
+namespace aidl::android::hardware::audio::core {
+template <typename P>
+std::enable_if_t<std::is_function_v<typename mf_traits<decltype(&P::toString)>::member_type>,
+                 std::ostream&>
+operator<<(std::ostream& os, const P& p) {
+    return os << p.toString();
+}
+template <typename E>
+std::enable_if_t<std::is_enum_v<E>, std::ostream&> operator<<(std::ostream& os, const E& e) {
+    return os << toString(e);
+}
+}  // namespace aidl::android::hardware::audio::core
+
+using namespace android;
+
+class DeviceHalAidlTest : public testing::Test {
+  public:
+    void SetUp() override {
+        mModule = ndk::SharedRefBase::make<ModuleMock>();
+        mDevice = sp<DeviceHalAidl>::make("test", mModule, nullptr /*vext*/);
+    }
+    void TearDown() override {
+        mDevice.clear();
+        mModule.reset();
+    }
+
+  protected:
+    std::shared_ptr<ModuleMock> mModule;
+    sp<DeviceHalAidl> mDevice;
+};
+
+TEST_F(DeviceHalAidlTest, ScreenState) {
+    EXPECT_FALSE(mModule->isScreenTurnedOn());
+    EXPECT_EQ(OK, mDevice->setParameters(createParameterString(AudioParameter::keyScreenState,
+                                                               AudioParameter::valueOn)));
+    EXPECT_TRUE(mModule->isScreenTurnedOn());
+    EXPECT_EQ(OK, mDevice->setParameters(createParameterString(AudioParameter::keyScreenState,
+                                                               AudioParameter::valueOff)));
+    EXPECT_FALSE(mModule->isScreenTurnedOn());
+    // The adaptation layer only logs a warning.
+    EXPECT_EQ(OK, mDevice->setParameters(
+                          createParameterString(AudioParameter::keyScreenState, "blah")));
+    EXPECT_FALSE(mModule->isScreenTurnedOn());
+}
+
+TEST_F(DeviceHalAidlTest, ScreenRotation) {
+    using ScreenRotation = ::aidl::android::hardware::audio::core::IModule::ScreenRotation;
+    EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
+    EXPECT_EQ(OK,
+              mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 90)));
+    EXPECT_EQ(ScreenRotation::DEG_90, mModule->getScreenRotation());
+    EXPECT_EQ(OK,
+              mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 0)));
+    EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
+    // The adaptation layer only logs a warning.
+    EXPECT_EQ(OK,
+              mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 42)));
+    EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
+}
+
+// Without a vendor extension, any unrecognized parameters must be ignored.
+TEST_F(DeviceHalAidlTest, VendorParameterIgnored) {
+    EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+    EXPECT_EQ(0UL, mModule->getSyncParameters().size());
+    EXPECT_EQ(OK, mDevice->setParameters(createParameterString("random_name", "random_value")));
+    EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+    EXPECT_EQ(0UL, mModule->getSyncParameters().size());
+
+    EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size());
+    String8 values;
+    EXPECT_EQ(OK, mDevice->getParameters(String8("random_name"), &values));
+    EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size());
+    EXPECT_TRUE(values.empty());
+}
+
+class DeviceHalAidlVendorParametersTest : public testing::Test {
+  public:
+    void SetUp() override {
+        mModule = ndk::SharedRefBase::make<ModuleMock>();
+        mVendorExt = ndk::SharedRefBase::make<TestHalAdapterVendorExtension>();
+        mDevice = sp<DeviceHalAidl>::make("test", mModule, mVendorExt);
+    }
+    void TearDown() override {
+        mDevice.clear();
+        mVendorExt.reset();
+        mModule.reset();
+    }
+
+  protected:
+    std::shared_ptr<ModuleMock> mModule;
+    std::shared_ptr<TestHalAdapterVendorExtension> mVendorExt;
+    sp<DeviceHalAidl> mDevice;
+};
+
+TEST_F(DeviceHalAidlVendorParametersTest, GetVendorParameter) {
+    EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size());
+    String8 values;
+    EXPECT_EQ(OK, mDevice->getParameters(
+                          String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()),
+                          &values));
+    EXPECT_EQ(1UL, mModule->getRetrievedParameterIds().size());
+    if (mModule->getRetrievedParameterIds().size() >= 1) {
+        EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId,
+                  mModule->getRetrievedParameterIds()[0]);
+    }
+}
+
+TEST_F(DeviceHalAidlVendorParametersTest, SetVendorParameter) {
+    EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+    EXPECT_EQ(0UL, mModule->getSyncParameters().size());
+    EXPECT_EQ(OK, mDevice->setParameters(createParameterString(
+                          TestHalAdapterVendorExtension::kLegacyParameterKey, 42)));
+    EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+    EXPECT_EQ(1UL, mModule->getSyncParameters().size());
+    EXPECT_EQ(OK, mDevice->setParameters(createParameterString(
+                          TestHalAdapterVendorExtension::kLegacyAsyncParameterKey, 43)));
+    EXPECT_EQ(1UL, mModule->getAsyncParameters().size());
+    EXPECT_EQ(1UL, mModule->getSyncParameters().size());
+    if (mModule->getSyncParameters().size() >= 1) {
+        EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId,
+                  mModule->getSyncParameters()[0].id);
+        int value{};
+        EXPECT_EQ(android::OK, parseVendorParameter(mModule->getSyncParameters()[0], &value));
+        EXPECT_EQ(42, value);
+    }
+    if (mModule->getAsyncParameters().size() >= 1) {
+        EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId,
+                  mModule->getAsyncParameters()[0].id);
+        int value{};
+        EXPECT_EQ(android::OK, parseVendorParameter(mModule->getAsyncParameters()[0], &value));
+        EXPECT_EQ(43, value);
+    }
+}
+
+TEST_F(DeviceHalAidlVendorParametersTest, SetInvalidVendorParameters) {
+    android::AudioParameter legacy;
+    legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()), 42);
+    legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyAsyncParameterKey.c_str()),
+                  43);
+    legacy.addInt(android::String8("random_name"), 44);
+    EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+    EXPECT_EQ(0UL, mModule->getSyncParameters().size());
+    // TestHalAdapterVendorExtension throws an error for unknown parameters.
+    EXPECT_EQ(android::BAD_VALUE, mDevice->setParameters(legacy.toString()));
+    EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+    EXPECT_EQ(0UL, mModule->getSyncParameters().size());
+}
+
+class StreamHalAidlVendorParametersTest : public testing::Test {
+  public:
+    void SetUp() override {
+        mStreamCommon = ndk::SharedRefBase::make<StreamCommonMock>();
+        mVendorExt = ndk::SharedRefBase::make<TestHalAdapterVendorExtension>();
+        struct audio_config config = AUDIO_CONFIG_INITIALIZER;
+        ::aidl::android::hardware::audio::core::StreamDescriptor descriptor;
+        mStream = sp<StreamHalAidl>::make("test", false /*isInput*/, config, 0 /*nominalLatency*/,
+                                          StreamContextAidl(descriptor, false /*isAsynchronous*/),
+                                          mStreamCommon, mVendorExt);
+    }
+    void TearDown() override {
+        mStream.clear();
+        mVendorExt.reset();
+        mStreamCommon.reset();
+    }
+
+  protected:
+    std::shared_ptr<StreamCommonMock> mStreamCommon;
+    std::shared_ptr<TestHalAdapterVendorExtension> mVendorExt;
+    sp<StreamHalAidl> mStream;
+};
+
+TEST_F(StreamHalAidlVendorParametersTest, GetVendorParameter) {
+    EXPECT_EQ(0UL, mStreamCommon->getRetrievedParameterIds().size());
+    String8 values;
+    EXPECT_EQ(OK, mStream->getParameters(
+                          String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()),
+                          &values));
+    EXPECT_EQ(1UL, mStreamCommon->getRetrievedParameterIds().size());
+    if (mStreamCommon->getRetrievedParameterIds().size() >= 1) {
+        EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId,
+                  mStreamCommon->getRetrievedParameterIds()[0]);
+    }
+}
+
+TEST_F(StreamHalAidlVendorParametersTest, SetVendorParameter) {
+    EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
+    EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size());
+    EXPECT_EQ(OK, mStream->setParameters(createParameterString(
+                          TestHalAdapterVendorExtension::kLegacyParameterKey, 42)));
+    EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
+    EXPECT_EQ(1UL, mStreamCommon->getSyncParameters().size());
+    EXPECT_EQ(OK, mStream->setParameters(createParameterString(
+                          TestHalAdapterVendorExtension::kLegacyAsyncParameterKey, 43)));
+    EXPECT_EQ(1UL, mStreamCommon->getAsyncParameters().size());
+    EXPECT_EQ(1UL, mStreamCommon->getSyncParameters().size());
+    if (mStreamCommon->getSyncParameters().size() >= 1) {
+        EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId,
+                  mStreamCommon->getSyncParameters()[0].id);
+        int value{};
+        EXPECT_EQ(android::OK, parseVendorParameter(mStreamCommon->getSyncParameters()[0], &value));
+        EXPECT_EQ(42, value);
+    }
+    if (mStreamCommon->getAsyncParameters().size() >= 1) {
+        EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId,
+                  mStreamCommon->getAsyncParameters()[0].id);
+        int value{};
+        EXPECT_EQ(android::OK,
+                  parseVendorParameter(mStreamCommon->getAsyncParameters()[0], &value));
+        EXPECT_EQ(43, value);
+    }
+}
+
+TEST_F(StreamHalAidlVendorParametersTest, SetInvalidVendorParameters) {
+    android::AudioParameter legacy;
+    legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()), 42);
+    legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyAsyncParameterKey.c_str()),
+                  43);
+    legacy.addInt(android::String8("random_name"), 44);
+    EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
+    EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size());
+    // TestHalAdapterVendorExtension throws an error for unknown parameters.
+    EXPECT_EQ(android::BAD_VALUE, mStream->setParameters(legacy.toString()));
+    EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
+    EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size());
+}
diff --git a/media/libaudioprocessing/Android.bp b/media/libaudioprocessing/Android.bp
index 309765a..6160d7d 100644
--- a/media/libaudioprocessing/Android.bp
+++ b/media/libaudioprocessing/Android.bp
@@ -72,6 +72,10 @@
     ],
 
     whole_static_libs: ["libaudioprocessing_base"],
+
+    export_shared_lib_headers: [
+        "libvibrator",
+    ],
 }
 
 cc_library_static {
diff --git a/media/libmediahelper/AudioParameter.cpp b/media/libmediahelper/AudioParameter.cpp
index a61a1bc..3832e90 100644
--- a/media/libmediahelper/AudioParameter.cpp
+++ b/media/libmediahelper/AudioParameter.cpp
@@ -33,6 +33,7 @@
 const char * const AudioParameter::keyFrameCount = AUDIO_PARAMETER_STREAM_FRAME_COUNT;
 const char * const AudioParameter::keyInputSource = AUDIO_PARAMETER_STREAM_INPUT_SOURCE;
 const char * const AudioParameter::keyScreenState = AUDIO_PARAMETER_KEY_SCREEN_STATE;
+const char * const AudioParameter::keyScreenRotation = AUDIO_PARAMETER_KEY_ROTATION;
 const char * const AudioParameter::keyClosing = AUDIO_PARAMETER_KEY_CLOSING;
 const char * const AudioParameter::keyExiting = AUDIO_PARAMETER_KEY_EXITING;
 const char * const AudioParameter::keyBtSco = AUDIO_PARAMETER_KEY_BT_SCO;
diff --git a/media/libmediahelper/include/media/AudioParameter.h b/media/libmediahelper/include/media/AudioParameter.h
index 70f8af3..8568b8f 100644
--- a/media/libmediahelper/include/media/AudioParameter.h
+++ b/media/libmediahelper/include/media/AudioParameter.h
@@ -41,6 +41,7 @@
     //  keyInputSource: to change audio input source, value is an int in audio_source_t
     //     (defined in media/mediarecorder.h)
     //  keyScreenState: either "on" or "off"
+    //  keyScreenRotation: one of: 0, 90, 180, 270
     static const char * const keyRouting;
     static const char * const keySamplingRate;
     static const char * const keyFormat;
@@ -48,6 +49,7 @@
     static const char * const keyFrameCount;
     static const char * const keyInputSource;
     static const char * const keyScreenState;
+    static const char * const keyScreenRotation;
 
     // TODO(b/73175392) consider improvement to AIDL StreamOut interface.
     // keyClosing: "true" when AudioOutputDescriptor is closing.  Used by A2DP HAL.
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index d205990..f73c5a8 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -2217,6 +2217,11 @@
                 -ret, strerror(-ret));
             return ret;
         }
+        if (mVideoDecoder != NULL) {
+            sp<AMessage> params = new AMessage();
+            params->setInt32("android._video-scaling", mode);
+            mVideoDecoder->setParameters(params);
+        }
     }
     return OK;
 }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 8da09c4..f4143da 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -459,6 +459,14 @@
         codecParams->setFloat("operating-rate", decodeFrameRate * mPlaybackSpeed);
         mCodec->setParameters(codecParams);
     }
+
+    int32_t videoScalingMode;
+    if (params->findInt32("android._video-scaling", &videoScalingMode)
+            && mCodec != NULL) {
+        sp<AMessage> codecParams = new AMessage();
+        codecParams->setInt32("android._video-scaling", videoScalingMode);
+        mCodec->setParameters(codecParams);
+    }
 }
 
 void NuPlayer::Decoder::onSetRenderer(const sp<Renderer> &renderer) {
diff --git a/media/module/extractors/mp4/MPEG4Extractor.cpp b/media/module/extractors/mp4/MPEG4Extractor.cpp
index eaca75c..38cf29d 100644
--- a/media/module/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/module/extractors/mp4/MPEG4Extractor.cpp
@@ -6500,6 +6500,16 @@
             AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
         }
 
+        void *presentationsData;
+        size_t presentationsSize;
+        if (AMediaFormat_getBuffer(
+                    mFormat, AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO,
+                    &presentationsData, &presentationsSize)) {
+            AMediaFormat_setBuffer(
+                    meta, AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO,
+                    presentationsData, presentationsSize);
+        }
+
         ++mCurrentSampleIndex;
 
         *out = mBuffer;
diff --git a/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml b/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
index 1890661..1b66b01 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
+++ b/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
@@ -14,18 +14,26 @@
      limitations under the License.
 -->
 <configuration description="Runs Media Benchmark Tests">
+    <option name="test-tag" value="MediaBenchmarkTest" />
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/tests/benchmark/MediaBenchmark.zip?unzip=true"
-            value="/data/local/tmp/MediaBenchmark/res/" />
     </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
-        <option name="cleanup-apks" value="false" />
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="MediaBenchmarkTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="MediaBenchmarkTest-1.1" />
+        <option name="dynamic-config-module" value="MediaBenchmarkTest" />
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="MediaBenchmarkTest.apk" />
     </target_preparer>
 
-    <option name="test-tag" value="MediaBenchmarkTest" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.media.benchmark" />
         <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
diff --git a/media/tests/benchmark/MediaBenchmarkTest/DynamicConfig.xml b/media/tests/benchmark/MediaBenchmarkTest/DynamicConfig.xml
new file mode 100644
index 0000000..1278f29
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/tests/benchmark/MediaBenchmark-1.1.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml b/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml
index 24dbccc..2bef254 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml
+++ b/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml
@@ -1,4 +1,4 @@
 <resources>
-    <string name="input_file_path">/data/local/tmp/MediaBenchmark/res/</string>
+    <string name="input_file_path">/sdcard/test/MediaBenchmarkTest-1.1/</string>
     <string name="output_file_path">/data/local/tmp/MediaBenchmark/output/</string>
 </resources>
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 7af2a90..90b4057 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -146,27 +146,13 @@
         "AudioFlinger.cpp",
         "AudioHwDevice.cpp",
         "AudioStreamOut.cpp",
-        "AudioWatchdog.cpp",
-        "BufLog.cpp",
         "DeviceEffectManager.cpp",
         "Effects.cpp",
-        "FastCapture.cpp",
-        "FastCaptureDumpState.cpp",
-        "FastCaptureState.cpp",
-        "FastMixer.cpp",
-        "FastMixerDumpState.cpp",
-        "FastMixerState.cpp",
-        "FastThread.cpp",
-        "FastThreadDumpState.cpp",
-        "FastThreadState.cpp",
-        "NBAIO_Tee.cpp",
         "PatchPanel.cpp",
         "PropertyUtils.cpp",
         "SpdifStreamOut.cpp",
-        "StateQueue.cpp",
         "Threads.cpp",
         "Tracks.cpp",
-        "TypedLogger.cpp",
     ],
 
     include_dirs: [
@@ -180,7 +166,9 @@
         "av-types-aidl-cpp",
         "effect-aidl-cpp",
         "libaudioclient_aidl_conversion",
+        "libaudioflinger_fastpath",
         "libaudioflinger_timing",
+        "libaudioflinger_utils",
         "libaudiofoundation",
         "libaudiohal",
         "libaudioprocessing",
@@ -208,7 +196,6 @@
 
     static_libs: [
         "libcpustats",
-        "libsndfile",
         "libpermission",
     ],
 
@@ -224,7 +211,6 @@
     ],
 
     cflags: [
-        "-DSTATE_QUEUE_INSTANTIATIONS=\"StateQueueInstantiations.cpp\"",
         "-fvisibility=hidden",
         "-Werror",
         "-Wall",
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 1634051..4f1d554 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -58,7 +58,6 @@
 #include <audiomanager/AudioManager.h>
 
 #include "AudioFlinger.h"
-#include "NBAIO_Tee.h"
 #include "PropertyUtils.h"
 
 #include <media/AudioResamplerPublic.h>
@@ -86,9 +85,8 @@
 #include <private/android_filesystem_config.h>
 
 //#define BUFLOG_NDEBUG 0
-#include <BufLog.h>
-
-#include "TypedLogger.h"
+#include <afutils/BufLog.h>
+#include <afutils/TypedLogger.h>
 
 // ----------------------------------------------------------------------------
 
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index f0858fc..6d422b6 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -78,6 +78,9 @@
 #include <mediautils/Synchronization.h>
 #include <mediautils/ThreadSnapshot.h>
 
+#include <afutils/AudioWatchdog.h>
+#include <afutils/NBAIO_Tee.h>
+
 #include <audio_utils/clock.h>
 #include <audio_utils/FdToString.h>
 #include <audio_utils/LinearMap.h>
@@ -88,14 +91,12 @@
 #include <timing/SyncEvent.h>
 #include <timing/SynchronizedRecordState.h>
 
-#include "FastCapture.h"
-#include "FastMixer.h"
+#include <fastpath/FastCapture.h>
+#include <fastpath/FastMixer.h>
 #include <media/nbaio/NBAIO.h>
-#include "AudioWatchdog.h"
 #include "AudioStreamOut.h"
 #include "SpdifStreamOut.h"
 #include "AudioHwDevice.h"
-#include "NBAIO_Tee.h"
 #include "ThreadMetrics.h"
 #include "TrackMetrics.h"
 
@@ -596,8 +597,6 @@
     };
 
     // --- PlaybackThread ---
-#define EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_FLOAT
-using effect_buffer_t = float;
 
 #include "Threads.h"
 
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 4f39e54..6963bb9 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -867,8 +867,8 @@
     mOutChannelCountRequested =
             audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
 
-    mConfig.inputCfg.format = EFFECT_BUFFER_FORMAT;
-    mConfig.outputCfg.format = EFFECT_BUFFER_FORMAT;
+    mConfig.inputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
+    mConfig.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
 
     // Don't use sample rate for thread if effect isn't offloadable.
     if (callback->isOffloadOrDirect() && !isOffloaded()) {
@@ -2177,7 +2177,7 @@
     if (mInBuffer == NULL) {
         return;
     }
-    const size_t frameSize = audio_bytes_per_sample(EFFECT_BUFFER_FORMAT)
+    const size_t frameSize = audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT)
             * mEffectCallback->inChannelCount(mEffects[0]->id());
 
     memset(mInBuffer->audioBuffer()->raw, 0, mEffectCallback->frameCount() * frameSize);
@@ -2447,7 +2447,8 @@
 
             // make sure the input buffer configuration for the new first effect in the chain
             // is updated if needed (can switch from HAL channel mask to mixer channel mask)
-            if (i == 0 && size > 1) {
+            if (type != EFFECT_FLAG_TYPE_AUXILIARY // TODO(b/284522658) breaks for aux FX, why?
+                    && i == 0 && size > 1) {
                 mEffects[0]->configure();
                 mEffects[0]->setInBuffer(mInBuffer);
                 mEffects[0]->updateAccessMode();      // reconfig if neeeded.
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index e677061..e1a76fc 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -491,14 +491,14 @@
     void setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
         mInBuffer = buffer;
     }
-    effect_buffer_t *inBuffer() const {
-        return mInBuffer != 0 ? reinterpret_cast<effect_buffer_t*>(mInBuffer->ptr()) : NULL;
+    float *inBuffer() const {
+        return mInBuffer != 0 ? reinterpret_cast<float*>(mInBuffer->ptr()) : NULL;
     }
     void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
         mOutBuffer = buffer;
     }
-    effect_buffer_t *outBuffer() const {
-        return mOutBuffer != 0 ? reinterpret_cast<effect_buffer_t*>(mOutBuffer->ptr()) : NULL;
+    float *outBuffer() const {
+        return mOutBuffer != 0 ? reinterpret_cast<float*>(mOutBuffer->ptr()) : NULL;
     }
 
     void incTrackCnt() { android_atomic_inc(&mTrackCnt); }
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index efcd832..78da621 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -116,8 +116,8 @@
             status_t    attachAuxEffect(int EffectId);
             void        setAuxBuffer(int EffectId, int32_t *buffer);
             int32_t     *auxBuffer() const { return mAuxBuffer; }
-            void        setMainBuffer(effect_buffer_t *buffer) { mMainBuffer = buffer; }
-            effect_buffer_t *mainBuffer() const { return mMainBuffer; }
+            void        setMainBuffer(float *buffer) { mMainBuffer = buffer; }
+            float       *mainBuffer() const { return mMainBuffer; }
             int         auxEffectId() const { return mAuxEffectId; }
     virtual status_t    getTimestamp(AudioTimestamp& timestamp);
             void        signal();
@@ -283,7 +283,7 @@
 
     bool                mResetDone;
     const audio_stream_type_t mStreamType;
-    effect_buffer_t     *mMainBuffer;
+    float     *mMainBuffer;
 
     int32_t             *mAuxBuffer;
     int                 mAuxEffectId;
diff --git a/services/audioflinger/StateQueueInstantiations.cpp b/services/audioflinger/StateQueueInstantiations.cpp
deleted file mode 100644
index 6f4505e..0000000
--- a/services/audioflinger/StateQueueInstantiations.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#include "Configuration.h"
-#include "FastMixerState.h"
-#include "FastCaptureState.h"
-#include "StateQueue.h"
-
-// FIXME hack for gcc
-
-namespace android {
-
-template class StateQueue<FastMixerState>;      // typedef FastMixerStateQueue
-template class StateQueue<FastCaptureState>;    // typedef FastCaptureStateQueue
-
-}
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index f35e04a..8c09477 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -74,8 +74,6 @@
 #include <media/audiohal/StreamHalInterface.h>
 
 #include "AudioFlinger.h"
-#include "FastMixer.h"
-#include "FastCapture.h"
 #include <mediautils/SchedulingPolicyService.h>
 #include <mediautils/ServiceUtilities.h>
 
@@ -89,10 +87,10 @@
 #include <cpustats/ThreadCpuUsage.h>
 #endif
 
-#include "AutoPark.h"
+#include <fastpath/AutoPark.h>
 
 #include <pthread.h>
-#include "TypedLogger.h"
+#include <afutils/TypedLogger.h>
 
 // ----------------------------------------------------------------------------
 
@@ -3106,7 +3104,7 @@
     free(mEffectBuffer);
     mEffectBuffer = NULL;
     if (mEffectBufferEnabled) {
-        mEffectBufferFormat = EFFECT_BUFFER_FORMAT;
+        mEffectBufferFormat = AUDIO_FORMAT_PCM_FLOAT;
         mEffectBufferSize = mNormalFrameCount * mixerChannelCount
                 * audio_bytes_per_sample(mEffectBufferFormat);
         (void)posix_memalign(&mEffectBuffer, 32, mEffectBufferSize);
@@ -3500,7 +3498,7 @@
 {
     audio_session_t session = chain->sessionId();
     sp<EffectBufferHalInterface> halInBuffer, halOutBuffer;
-    effect_buffer_t *buffer = nullptr; // only used for non global sessions
+    float *buffer = nullptr; // only used for non global sessions
 
     if (mType == SPATIALIZER) {
         if (!audio_is_global_session(session)) {
@@ -3518,7 +3516,7 @@
             size_t numSamples = mNormalFrameCount
                     * (audio_channel_count_from_out_mask(channelMask) + mHapticChannelCount);
             status_t result = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
-                    numSamples * sizeof(effect_buffer_t),
+                    numSamples * sizeof(float),
                     &halInBuffer);
             if (result != OK) return result;
 
@@ -3557,7 +3555,7 @@
         halOutBuffer = halInBuffer;
         ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
         if (!audio_is_global_session(session)) {
-            buffer = halInBuffer ? reinterpret_cast<effect_buffer_t*>(halInBuffer->externalData())
+            buffer = halInBuffer ? reinterpret_cast<float*>(halInBuffer->externalData())
                                  : buffer;
             // Only one effect chain can be present in direct output thread and it uses
             // the sink buffer as input
@@ -3566,7 +3564,7 @@
                         * (audio_channel_count_from_out_mask(mMixerChannelMask)
                                                              + mHapticChannelCount);
                 const status_t allocateStatus = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
-                        numSamples * sizeof(effect_buffer_t),
+                        numSamples * sizeof(float),
                         &halInBuffer);
                 if (allocateStatus != OK) return allocateStatus;
 
@@ -3654,7 +3652,7 @@
             for (size_t j = 0; j < mTracks.size(); ++j) {
                 sp<Track> track = mTracks[j];
                 if (session == track->sessionId()) {
-                    track->setMainBuffer(reinterpret_cast<effect_buffer_t*>(mSinkBuffer));
+                    track->setMainBuffer(reinterpret_cast<float*>(mSinkBuffer));
                     chain->decTrackCnt();
                 }
             }
@@ -3707,7 +3705,7 @@
 bool AudioFlinger::PlaybackThread::threadLoop()
 NO_THREAD_SAFETY_ANALYSIS  // manual locking of AudioFlinger
 {
-    tlNBLogWriter = mNBLogWriter.get();
+    aflog::setThreadWriter(mNBLogWriter.get());
 
     Vector< sp<Track> > tracksToRemove;
 
@@ -4059,12 +4057,12 @@
 
                         const size_t audioBufferSize = mNormalFrameCount
                             * audio_bytes_per_frame(hapticSessionChannelCount,
-                                                    EFFECT_BUFFER_FORMAT);
+                                                    AUDIO_FORMAT_PCM_FLOAT);
                         memcpy_by_audio_format(
                                 (uint8_t*)effectChains[i]->outBuffer() + audioBufferSize,
-                                EFFECT_BUFFER_FORMAT,
+                                AUDIO_FORMAT_PCM_FLOAT,
                                 (const uint8_t*)effectChains[i]->inBuffer() + audioBufferSize,
-                                EFFECT_BUFFER_FORMAT, mNormalFrameCount * mHapticChannelCount);
+                                AUDIO_FORMAT_PCM_FLOAT, mNormalFrameCount * mHapticChannelCount);
                     }
                 }
             }
@@ -4552,7 +4550,8 @@
     if ((mOutput->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) != 0) {
         if (*volume != mLeftVolFloat) {
             result = mOutput->stream->setVolume(*volume, *volume);
-            ALOGE_IF(result != OK,
+            // HAL can return INVALID_OPERATION if operation is not supported.
+            ALOGE_IF(result != OK && result != INVALID_OPERATION,
                      "Error when setting output stream volume: %d", result);
             if (result == NO_ERROR) {
                 mLeftVolFloat = *volume;
@@ -5706,7 +5705,7 @@
                 mAudioMixer->setParameter(
                         trackId,
                         AudioMixer::TRACK,
-                        AudioMixer::MIXER_FORMAT, (void *)EFFECT_BUFFER_FORMAT);
+                        AudioMixer::MIXER_FORMAT, (void *)AUDIO_FORMAT_PCM_FLOAT);
                 mAudioMixer->setParameter(
                         trackId,
                         AudioMixer::TRACK,
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 0094a9f..45a4a95 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1002,8 +1002,8 @@
                 status_t    getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
                 // Consider also removing and passing an explicit mMainBuffer initialization
                 // parameter to AF::PlaybackThread::Track::Track().
-                effect_buffer_t *sinkBuffer() const {
-                    return reinterpret_cast<effect_buffer_t *>(mSinkBuffer); };
+                float *sinkBuffer() const {
+                    return reinterpret_cast<float *>(mSinkBuffer); };
 
     virtual     void detachAuxEffect_l(int effectId);
                 status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track>& track,
diff --git a/services/audioflinger/TypedLogger.cpp b/services/audioflinger/TypedLogger.cpp
deleted file mode 100644
index 57c206b..0000000
--- a/services/audioflinger/TypedLogger.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *
- * Copyright 2017, 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.
- */
-
-#define LOG_TAG "AudioFlinger"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include <pthread.h>
-#include "TypedLogger.h"
-
-namespace android {
-thread_local NBLog::Writer *tlNBLogWriter;
-}
diff --git a/services/audioflinger/afutils/Android.bp b/services/audioflinger/afutils/Android.bp
new file mode 100644
index 0000000..4309bf5
--- /dev/null
+++ b/services/audioflinger/afutils/Android.bp
@@ -0,0 +1,40 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
+}
+
+cc_library {
+    name: "libaudioflinger_utils",
+
+    defaults: [
+        "audioflinger_flags_defaults",
+    ],
+
+    srcs: [
+        "AudioWatchdog.cpp",
+        "BufLog.cpp",
+        "NBAIO_Tee.cpp",
+        "TypedLogger.cpp",
+    ],
+
+    shared_libs: [
+        "libaudioutils",
+        "libbase",
+        "liblog",
+        "libnbaio",
+        "libnblog",
+        "libutils",
+    ],
+
+    static_libs: [
+        "libsndfile",
+    ],
+
+    include_dirs: [
+        "frameworks/av/services/audioflinger",  // for configuration
+    ],
+}
diff --git a/services/audioflinger/AudioWatchdog.cpp b/services/audioflinger/afutils/AudioWatchdog.cpp
similarity index 100%
rename from services/audioflinger/AudioWatchdog.cpp
rename to services/audioflinger/afutils/AudioWatchdog.cpp
diff --git a/services/audioflinger/AudioWatchdog.h b/services/audioflinger/afutils/AudioWatchdog.h
similarity index 100%
rename from services/audioflinger/AudioWatchdog.h
rename to services/audioflinger/afutils/AudioWatchdog.h
diff --git a/services/audioflinger/BufLog.cpp b/services/audioflinger/afutils/BufLog.cpp
similarity index 100%
rename from services/audioflinger/BufLog.cpp
rename to services/audioflinger/afutils/BufLog.cpp
diff --git a/services/audioflinger/BufLog.h b/services/audioflinger/afutils/BufLog.h
similarity index 100%
rename from services/audioflinger/BufLog.h
rename to services/audioflinger/afutils/BufLog.h
diff --git a/services/audioflinger/NBAIO_Tee.cpp b/services/audioflinger/afutils/NBAIO_Tee.cpp
similarity index 100%
rename from services/audioflinger/NBAIO_Tee.cpp
rename to services/audioflinger/afutils/NBAIO_Tee.cpp
diff --git a/services/audioflinger/NBAIO_Tee.h b/services/audioflinger/afutils/NBAIO_Tee.h
similarity index 100%
rename from services/audioflinger/NBAIO_Tee.h
rename to services/audioflinger/afutils/NBAIO_Tee.h
diff --git a/services/audioflinger/afutils/TypedLogger.cpp b/services/audioflinger/afutils/TypedLogger.cpp
new file mode 100644
index 0000000..7c546a5
--- /dev/null
+++ b/services/audioflinger/afutils/TypedLogger.cpp
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright 2017, 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.
+ */
+
+#define LOG_TAG "AudioFlinger"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <pthread.h>
+#include "TypedLogger.h"
+
+namespace android::aflog {
+
+// External linkage access of thread local storage outside of this shared library
+// causes orphaned memory allocations.  This occurs in the implementation of
+// __emutls_get_address(), see b/284657986.
+//
+// We only expose a thread local storage getter and setter here, not the
+// actual thread local variable.
+
+namespace {
+thread_local NBLog::Writer *tlNBLogWriter;
+} // namespace
+
+NBLog::Writer *getThreadWriter() {
+    return tlNBLogWriter;
+}
+
+void setThreadWriter(NBLog::Writer *writer) {
+    tlNBLogWriter = writer;
+}
+
+} // namespace android::aflog
diff --git a/services/audioflinger/TypedLogger.h b/services/audioflinger/afutils/TypedLogger.h
similarity index 79%
rename from services/audioflinger/TypedLogger.h
rename to services/audioflinger/afutils/TypedLogger.h
index feb71e3..f34a50c 100644
--- a/services/audioflinger/TypedLogger.h
+++ b/services/audioflinger/afutils/TypedLogger.h
@@ -85,56 +85,57 @@
 //      slower than nullptr check when logging is enabled at compile-time and disabled at runtime.
 
 // Write formatted entry to log
-#define LOGT(fmt, ...) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOGT(fmt, ...) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
                                 x->logFormat((fmt), hash(__FILE__, __LINE__), ##__VA_ARGS__); } \
                                 while (0)
 
 // Write histogram timestamp entry
-#define LOG_HIST_TS() do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_HIST_TS() do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
         x->logEventHistTs(NBLog::EVENT_HISTOGRAM_ENTRY_TS, hash(__FILE__, __LINE__)); } while(0)
 
 // Record that audio was turned on/off
-#define LOG_AUDIO_STATE() do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_AUDIO_STATE() do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
         x->logEventHistTs(NBLog::EVENT_AUDIO_STATE, hash(__FILE__, __LINE__)); } while(0)
 
 // Log the difference bewteen frames presented by HAL and frames written to HAL output sink,
 // divided by the sample rate. Parameter ms is of type double.
-#define LOG_LATENCY(ms) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_LATENCY(ms) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
         x->log<NBLog::EVENT_LATENCY>(ms); } while (0)
 
 // Record thread overrun event nanosecond timestamp. Parameter ns is an int64_t.
-#define LOG_OVERRUN(ns) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_OVERRUN(ns) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
         x->log<NBLog::EVENT_OVERRUN>(ns); } while (0)
 
 // Record thread info. This currently includes type, frameCount, and sampleRate.
 // Parameter type is thread_info_t as defined in NBLog.h.
-#define LOG_THREAD_INFO(info) do { NBLog::Writer *x = tlNBLogWriter; \
+#define LOG_THREAD_INFO(info) do { NBLog::Writer *x = aflog::getThreadWriter(); \
         if (x != nullptr) x->log<NBLog::EVENT_THREAD_INFO>(info); } while (0)
 
-#define LOG_THREAD_PARAMS(params) do {NBLog::Writer *x = tlNBLogWriter; \
+#define LOG_THREAD_PARAMS(params) do {NBLog::Writer *x = aflog::getThreadWriter(); \
         if (x != nullptr) x->log<NBLog::EVENT_THREAD_PARAMS>(params); } while (0)
 
 // Record thread underrun event nanosecond timestamp. Parameter ns is an int64_t.
-#define LOG_UNDERRUN(ns) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_UNDERRUN(ns) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
         x->log<NBLog::EVENT_UNDERRUN>(ns); } while (0)
 
 // Record thread warmup time in milliseconds. Parameter ms is of type double.
-#define LOG_WARMUP_TIME(ms) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_WARMUP_TIME(ms) do { \
+        NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
         x->log<NBLog::EVENT_WARMUP_TIME>(ms); } while (0)
 
 // Record a typed entry that represents a thread's work time in nanoseconds.
 // Parameter ns should be of type uint32_t.
-#define LOG_WORK_TIME(ns) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_WORK_TIME(ns) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
         x->log<NBLog::EVENT_WORK_TIME>(ns); } while (0)
 
-namespace android {
-extern "C" {
+namespace android::aflog {
 // TODO consider adding a thread_local NBLog::Writer tlStubNBLogWriter and then
-// initialize below tlNBLogWriter to &tlStubNBLogWriter to remove the need to
+// initialize setThreadWriter() to &tlStubNBLogWriter to remove the need to
 // check for nullptr every time. Also reduces the need to add a new logging macro above
 // each time we want to log a new type.
-extern thread_local NBLog::Writer *tlNBLogWriter;
-}
-} // namespace android
+
+NBLog::Writer *getThreadWriter();
+void setThreadWriter(NBLog::Writer *writer);
+} // namespace android::aflog
 
 #endif // ANDROID_TYPED_LOGGER_H
diff --git a/services/audioflinger/fastpath/Android.bp b/services/audioflinger/fastpath/Android.bp
new file mode 100644
index 0000000..10f1af9
--- /dev/null
+++ b/services/audioflinger/fastpath/Android.bp
@@ -0,0 +1,161 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
+}
+
+fastpath_tidy_errors = [
+    // https://clang.llvm.org/extra/clang-tidy/checks/list.html
+    // For many categories, the checks are too many to specify individually.
+    // Feel free to disable as needed - as warnings are generally ignored,
+    // we treat warnings as errors.
+    "android-*",
+    "bugprone-*",
+    "cert-*",
+    "clang-analyzer-security*",
+    "google-*",
+    "misc-*",
+    //"modernize-*",  // explicitly list the modernize as they can be subjective.
+    "modernize-avoid-bind",
+    //"modernize-avoid-c-arrays", // std::array<> can be verbose
+    "modernize-concat-nested-namespaces",
+    //"modernize-deprecated-headers", // C headers still ok even if there is C++ equivalent.
+    "modernize-deprecated-ios-base-aliases",
+    "modernize-loop-convert",
+    "modernize-make-shared",
+    "modernize-make-unique",
+    // "modernize-pass-by-value",
+    "modernize-raw-string-literal",
+    "modernize-redundant-void-arg",
+    "modernize-replace-auto-ptr",
+    "modernize-replace-random-shuffle",
+    "modernize-return-braced-init-list",
+    "modernize-shrink-to-fit",
+    "modernize-unary-static-assert",
+    // "modernize-use-auto",  // found in MediaMetricsService.h, debatable - auto can obscure type
+    "modernize-use-bool-literals",
+    "modernize-use-default-member-init",
+    "modernize-use-emplace",
+    "modernize-use-equals-default",
+    "modernize-use-equals-delete",
+    // "modernize-use-nodiscard",
+    "modernize-use-noexcept",
+    "modernize-use-nullptr",
+    "modernize-use-override",
+    //"modernize-use-trailing-return-type", // not necessarily more readable
+    "modernize-use-transparent-functors",
+    "modernize-use-uncaught-exceptions",
+    "modernize-use-using",
+    "performance-*",
+
+    // Remove some pedantic stylistic requirements.
+    "-google-readability-casting", // C++ casts not always necessary and may be verbose
+    "-google-readability-todo",    // do not require TODO(info)
+
+    "-bugprone-unhandled-self-assignment",
+    "-bugprone-suspicious-string-compare",
+    "-cert-oop54-cpp", // found in TransactionLog.h
+    "-bugprone-narrowing-conversions", // b/182410845
+
+    // TODO(b/275642749) Reenable these warnings
+    "-bugprone-assignment-in-if-condition",
+    "-bugprone-forward-declaration-namespace",
+    "-bugprone-parent-virtual-call",
+    "-cert-dcl59-cpp",
+    "-cert-err34-c",
+    "-google-runtime-int",
+    "-misc-non-private-member-variables-in-classes",
+    "-modernize-concat-nested-namespaces",
+    "-modernize-loop-convert",
+    "-modernize-use-default-member-init",
+    "-performance-no-int-to-ptr",
+]
+
+// Eventually use common tidy defaults
+cc_defaults {
+    name: "fastpath_flags_defaults",
+    // https://clang.llvm.org/docs/UsersManual.html#command-line-options
+    // https://clang.llvm.org/docs/DiagnosticsReference.html
+    cflags: [
+        "-Wall",
+        "-Wdeprecated",
+        "-Werror",
+        "-Werror=implicit-fallthrough",
+        "-Werror=sometimes-uninitialized",
+        "-Werror=conditional-uninitialized",
+        "-Wextra",
+
+        // suppress some warning chatter.
+        "-Wno-deprecated-copy-with-dtor",
+        "-Wno-deprecated-copy-with-user-provided-dtor",
+
+        "-Wredundant-decls",
+        "-Wshadow",
+        "-Wstrict-aliasing",
+        "-fstrict-aliasing",
+        "-Wthread-safety",
+        //"-Wthread-safety-negative", // experimental - looks broken in R.
+        "-Wunreachable-code",
+        "-Wunreachable-code-break",
+        "-Wunreachable-code-return",
+        "-Wunused",
+        "-Wused-but-marked-unused",
+        "-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS",
+    ],
+    // https://clang.llvm.org/extra/clang-tidy/
+    tidy: true,
+    tidy_checks: fastpath_tidy_errors,
+    tidy_checks_as_errors: fastpath_tidy_errors,
+    tidy_flags: [
+      "-format-style=file",
+    ],
+}
+
+cc_library_shared {
+    name: "libaudioflinger_fastpath",
+
+    defaults: [
+        "fastpath_flags_defaults",
+    ],
+
+    srcs: [
+        "FastCapture.cpp",
+        "FastCaptureDumpState.cpp",
+        "FastCaptureState.cpp",
+        "FastMixer.cpp",
+        "FastMixerDumpState.cpp",
+        "FastMixerState.cpp",
+        "FastThread.cpp",
+        "FastThreadDumpState.cpp",
+        "FastThreadState.cpp",
+        "StateQueue.cpp",
+    ],
+
+    include_dirs: [
+        "frameworks/av/services/audioflinger", // for Configuration
+    ],
+
+    shared_libs: [
+        "libaudioflinger_utils", // NBAIO_Tee
+        "libaudioprocessing",
+        "libaudioutils",
+        "libcutils",
+        "liblog",
+        "libnbaio",
+        "libnblog", // legacy NBLog that can be removed.
+        "libutils",
+    ],
+
+    header_libs: [
+        "libaudiohal_headers",
+        "libmedia_headers",
+    ],
+
+    sanitize: {
+        integer_overflow: true,
+    },
+
+}
diff --git a/services/audioflinger/AutoPark.h b/services/audioflinger/fastpath/AutoPark.h
similarity index 99%
rename from services/audioflinger/AutoPark.h
rename to services/audioflinger/fastpath/AutoPark.h
index 83f6b7d..6e68327 100644
--- a/services/audioflinger/AutoPark.h
+++ b/services/audioflinger/fastpath/AutoPark.h
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#pragma once
+
 namespace android {
 
 // T is FastMixer or FastCapture
diff --git a/services/audioflinger/FastCapture.cpp b/services/audioflinger/fastpath/FastCapture.cpp
similarity index 86%
rename from services/audioflinger/FastCapture.cpp
rename to services/audioflinger/fastpath/FastCapture.cpp
index 2963202..5c76649 100644
--- a/services/audioflinger/FastCapture.cpp
+++ b/services/audioflinger/fastpath/FastCapture.cpp
@@ -33,8 +33,8 @@
 /*static*/ const FastCaptureState FastCapture::sInitial;
 
 FastCapture::FastCapture() : FastThread("cycleC_ms", "loadC_us"),
-    mInputSource(NULL), mInputSourceGen(0), mPipeSink(NULL), mPipeSinkGen(0),
-    mReadBuffer(NULL), mReadBufferState(-1), mFormat(Format_Invalid), mSampleRate(0),
+    mInputSource(nullptr), mInputSourceGen(0), mPipeSink(nullptr), mPipeSinkGen(0),
+    mReadBuffer(nullptr), mReadBufferState(-1), mFormat(Format_Invalid), mSampleRate(0),
     // mDummyDumpState
     mTotalNativeFramesRead(0)
 {
@@ -44,10 +44,6 @@
     mDummyDumpState = &mDummyFastCaptureDumpState;
 }
 
-FastCapture::~FastCapture()
-{
-}
-
 FastCaptureStateQueue* FastCapture::sq()
 {
     return &mSQ;
@@ -95,11 +91,11 @@
     bool eitherChanged = false;
 
     // check for change in input HAL configuration
-    NBAIO_Format previousFormat = mFormat;
+    const NBAIO_Format previousFormat = mFormat;
     if (current->mInputSourceGen != mInputSourceGen) {
         mInputSource = current->mInputSource;
         mInputSourceGen = current->mInputSourceGen;
-        if (mInputSource == NULL) {
+        if (mInputSource == nullptr) {
             mFormat = Format_Invalid;
             mSampleRate = 0;
         } else {
@@ -122,19 +118,19 @@
     }
 
     // input source and pipe sink must be compatible
-    if (eitherChanged && mInputSource != NULL && mPipeSink != NULL) {
+    if (eitherChanged && mInputSource != nullptr && mPipeSink != nullptr) {
         ALOG_ASSERT(Format_isEqual(mFormat, mPipeSink->format()));
     }
 
     if ((!Format_isEqual(mFormat, previousFormat)) || (frameCount != previous->mFrameCount)) {
         // FIXME to avoid priority inversion, don't free here
         free(mReadBuffer);
-        mReadBuffer = NULL;
+        mReadBuffer = nullptr;
         if (frameCount > 0 && mSampleRate > 0) {
             // FIXME new may block for unbounded time at internal mutex of the heap
             //       implementation; it would be better to have normal capture thread allocate for
             //       us to avoid blocking here and to prevent possible priority inversion
-            size_t bufferSize = frameCount * Format_frameSize(mFormat);
+            const size_t bufferSize = frameCount * Format_frameSize(mFormat);
             (void)posix_memalign(&mReadBuffer, 32, bufferSize);
             memset(mReadBuffer, 0, bufferSize); // if posix_memalign fails, will segv here.
             mPeriodNs = (frameCount * 1000000000LL) / mSampleRate;      // 1.00
@@ -166,9 +162,9 @@
     AudioBufferProvider* fastPatchRecordBufferProvider = current->mFastPatchRecordBufferProvider;
     AudioBufferProvider::Buffer patchBuffer;
 
-    if (fastPatchRecordBufferProvider != 0) {
+    if (fastPatchRecordBufferProvider != nullptr) {
         patchBuffer.frameCount = ~0;
-        status_t status = fastPatchRecordBufferProvider->getNextBuffer(&patchBuffer);
+        const status_t status = fastPatchRecordBufferProvider->getNextBuffer(&patchBuffer);
         if (status != NO_ERROR) {
             frameCount = 0;
         } else if (patchBuffer.frameCount < frameCount) {
@@ -179,11 +175,11 @@
     }
 
     if ((command & FastCaptureState::READ) /*&& isWarm*/) {
-        ALOG_ASSERT(mInputSource != NULL);
-        ALOG_ASSERT(mReadBuffer != NULL);
+        ALOG_ASSERT(mInputSource != nullptr);
+        ALOG_ASSERT(mReadBuffer != nullptr);
         dumpState->mReadSequence++;
         ATRACE_BEGIN("read");
-        ssize_t framesRead = mInputSource->read(mReadBuffer, frameCount);
+        const ssize_t framesRead = mInputSource->read(mReadBuffer, frameCount);
         ATRACE_END();
         dumpState->mReadSequence++;
         if (framesRead >= 0) {
@@ -201,8 +197,8 @@
     }
 
     if (command & FastCaptureState::WRITE) {
-        ALOG_ASSERT(mPipeSink != NULL);
-        ALOG_ASSERT(mReadBuffer != NULL);
+        ALOG_ASSERT(mPipeSink != nullptr);
+        ALOG_ASSERT(mReadBuffer != nullptr);
         if (mReadBufferState < 0) {
             memset(mReadBuffer, 0, frameCount * Format_frameSize(mFormat));
             mReadBufferState = frameCount;
@@ -211,23 +207,23 @@
             if (current->mSilenceCapture) {
                 memset(mReadBuffer, 0, mReadBufferState * Format_frameSize(mFormat));
             }
-            ssize_t framesWritten = mPipeSink->write(mReadBuffer, mReadBufferState);
+            const ssize_t framesWritten = mPipeSink->write(mReadBuffer, mReadBufferState);
             audio_track_cblk_t* cblk = current->mCblk;
-            if (fastPatchRecordBufferProvider != 0) {
+            if (fastPatchRecordBufferProvider != nullptr) {
                 // This indicates the fast track is a patch record, update the cblk by
                 // calling releaseBuffer().
                 memcpy_by_audio_format(patchBuffer.raw, current->mFastPatchRecordFormat,
                         mReadBuffer, mFormat.mFormat, framesWritten * mFormat.mChannelCount);
                 patchBuffer.frameCount = framesWritten;
                 fastPatchRecordBufferProvider->releaseBuffer(&patchBuffer);
-            } else if (cblk != NULL && framesWritten > 0) {
+            } else if (cblk != nullptr && framesWritten > 0) {
                 // FIXME This supports at most one fast capture client.
                 //       To handle multiple clients this could be converted to an array,
                 //       or with a lot more work the control block could be shared by all clients.
-                int32_t rear = cblk->u.mStreaming.mRear;
+                const int32_t rear = cblk->u.mStreaming.mRear;
                 android_atomic_release_store(framesWritten + rear, &cblk->u.mStreaming.mRear);
                 cblk->mServer += framesWritten;
-                int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
+                const int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
                 if (!(old & CBLK_FUTEX_WAKE)) {
                     // client is never in server process, so don't use FUTEX_WAKE_PRIVATE
                     (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, 1);
diff --git a/services/audioflinger/FastCapture.h b/services/audioflinger/fastpath/FastCapture.h
similarity index 77%
rename from services/audioflinger/FastCapture.h
rename to services/audioflinger/fastpath/FastCapture.h
index c3817c0..657a324 100644
--- a/services/audioflinger/FastCapture.h
+++ b/services/audioflinger/fastpath/FastCapture.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_FAST_CAPTURE_H
-#define ANDROID_AUDIO_FAST_CAPTURE_H
+#pragma once
 
 #include "FastThread.h"
 #include "StateQueue.h"
@@ -24,13 +23,12 @@
 
 namespace android {
 
-typedef StateQueue<FastCaptureState> FastCaptureStateQueue;
+using FastCaptureStateQueue = StateQueue<FastCaptureState>;
 
 class FastCapture : public FastThread {
 
 public:
             FastCapture();
-    virtual ~FastCapture();
 
             FastCaptureStateQueue*  sq();
 
@@ -38,13 +36,13 @@
             FastCaptureStateQueue   mSQ;
 
     // callouts
-    virtual const FastThreadState *poll();
-    virtual void setNBLogWriter(NBLog::Writer *logWriter);
-    virtual void onIdle();
-    virtual void onExit();
-    virtual bool isSubClassCommand(FastThreadState::Command command);
-    virtual void onStateChange();
-    virtual void onWork();
+    const FastThreadState *poll() override;
+    void setNBLogWriter(NBLog::Writer *logWriter) override;
+    void onIdle() override;
+    void onExit() override;
+    bool isSubClassCommand(FastThreadState::Command command) override;
+    void onStateChange() override;
+    void onWork() override;
 
     static const FastCaptureState sInitial;
 
@@ -65,5 +63,3 @@
 };  // class FastCapture
 
 }   // namespace android
-
-#endif  // ANDROID_AUDIO_FAST_CAPTURE_H
diff --git a/services/audioflinger/FastCaptureDumpState.cpp b/services/audioflinger/fastpath/FastCaptureDumpState.cpp
similarity index 90%
rename from services/audioflinger/FastCaptureDumpState.cpp
rename to services/audioflinger/fastpath/FastCaptureDumpState.cpp
index 243dfa5..e0ac9cc 100644
--- a/services/audioflinger/FastCaptureDumpState.cpp
+++ b/services/audioflinger/fastpath/FastCaptureDumpState.cpp
@@ -29,19 +29,15 @@
 {
 }
 
-FastCaptureDumpState::~FastCaptureDumpState()
-{
-}
-
 void FastCaptureDumpState::dump(int fd) const
 {
     if (mCommand == FastCaptureState::INITIAL) {
         dprintf(fd, "  FastCapture not initialized\n");
         return;
     }
-    double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
+    const double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
             (mMeasuredWarmupTs.tv_nsec / 1000000.0);
-    double periodSec = (double) mFrameCount / mSampleRate;
+    const double periodSec = (double) mFrameCount / mSampleRate;
     dprintf(fd, "  FastCapture command=%s readSequence=%u framesRead=%u\n"
                 "              readErrors=%u sampleRate=%u frameCount=%zu\n"
                 "              measuredWarmup=%.3g ms, warmupCycles=%u period=%.2f ms\n"
diff --git a/services/audioflinger/FastCaptureDumpState.h b/services/audioflinger/fastpath/FastCaptureDumpState.h
similarity index 87%
rename from services/audioflinger/FastCaptureDumpState.h
rename to services/audioflinger/fastpath/FastCaptureDumpState.h
index 34ce456..e205518 100644
--- a/services/audioflinger/FastCaptureDumpState.h
+++ b/services/audioflinger/fastpath/FastCaptureDumpState.h
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
-#define ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
+#pragma once
 
 #include <stdint.h>
+#include <type_traits>
 #include "Configuration.h"
 #include "FastThreadDumpState.h"
 
@@ -25,7 +25,6 @@
 
 struct FastCaptureDumpState : FastThreadDumpState {
     FastCaptureDumpState();
-    /*virtual*/ ~FastCaptureDumpState();
 
     void dump(int fd) const;    // should only be called on a stable copy, not the original
 
@@ -38,6 +37,7 @@
     bool     mSilenced = false; // capture is silenced
 };
 
-}  // namespace android
+// No virtuals
+static_assert(!std::is_polymorphic_v<FastCaptureDumpState>);
 
-#endif  // ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
+}  // namespace android
diff --git a/services/audioflinger/FastCaptureState.cpp b/services/audioflinger/fastpath/FastCaptureState.cpp
similarity index 87%
rename from services/audioflinger/FastCaptureState.cpp
rename to services/audioflinger/fastpath/FastCaptureState.cpp
index 918ba9c..d2df62a 100644
--- a/services/audioflinger/FastCaptureState.cpp
+++ b/services/audioflinger/fastpath/FastCaptureState.cpp
@@ -19,11 +19,7 @@
 namespace android {
 
 FastCaptureState::FastCaptureState() : FastThreadState(),
-    mInputSource(NULL), mInputSourceGen(0), mPipeSink(NULL), mPipeSinkGen(0), mFrameCount(0)
-{
-}
-
-FastCaptureState::~FastCaptureState()
+    mInputSource(nullptr), mInputSourceGen(0), mPipeSink(nullptr), mPipeSinkGen(0), mFrameCount(0)
 {
 }
 
@@ -31,7 +27,7 @@
 const char *FastCaptureState::commandToString(Command command)
 {
     const char *str = FastThreadState::commandToString(command);
-    if (str != NULL) {
+    if (str != nullptr) {
         return str;
     }
     switch (command) {
diff --git a/services/audioflinger/FastCaptureState.h b/services/audioflinger/fastpath/FastCaptureState.h
similarity index 93%
rename from services/audioflinger/FastCaptureState.h
rename to services/audioflinger/fastpath/FastCaptureState.h
index f949275..82ea0ed 100644
--- a/services/audioflinger/FastCaptureState.h
+++ b/services/audioflinger/fastpath/FastCaptureState.h
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_FAST_CAPTURE_STATE_H
-#define ANDROID_AUDIO_FAST_CAPTURE_STATE_H
+#pragma once
 
+#include <type_traits>
 #include <media/nbaio/NBAIO.h>
 #include <media/AudioBufferProvider.h>
 #include "FastThreadState.h"
@@ -27,7 +27,6 @@
 // Represent a single state of the fast capture
 struct FastCaptureState : FastThreadState {
                 FastCaptureState();
-    /*virtual*/ ~FastCaptureState();
 
     // all pointer fields use raw pointers; objects are owned and ref-counted by RecordThread
     NBAIO_Source*   mInputSource;       // HAL input device, must already be negotiated
@@ -55,6 +54,7 @@
     static const char *commandToString(Command command);
 };  // struct FastCaptureState
 
-}   // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastCaptureState>);
 
-#endif  // ANDROID_AUDIO_FAST_CAPTURE_STATE_H
+}   // namespace android
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/fastpath/FastMixer.cpp
similarity index 94%
rename from services/audioflinger/FastMixer.cpp
rename to services/audioflinger/fastpath/FastMixer.cpp
index 61dd3f2..e13adab 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/fastpath/FastMixer.cpp
@@ -42,7 +42,7 @@
 #include <cutils/bitops.h>
 #include <media/AudioMixer.h>
 #include "FastMixer.h"
-#include "TypedLogger.h"
+#include <afutils/TypedLogger.h>
 
 namespace android {
 
@@ -61,13 +61,13 @@
     : FastThread("cycle_ms", "load_us"),
     // mFastTrackNames
     // mGenerations
-    mOutputSink(NULL),
+    mOutputSink(nullptr),
     mOutputSinkGen(0),
-    mMixer(NULL),
-    mSinkBuffer(NULL),
+    mMixer(nullptr),
+    mSinkBuffer(nullptr),
     mSinkBufferSize(0),
     mSinkChannelCount(FCC_2),
-    mMixerBuffer(NULL),
+    mMixerBuffer(nullptr),
     mMixerBufferSize(0),
     mMixerBufferState(UNDEFINED),
     mFormat(Format_Invalid),
@@ -99,10 +99,6 @@
 #endif
 }
 
-FastMixer::~FastMixer()
-{
-}
-
 FastMixerStateQueue* FastMixer::sq()
 {
     return &mSQ;
@@ -229,13 +225,13 @@
     unsigned previousTrackMask;
 
     // check for change in output HAL configuration
-    NBAIO_Format previousFormat = mFormat;
+    const NBAIO_Format previousFormat = mFormat;
     if (current->mOutputSinkGen != mOutputSinkGen) {
         mOutputSink = current->mOutputSink;
         mOutputSinkGen = current->mOutputSinkGen;
         mSinkChannelMask = current->mSinkChannelMask;
         mBalance.setChannelMask(mSinkChannelMask);
-        if (mOutputSink == NULL) {
+        if (mOutputSink == nullptr) {
             mFormat = Format_Invalid;
             mSampleRate = 0;
             mSinkChannelCount = 0;
@@ -259,11 +255,11 @@
     if ((!Format_isEqual(mFormat, previousFormat)) || (frameCount != previous->mFrameCount)) {
         // FIXME to avoid priority inversion, don't delete here
         delete mMixer;
-        mMixer = NULL;
+        mMixer = nullptr;
         free(mMixerBuffer);
-        mMixerBuffer = NULL;
+        mMixerBuffer = nullptr;
         free(mSinkBuffer);
-        mSinkBuffer = NULL;
+        mSinkBuffer = nullptr;
         if (frameCount > 0 && mSampleRate > 0) {
             // FIXME new may block for unbounded time at internal mutex of the heap
             //       implementation; it would be better to have normal mixer allocate for us
@@ -320,7 +316,7 @@
         // process removed tracks first to avoid running out of track names
         unsigned removedTracks = previousTrackMask & ~currentTrackMask;
         while (removedTracks != 0) {
-            int i = __builtin_ctz(removedTracks);
+            const int i = __builtin_ctz(removedTracks);
             removedTracks &= ~(1 << i);
             updateMixerTrack(i, REASON_REMOVE);
             // don't reset track dump state, since other side is ignoring it
@@ -329,7 +325,7 @@
         // now process added tracks
         unsigned addedTracks = currentTrackMask & ~previousTrackMask;
         while (addedTracks != 0) {
-            int i = __builtin_ctz(addedTracks);
+            const int i = __builtin_ctz(addedTracks);
             addedTracks &= ~(1 << i);
             updateMixerTrack(i, REASON_ADD);
         }
@@ -338,7 +334,7 @@
         // but may have a different buffer provider or volume provider
         unsigned modifiedTracks = currentTrackMask & previousTrackMask;
         while (modifiedTracks != 0) {
-            int i = __builtin_ctz(modifiedTracks);
+            const int i = __builtin_ctz(modifiedTracks);
             modifiedTracks &= ~(1 << i);
             updateMixerTrack(i, REASON_MODIFY);
         }
@@ -373,8 +369,8 @@
     const FastMixerState::Command command = mCommand;
     const size_t frameCount = current->mFrameCount;
 
-    if ((command & FastMixerState::MIX) && (mMixer != NULL) && mIsWarm) {
-        ALOG_ASSERT(mMixerBuffer != NULL);
+    if ((command & FastMixerState::MIX) && (mMixer != nullptr) && mIsWarm) {
+        ALOG_ASSERT(mMixerBuffer != nullptr);
 
         // AudioMixer::mState.enabledTracks is undefined if mState.hook == process__validate,
         // so we keep a side copy of enabledTracks
@@ -383,7 +379,7 @@
         // for each track, update volume and check for underrun
         unsigned currentTrackMask = current->mTrackMask;
         while (currentTrackMask != 0) {
-            int i = __builtin_ctz(currentTrackMask);
+            const int i = __builtin_ctz(currentTrackMask);
             currentTrackMask &= ~(1 << i);
             const FastTrack* fastTrack = &current->mFastTracks[i];
 
@@ -406,8 +402,8 @@
             fastTrack->mBufferProvider->onTimestamp(perTrackTimestamp);
 
             const int name = i;
-            if (fastTrack->mVolumeProvider != NULL) {
-                gain_minifloat_packed_t vlr = fastTrack->mVolumeProvider->getVolumeLR();
+            if (fastTrack->mVolumeProvider != nullptr) {
+                const gain_minifloat_packed_t vlr = fastTrack->mVolumeProvider->getVolumeLR();
                 float vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
                 float vrf = float_from_gain(gain_minifloat_unpack_right(vlr));
 
@@ -418,7 +414,7 @@
             // takes a tryLock, which can block
             // up to 1 ms.  If enough active tracks all blocked in sequence, this would result
             // in the overall fast mix cycle being delayed.  Should use a non-blocking FIFO.
-            size_t framesReady = fastTrack->mBufferProvider->framesReady();
+            const size_t framesReady = fastTrack->mBufferProvider->framesReady();
             if (ATRACE_ENABLED()) {
                 // I wish we had formatted trace names
                 char traceName[16];
@@ -464,7 +460,8 @@
         mMixerBufferState = UNDEFINED;
     }
     //bool didFullWrite = false;    // dumpsys could display a count of partial writes
-    if ((command & FastMixerState::WRITE) && (mOutputSink != NULL) && (mMixerBuffer != NULL)) {
+    if ((command & FastMixerState::WRITE)
+            && (mOutputSink != nullptr) && (mMixerBuffer != nullptr)) {
         if (mMixerBufferState == UNDEFINED) {
             memset(mMixerBuffer, 0, mMixerBufferSize);
             mMixerBufferState = ZEROED;
@@ -481,7 +478,7 @@
         mBalance.process((float *)mMixerBuffer, frameCount);
 
         // prepare the buffer used to write to sink
-        void *buffer = mSinkBuffer != NULL ? mSinkBuffer : mMixerBuffer;
+        void *buffer = mSinkBuffer != nullptr ? mSinkBuffer : mMixerBuffer;
         if (mFormat.mFormat != mMixerBufferFormat) { // sink format not the same as mixer format
             memcpy_by_audio_format(buffer, mFormat.mFormat, mMixerBuffer, mMixerBufferFormat,
                     frameCount * Format_channelCount(mFormat));
@@ -493,7 +490,7 @@
                     audio_bytes_per_sample(mFormat.mFormat),
                     frameCount * audio_bytes_per_frame(mAudioChannelCount, mFormat.mFormat));
         }
-        // if non-NULL, then duplicate write() to this non-blocking sink
+        // if non-nullptr, then duplicate write() to this non-blocking sink
 #ifdef TEE_SINK
         mTee.write(buffer, frameCount);
 #endif
@@ -501,7 +498,7 @@
         //       but this code should be modified to handle both non-blocking and blocking sinks
         dumpState->mWriteSequence++;
         ATRACE_BEGIN("write");
-        ssize_t framesWritten = mOutputSink->write(buffer, frameCount);
+        const ssize_t framesWritten = mOutputSink->write(buffer, frameCount);
         ATRACE_END();
         dumpState->mWriteSequence++;
         if (framesWritten >= 0) {
diff --git a/services/audioflinger/FastMixer.h b/services/audioflinger/fastpath/FastMixer.h
similarity index 87%
rename from services/audioflinger/FastMixer.h
rename to services/audioflinger/fastpath/FastMixer.h
index d71519f..ab7bfe1 100644
--- a/services/audioflinger/FastMixer.h
+++ b/services/audioflinger/fastpath/FastMixer.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_FAST_MIXER_H
-#define ANDROID_AUDIO_FAST_MIXER_H
+#pragma once
 
 #include <atomic>
 #include <audio_utils/Balance.h>
@@ -23,13 +22,13 @@
 #include "StateQueue.h"
 #include "FastMixerState.h"
 #include "FastMixerDumpState.h"
-#include "NBAIO_Tee.h"
+#include <afutils/NBAIO_Tee.h>
 
 namespace android {
 
 class AudioMixer;
 
-typedef StateQueue<FastMixerState> FastMixerStateQueue;
+using FastMixerStateQueue = StateQueue<FastMixerState>;
 
 class FastMixer : public FastThread {
 
@@ -37,7 +36,6 @@
     /** FastMixer constructor takes as param the parent MixerThread's io handle (id)
         for purposes of identification. */
     explicit FastMixer(audio_io_handle_t threadIoHandle);
-    virtual ~FastMixer();
 
             FastMixerStateQueue* sq();
 
@@ -51,13 +49,13 @@
             FastMixerStateQueue mSQ;
 
     // callouts
-    virtual const FastThreadState *poll();
-    virtual void setNBLogWriter(NBLog::Writer *logWriter);
-    virtual void onIdle();
-    virtual void onExit();
-    virtual bool isSubClassCommand(FastThreadState::Command command);
-    virtual void onStateChange();
-    virtual void onWork();
+    const FastThreadState *poll() override;
+    void setNBLogWriter(NBLog::Writer *logWriter) override;
+    void onIdle() override;
+    void onExit() override;
+    bool isSubClassCommand(FastThreadState::Command command) override;
+    void onStateChange() override;
+    void onWork() override;
 
     enum Reason {
         REASON_REMOVE,
@@ -115,5 +113,3 @@
 };  // class FastMixer
 
 }   // namespace android
-
-#endif  // ANDROID_AUDIO_FAST_MIXER_H
diff --git a/services/audioflinger/FastMixerDumpState.cpp b/services/audioflinger/fastpath/FastMixerDumpState.cpp
similarity index 92%
rename from services/audioflinger/FastMixerDumpState.cpp
rename to services/audioflinger/fastpath/FastMixerDumpState.cpp
index d041882..f48f539 100644
--- a/services/audioflinger/FastMixerDumpState.cpp
+++ b/services/audioflinger/fastpath/FastMixerDumpState.cpp
@@ -37,15 +37,11 @@
 {
 }
 
-FastMixerDumpState::~FastMixerDumpState()
-{
-}
-
 // helper function called by qsort()
 static int compare_uint32_t(const void *pa, const void *pb)
 {
-    uint32_t a = *(const uint32_t *)pa;
-    uint32_t b = *(const uint32_t *)pb;
+    const uint32_t a = *(const uint32_t *)pa;
+    const uint32_t b = *(const uint32_t *)pb;
     if (a < b) {
         return -1;
     } else if (a > b) {
@@ -61,9 +57,9 @@
         dprintf(fd, "  FastMixer not initialized\n");
         return;
     }
-    double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
+    const double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
             (mMeasuredWarmupTs.tv_nsec / 1000000.0);
-    double mixPeriodSec = (double) mFrameCount / mSampleRate;
+    const double mixPeriodSec = (double) mFrameCount / mSampleRate;
     dprintf(fd, "  FastMixer command=%s writeSequence=%u framesWritten=%u\n"
                 "            numTracks=%u writeErrors=%u underruns=%u overruns=%u\n"
                 "            sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n"
@@ -99,16 +95,16 @@
     // the mean account for 99.73% of the population.  So if we take each tail to be 1/1000 of the
     // sample set, we get 99.8% combined, or close to three standard deviations.
     static const uint32_t kTailDenominator = 1000;
-    uint32_t *tail = n >= kTailDenominator ? new uint32_t[n] : NULL;
+    uint32_t *tail = n >= kTailDenominator ? new uint32_t[n] : nullptr;
     // loop over all the samples
     for (uint32_t j = 0; j < n; ++j) {
-        size_t i = oldestClosed++ & (mSamplingN - 1);
-        uint32_t wallNs = mMonotonicNs[i];
-        if (tail != NULL) {
+        const size_t i = oldestClosed++ & (mSamplingN - 1);
+        const uint32_t wallNs = mMonotonicNs[i];
+        if (tail != nullptr) {
             tail[j] = wallNs;
         }
         wall.add(wallNs);
-        uint32_t sampleLoadNs = mLoadNs[i];
+        const uint32_t sampleLoadNs = mLoadNs[i];
         loadNs.add(sampleLoadNs);
 #ifdef CPU_FREQUENCY_STATISTICS
         uint32_t sampleCpukHz = mCpukHz[i];
@@ -146,10 +142,10 @@
                 "    mean=%.1f min=%.1f max=%.1f stddev=%.1f\n",
                 loadMHz.getMean(), loadMHz.getMin(), loadMHz.getMax(), loadMHz.getStdDev());
 #endif
-    if (tail != NULL) {
+    if (tail != nullptr) {
         qsort(tail, n, sizeof(uint32_t), compare_uint32_t);
         // assume same number of tail samples on each side, left and right
-        uint32_t count = n / kTailDenominator;
+        const uint32_t count = n / kTailDenominator;
         audio_utils::Statistics<double> left, right;
         for (uint32_t i = 0; i < count; ++i) {
             left.add(tail[i]);
@@ -175,7 +171,7 @@
             FastMixerState::sMaxFastTracks, trackMask);
     dprintf(fd, "  Index Active Full Partial Empty  Recent Ready    Written\n");
     for (uint32_t i = 0; i < FastMixerState::sMaxFastTracks; ++i, trackMask >>= 1) {
-        bool isActive = trackMask & 1;
+        const bool isActive = trackMask & 1;
         const FastTrackDump *ftDump = &mTracks[i];
         const FastTrackUnderruns& underruns = ftDump->mUnderruns;
         const char *mostRecent;
diff --git a/services/audioflinger/FastMixerDumpState.h b/services/audioflinger/fastpath/FastMixerDumpState.h
similarity index 93%
rename from services/audioflinger/FastMixerDumpState.h
rename to services/audioflinger/fastpath/FastMixerDumpState.h
index 294ef78..91d85b1 100644
--- a/services/audioflinger/FastMixerDumpState.h
+++ b/services/audioflinger/fastpath/FastMixerDumpState.h
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
-#define ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
+#pragma once
 
 #include <stdint.h>
+#include <type_traits>
 #include <audio_utils/TimestampVerifier.h>
 #include "Configuration.h"
 #include "FastThreadDumpState.h"
@@ -55,15 +55,16 @@
 // Represents the dump state of a fast track
 struct FastTrackDump {
     FastTrackDump() : mFramesReady(0) { }
-    /*virtual*/ ~FastTrackDump() { }
     FastTrackUnderruns  mUnderruns;
     size_t              mFramesReady;        // most recent value only; no long-term statistics kept
     int64_t             mFramesWritten;      // last value from track
 };
 
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastTrackDump>);
+
 struct FastMixerDumpState : FastThreadDumpState {
     FastMixerDumpState();
-    /*virtual*/ ~FastMixerDumpState();
 
     void dump(int fd) const;    // should only be called on a stable copy, not the original
 
@@ -81,6 +82,7 @@
     TimestampVerifier<int64_t /* frame count */, int64_t /* time ns */> mTimestampVerifier;
 };
 
-}  // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastMixerDumpState>);
 
-#endif  // ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
+}  // namespace android
diff --git a/services/audioflinger/FastMixerState.cpp b/services/audioflinger/fastpath/FastMixerState.cpp
similarity index 82%
rename from services/audioflinger/FastMixerState.cpp
rename to services/audioflinger/fastpath/FastMixerState.cpp
index b98842d..dbccb10 100644
--- a/services/audioflinger/FastMixerState.cpp
+++ b/services/audioflinger/fastpath/FastMixerState.cpp
@@ -23,30 +23,22 @@
 namespace android {
 
 FastTrack::FastTrack() :
-    mBufferProvider(NULL), mVolumeProvider(NULL),
+    mBufferProvider(nullptr), mVolumeProvider(nullptr),
     mChannelMask(AUDIO_CHANNEL_OUT_STEREO), mFormat(AUDIO_FORMAT_INVALID), mGeneration(0)
 {
 }
 
-FastTrack::~FastTrack()
-{
-}
-
 FastMixerState::FastMixerState() : FastThreadState(),
     // mFastTracks
-    mFastTracksGen(0), mTrackMask(0), mOutputSink(NULL), mOutputSinkGen(0),
+    mFastTracksGen(0), mTrackMask(0), mOutputSink(nullptr), mOutputSinkGen(0),
     mFrameCount(0)
 {
-    int ok = pthread_once(&sMaxFastTracksOnce, sMaxFastTracksInit);
+    const int ok = pthread_once(&sMaxFastTracksOnce, sMaxFastTracksInit);
     if (ok != 0) {
         ALOGE("%s pthread_once failed: %d", __func__, ok);
     }
 }
 
-FastMixerState::~FastMixerState()
-{
-}
-
 // static
 unsigned FastMixerState::sMaxFastTracks = kDefaultFastTracks;
 
@@ -57,7 +49,7 @@
 const char *FastMixerState::commandToString(Command command)
 {
     const char *str = FastThreadState::commandToString(command);
-    if (str != NULL) {
+    if (str != nullptr) {
         return str;
     }
     switch (command) {
@@ -72,9 +64,9 @@
 void FastMixerState::sMaxFastTracksInit()
 {
     char value[PROPERTY_VALUE_MAX];
-    if (property_get("ro.audio.max_fast_tracks", value, NULL) > 0) {
+    if (property_get("ro.audio.max_fast_tracks", value, nullptr /* default_value */) > 0) {
         char *endptr;
-        unsigned long ul = strtoul(value, &endptr, 0);
+        const unsigned long ul = strtoul(value, &endptr, 0);
         if (*endptr == '\0' && kMinFastTracks <= ul && ul <= kMaxFastTracks) {
             sMaxFastTracks = (unsigned) ul;
         }
diff --git a/services/audioflinger/FastMixerState.h b/services/audioflinger/fastpath/FastMixerState.h
similarity index 94%
rename from services/audioflinger/FastMixerState.h
rename to services/audioflinger/fastpath/FastMixerState.h
index ce3cc14..f40f612 100644
--- a/services/audioflinger/FastMixerState.h
+++ b/services/audioflinger/fastpath/FastMixerState.h
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_FAST_MIXER_STATE_H
-#define ANDROID_AUDIO_FAST_MIXER_STATE_H
+#pragma once
 
 #include <math.h>
+#include <type_traits>
 
 #include <audio_utils/minifloat.h>
 #include <system/audio.h>
@@ -38,13 +38,12 @@
     virtual gain_minifloat_packed_t getVolumeLR() = 0;
 protected:
     VolumeProvider() { }
-    virtual ~VolumeProvider() { }
+    virtual ~VolumeProvider() = default;
 };
 
 // Represents the state of a fast track
 struct FastTrack {
     FastTrack();
-    /*virtual*/ ~FastTrack();
 
     ExtendedAudioBufferProvider* mBufferProvider; // must be NULL if inactive, or non-NULL if active
     VolumeProvider*         mVolumeProvider; // optional; if NULL then full-scale
@@ -56,10 +55,12 @@
     float                   mHapticMaxAmplitude = NAN; // max amplitude allowed for haptic data
 };
 
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastTrack>);
+
 // Represents a single state of the fast mixer
 struct FastMixerState : FastThreadState {
                 FastMixerState();
-    /*virtual*/ ~FastMixerState();
 
     // These are the minimum, maximum, and default values for maximum number of fast tracks
     static const unsigned kMinFastTracks = 2;
@@ -95,6 +96,7 @@
 
 };  // struct FastMixerState
 
-}   // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastMixerState>);
 
-#endif  // ANDROID_AUDIO_FAST_MIXER_STATE_H
+}   // namespace android
diff --git a/services/audioflinger/FastThread.cpp b/services/audioflinger/fastpath/FastThread.cpp
similarity index 93%
rename from services/audioflinger/FastThread.cpp
rename to services/audioflinger/fastpath/FastThread.cpp
index 47fe0b3..2ebdbc1 100644
--- a/services/audioflinger/FastThread.cpp
+++ b/services/audioflinger/fastpath/FastThread.cpp
@@ -28,7 +28,7 @@
 #include <utils/Trace.h>
 #include "FastThread.h"
 #include "FastThreadDumpState.h"
-#include "TypedLogger.h"
+#include <afutils/TypedLogger.h>
 
 #define FAST_DEFAULT_NS    999999999L   // ~1 sec: default time to sleep
 #define FAST_HOT_IDLE_NS     1000000L   // 1 ms: time to sleep while hot idling
@@ -40,7 +40,7 @@
 
 FastThread::FastThread(const char *cycleMs, const char *loadUs) : Thread(false /*canCallJava*/),
     // re-initialized to &sInitial by subclass constructor
-    mPrevious(NULL), mCurrent(NULL),
+    mPrevious(nullptr), mCurrent(nullptr),
     /* mOldTs({0, 0}), */
     mOldTsValid(false),
     mSleepNs(-1),
@@ -51,8 +51,8 @@
     mWarmupNsMin(0),
     mWarmupNsMax(LONG_MAX),
     // re-initialized to &mDummySubclassDumpState by subclass constructor
-    mDummyDumpState(NULL),
-    mDumpState(NULL),
+    mDummyDumpState(nullptr),
+    mDumpState(nullptr),
     mIgnoreNextOverrun(true),
 #ifdef FAST_THREAD_STATISTICS
     // mOldLoad
@@ -84,15 +84,11 @@
     strlcpy(mLoadUs, loadUs, sizeof(mLoadUs));
 }
 
-FastThread::~FastThread()
-{
-}
-
 bool FastThread::threadLoop()
 {
     // LOGT now works even if tlNBLogWriter is nullptr, but we're considering changing that,
     // so this initialization permits a future change to remove the check for nullptr.
-    tlNBLogWriter = mDummyNBLogWriter.get();
+    aflog::setThreadWriter(mDummyNBLogWriter.get());
     for (;;) {
 
         // either nanosleep, sched_yield, or busy wait
@@ -100,7 +96,7 @@
             if (mSleepNs > 0) {
                 ALOG_ASSERT(mSleepNs < 1000000000);
                 const struct timespec req = {0, mSleepNs};
-                nanosleep(&req, NULL);
+                nanosleep(&req, nullptr);
             } else {
                 sched_yield();
             }
@@ -110,7 +106,7 @@
 
         // poll for state change
         const FastThreadState *next = poll();
-        if (next == NULL) {
+        if (next == nullptr) {
             // continue to use the default initial state until a real state is available
             // FIXME &sInitial not available, should save address earlier
             //ALOG_ASSERT(mCurrent == &sInitial && previous == &sInitial);
@@ -121,10 +117,11 @@
         if (next != mCurrent) {
 
             // As soon as possible of learning of a new dump area, start using it
-            mDumpState = next->mDumpState != NULL ? next->mDumpState : mDummyDumpState;
-            tlNBLogWriter = next->mNBLogWriter != NULL ?
+            mDumpState = next->mDumpState != nullptr ? next->mDumpState : mDummyDumpState;
+            NBLog::Writer * const writer = next->mNBLogWriter != nullptr ?
                     next->mNBLogWriter : mDummyNBLogWriter.get();
-            setNBLogWriter(tlNBLogWriter); // This is used for debugging only
+            aflog::setThreadWriter(writer);
+            setNBLogWriter(writer); // This is used for debugging only
 
             // We want to always have a valid reference to the previous (non-idle) state.
             // However, the state queue only guarantees access to current and previous states.
@@ -149,7 +146,7 @@
             mCurrent = next;
         }
 #if !LOG_NDEBUG
-        next = NULL;    // not referenced again
+        next = nullptr;    // not referenced again
 #endif
 
         mDumpState->mCommand = mCommand;
@@ -167,12 +164,12 @@
             // FIXME consider checking previous state and only perform if previous != COLD_IDLE
             if (mCurrent->mColdGen != mColdGen) {
                 int32_t *coldFutexAddr = mCurrent->mColdFutexAddr;
-                ALOG_ASSERT(coldFutexAddr != NULL);
-                int32_t old = android_atomic_dec(coldFutexAddr);
+                ALOG_ASSERT(coldFutexAddr != nullptr);
+                const int32_t old = android_atomic_dec(coldFutexAddr);
                 if (old <= 0) {
-                    syscall(__NR_futex, coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, NULL);
+                    syscall(__NR_futex, coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, nullptr);
                 }
-                int policy = sched_getscheduler(0) & ~SCHED_RESET_ON_FORK;
+                const int policy = sched_getscheduler(0) & ~SCHED_RESET_ON_FORK;
                 if (!(policy == SCHED_FIFO || policy == SCHED_RR)) {
                     ALOGE("did not receive expected priority boost on time");
                 }
@@ -267,7 +264,7 @@
                 mSleepNs = -1;
                 if (mIsWarm) {
                     if (sec > 0 || nsec > mUnderrunNs) {
-                        ATRACE_NAME("underrun");
+                        ATRACE_NAME("underrun");   // NOLINT(misc-const-correctness)
                         // FIXME only log occasionally
                         ALOGV("underrun: time since last cycle %d.%03ld sec",
                                 (int) sec, nsec / 1000000L);
@@ -298,7 +295,7 @@
 #ifdef FAST_THREAD_STATISTICS
                 if (mIsWarm) {
                     // advance the FIFO queue bounds
-                    size_t i = mBounds & (mDumpState->mSamplingN - 1);
+                    const size_t i = mBounds & (mDumpState->mSamplingN - 1);
                     mBounds = (mBounds & 0xFFFF0000) | ((mBounds + 1) & 0xFFFF);
                     if (mFull) {
                         //mBounds += 0x10000;
diff --git a/services/audioflinger/FastThread.h b/services/audioflinger/fastpath/FastThread.h
similarity index 95%
rename from services/audioflinger/FastThread.h
rename to services/audioflinger/fastpath/FastThread.h
index 2f0f73f..84dc4d2 100644
--- a/services/audioflinger/FastThread.h
+++ b/services/audioflinger/fastpath/FastThread.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_FAST_THREAD_H
-#define ANDROID_AUDIO_FAST_THREAD_H
+#pragma once
 
 #include "Configuration.h"
 #ifdef CPU_FREQUENCY_STATISTICS
@@ -31,11 +30,10 @@
 
 public:
             FastThread(const char *cycleMs, const char *loadUs);
-    virtual ~FastThread();
 
 private:
     // implement Thread::threadLoop()
-    virtual bool threadLoop();
+    bool threadLoop() override;
 
 protected:
     // callouts to subclass in same lexical order as they were in original FastMixer.cpp
@@ -93,5 +91,3 @@
 };  // class FastThread
 
 }  // namespace android
-
-#endif  // ANDROID_AUDIO_FAST_THREAD_H
diff --git a/services/audioflinger/FastThreadDumpState.cpp b/services/audioflinger/fastpath/FastThreadDumpState.cpp
similarity index 94%
rename from services/audioflinger/FastThreadDumpState.cpp
rename to services/audioflinger/fastpath/FastThreadDumpState.cpp
index e91073f..09d4744 100644
--- a/services/audioflinger/FastThreadDumpState.cpp
+++ b/services/audioflinger/fastpath/FastThreadDumpState.cpp
@@ -34,17 +34,13 @@
 #endif
 }
 
-FastThreadDumpState::~FastThreadDumpState()
-{
-}
-
 #ifdef FAST_THREAD_STATISTICS
 void FastThreadDumpState::increaseSamplingN(uint32_t samplingN)
 {
     if (samplingN <= mSamplingN || samplingN > kSamplingN || roundup(samplingN) != samplingN) {
         return;
     }
-    uint32_t additional = samplingN - mSamplingN;
+    const uint32_t additional = samplingN - mSamplingN;
     // sample arrays aren't accessed atomically with respect to the bounds,
     // so clearing reduces chance for dumpsys to read random uninitialized samples
     memset(&mMonotonicNs[mSamplingN], 0, sizeof(mMonotonicNs[0]) * additional);
diff --git a/services/audioflinger/FastThreadDumpState.h b/services/audioflinger/fastpath/FastThreadDumpState.h
similarity index 94%
rename from services/audioflinger/FastThreadDumpState.h
rename to services/audioflinger/fastpath/FastThreadDumpState.h
index 0b20e55..63e81d3 100644
--- a/services/audioflinger/FastThreadDumpState.h
+++ b/services/audioflinger/fastpath/FastThreadDumpState.h
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_FAST_THREAD_DUMP_STATE_H
-#define ANDROID_AUDIO_FAST_THREAD_DUMP_STATE_H
+#pragma once
+
+#include <type_traits>
 
 #include "Configuration.h"
 #include "FastThreadState.h"
@@ -30,7 +31,6 @@
 // It has a different lifetime than the FastThread, and so it can't be a member of FastThread.
 struct FastThreadDumpState {
     FastThreadDumpState();
-    /*virtual*/ ~FastThreadDumpState();
 
     FastThreadState::Command mCommand;   // current command
     uint32_t mUnderruns;        // total number of underruns
@@ -67,6 +67,7 @@
 
 };  // struct FastThreadDumpState
 
-}  // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastThreadDumpState>);
 
-#endif  // ANDROID_AUDIO_FAST_THREAD_DUMP_STATE_H
+}  // namespace android
diff --git a/services/audioflinger/FastThreadState.cpp b/services/audioflinger/fastpath/FastThreadState.cpp
similarity index 87%
rename from services/audioflinger/FastThreadState.cpp
rename to services/audioflinger/fastpath/FastThreadState.cpp
index ad5f31f..e6cb353 100644
--- a/services/audioflinger/FastThreadState.cpp
+++ b/services/audioflinger/fastpath/FastThreadState.cpp
@@ -20,12 +20,8 @@
 namespace android {
 
 FastThreadState::FastThreadState() :
-    mCommand(INITIAL), mColdFutexAddr(NULL), mColdGen(0), mDumpState(NULL), mNBLogWriter(NULL)
-
-{
-}
-
-FastThreadState::~FastThreadState()
+    mCommand(INITIAL), mColdFutexAddr(nullptr), mColdGen(0), mDumpState(nullptr)
+    , mNBLogWriter(nullptr)
 {
 }
 
@@ -38,7 +34,7 @@
     case FastThreadState::COLD_IDLE:    return "COLD_IDLE";
     case FastThreadState::EXIT:         return "EXIT";
     }
-    return NULL;
+    return nullptr;
 }
 
 }   // namespace android
diff --git a/services/audioflinger/FastThreadState.h b/services/audioflinger/fastpath/FastThreadState.h
similarity index 90%
rename from services/audioflinger/FastThreadState.h
rename to services/audioflinger/fastpath/FastThreadState.h
index 9fb4e06..2b8b079 100644
--- a/services/audioflinger/FastThreadState.h
+++ b/services/audioflinger/fastpath/FastThreadState.h
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_FAST_THREAD_STATE_H
-#define ANDROID_AUDIO_FAST_THREAD_STATE_H
+#pragma once
 
+#include <type_traits>
 #include "Configuration.h"
 #include <stdint.h>
 #include <media/nblog/NBLog.h>
@@ -28,9 +28,8 @@
 // Represents a single state of a FastThread
 struct FastThreadState {
                 FastThreadState();
-    /*virtual*/ ~FastThreadState();
 
-    typedef uint32_t Command;
+    using Command = uint32_t;
     static const Command
         INITIAL = 0,            // used only for the initial state
         HOT_IDLE = 1,           // do nothing
@@ -50,6 +49,7 @@
     static const char *commandToString(Command command);
 };  // struct FastThreadState
 
-}  // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastThreadState>);
 
-#endif  // ANDROID_AUDIO_FAST_THREAD_STATE_H
+}  // namespace android
diff --git a/services/audioflinger/StateQueue.cpp b/services/audioflinger/fastpath/StateQueue.cpp
similarity index 87%
rename from services/audioflinger/StateQueue.cpp
rename to services/audioflinger/fastpath/StateQueue.cpp
index 38ce2c2..62c00be 100644
--- a/services/audioflinger/StateQueue.cpp
+++ b/services/audioflinger/fastpath/StateQueue.cpp
@@ -41,8 +41,8 @@
 // Constructor and destructor
 
 template<typename T> StateQueue<T>::StateQueue() :
-    mAck(NULL), mCurrent(NULL),
-    mMutating(&mStates[0]), mExpecting(NULL),
+    mAck(nullptr), mCurrent(nullptr),
+    mMutating(&mStates[0]), mExpecting(nullptr),
     mInMutation(false), mIsDirty(false), mIsInitialized(false)
 #ifdef STATE_QUEUE_DUMP
     , mObserverDump(&mObserverDummyDump), mMutatorDump(&mMutatorDummyDump)
@@ -51,10 +51,6 @@
     atomic_init(&mNext, static_cast<uintptr_t>(0));
 }
 
-template<typename T> StateQueue<T>::~StateQueue()
-{
-}
-
 // Observer APIs
 
 template<typename T> const T* StateQueue<T>::poll()
@@ -112,7 +108,7 @@
 #endif
 
         // wait for prior push to be acknowledged
-        if (mExpecting != NULL) {
+        if (mExpecting != nullptr) {
 #ifdef STATE_QUEUE_DUMP
             unsigned count = 0;
 #endif
@@ -120,7 +116,7 @@
                 const T *ack = (const T *) mAck;    // no additional barrier needed
                 if (ack == mExpecting) {
                     // unnecessary as we're about to rewrite
-                    //mExpecting = NULL;
+                    //mExpecting = nullptr;
                     break;
                 }
                 if (block == BLOCK_NEVER) {
@@ -132,7 +128,7 @@
                 }
                 ++count;
 #endif
-                nanosleep(&req, NULL);
+                nanosleep(&req, nullptr);
             }
 #ifdef STATE_QUEUE_DUMP
             if (count > 1) {
@@ -156,14 +152,14 @@
 
     // optionally wait for this push or a prior push to be acknowledged
     if (block == BLOCK_UNTIL_ACKED) {
-        if (mExpecting != NULL) {
+        if (mExpecting != nullptr) {
 #ifdef STATE_QUEUE_DUMP
             unsigned count = 0;
 #endif
             for (;;) {
                 const T *ack = (const T *) mAck;    // no additional barrier needed
                 if (ack == mExpecting) {
-                    mExpecting = NULL;
+                    mExpecting = nullptr;
                     break;
                 }
 #ifdef STATE_QUEUE_DUMP
@@ -172,7 +168,7 @@
                 }
                 ++count;
 #endif
-                nanosleep(&req, NULL);
+                nanosleep(&req, nullptr);
             }
 #ifdef STATE_QUEUE_DUMP
             if (count > 1) {
@@ -187,9 +183,14 @@
 
 }   // namespace android
 
-// Hack to avoid explicit template instantiation of
-// template class StateQueue<FastCaptureState>;
-// template class StateQueue<FastMixerState>;
-#ifdef STATE_QUEUE_INSTANTIATIONS
-#include STATE_QUEUE_INSTANTIATIONS  // NOLINT(bugprone-suspicious-include)
-#endif
+// Instantiate StateQueue template for the types we need.
+// This needs to be done in the same translation unit as the template
+// method definitions above.
+
+#include "FastCaptureState.h"
+#include "FastMixerState.h"
+
+namespace android {
+template class StateQueue<FastCaptureState>;
+template class StateQueue<FastMixerState>;
+}   // namespace android
diff --git a/services/audioflinger/StateQueue.h b/services/audioflinger/fastpath/StateQueue.h
similarity index 98%
rename from services/audioflinger/StateQueue.h
rename to services/audioflinger/fastpath/StateQueue.h
index 27f6a28..dff8f3f 100644
--- a/services/audioflinger/StateQueue.h
+++ b/services/audioflinger/fastpath/StateQueue.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_STATE_QUEUE_H
-#define ANDROID_AUDIO_STATE_QUEUE_H
+#pragma once
 
 #include <stdatomic.h>
 
@@ -128,7 +127,7 @@
 
 public:
             StateQueue();
-    virtual ~StateQueue();
+    virtual ~StateQueue() = default;  // why is this virtual?
 
     // Observer APIs
 
@@ -211,5 +210,3 @@
 };  // class StateQueue
 
 }   // namespace android
-
-#endif  // ANDROID_AUDIO_STATE_QUEUE_H
diff --git a/services/mediaextractor/Android.bp b/services/mediaextractor/Android.bp
index acafe56..e22d749 100644
--- a/services/mediaextractor/Android.bp
+++ b/services/mediaextractor/Android.bp
@@ -89,3 +89,25 @@
         "code_coverage.policy",
     ],
 }
+
+cc_fuzz {
+    name: "mediaextractor_service_fuzzer",
+    shared_libs: [
+        "libmedia",
+        "libmediaextractorservice",
+        "libmediautils",
+        "liblog",
+        "libavservices_minijail",
+    ],
+    defaults: [
+        "service_fuzzer_defaults",
+        "fuzzer_disable_leaks",
+    ],
+    srcs: ["fuzzers/MediaExtractorServiceFuzzer.cpp"],
+    fuzz_config: {
+        cc: [
+            "android-media-playback+bugs@google.com",
+        ],
+        triage_assignee: "waghpawan@google.com",
+    },
+}
\ No newline at end of file
diff --git a/services/mediaextractor/fuzzers/MediaExtractorServiceFuzzer.cpp b/services/mediaextractor/fuzzers/MediaExtractorServiceFuzzer.cpp
new file mode 100644
index 0000000..d329e54
--- /dev/null
+++ b/services/mediaextractor/fuzzers/MediaExtractorServiceFuzzer.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+#include <fuzzbinder/libbinder_driver.h>
+
+#include "MediaExtractorService.h"
+
+using ::android::fuzzService;
+using ::android::sp;
+using ::android::MediaExtractorService;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    auto service = sp<MediaExtractorService>::make();
+    fuzzService(service, FuzzedDataProvider(data, size));
+    return 0;
+}