Merge "Camera: Add 3.8 version of ICameraDevice."
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
index 46a526c..cab184b 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -39,14 +39,6 @@
 
 class FakeVehicleHardware final : public IVehicleHardware {
   public:
-    using SetValuesCallback = std::function<void(
-            const std::vector<::aidl::android::hardware::automotive::vehicle::SetValueResult>&)>;
-    using GetValuesCallback = std::function<void(
-            const std::vector<::aidl::android::hardware::automotive::vehicle::GetValueResult>&)>;
-    using OnPropertyChangeCallback = std::function<void(
-            const std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>&)>;
-    using OnPropertySetErrorCallback = std::function<void(const std::vector<SetValueErrorEvent>&)>;
-
     FakeVehicleHardware();
 
     explicit FakeVehicleHardware(std::unique_ptr<VehiclePropValuePool> valuePool);
@@ -59,7 +51,7 @@
     // are sent to vehicle bus or before property set confirmation is received. The callback is
     // safe to be called after the function returns and is safe to be called in a different thread.
     ::aidl::android::hardware::automotive::vehicle::StatusCode setValues(
-            SetValuesCallback&& callback,
+            std::shared_ptr<const SetValuesCallback> callback,
             const std::vector<::aidl::android::hardware::automotive::vehicle::SetValueRequest>&
                     requests) override;
 
@@ -67,7 +59,7 @@
     // The callback is safe to be called after the function returns and is safe to be called in a
     // different thread.
     ::aidl::android::hardware::automotive::vehicle::StatusCode getValues(
-            GetValuesCallback&& callback,
+            std::shared_ptr<const GetValuesCallback> callback,
             const std::vector<::aidl::android::hardware::automotive::vehicle::GetValueRequest>&
                     requests) const override;
 
@@ -78,11 +70,13 @@
     ::aidl::android::hardware::automotive::vehicle::StatusCode checkHealth() override;
 
     // Register a callback that would be called when there is a property change event from vehicle.
-    void registerOnPropertyChangeEvent(OnPropertyChangeCallback&& callback) override;
+    void registerOnPropertyChangeEvent(
+            std::unique_ptr<const PropertyChangeCallback> callback) override;
 
     // Register a callback that would be called when there is a property set error event from
     // vehicle.
-    void registerOnPropertySetErrorEvent(OnPropertySetErrorCallback&& callback) override;
+    void registerOnPropertySetErrorEvent(
+            std::unique_ptr<const PropertySetErrorCallback> callback) override;
 
   private:
     // Expose private methods to unit test.
@@ -94,8 +88,10 @@
     const std::unique_ptr<obd2frame::FakeObd2Frame> mFakeObd2Frame;
     const std::unique_ptr<FakeUserHal> mFakeUserHal;
     std::mutex mCallbackLock;
-    OnPropertyChangeCallback mOnPropertyChangeCallback GUARDED_BY(mCallbackLock);
-    OnPropertySetErrorCallback mOnPropertySetErrorCallback GUARDED_BY(mCallbackLock);
+    std::unique_ptr<const PropertyChangeCallback> mOnPropertyChangeCallback
+            GUARDED_BY(mCallbackLock);
+    std::unique_ptr<const PropertySetErrorCallback> mOnPropertySetErrorCallback
+            GUARDED_BY(mCallbackLock);
 
     void init();
     // Stores the initial value to property store.
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 5b2003e..e75f0e7 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -379,7 +379,7 @@
     return {};
 }
 
-StatusCode FakeVehicleHardware::setValues(FakeVehicleHardware::SetValuesCallback&& callback,
+StatusCode FakeVehicleHardware::setValues(std::shared_ptr<const SetValuesCallback> callback,
                                           const std::vector<SetValueRequest>& requests) {
     std::vector<VehiclePropValue> updatedValues;
     std::vector<SetValueResult> results;
@@ -424,12 +424,12 @@
 
     // In the real vhal, the values will be sent to Car ECU. We just pretend it is done here and
     // send back the updated property values to client.
-    callback(std::move(results));
+    (*callback)(std::move(results));
 
     return StatusCode::OK;
 }
 
-StatusCode FakeVehicleHardware::getValues(FakeVehicleHardware::GetValuesCallback&& callback,
+StatusCode FakeVehicleHardware::getValues(std::shared_ptr<const GetValuesCallback> callback,
                                           const std::vector<GetValueRequest>& requests) const {
     std::vector<GetValueResult> results;
     for (auto& request : requests) {
@@ -471,7 +471,7 @@
         results.push_back(std::move(getValueResult));
     }
 
-    callback(std::move(results));
+    (*callback)(std::move(results));
 
     return StatusCode::OK;
 }
@@ -487,23 +487,28 @@
     return StatusCode::OK;
 }
 
-void FakeVehicleHardware::registerOnPropertyChangeEvent(OnPropertyChangeCallback&& callback) {
+void FakeVehicleHardware::registerOnPropertyChangeEvent(
+        std::unique_ptr<const PropertyChangeCallback> callback) {
     std::scoped_lock<std::mutex> lockGuard(mCallbackLock);
     mOnPropertyChangeCallback = std::move(callback);
 }
 
-void FakeVehicleHardware::registerOnPropertySetErrorEvent(OnPropertySetErrorCallback&& callback) {
+void FakeVehicleHardware::registerOnPropertySetErrorEvent(
+        std::unique_ptr<const PropertySetErrorCallback> callback) {
     std::scoped_lock<std::mutex> lockGuard(mCallbackLock);
     mOnPropertySetErrorCallback = std::move(callback);
 }
 
 void FakeVehicleHardware::onValueChangeCallback(const VehiclePropValue& value) {
     std::scoped_lock<std::mutex> lockGuard(mCallbackLock);
-    if (mOnPropertyChangeCallback != nullptr) {
-        std::vector<VehiclePropValue> updatedValues;
-        updatedValues.push_back(value);
-        mOnPropertyChangeCallback(std::move(updatedValues));
+
+    if (mOnPropertyChangeCallback == nullptr) {
+        return;
     }
+
+    std::vector<VehiclePropValue> updatedValues;
+    updatedValues.push_back(value);
+    (*mOnPropertyChangeCallback)(std::move(updatedValues));
 }
 
 void FakeVehicleHardware::maybeOverrideProperties(const char* overrideDir) {
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
index 88834f3..f8df6e6 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -76,24 +76,25 @@
 class FakeVehicleHardwareTest : public ::testing::Test {
   protected:
     void SetUp() override {
-        getHardware()->registerOnPropertyChangeEvent(
+        auto callback = std::make_unique<IVehicleHardware::PropertyChangeCallback>(
                 [this](const std::vector<VehiclePropValue>& values) {
-                    return onPropertyChangeEvent(values);
+                    onPropertyChangeEvent(values);
                 });
+        getHardware()->registerOnPropertyChangeEvent(std::move(callback));
+        mSetValuesCallback = std::make_shared<IVehicleHardware::SetValuesCallback>(
+                [this](std::vector<SetValueResult> results) { onSetValues(results); });
+        mGetValuesCallback = std::make_shared<IVehicleHardware::GetValuesCallback>(
+                [this](std::vector<GetValueResult> results) { onGetValues(results); });
     }
 
     FakeVehicleHardware* getHardware() { return &mHardware; }
 
     StatusCode setValues(const std::vector<SetValueRequest>& requests) {
-        return getHardware()->setValues(
-                [this](const std::vector<SetValueResult> results) { return onSetValues(results); },
-                requests);
+        return getHardware()->setValues(mSetValuesCallback, requests);
     }
 
     StatusCode getValues(const std::vector<GetValueRequest>& requests) {
-        return getHardware()->getValues(
-                [this](const std::vector<GetValueResult> results) { return onGetValues(results); },
-                requests);
+        return getHardware()->getValues(mGetValuesCallback, requests);
     }
 
     StatusCode setValue(const VehiclePropValue& value) {
@@ -245,6 +246,8 @@
     std::vector<SetValueResult> mSetValueResults;
     std::vector<GetValueResult> mGetValueResults;
     std::vector<VehiclePropValue> mChangedProperties;
+    std::shared_ptr<IVehicleHardware::SetValuesCallback> mSetValuesCallback;
+    std::shared_ptr<IVehicleHardware::GetValuesCallback> mGetValuesCallback;
 };
 
 TEST_F(FakeVehicleHardwareTest, testGetAllPropertyConfigs) {
@@ -367,9 +370,9 @@
 
 TEST_F(FakeVehicleHardwareTest, testRegisterOnPropertyChangeEvent) {
     // We have already registered this callback in Setup, here we are registering again.
-    getHardware()->registerOnPropertyChangeEvent(std::bind(
-            &FakeVehicleHardwareTest_testRegisterOnPropertyChangeEvent_Test::onPropertyChangeEvent,
-            this, std::placeholders::_1));
+    auto callback = std::make_unique<IVehicleHardware::PropertyChangeCallback>(
+            [this](const std::vector<VehiclePropValue>& values) { onPropertyChangeEvent(values); });
+    getHardware()->registerOnPropertyChangeEvent(std::move(callback));
 
     auto testValues = getTestPropValues();
     std::vector<SetValueRequest> requests;
diff --git a/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h b/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
index 2e12327..4b9de2d 100644
--- a/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
@@ -19,6 +19,7 @@
 
 #include <VehicleHalTypes.h>
 
+#include <memory>
 #include <vector>
 
 namespace android {
@@ -49,6 +50,14 @@
 // with a VehicleHardware through this interface.
 class IVehicleHardware {
   public:
+    using SetValuesCallback = std::function<void(
+            std::vector<::aidl::android::hardware::automotive::vehicle::SetValueResult>)>;
+    using GetValuesCallback = std::function<void(
+            std::vector<::aidl::android::hardware::automotive::vehicle::GetValueResult>)>;
+    using PropertyChangeCallback = std::function<void(
+            std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>)>;
+    using PropertySetErrorCallback = std::function<void(std::vector<SetValueErrorEvent>)>;
+
     virtual ~IVehicleHardware() = default;
 
     // Get all the property configs.
@@ -59,9 +68,7 @@
     // are sent to vehicle bus or before property set confirmation is received. The callback is
     // safe to be called after the function returns and is safe to be called in a different thread.
     virtual ::aidl::android::hardware::automotive::vehicle::StatusCode setValues(
-            std::function<void(const std::vector<
-                               ::aidl::android::hardware::automotive::vehicle::SetValueResult>&)>&&
-                    callback,
+            std::shared_ptr<const SetValuesCallback> callback,
             const std::vector<::aidl::android::hardware::automotive::vehicle::SetValueRequest>&
                     requests) = 0;
 
@@ -69,9 +76,7 @@
     // The callback is safe to be called after the function returns and is safe to be called in a
     // different thread.
     virtual ::aidl::android::hardware::automotive::vehicle::StatusCode getValues(
-            std::function<void(const std::vector<
-                               ::aidl::android::hardware::automotive::vehicle::GetValueResult>&)>&&
-                    callback,
+            std::shared_ptr<const GetValuesCallback> callback,
             const std::vector<::aidl::android::hardware::automotive::vehicle::GetValueRequest>&
                     requests) const = 0;
 
@@ -83,13 +88,12 @@
 
     // Register a callback that would be called when there is a property change event from vehicle.
     virtual void registerOnPropertyChangeEvent(
-            std::function<void(const std::vector<::aidl::android::hardware::automotive::vehicle::
-                                                         VehiclePropValue>&)>&& callback) = 0;
+            std::unique_ptr<const PropertyChangeCallback> callback) = 0;
 
     // Register a callback that would be called when there is a property set error event from
     // vehicle.
     virtual void registerOnPropertySetErrorEvent(
-            std::function<void(const std::vector<SetValueErrorEvent>&)>&& callback) = 0;
+            std::unique_ptr<const PropertySetErrorCallback> callback) = 0;
 };
 
 }  // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/vhal/Android.bp b/automotive/vehicle/aidl/impl/vhal/Android.bp
index 79d3ebd..454fea5 100644
--- a/automotive/vehicle/aidl/impl/vhal/Android.bp
+++ b/automotive/vehicle/aidl/impl/vhal/Android.bp
@@ -19,7 +19,7 @@
 }
 
 cc_binary {
-    name: "android.hardware.automotive.vehicle-aidl-default-service",
+    name: "android.hardware.automotive.vehicle@V1-default-service",
     vendor: true,
     defaults: [
         "FakeVehicleHardwareDefaults",
diff --git a/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp b/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp
index 14224a5..c8b5c65 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp
@@ -32,8 +32,8 @@
             ::ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
 
     ALOGI("Registering as service...");
-    binder_exception_t err = AServiceManager_addService(vhal->asBinder().get(),
-                                                        "android.hardware.automotive.vehicle");
+    binder_exception_t err = AServiceManager_addService(
+            vhal->asBinder().get(), "android.hardware.automotive.vehicle.IVehicle/default");
     if (err != EX_NONE) {
         ALOGE("failed to register android.hardware.automotive.vehicle service, exception: %d", err);
         return 1;
diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
index 62a7098..2b5ca70 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
@@ -19,6 +19,7 @@
 #include <IVehicleHardware.h>
 #include <LargeParcelableBase.h>
 #include <aidl/android/hardware/automotive/vehicle/IVehicle.h>
+#include <android-base/thread_annotations.h>
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
@@ -53,16 +54,17 @@
 class MockVehicleHardware final : public IVehicleHardware {
   public:
     std::vector<VehiclePropConfig> getAllPropertyConfigs() const override {
+        std::scoped_lock<std::mutex> lockGuard(mLock);
         return mPropertyConfigs;
     }
 
-    StatusCode setValues(std::function<void(const std::vector<SetValueResult>&)>&&,
+    StatusCode setValues(std::shared_ptr<const SetValuesCallback>,
                          const std::vector<SetValueRequest>&) override {
         // TODO(b/200737967): mock this.
         return StatusCode::OK;
     }
 
-    StatusCode getValues(std::function<void(const std::vector<GetValueResult>&)>&&,
+    StatusCode getValues(std::shared_ptr<const GetValuesCallback>,
                          const std::vector<GetValueRequest>&) const override {
         // TODO(b/200737967): mock this.
         return StatusCode::OK;
@@ -78,23 +80,23 @@
         return StatusCode::OK;
     }
 
-    void registerOnPropertyChangeEvent(
-            std::function<void(const std::vector<VehiclePropValue>&)>&&) override {
+    void registerOnPropertyChangeEvent(std::unique_ptr<const PropertyChangeCallback>) override {
         // TODO(b/200737967): mock this.
     }
 
-    void registerOnPropertySetErrorEvent(
-            std::function<void(const std::vector<SetValueErrorEvent>&)>&&) override {
+    void registerOnPropertySetErrorEvent(std::unique_ptr<const PropertySetErrorCallback>) override {
         // TODO(b/200737967): mock this.
     }
 
     // Test functions.
     void setPropertyConfigs(const std::vector<VehiclePropConfig>& configs) {
+        std::scoped_lock<std::mutex> lockGuard(mLock);
         mPropertyConfigs = configs;
     }
 
   private:
-    std::vector<VehiclePropConfig> mPropertyConfigs;
+    mutable std::mutex mLock;
+    std::vector<VehiclePropConfig> mPropertyConfigs GUARDED_BY(mLock);
 };
 
 struct PropConfigCmp {
diff --git a/automotive/vehicle/aidl/impl/vhal/vhal-default-service.rc b/automotive/vehicle/aidl/impl/vhal/vhal-default-service.rc
index 4c8865a..19267cd 100644
--- a/automotive/vehicle/aidl/impl/vhal/vhal-default-service.rc
+++ b/automotive/vehicle/aidl/impl/vhal/vhal-default-service.rc
@@ -1,4 +1,4 @@
-service vendor.vehicle-hal-default /vendor/bin/hw/android.hardware.automotive.vehicle-aidl-default-service
+service vendor.vehicle-hal-default /vendor/bin/hw/android.hardware.automotive.vehicle@V1-default-service
     class early_hal
     user vehicle_network
     group system inet
diff --git a/bluetooth/audio/2.2/Android.bp b/bluetooth/audio/2.2/Android.bp
index 6449c08..8d52ce9 100644
--- a/bluetooth/audio/2.2/Android.bp
+++ b/bluetooth/audio/2.2/Android.bp
@@ -14,6 +14,7 @@
     root: "android.hardware",
     srcs: [
         "types.hal",
+        "IBluetoothAudioPort.hal",
         "IBluetoothAudioProvider.hal",
         "IBluetoothAudioProvidersFactory.hal",
     ],
diff --git a/bluetooth/audio/2.2/IBluetoothAudioPort.hal b/bluetooth/audio/2.2/IBluetoothAudioPort.hal
new file mode 100644
index 0000000..344899c
--- /dev/null
+++ b/bluetooth/audio/2.2/IBluetoothAudioPort.hal
@@ -0,0 +1,30 @@
+/*
+ * Copyright 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.
+ */
+
+package android.hardware.bluetooth.audio@2.2;
+
+import @2.0::IBluetoothAudioPort;
+import android.hardware.audio.common@5.0::SinkMetadata;
+
+interface IBluetoothAudioPort extends @2.0::IBluetoothAudioPort  {
+    /**
+     * Called when the metadata of the stream's sink has been changed.
+     *
+     * @param sinkMetadata Description of the audio that is recorded by the
+     *    clients.
+     */
+    updateSinkMetadata(SinkMetadata sinkMetadata);
+};
diff --git a/bluetooth/audio/2.2/IBluetoothAudioProvider.hal b/bluetooth/audio/2.2/IBluetoothAudioProvider.hal
index ad8c839..bc16b01 100644
--- a/bluetooth/audio/2.2/IBluetoothAudioProvider.hal
+++ b/bluetooth/audio/2.2/IBluetoothAudioProvider.hal
@@ -17,7 +17,7 @@
 package android.hardware.bluetooth.audio@2.2;
 
 import @2.1::IBluetoothAudioProvider;
-import @2.0::IBluetoothAudioPort;
+import @2.2::IBluetoothAudioPort;
 import @2.0::Status;
 
 /**
diff --git a/bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.cpp b/bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.cpp
index 126bc9e..2a6d93a 100644
--- a/bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.cpp
+++ b/bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.cpp
@@ -54,7 +54,7 @@
 }
 
 Return<void> A2dpOffloadAudioProvider::startSession(
-    const sp<IBluetoothAudioPort>& hostIf,
+    const sp<V2_0::IBluetoothAudioPort>& hostIf,
     const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
   /**
    * Initialize the audio platform if audioConfiguration is supported.
diff --git a/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.cpp b/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.cpp
index 0d918e1..ba31d39 100644
--- a/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.cpp
+++ b/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.cpp
@@ -70,7 +70,7 @@
 }
 
 Return<void> A2dpSoftwareAudioProvider::startSession(
-    const sp<IBluetoothAudioPort>& hostIf,
+    const sp<V2_0::IBluetoothAudioPort>& hostIf,
     const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
   /**
    * Initialize the audio platform if audioConfiguration is supported.
diff --git a/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.h b/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.h
index 3d4f0cc..ac3aece 100644
--- a/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.h
+++ b/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.h
@@ -40,7 +40,7 @@
   bool isValid(const V2_1::SessionType& sessionType) override;
   bool isValid(const V2_0::SessionType& sessionType) override;
 
-  Return<void> startSession(const sp<IBluetoothAudioPort>& hostIf,
+  Return<void> startSession(const sp<V2_0::IBluetoothAudioPort>& hostIf,
                             const V2_0::AudioConfiguration& audioConfig,
                             startSession_cb _hidl_cb) override;
 
diff --git a/bluetooth/audio/2.2/default/AudioPort_2_0_to_2_2_Wrapper.h b/bluetooth/audio/2.2/default/AudioPort_2_0_to_2_2_Wrapper.h
new file mode 100644
index 0000000..c5613fb
--- /dev/null
+++ b/bluetooth/audio/2.2/default/AudioPort_2_0_to_2_2_Wrapper.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <android/hardware/bluetooth/audio/2.2/types.h>
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_2 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::audio::common::V5_0::SinkMetadata;
+using ::android::hardware::audio::common::V5_0::SourceMetadata;
+using ::android::hardware::bluetooth::audio::V2_2::IBluetoothAudioPort;
+
+class AudioPort_2_0_to_2_2_Wrapper : public V2_2::IBluetoothAudioPort {
+ public:
+  AudioPort_2_0_to_2_2_Wrapper(const sp<V2_0::IBluetoothAudioPort>& port) {
+    this->port = port;
+  }
+
+  Return<void> startStream() override { return port->startStream(); }
+  Return<void> suspendStream() override { return port->suspendStream(); }
+  Return<void> stopStream() override { return port->stopStream(); }
+  Return<void> getPresentationPosition(
+      getPresentationPosition_cb _hidl_cb) override {
+    return port->getPresentationPosition(_hidl_cb);
+  }
+  Return<void> updateMetadata(const SourceMetadata& sourceMetadata) override {
+    return port->updateMetadata(sourceMetadata);
+  }
+  Return<void> updateSinkMetadata(const SinkMetadata&) override {
+    // DO NOTHING, 2.0 AudioPort doesn't support sink metadata updates
+    return Void();
+  }
+
+  sp<V2_0::IBluetoothAudioPort> port;
+};
+
+}  // namespace implementation
+}  // namespace V2_2
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
\ No newline at end of file
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp b/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp
index 3655bc0..3c0ff42 100644
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp
+++ b/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp
@@ -20,6 +20,7 @@
 
 #include <android-base/logging.h>
 
+#include "AudioPort_2_0_to_2_2_Wrapper.h"
 #include "BluetoothAudioSessionReport_2_2.h"
 #include "BluetoothAudioSupportedCodecsDB_2_1.h"
 
@@ -51,7 +52,7 @@
       audio_config_({}) {}
 
 Return<void> BluetoothAudioProvider::startSession(
-    const sp<IBluetoothAudioPort>& hostIf,
+    const sp<V2_0::IBluetoothAudioPort>& hostIf,
     const V2_0::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
   AudioConfiguration audioConfig_2_2;
 
@@ -67,11 +68,13 @@
     audioConfig_2_2.codecConfig(audioConfig.codecConfig());
   }
 
-  return startSession_2_2(hostIf, audioConfig_2_2, _hidl_cb);
+  sp<V2_2::IBluetoothAudioPort> hostIf_2_2 =
+      new AudioPort_2_0_to_2_2_Wrapper(hostIf);
+  return startSession_2_2(hostIf_2_2, audioConfig_2_2, _hidl_cb);
 }
 
 Return<void> BluetoothAudioProvider::startSession_2_1(
-    const sp<IBluetoothAudioPort>& hostIf,
+    const sp<V2_0::IBluetoothAudioPort>& hostIf,
     const V2_1::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
   AudioConfiguration audioConfig_2_2;
   if (audioConfig.getDiscriminator() ==
@@ -92,11 +95,13 @@
     audioConfig_2_2.codecConfig(audioConfig.codecConfig());
   }
 
-  return startSession_2_2(hostIf, audioConfig_2_2, _hidl_cb);
+  sp<V2_2::IBluetoothAudioPort> hostIf_2_2 =
+      new AudioPort_2_0_to_2_2_Wrapper(hostIf);
+  return startSession_2_2(hostIf_2_2, audioConfig_2_2, _hidl_cb);
 }
 
 Return<void> BluetoothAudioProvider::startSession_2_2(
-    const sp<IBluetoothAudioPort>& hostIf,
+    const sp<V2_2::IBluetoothAudioPort>& hostIf,
     const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
   if (hostIf == nullptr) {
     _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvider.h b/bluetooth/audio/2.2/default/BluetoothAudioProvider.h
index b7581ba..0f1f3c6 100644
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvider.h
+++ b/bluetooth/audio/2.2/default/BluetoothAudioProvider.h
@@ -26,7 +26,7 @@
 namespace implementation {
 
 using ::android::sp;
-using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort;
+using ::android::hardware::bluetooth::audio::V2_2::IBluetoothAudioPort;
 
 using BluetoothAudioStatus =
     ::android::hardware::bluetooth::audio::V2_0::Status;
@@ -41,13 +41,13 @@
   virtual bool isValid(const V2_1::SessionType& sessionType) = 0;
   virtual bool isValid(const V2_0::SessionType& sessionType) = 0;
 
-  Return<void> startSession(const sp<IBluetoothAudioPort>& hostIf,
+  Return<void> startSession(const sp<V2_0::IBluetoothAudioPort>& hostIf,
                             const V2_0::AudioConfiguration& audioConfig,
                             startSession_cb _hidl_cb) override;
-  Return<void> startSession_2_1(const sp<IBluetoothAudioPort>& hostIf,
+  Return<void> startSession_2_1(const sp<V2_0::IBluetoothAudioPort>& hostIf,
                                 const V2_1::AudioConfiguration& audioConfig,
                                 startSession_cb _hidl_cb) override;
-  Return<void> startSession_2_2(const sp<IBluetoothAudioPort>& hostIf,
+  Return<void> startSession_2_2(const sp<V2_2::IBluetoothAudioPort>& hostIf,
                                 const AudioConfiguration& audioConfig,
                                 startSession_cb _hidl_cb) override;
   Return<void> streamStarted(BluetoothAudioStatus status) override;
@@ -59,7 +59,7 @@
 
   V2_1::SessionType session_type_;
   AudioConfiguration audio_config_;
-  sp<V2_0::IBluetoothAudioPort> stack_iface_;
+  sp<V2_2::IBluetoothAudioPort> stack_iface_;
 
   virtual Return<void> onSessionReady(startSession_cb _hidl_cb) = 0;
 };
diff --git a/bluetooth/audio/2.2/default/HearingAidAudioProvider.cpp b/bluetooth/audio/2.2/default/HearingAidAudioProvider.cpp
index c79b910..9b3294f 100644
--- a/bluetooth/audio/2.2/default/HearingAidAudioProvider.cpp
+++ b/bluetooth/audio/2.2/default/HearingAidAudioProvider.cpp
@@ -66,7 +66,7 @@
 }
 
 Return<void> HearingAidAudioProvider::startSession(
-    const sp<IBluetoothAudioPort>& hostIf,
+    const sp<V2_0::IBluetoothAudioPort>& hostIf,
     const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
   /**
    * Initialize the audio platform if audioConfiguration is supported.
diff --git a/bluetooth/audio/2.2/default/HearingAidAudioProvider.h b/bluetooth/audio/2.2/default/HearingAidAudioProvider.h
index 426c443..63290b5 100644
--- a/bluetooth/audio/2.2/default/HearingAidAudioProvider.h
+++ b/bluetooth/audio/2.2/default/HearingAidAudioProvider.h
@@ -40,7 +40,7 @@
   bool isValid(const V2_1::SessionType& sessionType) override;
   bool isValid(const V2_0::SessionType& sessionType) override;
 
-  Return<void> startSession(const sp<IBluetoothAudioPort>& hostIf,
+  Return<void> startSession(const sp<V2_0::IBluetoothAudioPort>& hostIf,
                             const V2_0::AudioConfiguration& audioConfig,
                             startSession_cb _hidl_cb) override;
 
diff --git a/bluetooth/audio/2.2/default/LeAudioAudioProvider.cpp b/bluetooth/audio/2.2/default/LeAudioAudioProvider.cpp
index af6ec99..9ec1776 100644
--- a/bluetooth/audio/2.2/default/LeAudioAudioProvider.cpp
+++ b/bluetooth/audio/2.2/default/LeAudioAudioProvider.cpp
@@ -20,6 +20,7 @@
 
 #include <android-base/logging.h>
 
+#include "AudioPort_2_0_to_2_2_Wrapper.h"
 #include "BluetoothAudioSessionReport_2_2.h"
 #include "BluetoothAudioSupportedCodecsDB_2_1.h"
 
@@ -83,11 +84,13 @@
        .bitsPerSample = audioConfig.pcmConfig().bitsPerSample,
        .dataIntervalUs = 0});
 
-  return startSession_2_2(hostIf, audioConfig_2_2, _hidl_cb);
+  sp<V2_2::IBluetoothAudioPort> hostIf_2_2 =
+      new AudioPort_2_0_to_2_2_Wrapper(hostIf);
+  return startSession_2_2(hostIf_2_2, audioConfig_2_2, _hidl_cb);
 }
 
 Return<void> LeAudioAudioProvider::startSession_2_2(
-    const sp<V2_0::IBluetoothAudioPort>& hostIf,
+    const sp<V2_2::IBluetoothAudioPort>& hostIf,
     const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
   /**
    * Initialize the audio platform if audioConfiguration is supported.
diff --git a/bluetooth/audio/2.2/default/LeAudioAudioProvider.h b/bluetooth/audio/2.2/default/LeAudioAudioProvider.h
index 40c26e0..3de1724 100644
--- a/bluetooth/audio/2.2/default/LeAudioAudioProvider.h
+++ b/bluetooth/audio/2.2/default/LeAudioAudioProvider.h
@@ -45,7 +45,7 @@
                                 const V2_1::AudioConfiguration& audioConfig,
                                 startSession_cb _hidl_cb) override;
 
-  Return<void> startSession_2_2(const sp<V2_0::IBluetoothAudioPort>& hostIf,
+  Return<void> startSession_2_2(const sp<V2_2::IBluetoothAudioPort>& hostIf,
                                 const AudioConfiguration& audioConfig,
                                 startSession_cb _hidl_cb) override;
 
diff --git a/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.cpp
index 7b70654..e3da267 100644
--- a/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.cpp
+++ b/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.cpp
@@ -20,6 +20,7 @@
 
 #include <android-base/logging.h>
 
+#include "AudioPort_2_0_to_2_2_Wrapper.h"
 #include "BluetoothAudioSessionReport_2_2.h"
 #include "BluetoothAudioSupportedCodecsDB_2_1.h"
 #include "BluetoothAudioSupportedCodecsDB_2_2.h"
@@ -91,11 +92,13 @@
       .peerDelay = 0,
       .lc3Config = audioConfig.leAudioCodecConfig().lc3Config};
 
-  return startSession_2_2(hostIf, audioConfig_2_2, _hidl_cb);
+  sp<V2_2::IBluetoothAudioPort> hostIf_2_2 =
+      new AudioPort_2_0_to_2_2_Wrapper(hostIf);
+  return startSession_2_2(hostIf_2_2, audioConfig_2_2, _hidl_cb);
 }
 
 Return<void> LeAudioOffloadAudioProvider::startSession_2_2(
-    const sp<V2_0::IBluetoothAudioPort>& hostIf,
+    const sp<V2_2::IBluetoothAudioPort>& hostIf,
     const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
   /**
    * Initialize the audio platform if audioConfiguration is supported.
diff --git a/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.h b/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.h
index 5620295..fe58de5 100644
--- a/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.h
+++ b/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.h
@@ -38,7 +38,7 @@
                                 const V2_1::AudioConfiguration& audioConfig,
                                 startSession_cb _hidl_cb) override;
 
-  Return<void> startSession_2_2(const sp<V2_0::IBluetoothAudioPort>& hostIf,
+  Return<void> startSession_2_2(const sp<V2_2::IBluetoothAudioPort>& hostIf,
                                 const AudioConfiguration& audioConfig,
                                 startSession_cb _hidl_cb) override;
 
diff --git a/bluetooth/audio/aidl/Android.bp b/bluetooth/audio/aidl/Android.bp
index 60da877..12eed55 100644
--- a/bluetooth/audio/aidl/Android.bp
+++ b/bluetooth/audio/aidl/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
 aidl_interface {
     name: "android.hardware.bluetooth.audio",
     vendor_available: true,
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
index e389ef3..9a1557a 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
@@ -38,5 +38,6 @@
   void startStream();
   void stopStream();
   void suspendStream();
-  void updateMetadata(in android.hardware.audio.common.SourceMetadata sourceMetadata);
+  void updateSourceMetadata(in android.hardware.audio.common.SourceMetadata sourceMetadata);
+  void updateSinkMetadata(in android.hardware.audio.common.SinkMetadata sinkMetadata);
 }
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
index 50e3197..827f57d 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.bluetooth.audio;
 
+import android.hardware.audio.common.SinkMetadata;
 import android.hardware.audio.common.SourceMetadata;
 import android.hardware.bluetooth.audio.PresentationPosition;
 
@@ -69,5 +70,12 @@
      * @param sourceMetadata Description of the audio that is played by the
      *    clients.
      */
-    void updateMetadata(in SourceMetadata sourceMetadata);
+    void updateSourceMetadata(in SourceMetadata sourceMetadata);
+
+    /**
+     * Called when the metadata of the stream's sink has been changed.
+     *
+     * @param sinkMetadata as passed from Audio Framework
+     */
+    void updateSinkMetadata(in SinkMetadata sinkMetadata);
 }
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index 19d2d92..4f712bf 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -22,6 +22,7 @@
     export_include_dirs: ["session/"],
     header_libs: ["libhardware_headers"],
     shared_libs: [
+        "android.hardware.audio.common@5.0",
         "android.hardware.bluetooth.audio@2.0",
         "android.hardware.bluetooth.audio@2.1",
         "android.hardware.bluetooth.audio@2.2",
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h
index 95f7408..4d7be21 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h
@@ -35,7 +35,7 @@
     std::shared_ptr<BluetoothAudioSession_2_1> session_ptr =
         BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type);
     if (session_ptr != nullptr) {
-      return session_ptr->IsSessionReady();
+      return session_ptr->GetAudioSession()->IsSessionReady();
     }
     return false;
   }
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
index e20914e..b4ba8cf 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
@@ -132,6 +132,15 @@
     }
   }
 
+  static void UpdateSinkMetadata(const SessionType_2_1& session_type,
+                                 const struct sink_metadata* sink_metadata) {
+    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
+        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->UpdateSinkMetadata(sink_metadata);
+    }
+  }
+
   // The control API writes stream to FMQ
   static size_t OutWritePcmData(const SessionType_2_1& session_type,
                                 const void* buffer, size_t bytes) {
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
index c250ef1..646e225 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
@@ -60,16 +60,6 @@
   }
 }
 
-bool BluetoothAudioSession_2_1::IsSessionReady() {
-  if (session_type_2_1_ !=
-      SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
-    return audio_session->IsSessionReady();
-  }
-
-  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
-  return audio_session->stack_iface_ != nullptr;
-}
-
 std::shared_ptr<BluetoothAudioSession>
 BluetoothAudioSession_2_1::GetAudioSession() {
   return audio_session;
@@ -80,7 +70,7 @@
 const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration
 BluetoothAudioSession_2_1::GetAudioConfig() {
   std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
-  if (IsSessionReady()) {
+  if (audio_session->IsSessionReady()) {
     // If session is unknown it means it should be 2.0 type
     if (session_type_2_1_ != SessionType_2_1::UNKNOWN)
       return audio_config_2_1_;
@@ -122,9 +112,6 @@
            SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH);
   bool is_offload_a2dp_session =
       (session_type_2_1_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH);
-  bool is_offload_le_audio_session =
-      (session_type_2_1_ == SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
-       session_type_2_1_ == SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
   auto audio_config_discriminator = audio_config.getDiscriminator();
   bool is_software_audio_config =
       (is_software_session &&
@@ -136,13 +123,7 @@
        audio_config_discriminator ==
            ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::
                hidl_discriminator::codecConfig);
-  bool is_le_audio_offload_audio_config =
-      (is_offload_le_audio_session &&
-       audio_config_discriminator ==
-           ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::
-               hidl_discriminator::leAudioCodecConfig);
-  if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
-      !is_le_audio_offload_audio_config) {
+  if (!is_software_audio_config && !is_a2dp_offload_audio_config) {
     return false;
   }
   audio_config_2_1_ = audio_config;
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
index db82c73..5a35153 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
@@ -50,10 +50,6 @@
       const ::android::hardware::bluetooth::audio::V2_1::SessionType&
           session_type);
 
-  // The function helps to check if this session is ready or not
-  // @return: true if the Bluetooth stack has started the specified session
-  bool IsSessionReady();
-
   std::shared_ptr<BluetoothAudioSession> GetAudioSession();
 
   // The report function is used to report that the Bluetooth stack has started
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
index 5a6b2e7..80df5d9 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
@@ -20,10 +20,16 @@
 
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
+#include <android/hardware/bluetooth/audio/2.2/IBluetoothAudioPort.h>
 
 namespace android {
 namespace bluetooth {
 namespace audio {
+
+using ::android::hardware::audio::common::V5_0::AudioSource;
+using ::android::hardware::audio::common::V5_0::RecordTrackMetadata;
+using ::android::hardware::audio::common::V5_0::SinkMetadata;
+
 using SessionType_2_1 =
     ::android::hardware::bluetooth::audio::V2_1::SessionType;
 using SessionType_2_0 =
@@ -37,6 +43,9 @@
 ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
     BluetoothAudioSession_2_2::invalidOffloadAudioConfiguration = {};
 
+using IBluetoothAudioPort_2_2 =
+    ::android::hardware::bluetooth::audio::V2_2::IBluetoothAudioPort;
+
 namespace {
 bool is_2_0_session_type(
     const ::android::hardware::bluetooth::audio::V2_1::SessionType&
@@ -84,6 +93,54 @@
   return audio_session_2_1;
 }
 
+void BluetoothAudioSession_2_2::UpdateSinkMetadata(
+    const struct sink_metadata* sink_metadata) {
+  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+               << " has NO session";
+    return;
+  }
+
+  ssize_t track_count = sink_metadata->track_count;
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+            << ", " << track_count << " track(s)";
+  if (session_type_2_1_ == SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+      session_type_2_1_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+    return;
+  }
+
+  struct record_track_metadata* track = sink_metadata->tracks;
+  SinkMetadata sinkMetadata;
+  RecordTrackMetadata* halMetadata;
+
+  sinkMetadata.tracks.resize(track_count);
+  halMetadata = sinkMetadata.tracks.data();
+  while (track_count && track) {
+    halMetadata->source = static_cast<AudioSource>(track->source);
+    halMetadata->gain = track->gain;
+    // halMetadata->destination leave unspecified
+    LOG(INFO) << __func__
+              << " - SessionType=" << toString(GetAudioSession()->session_type_)
+              << ", source=" << track->source
+              << ", dest_device=" << track->dest_device
+              << ", gain=" << track->gain
+              << ", dest_device_address=" << track->dest_device_address;
+    --track_count;
+    ++track;
+    ++halMetadata;
+  }
+
+  /* This is called just for 2.2 sessions, so it's safe to do this casting*/
+  IBluetoothAudioPort_2_2* stack_iface_2_2_ =
+      static_cast<IBluetoothAudioPort_2_2*>(audio_session->stack_iface_.get());
+  auto hal_retval = stack_iface_2_2_->updateSinkMetadata(sinkMetadata);
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_2_1_) << " failed";
+  }
+}
+
 // The control function is for the bluetooth_audio module to get the current
 // AudioConfiguration
 const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
index 7213ede..d6ae3d7 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
@@ -74,6 +74,8 @@
   const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
   GetAudioConfig();
 
+  void UpdateSinkMetadata(const struct sink_metadata* sink_metadata);
+
   static constexpr ::android::hardware::bluetooth::audio::V2_2::
       AudioConfiguration& kInvalidSoftwareAudioConfiguration =
           invalidSoftwareAudioConfiguration;
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index a781b35..6919b9b 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -298,16 +298,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="false">
-        <name>android.hardware.health</name>
-        <version>2.1</version>
-        <interface>
-            <name>IHealth</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <!-- TODO(b/177269435): require health AIDL HAL and deprecate HIDL HAL -->
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="false">
         <name>android.hardware.health</name>
         <version>1</version>
         <interface>
@@ -332,6 +323,13 @@
         </interface>
     </hal>
     <hal format="aidl" optional="true">
+        <name>android.hardware.net.nlinterceptor</name>
+        <interface>
+            <name>IInterceptor</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
         <name>android.hardware.oemlock</name>
         <version>1</version>
         <interface>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index 720a767..2aa4bb2 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -56,7 +56,6 @@
             "android.hardware.common",
             "android.hardware.common.fmq",
             "android.hardware.graphics.common",
-            "android.hardware.graphics.composer3.command",
             "android.hardware.keymaster",
             "android.hardware.radio",
             "android.hardware.uwb.fira_android",
diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp
index 970d1cb..aac59db 100644
--- a/gnss/aidl/vts/gnss_hal_test_cases.cpp
+++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp
@@ -804,6 +804,9 @@
  * 3. Sets SUPL server host/port.
  */
 TEST_P(GnssHalTest, TestAGnssExtension) {
+    if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+        return;
+    }
     sp<IAGnss> iAGnss;
     auto status = aidl_gnss_hal_->getExtensionAGnss(&iAGnss);
     ASSERT_TRUE(status.isOk());
diff --git a/graphics/composer/aidl/Android.bp b/graphics/composer/aidl/Android.bp
index 9034138..5f5b54e 100644
--- a/graphics/composer/aidl/Android.bp
+++ b/graphics/composer/aidl/Android.bp
@@ -33,7 +33,6 @@
     },
     srcs: [
         "android/hardware/graphics/composer3/*.aidl",
-        "android/hardware/graphics/composer3/command/*.aidl",
     ],
     stability: "vintf",
     imports: [
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/Buffer.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Buffer.aidl
similarity index 96%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/Buffer.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Buffer.aidl
index cead848..a33ad23 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/Buffer.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Buffer.aidl
@@ -31,7 +31,7 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable Buffer {
   int slot;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableComposition.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ChangedCompositionLayer.aidl
similarity index 94%
copy from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableComposition.aidl
copy to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ChangedCompositionLayer.aidl
index 40637a9..7e47ba8 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableComposition.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ChangedCompositionLayer.aidl
@@ -31,8 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
-parcelable ParcelableComposition {
+parcelable ChangedCompositionLayer {
+  long layer;
   android.hardware.graphics.composer3.Composition composition;
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/PresentFence.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ChangedCompositionTypes.aidl
similarity index 91%
copy from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/PresentFence.aidl
copy to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ChangedCompositionTypes.aidl
index 906f20c..9a5ca97 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/PresentFence.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ChangedCompositionTypes.aidl
@@ -31,9 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
-parcelable PresentFence {
+parcelable ChangedCompositionTypes {
   long display;
-  ParcelFileDescriptor fence;
+  android.hardware.graphics.composer3.ChangedCompositionLayer[] layers;
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ClientTarget.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClientTarget.aidl
similarity index 93%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ClientTarget.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClientTarget.aidl
index c3f4700..7632707 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ClientTarget.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClientTarget.aidl
@@ -31,10 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable ClientTarget {
-  android.hardware.graphics.composer3.command.Buffer buffer;
+  android.hardware.graphics.composer3.Buffer buffer;
   android.hardware.graphics.common.Dataspace dataspace;
   android.hardware.graphics.common.Rect[] damage;
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ClientTargetPropertyWithNits.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClientTargetPropertyWithNits.aidl
similarity index 97%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ClientTargetPropertyWithNits.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClientTargetPropertyWithNits.aidl
index b690a57..f0fb22e 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ClientTargetPropertyWithNits.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClientTargetPropertyWithNits.aidl
@@ -31,7 +31,7 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable ClientTargetPropertyWithNits {
   long display;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ColorTransformPayload.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ColorTransformPayload.aidl
similarity index 96%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ColorTransformPayload.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ColorTransformPayload.aidl
index 0b3071c..df07c9c 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ColorTransformPayload.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ColorTransformPayload.aidl
@@ -31,7 +31,7 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable ColorTransformPayload {
   float[] matrix;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/Error.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/CommandError.aidl
similarity index 95%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/Error.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/CommandError.aidl
index 1726ea5..103bfdc 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/Error.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/CommandError.aidl
@@ -31,9 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
-parcelable Error {
+parcelable CommandError {
   int commandIndex;
   int errorCode;
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/CommandResultPayload.aidl
similarity index 74%
copy from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl
copy to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/CommandResultPayload.aidl
index 5e6d212..ebbb31e 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/CommandResultPayload.aidl
@@ -31,8 +31,14 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
-parcelable ParcelableBlendMode {
-  android.hardware.graphics.common.BlendMode blendMode;
+union CommandResultPayload {
+  android.hardware.graphics.composer3.CommandError error;
+  android.hardware.graphics.composer3.ChangedCompositionTypes changedCompositionTypes;
+  android.hardware.graphics.composer3.DisplayRequest displayRequest;
+  android.hardware.graphics.composer3.PresentFence presentFence;
+  android.hardware.graphics.composer3.ReleaseFences releaseFences;
+  android.hardware.graphics.composer3.PresentOrValidate presentOrValidateResult;
+  android.hardware.graphics.composer3.ClientTargetPropertyWithNits clientTargetProperty;
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl
index 0bcd870..9f5342e 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl
@@ -40,4 +40,5 @@
   BRIGHTNESS = 3,
   PROTECTED_CONTENTS = 4,
   AUTO_LOW_LATENCY_MODE = 5,
+  SUSPEND = 6,
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/DisplayCommand.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl
similarity index 84%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/DisplayCommand.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl
index 7446db0..2f5d00f 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/DisplayCommand.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCommand.aidl
@@ -31,13 +31,14 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable DisplayCommand {
   long display;
-  @nullable android.hardware.graphics.composer3.command.ColorTransformPayload colorTransform;
-  @nullable android.hardware.graphics.composer3.command.ClientTarget clientTarget;
-  @nullable android.hardware.graphics.composer3.command.Buffer virtualDisplayOutputBuffer;
+  android.hardware.graphics.composer3.LayerCommand[] layers;
+  @nullable android.hardware.graphics.composer3.ColorTransformPayload colorTransform;
+  @nullable android.hardware.graphics.composer3.ClientTarget clientTarget;
+  @nullable android.hardware.graphics.composer3.Buffer virtualDisplayOutputBuffer;
   boolean validateDisplay;
   boolean acceptDisplayChanges;
   boolean presentDisplay;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/DisplayRequest.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayRequest.aidl
similarity index 93%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/DisplayRequest.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayRequest.aidl
index 7f413a9..13462ce 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/DisplayRequest.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayRequest.aidl
@@ -31,12 +31,12 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable DisplayRequest {
   long display;
   int mask;
-  android.hardware.graphics.composer3.command.DisplayRequest.LayerRequest[] layerRequests;
+  android.hardware.graphics.composer3.DisplayRequest.LayerRequest[] layerRequests;
   const int FLIP_CLIENT_TARGET = 1;
   const int WRITE_CLIENT_TARGET_TO_OUTPUT = 2;
   @VintfStability
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/GenericMetadata.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/GenericMetadata.aidl
similarity index 96%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/GenericMetadata.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/GenericMetadata.aidl
index be889d8..c18529b 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/GenericMetadata.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/GenericMetadata.aidl
@@ -31,7 +31,7 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable GenericMetadata {
   android.hardware.graphics.composer3.LayerGenericMetadataKey key;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
index 65cf86c..2bdbc9f 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -38,12 +38,11 @@
   android.hardware.graphics.composer3.VirtualDisplay createVirtualDisplay(int width, int height, android.hardware.graphics.common.PixelFormat formatHint, int outputBufferSlotCount);
   void destroyLayer(long display, long layer);
   void destroyVirtualDisplay(long display);
-  android.hardware.graphics.composer3.command.CommandResultPayload[] executeCommands(in android.hardware.graphics.composer3.command.CommandPayload[] commands);
+  android.hardware.graphics.composer3.CommandResultPayload[] executeCommands(in android.hardware.graphics.composer3.DisplayCommand[] commands);
   int getActiveConfig(long display);
   android.hardware.graphics.composer3.ColorMode[] getColorModes(long display);
   float[] getDataspaceSaturationMatrix(android.hardware.graphics.common.Dataspace dataspace);
   int getDisplayAttribute(long display, int config, android.hardware.graphics.composer3.DisplayAttribute attribute);
-  boolean getDisplayBrightnessSupport(long display);
   android.hardware.graphics.composer3.DisplayCapability[] getDisplayCapabilities(long display);
   int[] getDisplayConfigs(long display);
   android.hardware.graphics.composer3.DisplayConnectionType getDisplayConnectionType(long display);
@@ -52,7 +51,6 @@
   int getDisplayVsyncPeriod(long display);
   android.hardware.graphics.composer3.DisplayContentSample getDisplayedContentSample(long display, long maxFrames, long timestamp);
   android.hardware.graphics.composer3.DisplayContentSamplingAttributes getDisplayedContentSamplingAttributes(long display);
-  boolean getDozeSupport(long display);
   android.hardware.graphics.composer3.HdrCapabilities getHdrCapabilities(long display);
   android.hardware.graphics.composer3.LayerGenericMetadataKey[] getLayerGenericMetadataKeys();
   int getMaxVirtualDisplayCount();
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/LayerCommand.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl
similarity index 75%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/LayerCommand.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl
index b5adbc3..bad72fc 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/LayerCommand.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl
@@ -31,29 +31,28 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable LayerCommand {
-  long display;
   long layer;
   @nullable android.hardware.graphics.common.Point cursorPosition;
-  @nullable android.hardware.graphics.composer3.command.Buffer buffer;
+  @nullable android.hardware.graphics.composer3.Buffer buffer;
   @nullable android.hardware.graphics.common.Rect[] damage;
-  @nullable android.hardware.graphics.composer3.command.ParcelableBlendMode blendMode;
+  @nullable android.hardware.graphics.composer3.ParcelableBlendMode blendMode;
   @nullable android.hardware.graphics.composer3.Color color;
   @nullable android.hardware.graphics.composer3.FloatColor floatColor;
-  @nullable android.hardware.graphics.composer3.command.ParcelableComposition composition;
-  @nullable android.hardware.graphics.composer3.command.ParcelableDataspace dataspace;
+  @nullable android.hardware.graphics.composer3.ParcelableComposition composition;
+  @nullable android.hardware.graphics.composer3.ParcelableDataspace dataspace;
   @nullable android.hardware.graphics.common.Rect displayFrame;
-  @nullable android.hardware.graphics.composer3.command.PlaneAlpha planeAlpha;
+  @nullable android.hardware.graphics.composer3.PlaneAlpha planeAlpha;
   @nullable android.hardware.common.NativeHandle sidebandStream;
   @nullable android.hardware.graphics.common.FRect sourceCrop;
-  @nullable android.hardware.graphics.composer3.command.ParcelableTransform transform;
+  @nullable android.hardware.graphics.composer3.ParcelableTransform transform;
   @nullable android.hardware.graphics.common.Rect[] visibleRegion;
-  @nullable android.hardware.graphics.composer3.command.ZOrder z;
+  @nullable android.hardware.graphics.composer3.ZOrder z;
   @nullable float[] colorTransform;
-  @nullable android.hardware.graphics.composer3.command.WhitePointNits whitePointNits;
-  @nullable android.hardware.graphics.composer3.command.GenericMetadata genericMetadata;
+  @nullable android.hardware.graphics.composer3.WhitePointNits whitePointNits;
+  @nullable android.hardware.graphics.composer3.GenericMetadata genericMetadata;
   @nullable android.hardware.graphics.composer3.PerFrameMetadata[] perFrameMetadata;
   @nullable android.hardware.graphics.composer3.PerFrameMetadataBlob[] perFrameMetadataBlob;
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableBlendMode.aidl
similarity index 96%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableBlendMode.aidl
index 5e6d212..f1fee5f 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableBlendMode.aidl
@@ -31,7 +31,7 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable ParcelableBlendMode {
   android.hardware.graphics.common.BlendMode blendMode;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableComposition.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableComposition.aidl
similarity index 96%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableComposition.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableComposition.aidl
index 40637a9..98fbb66 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableComposition.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableComposition.aidl
@@ -31,7 +31,7 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable ParcelableComposition {
   android.hardware.graphics.composer3.Composition composition;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableDataspace.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableDataspace.aidl
similarity index 96%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableDataspace.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableDataspace.aidl
index 8f06079..76ecf85 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableDataspace.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableDataspace.aidl
@@ -31,7 +31,7 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable ParcelableDataspace {
   android.hardware.graphics.common.Dataspace dataspace;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableTransform.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableTransform.aidl
similarity index 96%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableTransform.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableTransform.aidl
index 6d6fe5b..b673656 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableTransform.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ParcelableTransform.aidl
@@ -31,7 +31,7 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable ParcelableTransform {
   android.hardware.graphics.common.Transform transform;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/PlaneAlpha.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PlaneAlpha.aidl
similarity index 96%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/PlaneAlpha.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PlaneAlpha.aidl
index 97f5329..c48c2a8 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/PlaneAlpha.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PlaneAlpha.aidl
@@ -31,7 +31,7 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable PlaneAlpha {
   float alpha;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/PresentFence.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentFence.aidl
similarity index 96%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/PresentFence.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentFence.aidl
index 906f20c..3bb09cd 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/PresentFence.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentFence.aidl
@@ -31,7 +31,7 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable PresentFence {
   long display;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/PresentOrValidate.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentOrValidate.aidl
similarity index 93%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/PresentOrValidate.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentOrValidate.aidl
index 66f1c03..3514e53 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/PresentOrValidate.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentOrValidate.aidl
@@ -31,11 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable PresentOrValidate {
   long display;
-  android.hardware.graphics.composer3.command.PresentOrValidate.Result result;
+  android.hardware.graphics.composer3.PresentOrValidate.Result result;
   @VintfStability
   enum Result {
     Presented = 0,
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ReleaseFences.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ReleaseFences.aidl
similarity index 93%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ReleaseFences.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ReleaseFences.aidl
index b7d2586..d623661 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ReleaseFences.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ReleaseFences.aidl
@@ -31,11 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable ReleaseFences {
   long display;
-  android.hardware.graphics.composer3.command.ReleaseFences.Layer[] layers;
+  android.hardware.graphics.composer3.ReleaseFences.Layer[] layers;
   @VintfStability
   parcelable Layer {
     long layer;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/WhitePointNits.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/WhitePointNits.aidl
similarity index 96%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/WhitePointNits.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/WhitePointNits.aidl
index 2b25167..c3925d2 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/WhitePointNits.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/WhitePointNits.aidl
@@ -31,7 +31,7 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable WhitePointNits {
   float nits;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ZOrder.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ZOrder.aidl
similarity index 96%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ZOrder.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ZOrder.aidl
index 69b68c4..ea96ea3 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ZOrder.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ZOrder.aidl
@@ -31,7 +31,7 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 @VintfStability
 parcelable ZOrder {
   int z;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ChangedCompositionTypes.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ChangedCompositionTypes.aidl
deleted file mode 100644
index 1377c6c..0000000
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ChangedCompositionTypes.aidl
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * 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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL file. Do not edit it manually. There are
-// two cases:
-// 1). this is a frozen version file - do not edit this in any case.
-// 2). this is a 'current' file. If you make a backwards compatible change to
-//     the interface (from the latest frozen version), the build system will
-//     prompt you to update this file with `m <name>-update-api`.
-//
-// You must not make a backward incompatible change to any AIDL file built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.hardware.graphics.composer3.command;
-@VintfStability
-parcelable ChangedCompositionTypes {
-  long display;
-  android.hardware.graphics.composer3.command.ChangedCompositionTypes.Layer[] layers;
-  @VintfStability
-  parcelable Layer {
-    long layer;
-    android.hardware.graphics.composer3.Composition composition;
-  }
-}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/CommandPayload.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/CommandPayload.aidl
deleted file mode 100644
index 9848306..0000000
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/CommandPayload.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * 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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL file. Do not edit it manually. There are
-// two cases:
-// 1). this is a frozen version file - do not edit this in any case.
-// 2). this is a 'current' file. If you make a backwards compatible change to
-//     the interface (from the latest frozen version), the build system will
-//     prompt you to update this file with `m <name>-update-api`.
-//
-// You must not make a backward incompatible change to any AIDL file built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.hardware.graphics.composer3.command;
-@VintfStability
-union CommandPayload {
-  android.hardware.graphics.composer3.command.DisplayCommand displayCommand;
-  android.hardware.graphics.composer3.command.LayerCommand layerCommand;
-}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/CommandResultPayload.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/CommandResultPayload.aidl
deleted file mode 100644
index 1b3cae8..0000000
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/CommandResultPayload.aidl
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * 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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL file. Do not edit it manually. There are
-// two cases:
-// 1). this is a frozen version file - do not edit this in any case.
-// 2). this is a 'current' file. If you make a backwards compatible change to
-//     the interface (from the latest frozen version), the build system will
-//     prompt you to update this file with `m <name>-update-api`.
-//
-// You must not make a backward incompatible change to any AIDL file built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.hardware.graphics.composer3.command;
-@VintfStability
-union CommandResultPayload {
-  android.hardware.graphics.composer3.command.Error error;
-  android.hardware.graphics.composer3.command.ChangedCompositionTypes changedCompositionType;
-  android.hardware.graphics.composer3.command.DisplayRequest displayRequest;
-  android.hardware.graphics.composer3.command.PresentFence presentFence;
-  android.hardware.graphics.composer3.command.ReleaseFences releaseFences;
-  android.hardware.graphics.composer3.command.PresentOrValidate presentOrValidateResult;
-  android.hardware.graphics.composer3.command.ClientTargetPropertyWithNits clientTargetProperty;
-}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/Buffer.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/Buffer.aidl
similarity index 96%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/Buffer.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/Buffer.aidl
index 3a08d3b..415a9b6 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/Buffer.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/Buffer.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 import android.hardware.common.NativeHandle;
 
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ParcelableComposition.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ChangedCompositionLayer.aidl
similarity index 74%
copy from graphics/composer/aidl/android/hardware/graphics/composer3/command/ParcelableComposition.aidl
copy to graphics/composer/aidl/android/hardware/graphics/composer3/ChangedCompositionLayer.aidl
index 91979d8..fb25163 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ParcelableComposition.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ChangedCompositionLayer.aidl
@@ -14,11 +14,20 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 import android.hardware.graphics.composer3.Composition;
 
 @VintfStability
-parcelable ParcelableComposition {
+parcelable ChangedCompositionLayer {
+    /**
+     * The layer which this commands refers to.
+     * @see IComposer.createLayer
+     */
+    long layer;
+
+    /**
+     * The new composition type.
+     */
     Composition composition;
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ChangedCompositionTypes.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ChangedCompositionTypes.aidl
similarity index 72%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/ChangedCompositionTypes.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/ChangedCompositionTypes.aidl
index 3800eff..ddd45b7 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ChangedCompositionTypes.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ChangedCompositionTypes.aidl
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
+import android.hardware.graphics.composer3.ChangedCompositionLayer;
 import android.hardware.graphics.composer3.Composition;
 
 @VintfStability
@@ -26,22 +27,8 @@
      */
     long display;
 
-    @VintfStability
-    parcelable Layer {
-        /**
-         * The layer which this commands refers to.
-         * @see IComposer.createLayer
-         */
-        long layer;
-
-        /**
-         * The new composition type.
-         */
-        Composition composition;
-    }
-
     /**
      * Indicates which layers has composition changes
      */
-    Layer[] layers;
+    ChangedCompositionLayer[] layers;
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ClientTarget.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTarget.aidl
similarity index 89%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/ClientTarget.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/ClientTarget.aidl
index d8d45a1..56488d5 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ClientTarget.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTarget.aidl
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 import android.hardware.graphics.common.Dataspace;
 import android.hardware.graphics.common.Rect;
-import android.hardware.graphics.composer3.command.Buffer;
+import android.hardware.graphics.composer3.Buffer;
 
 @VintfStability
 parcelable ClientTarget {
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ClientTargetPropertyWithNits.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTargetPropertyWithNits.aidl
similarity index 95%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/ClientTargetPropertyWithNits.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/ClientTargetPropertyWithNits.aidl
index c80e4ce..5037651 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ClientTargetPropertyWithNits.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ClientTargetPropertyWithNits.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 import android.hardware.graphics.composer3.ClientTargetProperty;
 
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ColorTransformPayload.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ColorTransformPayload.aidl
similarity index 91%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/ColorTransformPayload.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/ColorTransformPayload.aidl
index 9cc8fa7..fc37dac 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ColorTransformPayload.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ColorTransformPayload.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 import android.hardware.graphics.common.ColorTransform;
 
@@ -27,7 +27,7 @@
 
     /**
      * Hint value which may be used instead of the given matrix unless it
-     * is ColorTransform::ARBITRARY.
+     * is ColorTransform.ARBITRARY.
      */
     ColorTransform hint;
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/Error.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/CommandError.aidl
similarity index 91%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/Error.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/CommandError.aidl
index 19843b9..ea48600 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/Error.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/CommandError.aidl
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 @VintfStability
-parcelable Error {
+parcelable CommandError {
     /**
      * The index in the command payload array.
      */
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/CommandResultPayload.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl
similarity index 85%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/CommandResultPayload.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl
index b6086ca..f2de68e 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/CommandResultPayload.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/CommandResultPayload.aidl
@@ -14,22 +14,22 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
-import android.hardware.graphics.composer3.command.ChangedCompositionTypes;
-import android.hardware.graphics.composer3.command.ClientTargetPropertyWithNits;
-import android.hardware.graphics.composer3.command.DisplayRequest;
-import android.hardware.graphics.composer3.command.Error;
-import android.hardware.graphics.composer3.command.PresentFence;
-import android.hardware.graphics.composer3.command.PresentOrValidate;
-import android.hardware.graphics.composer3.command.ReleaseFences;
+import android.hardware.graphics.composer3.ChangedCompositionTypes;
+import android.hardware.graphics.composer3.ClientTargetPropertyWithNits;
+import android.hardware.graphics.composer3.CommandError;
+import android.hardware.graphics.composer3.DisplayRequest;
+import android.hardware.graphics.composer3.PresentFence;
+import android.hardware.graphics.composer3.PresentOrValidate;
+import android.hardware.graphics.composer3.ReleaseFences;
 
 @VintfStability
 union CommandResultPayload {
     /**
      * Indicates an error generated by a command.
      */
-    Error error;
+    CommandError error;
 
     /**
      * Sets the layers for which the device requires a different composition
@@ -38,7 +38,7 @@
      * ACCEPT_DISPLAY_CHANGES, or must set new types and attempt to validate
      * the display again.
      */
-    ChangedCompositionTypes changedCompositionType;
+    ChangedCompositionTypes changedCompositionTypes;
 
     /**
      * Sets the display requests and the layer requests required for the last
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/Composition.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/Composition.aidl
index ea22af2..d1c9b30 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/Composition.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/Composition.aidl
@@ -66,7 +66,7 @@
     /**
      * The device must handle the composition of this layer, as well as
      * its buffer updates and content synchronization. Only supported on
-     * devices which provide Capability::SIDEBAND_STREAM.
+     * devices which provide Capability.SIDEBAND_STREAM.
      *
      * Upon validateDisplay, the device may request a change from this
      * type to either DEVICE or CLIENT, but it is unlikely that content
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl
index 54f09c1..eacf106 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl
@@ -41,14 +41,15 @@
      */
     SKIP_CLIENT_COLOR_TRANSFORM = 1,
     /**
-     * Indicates that the display supports PowerMode::DOZE and
-     * PowerMode::DOZE_SUSPEND. DOZE_SUSPEND may not provide any benefit
+     * Indicates that the display supports PowerMode.DOZE and
+     * potentially PowerMode.DOZE_SUSPEND if DisplayCapability.SUSPEND is also
+     * supported. DOZE_SUSPEND may not provide any benefit
      * over DOZE (see the definition of PowerMode for more information),
      * but if both DOZE and DOZE_SUSPEND are no different from
-     * PowerMode::ON, the device must not claim support.
+     * PowerMode.ON, the device must not claim support.
      * Must be returned by getDisplayCapabilities when getDozeSupport
-     * indicates the display supports PowerMode::DOZE and
-     * PowerMode::DOZE_SUSPEND.
+     * indicates the display supports PowerMode.DOZE and
+     * PowerMode.DOZE_SUSPEND.
      */
     DOZE = 2,
     /**
@@ -66,4 +67,12 @@
      * support a low latency mode, such as HDMI 2.1 Auto Low Latency Mode.
      */
     AUTO_LOW_LATENCY_MODE = 5,
+    /**
+     * Indicates that the display supports PowerMode.ON_SUSPEND.
+     * If PowerMode.ON_SUSPEND is no different from PowerMode.ON, the device must not
+     * claim support.
+     * If the display supports DisplayCapability.DOZE and DisplayCapability.SUSPEND, then
+     * PowerMode.ON_SUSPEND and PowerMode.DOZE_SUSPEND must be supported.
+     */
+    SUSPEND = 6,
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/DisplayCommand.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCommand.aidl
similarity index 87%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/DisplayCommand.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCommand.aidl
index 7295ada..21497c4 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/DisplayCommand.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCommand.aidl
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
-import android.hardware.graphics.composer3.command.Buffer;
-import android.hardware.graphics.composer3.command.ClientTarget;
-import android.hardware.graphics.composer3.command.ColorTransformPayload;
+import android.hardware.graphics.composer3.Buffer;
+import android.hardware.graphics.composer3.ClientTarget;
+import android.hardware.graphics.composer3.ColorTransformPayload;
+import android.hardware.graphics.composer3.LayerCommand;
 
 @VintfStability
 parcelable DisplayCommand {
@@ -29,9 +30,15 @@
     long display;
 
     /**
+     * Sets layer commands for this display.
+     * @see LayerCommand.
+     */
+    LayerCommand[] layers;
+
+    /**
      * Sets a color transform which will be applied after composition.
      *
-     * If hint is not ColorTransform::ARBITRARY, then the device may use the
+     * If hint is not ColorTransform.ARBITRARY, then the device may use the
      * hint to apply the desired color transform instead of using the color
      * matrix directly.
      *
@@ -39,7 +46,7 @@
      * apply the desired color transform, it must force all layers to client
      * composition during VALIDATE_DISPLAY.
      *
-     * If IComposer::Capability::SKIP_CLIENT_COLOR_TRANSFORM is present, then
+     * If Capability.SKIP_CLIENT_COLOR_TRANSFORM is present, then
      * the client must never apply the color transform during client
      * composition, even if all layers are being composed by the client.
      *
@@ -67,9 +74,9 @@
 
     /**
      * Sets the buffer handle which will receive the output of client
-     * composition.  Layers marked as Composition::CLIENT must be composited
+     * composition.  Layers marked as Composition.CLIENT must be composited
      * into this buffer prior to the call to PRESENT_DISPLAY, and layers not
-     * marked as Composition::CLIENT must be composited with this buffer by
+     * marked as Composition.CLIENT must be composited with this buffer by
      * the device.
      *
      * The buffer handle provided may be empty if no layers are being
@@ -87,7 +94,7 @@
      * the description of SET_LAYER_SURFACE_DAMAGE.
      *
      * Will be called before PRESENT_DISPLAY if any of the layers are marked
-     * as Composition::CLIENT. If no layers are so marked, then it is not
+     * as Composition.CLIENT. If no layers are so marked, then it is not
      * necessary to call this function. It is not necessary to call
      * validateDisplay after changing the target through this function.
      */
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/DisplayRequest.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayRequest.aidl
similarity index 94%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/DisplayRequest.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/DisplayRequest.aidl
index 10bd10c..27fe1e6 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/DisplayRequest.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayRequest.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 @VintfStability
 parcelable DisplayRequest {
@@ -27,7 +27,7 @@
     /**
      * Instructs the client to write the result of client composition
      * directly into the virtual display output buffer. If any of the
-     * layers are not marked as Composition::CLIENT or the given display
+     * layers are not marked as Composition.CLIENT or the given display
      * is not a virtual display, this request has no effect.
      */
     const int WRITE_CLIENT_TARGET_TO_OUTPUT = 1 << 1;
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/GenericMetadata.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/GenericMetadata.aidl
similarity index 94%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/GenericMetadata.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/GenericMetadata.aidl
index a4e1fe8..d0254dd 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/GenericMetadata.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/GenericMetadata.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 import android.hardware.graphics.composer3.LayerGenericMetadataKey;
 
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposer.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposer.aidl
index a6a9f73..b8edd80 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposer.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposer.aidl
@@ -27,7 +27,7 @@
     const int EX_NO_RESOURCES = 6;
 
     /**
-     * Creates a v2.4 client of the composer. Supersedes @2.3::createClient.
+     * Creates a client of the composer.
      *
      * @return is the newly created client.
      *
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerCallback.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerCallback.aidl
index 1709e6d..ac95b41 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerCallback.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerCallback.aidl
@@ -26,7 +26,7 @@
      * must trigger at least one hotplug notification, even if it only occurs
      * immediately after callback registration.
      *
-     * Displays which have been connected are assumed to be in PowerMode::OFF,
+     * Displays which have been connected are assumed to be in PowerMode.OFF,
      * and the onVsync callback should not be called for a display until vsync
      * has been enabled with setVsyncEnabled.
      *
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
index f661f8b..28bdb2c 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -18,9 +18,11 @@
 
 import android.hardware.graphics.composer3.ClientTargetProperty;
 import android.hardware.graphics.composer3.ColorMode;
+import android.hardware.graphics.composer3.CommandResultPayload;
 import android.hardware.graphics.composer3.ContentType;
 import android.hardware.graphics.composer3.DisplayAttribute;
 import android.hardware.graphics.composer3.DisplayCapability;
+import android.hardware.graphics.composer3.DisplayCommand;
 import android.hardware.graphics.composer3.DisplayConnectionType;
 import android.hardware.graphics.composer3.DisplayContentSample;
 import android.hardware.graphics.composer3.DisplayContentSamplingAttributes;
@@ -36,8 +38,6 @@
 import android.hardware.graphics.composer3.VirtualDisplay;
 import android.hardware.graphics.composer3.VsyncPeriodChangeConstraints;
 import android.hardware.graphics.composer3.VsyncPeriodChangeTimeline;
-import android.hardware.graphics.composer3.command.CommandPayload;
-import android.hardware.graphics.composer3.command.CommandResultPayload;
 
 @VintfStability
 interface IComposerClient {
@@ -163,7 +163,7 @@
      *
      * @return are the command statuses.
      */
-    CommandResultPayload[] executeCommands(in CommandPayload[] commands);
+    CommandResultPayload[] executeCommands(in DisplayCommand[] commands);
 
     /**
      * Retrieves which display configuration is currently active.
@@ -185,7 +185,7 @@
     /**
      * Returns the color modes supported on this display.
      *
-     * All devices must support at least ColorMode::NATIVE.
+     * All devices must support at least ColorMode.NATIVE.
      *
      * @param display is the display to query.
      *
@@ -201,7 +201,7 @@
      *
      * When the layer dataspace is a legacy dataspace (see
      * common@1.1::Dataspace) and the display render intent is
-     * RenderIntent::ENHANCE, the pixel values can go through an
+     * RenderIntent.ENHANCE, the pixel values can go through an
      * implementation-defined saturation transform before being mapped to the
      * current color mode colorimetrically.
      *
@@ -247,22 +247,6 @@
     int getDisplayAttribute(long display, int config, DisplayAttribute attribute);
 
     /**
-     * Use getDisplayCapabilities instead. If brightness is supported, must return
-     * DisplayCapability::BRIGHTNESS as one of the display capabilities via getDisplayCapabilities.
-     * Only use getDisplayCapabilities as the source of truth to query brightness support.
-     *
-     * Gets whether brightness operations are supported on a display.
-     *
-     * @param display The display.
-     *
-     * @return Whether brightness operations are supported on the display.
-     *
-     * @exception EX_BAD_DISPLAY   when the display is invalid, or
-     * @exception EX_BAD_PARAMETER when the output parameter is invalid.
-     */
-    boolean getDisplayBrightnessSupport(long display);
-
-    /**
      * Provides a list of supported capabilities (as described in the
      * definition of DisplayCapability above). This list must not change after
      * initialization.
@@ -371,21 +355,6 @@
     DisplayContentSamplingAttributes getDisplayedContentSamplingAttributes(long display);
 
     /**
-     * Returns whether the given display supports PowerMode::DOZE and
-     * PowerMode::DOZE_SUSPEND. DOZE_SUSPEND may not provide any benefit over
-     * DOZE (see the definition of PowerMode for more information), but if
-     * both DOZE and DOZE_SUSPEND are no different from PowerMode::ON, the
-     * device must not claim support.
-     *
-     * @param display is the display to query.
-     *
-     * @return is true only when the display supports doze modes.
-     *
-     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
-     */
-    boolean getDozeSupport(long display);
-
-    /**
      * Returns the high dynamic range (HDR) capabilities of the given display,
      * which are invariant with regard to the active configuration.
      *
@@ -440,8 +409,8 @@
      *
      * The width and height of this buffer must be those of the currently-active
      * display configuration, and the usage flags must consist of the following:
-     *   BufferUsage::CPU_READ | BufferUsage::GPU_TEXTURE |
-     *   BufferUsage::COMPOSER_OUTPUT
+     *   BufferUsage.CPU_READ | BufferUsage.GPU_TEXTURE |
+     *   BufferUsage.COMPOSER_OUTPUT
      *
      * The format and dataspace provided must be sufficient such that if a
      * correctly-configured buffer is passed into setReadbackBuffer, filled by
@@ -516,8 +485,8 @@
      * Returns the render intents supported by the specified display and color
      * mode.
      *
-     * For SDR color modes, RenderIntent::COLORIMETRIC must be supported. For
-     * HDR color modes, RenderIntent::TONE_MAP_COLORIMETRIC must be supported.
+     * For SDR color modes, RenderIntent.COLORIMETRIC must be supported. For
+     * HDR color modes, RenderIntent.TONE_MAP_COLORIMETRIC must be supported.
      *
      * @param display is the display to query.
      * @param mode is the color mode to query.
@@ -531,11 +500,11 @@
 
     /**
      * Provides a list of all the content types supported by this display (any of
-     * ContentType::{GRAPHICS, PHOTO, CINEMA, GAME}). This list must not change after
+     * ContentType.{GRAPHICS, PHOTO, CINEMA, GAME}). This list must not change after
      * initialization.
      *
      * Content types are introduced in HDMI 1.4 and supporting them is optional. The
-     * ContentType::NONE is always supported and will not be returned by this method..
+     * ContentType.NONE is always supported and will not be returned by this method..
      *
      * @return out is a list of supported content types.
      *
@@ -602,7 +571,7 @@
      * be triggered.
      *
      * This function should only be called if the display reports support for
-     * DisplayCapability::AUTO_LOW_LATENCY_MODE from getDisplayCapabilities_2_4.
+     * DisplayCapability.AUTO_LOW_LATENCY_MODE from getDisplayCapabilities_2_4.
      *
      * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
      * @exception EX_UNSUPPORTED when AUTO_LOW_LATENCY_MODE is not supported by the composer
@@ -626,8 +595,8 @@
      * The color mode and render intent change must take effect on next
      * presentDisplay.
      *
-     * All devices must support at least ColorMode::NATIVE and
-     * RenderIntent::COLORIMETRIC, and displays are assumed to be in this mode
+     * All devices must support at least ColorMode.NATIVE and
+     * RenderIntent.COLORIMETRIC, and displays are assumed to be in this mode
      * upon hotplug.
      *
      * @param display is the display to which the color mode is set.
@@ -713,8 +682,8 @@
      * complete when this function returns. It is valid to call this function
      * multiple times with the same power mode.
      *
-     * All displays must support PowerMode::ON and PowerMode::OFF.  Whether a
-     * display supports PowerMode::DOZE or PowerMode::DOZE_SUSPEND may be
+     * All displays must support PowerMode.ON and PowerMode.OFF.  Whether a
+     * display supports PowerMode.DOZE or PowerMode.DOZE_SUSPEND may be
      * queried using getDozeSupport.
      *
      * @param display is the display to which the power mode is set.
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/LayerCommand.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl
similarity index 88%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/LayerCommand.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl
index eac051b..761da9a 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/LayerCommand.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl
@@ -14,35 +14,29 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 import android.hardware.common.NativeHandle;
 import android.hardware.graphics.common.FRect;
 import android.hardware.graphics.common.Point;
 import android.hardware.graphics.common.Rect;
+import android.hardware.graphics.composer3.Buffer;
 import android.hardware.graphics.composer3.Color;
 import android.hardware.graphics.composer3.FloatColor;
+import android.hardware.graphics.composer3.GenericMetadata;
+import android.hardware.graphics.composer3.ParcelableBlendMode;
+import android.hardware.graphics.composer3.ParcelableComposition;
+import android.hardware.graphics.composer3.ParcelableDataspace;
+import android.hardware.graphics.composer3.ParcelableTransform;
 import android.hardware.graphics.composer3.PerFrameMetadata;
 import android.hardware.graphics.composer3.PerFrameMetadataBlob;
-import android.hardware.graphics.composer3.command.Buffer;
-import android.hardware.graphics.composer3.command.GenericMetadata;
-import android.hardware.graphics.composer3.command.ParcelableBlendMode;
-import android.hardware.graphics.composer3.command.ParcelableComposition;
-import android.hardware.graphics.composer3.command.ParcelableDataspace;
-import android.hardware.graphics.composer3.command.ParcelableTransform;
-import android.hardware.graphics.composer3.command.PlaneAlpha;
-import android.hardware.graphics.composer3.command.WhitePointNits;
-import android.hardware.graphics.composer3.command.ZOrder;
+import android.hardware.graphics.composer3.PlaneAlpha;
+import android.hardware.graphics.composer3.WhitePointNits;
+import android.hardware.graphics.composer3.ZOrder;
 
 @VintfStability
 parcelable LayerCommand {
     /**
-     * The display which this commands refers to.
-     * @see IComposer.createDisplay
-     */
-    long display;
-
-    /**
      * The layer which this commands refers to.
      * @see IComposer.createLayer
      */
@@ -51,7 +45,7 @@
     /**
      * Asynchronously sets the position of a cursor layer.
      *
-     * Prior to validateDisplay, a layer may be marked as Composition::CURSOR.
+     * Prior to validateDisplay, a layer may be marked as Composition.CURSOR.
      * If validation succeeds (i.e., the device does not request a composition
      * change for that layer), then once a buffer has been set for the layer
      * and it has been presented, its position may be set by this function at
@@ -79,8 +73,8 @@
      * may be passed instead.
      *
      * This function must return NONE and have no other effect if called for a
-     * layer with a composition type of Composition::SOLID_COLOR (because it
-     * has no buffer) or Composition::SIDEBAND or Composition::CLIENT (because
+     * layer with a composition type of Composition.SOLID_COLOR (because it
+     * has no buffer) or Composition.SIDEBAND or Composition.CLIENT (because
      * synchronization and buffer updates for these layers are handled
      * elsewhere).
      */
@@ -115,14 +109,14 @@
 
     /**
      * Sets the color of the given layer. If the composition type of the layer
-     * is not Composition::SOLID_COLOR, this call must succeed and have no
+     * is not Composition.SOLID_COLOR, this call must succeed and have no
      * other effect.
      */
     @nullable Color color;
 
     /**
      * Sets the color of the given layer. If the composition type of the layer
-     * is not Composition::SOLID_COLOR, this call must succeed and have no
+     * is not Composition.SOLID_COLOR, this call must succeed and have no
      * other effect.
      */
     @nullable FloatColor floatColor;
@@ -155,20 +149,20 @@
      * Sets an alpha value (a floating point value in the range [0.0, 1.0])
      * which will be applied to the whole layer. It can be conceptualized as a
      * preprocessing step which applies the following function:
-     *   if (blendMode == BlendMode::PREMULTIPLIED)
+     *   if (blendMode == BlendMode.PREMULTIPLIED)
      *       out.rgb = in.rgb * planeAlpha
      *   out.a = in.a * planeAlpha
      *
      * If the device does not support this operation on a layer which is
-     * marked Composition::DEVICE, it must request a composition type change
-     * to Composition::CLIENT upon the next validateDisplay call.
+     * marked Composition.DEVICE, it must request a composition type change
+     * to Composition.CLIENT upon the next validateDisplay call.
      *
      */
     @nullable PlaneAlpha planeAlpha;
 
     /**
      * Sets the sideband stream for this layer. If the composition type of the
-     * given layer is not Composition::SIDEBAND, this call must succeed and
+     * given layer is not Composition.SIDEBAND, this call must succeed and
      * have no other effect.
      */
     @nullable NativeHandle sidebandStream;
@@ -180,7 +174,7 @@
      *
      * If the device is not capable of supporting a true float source crop
      * (i.e., it will truncate or round the floats to integers), it must set
-     * this layer to Composition::CLIENT when crop is non-integral for the
+     * this layer to Composition.CLIENT when crop is non-integral for the
      * most accurate rendering.
      *
      * If the device cannot support float source crops, but still wants to
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableBlendMode.aidl
similarity index 93%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableBlendMode.aidl
index f912853..a6c016a 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableBlendMode.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 import android.hardware.graphics.common.BlendMode;
 
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ParcelableComposition.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableComposition.aidl
similarity index 93%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/ParcelableComposition.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableComposition.aidl
index 91979d8..0946ce7 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ParcelableComposition.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableComposition.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 import android.hardware.graphics.composer3.Composition;
 
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ParcelableDataspace.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableDataspace.aidl
similarity index 93%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/ParcelableDataspace.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableDataspace.aidl
index 6be750d..528cdf9 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ParcelableDataspace.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableDataspace.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 import android.hardware.graphics.common.Dataspace;
 
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ParcelableTransform.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableTransform.aidl
similarity index 93%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/ParcelableTransform.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableTransform.aidl
index 910d014..75f9f7e 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ParcelableTransform.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ParcelableTransform.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 import android.hardware.graphics.common.Transform;
 
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/PlaneAlpha.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/PlaneAlpha.aidl
similarity index 93%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/PlaneAlpha.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/PlaneAlpha.aidl
index fa1889b..347dc19 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/PlaneAlpha.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/PlaneAlpha.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 @VintfStability
 parcelable PlaneAlpha {
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/PresentFence.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/PresentFence.aidl
similarity index 94%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/PresentFence.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/PresentFence.aidl
index 0c14406..244b4e5 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/PresentFence.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/PresentFence.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 @VintfStability
 parcelable PresentFence {
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/PresentOrValidate.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/PresentOrValidate.aidl
similarity index 94%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/PresentOrValidate.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/PresentOrValidate.aidl
index 7fc60c4..f3153bd 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/PresentOrValidate.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/PresentOrValidate.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 @VintfStability
 parcelable PresentOrValidate {
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ReleaseFences.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ReleaseFences.aidl
similarity index 95%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/ReleaseFences.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/ReleaseFences.aidl
index 762f5eb..459a042 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ReleaseFences.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ReleaseFences.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 @VintfStability
 parcelable ReleaseFences {
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/RenderIntent.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/RenderIntent.aidl
index 043b24d..debf32c 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/RenderIntent.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/RenderIntent.aidl
@@ -25,8 +25,8 @@
  * modes should not affect the mapping.
  *
  * RenderIntent overrides the render intents defined for individual color
- * modes. It is ignored when the color mode is ColorMode::NATIVE, because
- * ColorMode::NATIVE colors are already display colors.
+ * modes. It is ignored when the color mode is ColorMode.NATIVE, because
+ * ColorMode.NATIVE colors are already display colors.
  */
 @VintfStability
 @Backing(type="int")
@@ -36,7 +36,7 @@
      * gamut are hard-clipped.
      *
      * This implies that the display must have been calibrated unless
-     * ColorMode::NATIVE is the only supported color mode.
+     * ColorMode.NATIVE is the only supported color mode.
      */
     COLORIMETRIC = 0,
     /**
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/WhitePointNits.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/WhitePointNits.aidl
similarity index 94%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/WhitePointNits.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/WhitePointNits.aidl
index ec46cdf..2a1d1c6 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/WhitePointNits.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/WhitePointNits.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 @VintfStability
 parcelable WhitePointNits {
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ZOrder.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ZOrder.aidl
similarity index 93%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/command/ZOrder.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/ZOrder.aidl
index 68120b0..56cc200 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/ZOrder.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ZOrder.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.graphics.composer3;
 
 @VintfStability
 parcelable ZOrder {
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/CommandPayload.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/command/CommandPayload.aidl
deleted file mode 100644
index c1555e6..0000000
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/CommandPayload.aidl
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * 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.
- */
-
-package android.hardware.graphics.composer3.command;
-
-import android.hardware.graphics.composer3.command.DisplayCommand;
-import android.hardware.graphics.composer3.command.LayerCommand;
-
-/**
- * Type of commands that can be used in IComposerClient.executeCommands.
- * Note that this is a union and each command can only have one type.
- */
-@VintfStability
-union CommandPayload {
-    DisplayCommand displayCommand;
-    LayerCommand layerCommand;
-}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/translate-ndk.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/translate-ndk.cpp
index 5bda15a..a3c8176 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/translate-ndk.cpp
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/translate-ndk.cpp
@@ -74,7 +74,7 @@
 static_assert(aidl::android::hardware::graphics::composer3::Capability::SKIP_VALIDATE ==
               static_cast<aidl::android::hardware::graphics::composer3::Capability>(4));
 
-static_assert(aidl::android::hardware::graphics::composer3::command::DisplayRequest::LayerRequest::
+static_assert(aidl::android::hardware::graphics::composer3::DisplayRequest::LayerRequest::
                       CLEAR_CLIENT_TARGET ==
               static_cast<int>(::android::hardware::graphics::composer::V2_1::IComposerClient::
                                        LayerRequest::CLEAR_CLIENT_TARGET));
@@ -121,11 +121,10 @@
                       ::android::hardware::graphics::composer::V2_1::IComposerClient::Composition::
                               SIDEBAND));
 
-static_assert(
-        aidl::android::hardware::graphics::composer3::command::DisplayRequest::FLIP_CLIENT_TARGET ==
-        static_cast<int>(::android::hardware::graphics::composer::V2_1::IComposerClient::
-                                 DisplayRequest::FLIP_CLIENT_TARGET));
-static_assert(aidl::android::hardware::graphics::composer3::command::DisplayRequest::
+static_assert(aidl::android::hardware::graphics::composer3::DisplayRequest::FLIP_CLIENT_TARGET ==
+              static_cast<int>(::android::hardware::graphics::composer::V2_1::IComposerClient::
+                                       DisplayRequest::FLIP_CLIENT_TARGET));
+static_assert(aidl::android::hardware::graphics::composer3::DisplayRequest::
                       WRITE_CLIENT_TARGET_TO_OUTPUT ==
               static_cast<int>(::android::hardware::graphics::composer::V2_1::IComposerClient::
                                        DisplayRequest::WRITE_CLIENT_TARGET_TO_OUTPUT));
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_ReadbackTest.cpp
index 717b60c..8726043 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -140,7 +140,7 @@
             return;
         }
 
-        std::vector<command::CommandResultPayload> results;
+        std::vector<CommandResultPayload> results;
         const auto status = mComposerClient->executeCommands(commands, &results);
         ASSERT_TRUE(status.isOk()) << "executeCommands failed " << status.getDescription();
 
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp
index 7a20a53..272da7e 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -566,25 +566,6 @@
     }
 }
 
-TEST_P(GraphicsComposerAidlTest, getDisplayCapabilitiesBasic) {
-    std::vector<DisplayCapability> capabilities;
-    const auto error = mComposerClient->getDisplayCapabilities(mPrimaryDisplay, &capabilities);
-    ASSERT_TRUE(error.isOk());
-    const bool hasDozeSupport = std::find(capabilities.begin(), capabilities.end(),
-                                          DisplayCapability::DOZE) != capabilities.end();
-    bool isDozeSupported = false;
-    EXPECT_TRUE(mComposerClient->getDozeSupport(mPrimaryDisplay, &isDozeSupported).isOk());
-    EXPECT_EQ(hasDozeSupport, isDozeSupported);
-
-    bool hasBrightnessSupport = std::find(capabilities.begin(), capabilities.end(),
-                                          DisplayCapability::BRIGHTNESS) != capabilities.end();
-    bool isBrightnessSupported = false;
-    EXPECT_TRUE(
-            mComposerClient->getDisplayBrightnessSupport(mPrimaryDisplay, &isBrightnessSupported)
-                    .isOk());
-    EXPECT_EQ(isBrightnessSupported, hasBrightnessSupport);
-}
-
 /*
  * Test that if brightness operations are supported, setDisplayBrightness works as expected.
  */
@@ -1009,16 +990,14 @@
     }
 }
 
-TEST_P(GraphicsComposerAidlTest, GetDozeSupportBadDisplay) {
-    bool isDozeSupport;
-    const auto error = mComposerClient->getDozeSupport(mInvalidDisplayId, &isDozeSupport);
-    EXPECT_FALSE(error.isOk());
-    ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
-}
-
 TEST_P(GraphicsComposerAidlTest, SetPowerModeUnsupported) {
-    bool isDozeSupported;
-    mComposerClient->getDozeSupport(mPrimaryDisplay, &isDozeSupported).isOk();
+    std::vector<DisplayCapability> capabilities;
+    const auto error = mComposerClient->getDisplayCapabilities(mPrimaryDisplay, &capabilities);
+    ASSERT_TRUE(error.isOk());
+    const bool isDozeSupported = std::find(capabilities.begin(), capabilities.end(),
+                                           DisplayCapability::DOZE) != capabilities.end();
+    const bool isSuspendSupported = std::find(capabilities.begin(), capabilities.end(),
+                                              DisplayCapability::SUSPEND) != capabilities.end();
     if (!isDozeSupported) {
         auto error = mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::DOZE);
         EXPECT_FALSE(error.isOk());
@@ -1028,6 +1007,16 @@
         EXPECT_FALSE(error.isOk());
         EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, error.getServiceSpecificError());
     }
+
+    if (!isSuspendSupported) {
+        auto error = mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON_SUSPEND);
+        EXPECT_FALSE(error.isOk());
+        EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, error.getServiceSpecificError());
+
+        error = mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::DOZE_SUSPEND);
+        EXPECT_FALSE(error.isOk());
+        EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, error.getServiceSpecificError());
+    }
 }
 
 TEST_P(GraphicsComposerAidlTest, SetVsyncEnabled) {
@@ -1041,15 +1030,27 @@
 }
 
 TEST_P(GraphicsComposerAidlTest, SetPowerMode) {
+    std::vector<DisplayCapability> capabilities;
+    const auto error = mComposerClient->getDisplayCapabilities(mPrimaryDisplay, &capabilities);
+    ASSERT_TRUE(error.isOk());
+    const bool isDozeSupported = std::find(capabilities.begin(), capabilities.end(),
+                                           DisplayCapability::DOZE) != capabilities.end();
+    const bool isSuspendSupported = std::find(capabilities.begin(), capabilities.end(),
+                                              DisplayCapability::SUSPEND) != capabilities.end();
+
     std::vector<PowerMode> modes;
     modes.push_back(PowerMode::OFF);
-    modes.push_back(PowerMode::ON_SUSPEND);
     modes.push_back(PowerMode::ON);
 
-    bool isDozeSupported;
-    EXPECT_TRUE(mComposerClient->getDozeSupport(mPrimaryDisplay, &isDozeSupported).isOk());
+    if (isSuspendSupported) {
+        modes.push_back(PowerMode::ON_SUSPEND);
+    }
+
     if (isDozeSupported) {
         modes.push_back(PowerMode::DOZE);
+    }
+
+    if (isSuspendSupported && isDozeSupported) {
         modes.push_back(PowerMode::DOZE_SUSPEND);
     }
 
@@ -1059,6 +1060,14 @@
 }
 
 TEST_P(GraphicsComposerAidlTest, SetPowerModeVariations) {
+    std::vector<DisplayCapability> capabilities;
+    const auto error = mComposerClient->getDisplayCapabilities(mPrimaryDisplay, &capabilities);
+    ASSERT_TRUE(error.isOk());
+    const bool isDozeSupported = std::find(capabilities.begin(), capabilities.end(),
+                                           DisplayCapability::DOZE) != capabilities.end();
+    const bool isSuspendSupported = std::find(capabilities.begin(), capabilities.end(),
+                                              DisplayCapability::SUSPEND) != capabilities.end();
+
     std::vector<PowerMode> modes;
 
     modes.push_back(PowerMode::OFF);
@@ -1083,15 +1092,15 @@
     }
     modes.clear();
 
-    modes.push_back(PowerMode::ON_SUSPEND);
-    modes.push_back(PowerMode::ON_SUSPEND);
-    for (auto mode : modes) {
-        EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
+    if (isSuspendSupported) {
+        modes.push_back(PowerMode::ON_SUSPEND);
+        modes.push_back(PowerMode::ON_SUSPEND);
+        for (auto mode : modes) {
+            EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
+        }
+        modes.clear();
     }
-    modes.clear();
 
-    bool isDozeSupported = false;
-    ASSERT_TRUE(mComposerClient->getDozeSupport(mPrimaryDisplay, &isDozeSupported).isOk());
     if (isDozeSupported) {
         modes.push_back(PowerMode::DOZE);
         modes.push_back(PowerMode::DOZE);
@@ -1099,12 +1108,15 @@
             EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
         }
         modes.clear();
+    }
 
+    if (isSuspendSupported && isDozeSupported) {
         modes.push_back(PowerMode::DOZE_SUSPEND);
         modes.push_back(PowerMode::DOZE_SUSPEND);
         for (auto mode : modes) {
             EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, mode).isOk());
         }
+        modes.clear();
     }
 }
 
@@ -1168,7 +1180,7 @@
             return;
         }
 
-        std::vector<command::CommandResultPayload> results;
+        std::vector<CommandResultPayload> results;
         const auto status = mComposerClient->executeCommands(commands, &results);
         ASSERT_TRUE(status.isOk()) << "executeCommands failed " << status.getDescription();
 
@@ -1251,7 +1263,7 @@
         int64_t layer = 0;
         ASSERT_NO_FATAL_FAILURE(layer = createLayer(display));
         {
-            auto buffer = allocate();
+            const auto buffer = allocate();
             ASSERT_NE(nullptr, buffer);
             ASSERT_EQ(::android::OK, buffer->initCheck());
             ASSERT_NE(nullptr, buffer->handle);
@@ -1280,7 +1292,7 @@
         }
 
         {
-            auto buffer = allocate();
+            const auto buffer = allocate();
             ASSERT_NE(nullptr, buffer->handle);
 
             mWriter.setLayerBuffer(display.get(), layer, 0, buffer->handle, -1);
@@ -1442,7 +1454,8 @@
                                                kBufferSlotCount, &display)
                         .isOk());
 
-    auto handle = allocate()->handle;
+    const auto buffer = allocate();
+    const auto handle = buffer->handle;
     mWriter.setOutputBuffer(display.display, 0, handle, -1);
     execute();
 }
@@ -1488,7 +1501,8 @@
     for (auto intent : renderIntents) {
         mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::NATIVE, intent);
 
-        auto handle = allocate()->handle;
+        const auto buffer = allocate();
+        const auto handle = buffer->handle;
         ASSERT_NE(nullptr, handle);
 
         Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight};
@@ -1523,7 +1537,8 @@
         execute();
         ASSERT_TRUE(mReader.takeErrors().empty());
 
-        auto handle2 = allocate()->handle;
+        const auto buffer2 = allocate();
+        const auto handle2 = buffer2->handle;
         ASSERT_NE(nullptr, handle2);
         mWriter.setLayerBuffer(mPrimaryDisplay, layer, 0, handle2, -1);
         mWriter.setLayerSurfaceDamage(mPrimaryDisplay, layer, std::vector<Rect>(1, {0, 0, 10, 10}));
@@ -1537,7 +1552,8 @@
     int64_t layer;
     EXPECT_TRUE(mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount, &layer).isOk());
 
-    auto handle = allocate()->handle;
+    const auto buffer = allocate();
+    const auto handle = buffer->handle;
     ASSERT_NE(nullptr, handle);
     Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight};
 
@@ -1576,7 +1592,8 @@
 }
 
 TEST_P(GraphicsComposerAidlCommandTest, SET_LAYER_BUFFER) {
-    auto handle = allocate()->handle;
+    const auto buffer = allocate();
+    const auto handle = buffer->handle;
     ASSERT_NE(nullptr, handle);
 
     int64_t layer;
@@ -1696,7 +1713,8 @@
         return;
     }
 
-    auto handle = allocate()->handle;
+    const auto buffer = allocate();
+    const auto handle = buffer->handle;
     ASSERT_NE(nullptr, handle);
 
     int64_t layer;
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/command-buffer.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/command-buffer.h
index bdf97ca..fcf2a34 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/command-buffer.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/command-buffer.h
@@ -37,8 +37,8 @@
 #include <aidl/android/hardware/graphics/composer3/PerFrameMetadata.h>
 #include <aidl/android/hardware/graphics/composer3/PerFrameMetadataBlob.h>
 
-#include <aidl/android/hardware/graphics/composer3/command/CommandPayload.h>
-#include <aidl/android/hardware/graphics/composer3/command/CommandResultPayload.h>
+#include <aidl/android/hardware/graphics/composer3/CommandResultPayload.h>
+#include <aidl/android/hardware/graphics/composer3/DisplayCommand.h>
 
 #include <aidl/android/hardware/graphics/common/ColorTransform.h>
 #include <aidl/android/hardware/graphics/common/FRect.h>
@@ -79,14 +79,14 @@
     }
 
     void setError(int32_t index, int32_t errorCode) {
-        command::Error error;
+        CommandError error;
         error.commandIndex = index;
         error.errorCode = errorCode;
         mCommandsResults.emplace_back(std::move(error));
     }
 
-    void setPresentOrValidateResult(int64_t display, command::PresentOrValidate::Result result) {
-        command::PresentOrValidate presentOrValidate;
+    void setPresentOrValidateResult(int64_t display, PresentOrValidate::Result result) {
+        PresentOrValidate presentOrValidate;
         presentOrValidate.display = display;
         presentOrValidate.result = result;
         mCommandsResults.emplace_back(std::move(presentOrValidate));
@@ -94,12 +94,11 @@
 
     void setChangedCompositionTypes(int64_t display, const std::vector<int64_t>& layers,
                                     const std::vector<Composition>& types) {
-        command::ChangedCompositionTypes changedCompositionTypes;
+        ChangedCompositionTypes changedCompositionTypes;
         changedCompositionTypes.display = display;
         changedCompositionTypes.layers.reserve(layers.size());
         for (int i = 0; i < layers.size(); i++) {
-            auto layer = command::ChangedCompositionTypes::Layer{.layer = layers[i],
-                                                                 .composition = types[i]};
+            auto layer = ChangedCompositionLayer{.layer = layers[i], .composition = types[i]};
             changedCompositionTypes.layers.emplace_back(std::move(layer));
         }
         mCommandsResults.emplace_back(std::move(changedCompositionTypes));
@@ -108,13 +107,13 @@
     void setDisplayRequests(int64_t display, int32_t displayRequestMask,
                             const std::vector<int64_t>& layers,
                             const std::vector<int32_t>& layerRequestMasks) {
-        command::DisplayRequest displayRequest;
+        DisplayRequest displayRequest;
         displayRequest.display = display;
         displayRequest.mask = displayRequestMask;
         displayRequest.layerRequests.reserve(layers.size());
         for (int i = 0; i < layers.size(); i++) {
-            auto layerRequest = command::DisplayRequest::LayerRequest{.layer = layers[i],
-                                                                      .mask = layerRequestMasks[i]};
+            auto layerRequest =
+                    DisplayRequest::LayerRequest{.layer = layers[i], .mask = layerRequestMasks[i]};
             displayRequest.layerRequests.emplace_back(std::move(layerRequest));
         }
         mCommandsResults.emplace_back(std::move(displayRequest));
@@ -122,7 +121,7 @@
 
     void setPresentFence(int64_t display, ::ndk::ScopedFileDescriptor presentFence) {
         if (presentFence.get() >= 0) {
-            command::PresentFence presentFenceCommand;
+            PresentFence presentFenceCommand;
             presentFenceCommand.fence = std::move(presentFence);
             presentFenceCommand.display = display;
             mCommandsResults.emplace_back(std::move(presentFenceCommand));
@@ -133,11 +132,11 @@
 
     void setReleaseFences(int64_t display, const std::vector<int64_t>& layers,
                           std::vector<::ndk::ScopedFileDescriptor> releaseFences) {
-        command::ReleaseFences releaseFencesCommand;
+        ReleaseFences releaseFencesCommand;
         releaseFencesCommand.display = display;
         for (int i = 0; i < layers.size(); i++) {
             if (releaseFences[i].get() >= 0) {
-                command::ReleaseFences::Layer layer;
+                ReleaseFences::Layer layer;
                 layer.layer = layers[i];
                 layer.fence = std::move(releaseFences[i]);
                 releaseFencesCommand.layers.emplace_back(std::move(layer));
@@ -150,7 +149,7 @@
 
     void setClientTargetProperty(int64_t display, const ClientTargetProperty& clientTargetProperty,
                                  float whitePointNits) {
-        command::ClientTargetPropertyWithNits clientTargetPropertyWithNits;
+        ClientTargetPropertyWithNits clientTargetPropertyWithNits;
         clientTargetPropertyWithNits.display = display;
         clientTargetPropertyWithNits.clientTargetProperty = clientTargetProperty;
         clientTargetPropertyWithNits.whitePointNits = whitePointNits;
@@ -158,7 +157,7 @@
     }
 
     void setColorTransform(int64_t display, const float* matrix, ColorTransform hint) {
-        command::ColorTransformPayload colorTransformPayload;
+        ColorTransformPayload colorTransformPayload;
         colorTransformPayload.matrix.assign(matrix, matrix + 16);
         colorTransformPayload.hint = hint;
         getDisplayCommand(display).colorTransform.emplace(std::move(colorTransformPayload));
@@ -166,7 +165,7 @@
 
     void setClientTarget(int64_t display, uint32_t slot, const native_handle_t* target,
                          int acquireFence, Dataspace dataspace, const std::vector<Rect>& damage) {
-        command::ClientTarget clientTargetCommand;
+        ClientTarget clientTargetCommand;
         clientTargetCommand.buffer = getBuffer(slot, target, acquireFence);
         clientTargetCommand.dataspace = dataspace;
         clientTargetCommand.damage.assign(damage.begin(), damage.end());
@@ -208,7 +207,7 @@
     }
 
     void setLayerBlendMode(int64_t display, int64_t layer, BlendMode mode) {
-        command::ParcelableBlendMode parcelableBlendMode;
+        ParcelableBlendMode parcelableBlendMode;
         parcelableBlendMode.blendMode = mode;
         getLayerCommand(display, layer).blendMode.emplace(std::move(parcelableBlendMode));
     }
@@ -218,13 +217,13 @@
     }
 
     void setLayerCompositionType(int64_t display, int64_t layer, Composition type) {
-        command::ParcelableComposition compositionPayload;
+        ParcelableComposition compositionPayload;
         compositionPayload.composition = type;
         getLayerCommand(display, layer).composition.emplace(std::move(compositionPayload));
     }
 
     void setLayerDataspace(int64_t display, int64_t layer, Dataspace dataspace) {
-        command::ParcelableDataspace dataspacePayload;
+        ParcelableDataspace dataspacePayload;
         dataspacePayload.dataspace = dataspace;
         getLayerCommand(display, layer).dataspace.emplace(std::move(dataspacePayload));
     }
@@ -234,7 +233,7 @@
     }
 
     void setLayerPlaneAlpha(int64_t display, int64_t layer, float alpha) {
-        command::PlaneAlpha planeAlpha;
+        PlaneAlpha planeAlpha;
         planeAlpha.alpha = alpha;
         getLayerCommand(display, layer).planeAlpha.emplace(std::move(planeAlpha));
     }
@@ -250,7 +249,7 @@
     }
 
     void setLayerTransform(int64_t display, int64_t layer, Transform transform) {
-        command::ParcelableTransform transformPayload;
+        ParcelableTransform transformPayload;
         transformPayload.transform = transform;
         getLayerCommand(display, layer).transform.emplace(std::move(transformPayload));
     }
@@ -260,7 +259,7 @@
     }
 
     void setLayerZOrder(int64_t display, int64_t layer, uint32_t z) {
-        command::ZOrder zorder;
+        ZOrder zorder;
         zorder.z = z;
         getLayerCommand(display, layer).z.emplace(std::move(zorder));
     }
@@ -287,63 +286,73 @@
 
     void setLayerGenericMetadata(int64_t display, int64_t layer, const std::string& key,
                                  const bool mandatory, const std::vector<uint8_t>& value) {
-        command::GenericMetadata metadata;
+        GenericMetadata metadata;
         metadata.key.name = key;
         metadata.key.mandatory = mandatory;
         metadata.value.assign(value.begin(), value.end());
         getLayerCommand(display, layer).genericMetadata.emplace(std::move(metadata));
     }
 
-    const std::vector<command::CommandPayload>& getPendingCommands() {
-        if (mLayerCommand.has_value()) {
-            mCommands.emplace_back(std::move(*mLayerCommand));
-            mLayerCommand.reset();
-        }
-        if (mDisplayCommand.has_value()) {
-            mCommands.emplace_back(std::move(*mDisplayCommand));
-            mDisplayCommand.reset();
-        }
+    void setLayerWhitePointNits(int64_t display, int64_t layer, float whitePointNits) {
+        getLayerCommand(display, layer)
+                .whitePointNits.emplace(WhitePointNits{.nits = whitePointNits});
+    }
+
+    const std::vector<DisplayCommand>& getPendingCommands() {
+        flushLayerCommand();
+        flushDisplayCommand();
         return mCommands;
     }
-    std::vector<command::CommandResultPayload> getPendingCommandResults() {
+
+    std::vector<CommandResultPayload> getPendingCommandResults() {
         return std::move(mCommandsResults);
     }
 
   protected:
-    command::Buffer getBuffer(int slot, const native_handle_t* bufferHandle, int fence) {
-        command::Buffer bufferCommand;
+    Buffer getBuffer(int slot, const native_handle_t* bufferHandle, int fence) {
+        Buffer bufferCommand;
         bufferCommand.slot = slot;
         if (bufferHandle) bufferCommand.handle.emplace(::android::dupToAidl(bufferHandle));
         if (fence > 0) bufferCommand.fence = ::ndk::ScopedFileDescriptor(fence);
         return bufferCommand;
     }
 
-    std::optional<command::DisplayCommand> mDisplayCommand;
-    std::optional<command::LayerCommand> mLayerCommand;
-    std::vector<command::CommandPayload> mCommands;
-    std::vector<command::CommandResultPayload> mCommandsResults;
+    std::optional<DisplayCommand> mDisplayCommand;
+    std::optional<LayerCommand> mLayerCommand;
+    std::vector<DisplayCommand> mCommands;
+    std::vector<CommandResultPayload> mCommandsResults;
 
   private:
-    // std::vector<native_handle_t*> mTemporaryHandles;
+    void flushLayerCommand() {
+        if (mLayerCommand.has_value()) {
+            mDisplayCommand->layers.emplace_back(std::move(*mLayerCommand));
+            mLayerCommand.reset();
+        }
+    }
 
-    command::DisplayCommand& getDisplayCommand(int64_t display) {
+    void flushDisplayCommand() {
+        if (mDisplayCommand.has_value()) {
+            mCommands.emplace_back(std::move(*mDisplayCommand));
+            mDisplayCommand.reset();
+        }
+    }
+
+    DisplayCommand& getDisplayCommand(int64_t display) {
         if (!mDisplayCommand.has_value() || mDisplayCommand->display != display) {
-            if (mDisplayCommand.has_value()) mCommands.emplace_back(std::move(*mDisplayCommand));
+            flushLayerCommand();
+            flushDisplayCommand();
             mDisplayCommand.emplace();
             mDisplayCommand->display = display;
-            return *mDisplayCommand;
         }
         return *mDisplayCommand;
     }
 
-    command::LayerCommand& getLayerCommand(int64_t display, int64_t layer) {
-        if (!mLayerCommand.has_value() || mLayerCommand->display != display ||
-            mLayerCommand->layer != layer) {
-            if (mLayerCommand.has_value()) mCommands.emplace_back(std::move(*mLayerCommand));
+    LayerCommand& getLayerCommand(int64_t display, int64_t layer) {
+        getDisplayCommand(display);
+        if (!mLayerCommand.has_value() || mLayerCommand->layer != layer) {
+            flushLayerCommand();
             mLayerCommand.emplace();
-            mLayerCommand->display = display;
             mLayerCommand->layer = layer;
-            return *mLayerCommand;
         }
         return *mLayerCommand;
     }
@@ -355,45 +364,41 @@
 
     // Parse and execute commands from the command queue.  The commands are
     // actually return values from the server and will be saved in ReturnData.
-    void parse(const std::vector<command::CommandResultPayload>& results) {
+    void parse(const std::vector<CommandResultPayload>& results) {
         resetData();
 
         for (const auto& result : results) {
             switch (result.getTag()) {
-                case command::CommandResultPayload::Tag::error:
-                    parseSetError(result.get<command::CommandResultPayload::Tag::error>());
+                case CommandResultPayload::Tag::error:
+                    parseSetError(result.get<CommandResultPayload::Tag::error>());
                     break;
-                case command::CommandResultPayload::Tag::changedCompositionType:
+                case CommandResultPayload::Tag::changedCompositionTypes:
                     parseSetChangedCompositionTypes(
-                            result.get<
-                                    command::CommandResultPayload::Tag::changedCompositionType>());
+                            result.get<CommandResultPayload::Tag::changedCompositionTypes>());
                     break;
-                case command::CommandResultPayload::Tag::displayRequest:
+                case CommandResultPayload::Tag::displayRequest:
                     parseSetDisplayRequests(
-                            result.get<command::CommandResultPayload::Tag::displayRequest>());
+                            result.get<CommandResultPayload::Tag::displayRequest>());
                     break;
-                case command::CommandResultPayload::Tag::presentFence:
-                    parseSetPresentFence(
-                            result.get<command::CommandResultPayload::Tag::presentFence>());
+                case CommandResultPayload::Tag::presentFence:
+                    parseSetPresentFence(result.get<CommandResultPayload::Tag::presentFence>());
                     break;
-                case command::CommandResultPayload::Tag::releaseFences:
-                    parseSetReleaseFences(
-                            result.get<command::CommandResultPayload::Tag::releaseFences>());
+                case CommandResultPayload::Tag::releaseFences:
+                    parseSetReleaseFences(result.get<CommandResultPayload::Tag::releaseFences>());
                     break;
-                case command::CommandResultPayload::Tag::presentOrValidateResult:
+                case CommandResultPayload::Tag::presentOrValidateResult:
                     parseSetPresentOrValidateDisplayResult(
-                            result.get<
-                                    command::CommandResultPayload::Tag::presentOrValidateResult>());
+                            result.get<CommandResultPayload::Tag::presentOrValidateResult>());
                     break;
-                case command::CommandResultPayload::Tag::clientTargetProperty:
+                case CommandResultPayload::Tag::clientTargetProperty:
                     parseSetClientTargetProperty(
-                            result.get<command::CommandResultPayload::Tag::clientTargetProperty>());
+                            result.get<CommandResultPayload::Tag::clientTargetProperty>());
                     break;
             }
         }
     }
 
-    std::vector<command::Error> takeErrors() { return std::move(mErrors); }
+    std::vector<CommandError> takeErrors() { return std::move(mErrors); }
 
     bool hasChanges(int64_t display, uint32_t* outNumChangedCompositionTypes,
                     uint32_t* outNumLayerRequestMasks) const {
@@ -489,18 +494,21 @@
     }
 
     // Get the client target properties requested by hardware composer.
-    void takeClientTargetProperty(int64_t display, ClientTargetProperty* outClientTargetProperty) {
+    void takeClientTargetProperty(int64_t display, ClientTargetProperty* outClientTargetProperty,
+                                  float* outWhitePointNits) {
         auto found = mReturnData.find(display);
 
         // If not found, return the default values.
         if (found == mReturnData.end()) {
             outClientTargetProperty->pixelFormat = common::PixelFormat::RGBA_8888;
             outClientTargetProperty->dataspace = Dataspace::UNKNOWN;
+            *outWhitePointNits = -1.f;
             return;
         }
 
         ReturnData& data = found->second;
         *outClientTargetProperty = data.clientTargetProperty;
+        *outWhitePointNits = data.clientTargetWhitePointNits;
     }
 
   private:
@@ -521,10 +529,9 @@
         mReturnData.clear();
     }
 
-    void parseSetError(const command::Error& error) { mErrors.emplace_back(error); }
+    void parseSetError(const CommandError& error) { mErrors.emplace_back(error); }
 
-    void parseSetChangedCompositionTypes(
-            const command::ChangedCompositionTypes& changedCompositionTypes) {
+    void parseSetChangedCompositionTypes(const ChangedCompositionTypes& changedCompositionTypes) {
         auto& data = mReturnData[changedCompositionTypes.display];
 
         data.changedLayers.reserve(changedCompositionTypes.layers.size());
@@ -535,7 +542,7 @@
         }
     }
 
-    void parseSetDisplayRequests(const command::DisplayRequest& displayRequest) {
+    void parseSetDisplayRequests(const DisplayRequest& displayRequest) {
         auto& data = mReturnData[displayRequest.display];
 
         data.displayRequests = displayRequest.mask;
@@ -547,7 +554,7 @@
         }
     }
 
-    void parseSetPresentFence(const command::PresentFence& presentFence) {
+    void parseSetPresentFence(const PresentFence& presentFence) {
         auto& data = mReturnData[presentFence.display];
         if (data.presentFence >= 0) {
             close(data.presentFence);
@@ -555,7 +562,7 @@
         data.presentFence = dup(presentFence.fence.get());
     }
 
-    void parseSetReleaseFences(const command::ReleaseFences& releaseFences) {
+    void parseSetReleaseFences(const ReleaseFences& releaseFences) {
         auto& data = mReturnData[releaseFences.display];
         data.releasedLayers.reserve(releaseFences.layers.size());
         data.releaseFences.reserve(releaseFences.layers.size());
@@ -565,19 +572,18 @@
         }
     }
 
-    void parseSetPresentOrValidateDisplayResult(
-            const command::PresentOrValidate& presentOrValidate) {
+    void parseSetPresentOrValidateDisplayResult(const PresentOrValidate& presentOrValidate) {
         auto& data = mReturnData[presentOrValidate.display];
         data.presentOrValidateState =
-                presentOrValidate.result == command::PresentOrValidate::Result::Presented ? 1 : 0;
+                presentOrValidate.result == PresentOrValidate::Result::Presented ? 1 : 0;
     }
 
-    void parseSetClientTargetProperty(
-            const command::ClientTargetPropertyWithNits& clientTargetProperty) {
+    void parseSetClientTargetProperty(const ClientTargetPropertyWithNits& clientTargetProperty) {
         auto& data = mReturnData[clientTargetProperty.display];
         data.clientTargetProperty.pixelFormat =
                 clientTargetProperty.clientTargetProperty.pixelFormat;
         data.clientTargetProperty.dataspace = clientTargetProperty.clientTargetProperty.dataspace;
+        data.clientTargetWhitePointNits = clientTargetProperty.whitePointNits;
     }
 
     struct ReturnData {
@@ -598,9 +604,10 @@
 
         ClientTargetProperty clientTargetProperty{common::PixelFormat::RGBA_8888,
                                                   Dataspace::UNKNOWN};
+        float clientTargetWhitePointNits = -1.f;
     };
 
-    std::vector<command::Error> mErrors;
+    std::vector<CommandError> mErrors;
     std::unordered_map<int64_t, ReturnData> mReturnData;
 };
 
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/OperationType.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/OperationType.aidl
index aebe8d9..0ad254d 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/OperationType.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/OperationType.aidl
@@ -5385,7 +5385,7 @@
      *      must be in the range [0, n).
      *
      * Outputs:
-     * * 0: The reversed tensor.
+     * * 0: The reversed tensor of the same shape as the input tensor.
      *      For {@link OperandType::TENSOR_QUANT8_ASYMM} and
      *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensors,
      *      the scales and zeroPoint must be the same as input0.
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsInfo.aidl
index 2da0167..93940fd 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsInfo.aidl
@@ -36,6 +36,5 @@
 parcelable ActivityStatsInfo {
   int sleepModeTimeMs;
   int idleModeTimeMs;
-  int[] txmModetimeMs;
-  int rxModeTimeMs;
+  android.hardware.radio.modem.ActivityStatsTechSpecificInfo[] techSpecificInfo;
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
similarity index 75%
copy from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl
copy to radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
index 5e6d212..798ec36 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
@@ -1,11 +1,11 @@
-/**
- * Copyright (c) 2021, The Android Open Source Project
+/*
+ * 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
+ *      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,
@@ -31,8 +31,16 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.radio.modem;
 @VintfStability
-parcelable ParcelableBlendMode {
-  android.hardware.graphics.common.BlendMode blendMode;
+parcelable ActivityStatsTechSpecificInfo {
+  android.hardware.radio.AccessNetwork rat;
+  int frequencyRange;
+  int[] txmModetimeMs;
+  int rxModeTimeMs;
+  const int FREQUENCY_RANGE_UNKNOWN = 0;
+  const int FREQUENCY_RANGE_LOW = 1;
+  const int FREQUENCY_RANGE_MID = 2;
+  const int FREQUENCY_RANGE_HIGH = 3;
+  const int FREQUENCY_RANGE_MMWAVE = 4;
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
index 16433be..c618791 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
@@ -68,4 +68,6 @@
   oneway void startNetworkScan(in int serial, in android.hardware.radio.network.NetworkScanRequest request);
   oneway void stopNetworkScan(in int serial);
   oneway void supplyNetworkDepersonalization(in int serial, in String netPin);
+  oneway void setUsageSetting(in int serial, in android.hardware.radio.network.UsageSetting usageSetting);
+  oneway void getUsageSetting(in int serial);
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
index ff95396..8cf4c31 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -67,4 +67,6 @@
   oneway void startNetworkScanResponse(in android.hardware.radio.RadioResponseInfo info);
   oneway void stopNetworkScanResponse(in android.hardware.radio.RadioResponseInfo info);
   oneway void supplyNetworkDepersonalizationResponse(in android.hardware.radio.RadioResponseInfo info, in int remainingRetries);
+  oneway void setUsageSettingResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void getUsageSettingResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.UsageSetting usageSetting);
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/WhitePointNits.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl
similarity index 85%
copy from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/WhitePointNits.aidl
copy to radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl
index 2b25167..7fdf831 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/WhitePointNits.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl
@@ -1,11 +1,11 @@
-/**
- * Copyright (c) 2021, The Android Open Source Project
+/*
+ * 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
+ *      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,
@@ -31,8 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
-@VintfStability
-parcelable WhitePointNits {
-  float nits;
+package android.hardware.radio.network;
+@Backing(type="int") @VintfStability
+enum UsageSetting {
+  VOICE_CENTRIC = 1,
+  DATA_CENTRIC = 2,
 }
diff --git a/radio/aidl/android/hardware/radio/modem/ActivityStatsInfo.aidl b/radio/aidl/android/hardware/radio/modem/ActivityStatsInfo.aidl
index 764a86d..d0aa695 100644
--- a/radio/aidl/android/hardware/radio/modem/ActivityStatsInfo.aidl
+++ b/radio/aidl/android/hardware/radio/modem/ActivityStatsInfo.aidl
@@ -16,6 +16,8 @@
 
 package android.hardware.radio.modem;
 
+import android.hardware.radio.modem.ActivityStatsTechSpecificInfo;
+
 @VintfStability
 parcelable ActivityStatsInfo {
     /**
@@ -28,17 +30,10 @@
      */
     int idleModeTimeMs;
     /**
-     * Each index represent total time (in ms) during which the transmitter is active/awake for a
-     * particular power range as shown below.
-     * index 0 = tx_power < 0dBm
-     * index 1 = 0dBm < tx_power < 5dBm
-     * index 2 = 5dBm < tx_power < 15dBm
-     * index 3 = 15dBm < tx_power < 20dBm
-     * index 4 = tx_power > 20dBm
+     * Technology specific activity stats info.
+     * List of the activity stats for each RATs (2G, 3G, 4G and 5G) and frequency ranges (HIGH for
+     * sub6 and MMWAVE) in case of 5G. In case implementation doesn't have RAT specific activity
+     * stats then send only one activity stats info with RAT unknown.
      */
-    int[] txmModetimeMs;
-    /**
-     * Total time (in ms) for which receiver is active/awake and the transmitter is inactive
-     */
-    int rxModeTimeMs;
+    ActivityStatsTechSpecificInfo[] techSpecificInfo;
 }
diff --git a/radio/aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl b/radio/aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
new file mode 100644
index 0000000..fb14223
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+package android.hardware.radio.modem;
+
+import android.hardware.radio.AccessNetwork;
+
+@VintfStability
+parcelable ActivityStatsTechSpecificInfo {
+    /** Indicates the frequency range is unknown. */
+    const int FREQUENCY_RANGE_UNKNOWN = 0;
+    /** Indicates the frequency range is below 1GHz. */
+    const int FREQUENCY_RANGE_LOW = 1;
+    /** Indicates the frequency range is between 1GHz and 3GHz. */
+    const int FREQUENCY_RANGE_MID = 2;
+    /** Indicates the frequency range is between 3GHz and 6GHz. */
+    const int FREQUENCY_RANGE_HIGH = 3;
+    /** Indicates the frequency range is above 6GHz (millimeter wave frequency). */
+    const int FREQUENCY_RANGE_MMWAVE = 4;
+    /**
+     * Radio access technology. Set UNKNOWN if the Activity statistics
+     * is RAT independent.
+     */
+    AccessNetwork rat;
+    /**
+     * Frequency range. Values are FREQUENCY_RANGE_
+     * Set FREQUENCY_RANGE_UNKNOWN if the Activity statistics when frequency range
+     * is not applicable.
+     */
+    int frequencyRange;
+    /**
+     * Each index represent total time (in ms) during which the transmitter is active/awake for a
+     * particular power range as shown below.
+     * index 0 = tx_power <= 0dBm
+     * index 1 = 0dBm < tx_power <= 5dBm
+     * index 2 = 5dBm < tx_power <= 15dBm
+     * index 3 = 15dBm < tx_power <= 20dBm
+     * index 4 = tx_power > 20dBm
+     */
+    int[] txmModetimeMs;
+    /**
+     * Total time (in ms) for which receiver is active/awake and the transmitter is inactive
+     */
+    int rxModeTimeMs;
+}
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
index 1081a75..aaf432a 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
@@ -27,6 +27,7 @@
 import android.hardware.radio.network.RadioAccessSpecifier;
 import android.hardware.radio.network.RadioBandMode;
 import android.hardware.radio.network.SignalThresholdInfo;
+import android.hardware.radio.network.UsageSetting;
 
 /**
  * This interface is used by telephony and telecom to talk to cellular radio for network APIs.
@@ -416,4 +417,25 @@
      * Response function is IRadioNetworkResponse.supplyNetworkDepersonalizationResponse()
      */
     void supplyNetworkDepersonalization(in int serial, in String netPin);
+
+    /**
+     * Set the UE usage setting for data/voice centric usage.
+     *
+     * <p>Sets the usage setting in accordance with 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3.
+     * <p>This value must be independently preserved for each SIM; (setting the value is not a
+     * "global" override).
+     *
+     * @param serial Serial number of request.
+     * @param usageSetting the usage setting for the current SIM.
+     */
+    oneway void setUsageSetting(in int serial, in UsageSetting usageSetting);
+
+    /**
+     * Get the UE usage setting for data/voice centric usage.
+     *
+     * <p>Gets the usage setting in accordance with 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3.
+     *
+     * @param serial Serial number of request.
+     */
+    oneway void getUsageSetting(in int serial);
 }
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
index 429b5a8..30f4221 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -31,6 +31,7 @@
 import android.hardware.radio.network.RadioBandMode;
 import android.hardware.radio.network.RegStateResult;
 import android.hardware.radio.network.SignalStrength;
+import android.hardware.radio.network.UsageSetting;
 
 /**
  * Interface declaring response functions to solicited radio requests for network APIs.
@@ -549,4 +550,30 @@
      *   RadioError:SIM_ABSENT
      */
     void supplyNetworkDepersonalizationResponse(in RadioResponseInfo info, in int remainingRetries);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_STATE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SIM_ABSENT
+     */
+    oneway void setUsageSettingResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error.
+     * @param usageSetting the usage setting for the current SIM.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_STATE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SIM_ABSENT
+     */
+    oneway void getUsageSettingResponse(in RadioResponseInfo info, in UsageSetting usageSetting);
 }
diff --git a/radio/aidl/android/hardware/radio/network/UsageSetting.aidl b/radio/aidl/android/hardware/radio/network/UsageSetting.aidl
new file mode 100644
index 0000000..ba8fe93
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/UsageSetting.aidl
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+package android.hardware.radio.network;
+
+/**
+ * Cellular usage setting with values according to 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3.
+ *
+ * <p>Also refer to "UE's usage setting" as defined in 3gpp 24.301 section 3.1 and 3gpp 23.221
+ * Annex A.
+ */
+@VintfStability
+@Backing(type="int")
+enum UsageSetting {
+    /**
+     * UE operates in voice-centric mode. Generally speaking, in this mode of operation, the UE
+     * will not remain camped on a cell or attached to a network unless that cell/network provides
+     * voice service.
+     */
+    VOICE_CENTRIC = 1,
+
+    /**
+     * UE operates in data-centric mode. Generally speaking, in this mode of operation, the UE
+     * will not reselect away from a cell/network that only provides data services.
+     */
+    DATA_CENTRIC = 2,
+}
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
index c776fd1..09ae240 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
@@ -88,6 +88,10 @@
     ::ndk::ScopedAStatus stopNetworkScan(int32_t serial) override;
     ::ndk::ScopedAStatus supplyNetworkDepersonalization(int32_t serial,
                                                         const std::string& netPin) override;
+    ::ndk::ScopedAStatus setUsageSetting(
+            int32_t serial,
+            ::aidl::android::hardware::radio::network::UsageSetting usageSetting) override;
+    ::ndk::ScopedAStatus getUsageSetting(int32_t serial) override;
 
   public:
     using RadioCompatBase::RadioCompatBase;
diff --git a/radio/aidl/compat/libradiocompat/modem/structs.cpp b/radio/aidl/compat/libradiocompat/modem/structs.cpp
index c1cd64c..53d5753 100644
--- a/radio/aidl/compat/libradiocompat/modem/structs.cpp
+++ b/radio/aidl/compat/libradiocompat/modem/structs.cpp
@@ -24,6 +24,7 @@
 
 namespace android::hardware::radio::compat {
 
+using ::aidl::android::hardware::radio::AccessNetwork;
 using ::aidl::android::hardware::radio::RadioAccessFamily;
 using ::aidl::android::hardware::radio::RadioTechnology;
 namespace aidl = ::aidl::android::hardware::radio::modem;
@@ -82,11 +83,18 @@
 }
 
 aidl::ActivityStatsInfo toAidl(const V1_0::ActivityStatsInfo& info) {
+    const aidl::ActivityStatsTechSpecificInfo techSpecificInfo = {
+            .rat = AccessNetwork(AccessNetwork::UNKNOWN),
+            .frequencyRange = static_cast<int32_t>(
+                    aidl::ActivityStatsTechSpecificInfo::FREQUENCY_RANGE_UNKNOWN),
+            .txmModetimeMs = toAidl(info.txmModetimeMs),
+            .rxModeTimeMs = static_cast<int32_t>(info.rxModeTimeMs),
+    };
+
     return {
             .sleepModeTimeMs = static_cast<int32_t>(info.sleepModeTimeMs),
             .idleModeTimeMs = static_cast<int32_t>(info.idleModeTimeMs),
-            .txmModetimeMs = toAidl(info.txmModetimeMs),
-            .rxModeTimeMs = static_cast<int32_t>(info.rxModeTimeMs),
+            .techSpecificInfo = {techSpecificInfo},
     };
 }
 
diff --git a/radio/aidl/compat/libradiocompat/modem/structs.h b/radio/aidl/compat/libradiocompat/modem/structs.h
index 3ac1edb..af714c7 100644
--- a/radio/aidl/compat/libradiocompat/modem/structs.h
+++ b/radio/aidl/compat/libradiocompat/modem/structs.h
@@ -16,6 +16,7 @@
 #pragma once
 
 #include <aidl/android/hardware/radio/modem/ActivityStatsInfo.h>
+#include <aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.h>
 #include <aidl/android/hardware/radio/modem/HardwareConfig.h>
 #include <aidl/android/hardware/radio/modem/HardwareConfigModem.h>
 #include <aidl/android/hardware/radio/modem/HardwareConfigSim.h>
diff --git a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
index af0bc46..5fa1cf5 100644
--- a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
+++ b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
@@ -278,4 +278,19 @@
     return ok();
 }
 
+// TODO(b/210498497): is there a cleaner way to send a response back to Android, even though these
+// methods must never be called?
+ScopedAStatus RadioNetwork::setUsageSetting(
+        int32_t ser, ::aidl::android::hardware::radio::network::UsageSetting) {
+    LOG_CALL << ser;
+    LOG(ERROR) << "setUsageSetting is unsupported by HIDL HALs";
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::getUsageSetting(int32_t ser) {
+    LOG_CALL << ser;
+    LOG(ERROR) << "getUsageSetting is unsupported by HIDL HALs";
+    return ok();
+}
+
 }  // namespace android::hardware::radio::compat
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index 64550ef..73c3820 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -583,6 +583,7 @@
                               attest_key, &attested_key_blob, &attested_key_characteristics,
                               &attested_key_cert_chain));
 
+        ASSERT_GT(attested_key_cert_chain.size(), 0);
         CheckedDeleteKey(&attested_key_blob);
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
@@ -612,6 +613,7 @@
                               attest_key, &attested_key_blob, &attested_key_characteristics,
                               &attested_key_cert_chain));
 
+        ASSERT_GT(attested_key_cert_chain.size(), 0);
         CheckedDeleteKey(&attested_key_blob);
         CheckedDeleteKey(&attest_key.keyBlob);
 
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index c99e1d0..d8b19dc 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -3151,6 +3151,58 @@
     CheckedDeleteKey(&verification_key);
 }
 
+/*
+ * VerificationOperationsTest.HmacVerificationFailsForCorruptSignature
+ *
+ * Verifies HMAC signature verification should fails if message or signature is corrupted.
+ */
+TEST_P(VerificationOperationsTest, HmacVerificationFailsForCorruptSignature) {
+    string key_material = "HelloThisIsAKey";
+
+    vector<uint8_t> signing_key, verification_key;
+    vector<KeyCharacteristics> signing_key_chars, verification_key_chars;
+    EXPECT_EQ(ErrorCode::OK,
+              ImportKey(AuthorizationSetBuilder()
+                                .Authorization(TAG_NO_AUTH_REQUIRED)
+                                .Authorization(TAG_ALGORITHM, Algorithm::HMAC)
+                                .Authorization(TAG_PURPOSE, KeyPurpose::SIGN)
+                                .Digest(Digest::SHA_2_256)
+                                .Authorization(TAG_MIN_MAC_LENGTH, 160),
+                        KeyFormat::RAW, key_material, &signing_key, &signing_key_chars));
+    EXPECT_EQ(ErrorCode::OK,
+              ImportKey(AuthorizationSetBuilder()
+                                .Authorization(TAG_NO_AUTH_REQUIRED)
+                                .Authorization(TAG_ALGORITHM, Algorithm::HMAC)
+                                .Authorization(TAG_PURPOSE, KeyPurpose::VERIFY)
+                                .Digest(Digest::SHA_2_256)
+                                .Authorization(TAG_MIN_MAC_LENGTH, 160),
+                        KeyFormat::RAW, key_material, &verification_key, &verification_key_chars));
+
+    string message = "This is a message.";
+    string signature = SignMessage(
+            signing_key, message,
+            AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Authorization(TAG_MAC_LENGTH, 160));
+
+    AuthorizationSet begin_out_params;
+    ASSERT_EQ(ErrorCode::OK,
+              Begin(KeyPurpose::VERIFY, verification_key,
+                    AuthorizationSetBuilder().Digest(Digest::SHA_2_256), &begin_out_params));
+
+    string corruptMessage = "This is b message.";  // Corrupted message
+    string output;
+    EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(corruptMessage, signature, &output));
+
+    ASSERT_EQ(ErrorCode::OK,
+              Begin(KeyPurpose::VERIFY, verification_key,
+                    AuthorizationSetBuilder().Digest(Digest::SHA_2_256), &begin_out_params));
+
+    signature[0] += 1;  // Corrupt a signature
+    EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(message, signature, &output));
+
+    CheckedDeleteKey(&signing_key);
+    CheckedDeleteKey(&verification_key);
+}
+
 INSTANTIATE_KEYMINT_AIDL_TEST(VerificationOperationsTest);
 
 typedef KeyMintAidlTestBase ExportKeyTest;
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterDownloadEvent.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterDownloadEvent.aidl
index b51e633..8a05dbd 100644
--- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterDownloadEvent.aidl
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterDownloadEvent.aidl
@@ -36,6 +36,7 @@
 @VintfStability
 parcelable DemuxFilterDownloadEvent {
   int itemId;
+  int downloadId;
   int mpuSequenceNumber;
   int itemFragmentIndex;
   int lastItemFragmentIndex;
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterDownloadSettings.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterDownloadSettings.aidl
index ff06888..86ce646 100644
--- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterDownloadSettings.aidl
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterDownloadSettings.aidl
@@ -35,5 +35,6 @@
 /* @hide */
 @VintfStability
 parcelable DemuxFilterDownloadSettings {
+  boolean useDownloadId;
   int downloadId;
 }
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl
index a463d68..993c639 100644
--- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl
@@ -38,6 +38,8 @@
   int streamId;
   boolean isPtsPresent;
   long pts;
+  boolean isDtsPresent;
+  long dts;
   long dataLength;
   long offset;
   android.hardware.common.NativeHandle avMemory;
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionEvent.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionEvent.aidl
index 01b8a77..199a09c 100644
--- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionEvent.aidl
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterSectionEvent.aidl
@@ -38,5 +38,5 @@
   int tableId;
   int version;
   int sectionNum;
-  int dataLength;
+  long dataLength;
 }
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatus.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatus.aidl
index 7677221..c79b751 100644
--- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatus.aidl
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatus.aidl
@@ -74,4 +74,5 @@
   boolean isShortFrames;
   android.hardware.tv.tuner.FrontendIsdbtMode isdbtMode;
   android.hardware.tv.tuner.FrontendIsdbtPartialReceptionFlag partialReceptionFlag;
+  int[] streamIdList;
 }
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusType.aidl
index 6342479..9ea3200 100644
--- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusType.aidl
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusType.aidl
@@ -74,4 +74,5 @@
   IS_SHORT_FRAMES = 36,
   ISDBT_MODE = 37,
   ISDBT_PARTIAL_RECEPTION_FLAG = 38,
+  STREAM_ID_LIST = 39,
 }
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterDownloadEvent.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterDownloadEvent.aidl
index cf88928..b9df5a0 100644
--- a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterDownloadEvent.aidl
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterDownloadEvent.aidl
@@ -28,6 +28,11 @@
     int itemId;
 
     /**
+     * Uniquely identify data content within the same Package ID (PID).
+     */
+    int downloadId;
+
+    /**
      * MPU sequence number of filtered data (only for MMTP)
      */
     int mpuSequenceNumber;
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterDownloadSettings.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterDownloadSettings.aidl
index bd79bd5..1188b03 100644
--- a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterDownloadSettings.aidl
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterDownloadSettings.aidl
@@ -23,6 +23,11 @@
 @VintfStability
 parcelable DemuxFilterDownloadSettings {
     /**
+     * Whether download ID should be used.
+     */
+    boolean useDownloadId;
+
+    /**
      * Download ID (also known as the carousel ID) is carried in the PMT in
      * ISO/IEC 13818-1 for the service containing the object carousel.
      */
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl
index ec7bbf1..e92b711 100644
--- a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl
@@ -40,6 +40,16 @@
     long pts;
 
     /**
+     * true if DTS is present in the PES header.
+     */
+    boolean isDtsPresent;
+
+    /**
+     * Decode TimeStamp for audio or video frame.
+     */
+    long dts;
+
+    /**
      * Data size in bytes of audio or video frame
      */
     long dataLength;
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionEvent.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionEvent.aidl
index d666316..a5f9ca7 100644
--- a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionEvent.aidl
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterSectionEvent.aidl
@@ -40,5 +40,5 @@
     /**
      * Data size in bytes of filtered data
      */
-    int dataLength;
+    long dataLength;
 }
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatus.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatus.aidl
index 9302b76..234e183 100644
--- a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatus.aidl
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatus.aidl
@@ -202,4 +202,10 @@
      * ISDB-T Partial Reception Flag.
      */
     FrontendIsdbtPartialReceptionFlag partialReceptionFlag;
+
+    /**
+     * Stream ID list included in a transponder.
+     */
+    int[] streamIdList;
+
 }
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusType.aidl
index 103a4ab..7feb72d 100644
--- a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusType.aidl
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusType.aidl
@@ -218,4 +218,9 @@
      * ISDB-T Partial Reception Flag.
      */
     ISDBT_PARTIAL_RECEPTION_FLAG,
+
+    /**
+     * Stream ID list included in a transponder.
+     */
+   STREAM_ID_LIST,
 }
diff --git a/tv/tuner/aidl/default/Demux.cpp b/tv/tuner/aidl/default/Demux.cpp
index 4385461..a94b4ad 100644
--- a/tv/tuner/aidl/default/Demux.cpp
+++ b/tv/tuner/aidl/default/Demux.cpp
@@ -410,6 +410,37 @@
     return mIsRecording;
 }
 
+binder_status_t Demux::dump(int fd, const char** args, uint32_t numArgs) {
+    dprintf(fd, " Demux %d:\n", mDemuxId);
+    dprintf(fd, "  mIsRecording %d\n", mIsRecording);
+    {
+        dprintf(fd, "  Filters:\n");
+        map<int64_t, std::shared_ptr<Filter>>::iterator it;
+        for (it = mFilters.begin(); it != mFilters.end(); it++) {
+            it->second->dump(fd, args, numArgs);
+        }
+    }
+    {
+        dprintf(fd, "  TimeFilter:\n");
+        if (mTimeFilter != nullptr) {
+            mTimeFilter->dump(fd, args, numArgs);
+        }
+    }
+    {
+        dprintf(fd, "  DvrPlayback:\n");
+        if (mDvrPlayback != nullptr) {
+            mDvrPlayback->dump(fd, args, numArgs);
+        }
+    }
+    {
+        dprintf(fd, "  DvrRecord:\n");
+        if (mDvrRecord != nullptr) {
+            mDvrRecord->dump(fd, args, numArgs);
+        }
+    }
+    return STATUS_OK;
+}
+
 bool Demux::attachRecordFilter(int64_t filterId) {
     if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
         !mFilters[filterId]->isRecordFilter()) {
diff --git a/tv/tuner/aidl/default/Demux.h b/tv/tuner/aidl/default/Demux.h
index 1b789bd..7f0b0a7 100644
--- a/tv/tuner/aidl/default/Demux.h
+++ b/tv/tuner/aidl/default/Demux.h
@@ -71,6 +71,8 @@
     ::ndk::ScopedAStatus connectCiCam(int32_t in_ciCamId) override;
     ::ndk::ScopedAStatus disconnectCiCam() override;
 
+    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
     // Functions interacts with Tuner Service
     void stopFrontendInput();
     ::ndk::ScopedAStatus removeFilter(int64_t filterId);
diff --git a/tv/tuner/aidl/default/Dvr.cpp b/tv/tuner/aidl/default/Dvr.cpp
index 4f34b8e..c591d07 100644
--- a/tv/tuner/aidl/default/Dvr.cpp
+++ b/tv/tuner/aidl/default/Dvr.cpp
@@ -177,6 +177,13 @@
     return mDvrEventFlag;
 }
 
+binder_status_t Dvr::dump(int fd, const char** /* args */, uint32_t /* numArgs */) {
+    dprintf(fd, "    Dvr:\n");
+    dprintf(fd, "      mType: %hhd\n", mType);
+    dprintf(fd, "      mDvrThreadRunning: %d\n", (bool)mDvrThreadRunning);
+    return STATUS_OK;
+}
+
 void Dvr::playbackThreadLoop() {
     ALOGD("[Dvr] playback threadLoop start.");
 
diff --git a/tv/tuner/aidl/default/Dvr.h b/tv/tuner/aidl/default/Dvr.h
index ad8728e..6ff71cd 100644
--- a/tv/tuner/aidl/default/Dvr.h
+++ b/tv/tuner/aidl/default/Dvr.h
@@ -71,6 +71,8 @@
     ::ndk::ScopedAStatus flush() override;
     ::ndk::ScopedAStatus close() override;
 
+    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
     /**
      * To create a DvrMQ and its Event Flag.
      *
diff --git a/tv/tuner/aidl/default/Filter.cpp b/tv/tuner/aidl/default/Filter.cpp
index 54037be..769ebe2 100644
--- a/tv/tuner/aidl/default/Filter.cpp
+++ b/tv/tuner/aidl/default/Filter.cpp
@@ -22,6 +22,7 @@
 #include <aidl/android/hardware/tv/tuner/DemuxQueueNotifyBits.h>
 #include <aidl/android/hardware/tv/tuner/Result.h>
 #include <aidlcommonsupport/NativeHandle.h>
+#include <inttypes.h>
 #include <utils/Log.h>
 
 #include "Filter.h"
@@ -655,6 +656,17 @@
     mSharedAvMemHandle = nullptr;
 }
 
+binder_status_t Filter::dump(int fd, const char** /* args */, uint32_t /* numArgs */) {
+    dprintf(fd, "    Filter %" PRIu64 ":\n", mFilterId);
+    dprintf(fd, "      Main type: %d\n", mType.mainType);
+    dprintf(fd, "      mIsMediaFilter: %d\n", mIsMediaFilter);
+    dprintf(fd, "      mIsPcrFilter: %d\n", mIsPcrFilter);
+    dprintf(fd, "      mIsRecordFilter: %d\n", mIsRecordFilter);
+    dprintf(fd, "      mIsUsingFMQ: %d\n", mIsUsingFMQ);
+    dprintf(fd, "      mFilterThreadRunning: %d\n", (bool)mFilterThreadRunning);
+    return STATUS_OK;
+}
+
 void Filter::maySendFilterStatusCallback() {
     if (!mIsUsingFMQ) {
         return;
@@ -1148,6 +1160,7 @@
     DemuxFilterMediaEvent mediaEvent;
     mediaEvent.streamId = 1;
     mediaEvent.isPtsPresent = true;
+    mediaEvent.isDtsPresent = false;
     mediaEvent.dataLength = 3;
     mediaEvent.offset = 4;
     mediaEvent.isSecureMemory = true;
@@ -1238,6 +1251,7 @@
 void Filter::createDownloadEvent(vector<DemuxFilterEvent>& events) {
     DemuxFilterDownloadEvent download;
     download.itemId = 1;
+    download.downloadId = 1;
     download.mpuSequenceNumber = 2;
     download.itemFragmentIndex = 3;
     download.lastItemFragmentIndex = 4;
diff --git a/tv/tuner/aidl/default/Filter.h b/tv/tuner/aidl/default/Filter.h
index 8388c98..e301249 100644
--- a/tv/tuner/aidl/default/Filter.h
+++ b/tv/tuner/aidl/default/Filter.h
@@ -126,6 +126,8 @@
     ::ndk::ScopedAStatus setDataSource(const std::shared_ptr<IFilter>& in_filter) override;
     ::ndk::ScopedAStatus setDelayHint(const FilterDelayHint& in_hint) override;
 
+    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
     /**
      * To create a FilterMQ and its Event Flag.
      *
diff --git a/tv/tuner/aidl/default/Frontend.cpp b/tv/tuner/aidl/default/Frontend.cpp
index 77d20e2..a4dde2a 100644
--- a/tv/tuner/aidl/default/Frontend.cpp
+++ b/tv/tuner/aidl/default/Frontend.cpp
@@ -676,6 +676,11 @@
                         FrontendIsdbtPartialReceptionFlag::AUTO);
                 break;
             }
+            case FrontendStatusType::STREAM_ID_LIST: {
+                vector<int32_t> streamIds = {0, 1};
+                status.set<FrontendStatus::streamIdList>(streamIds);
+                break;
+            }
             default: {
                 continue;
             }
@@ -718,6 +723,14 @@
     return ::ndk::ScopedAStatus::ok();
 }
 
+binder_status_t Frontend::dump(int fd, const char** /* args */, uint32_t /* numArgs */) {
+    dprintf(fd, "  Frontend %d\n", mId);
+    dprintf(fd, "    mType: %d\n", mType);
+    dprintf(fd, "    mIsLocked: %d\n", mIsLocked);
+    dprintf(fd, "    mCiCamId: %d\n", mCiCamId);
+    return STATUS_OK;
+}
+
 FrontendType Frontend::getFrontendType() {
     return mType;
 }
diff --git a/tv/tuner/aidl/default/Frontend.h b/tv/tuner/aidl/default/Frontend.h
index 3c602cf..5e7b10c 100644
--- a/tv/tuner/aidl/default/Frontend.h
+++ b/tv/tuner/aidl/default/Frontend.h
@@ -50,6 +50,8 @@
     ::ndk::ScopedAStatus linkCiCam(int32_t in_ciCamId, int32_t* _aidl_return) override;
     ::ndk::ScopedAStatus unlinkCiCam(int32_t in_ciCamId) override;
 
+    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
     FrontendType getFrontendType();
     int32_t getFrontendId();
     string getSourceFile();
diff --git a/tv/tuner/aidl/default/TimeFilter.cpp b/tv/tuner/aidl/default/TimeFilter.cpp
index dde7be3..9611ed9 100644
--- a/tv/tuner/aidl/default/TimeFilter.cpp
+++ b/tv/tuner/aidl/default/TimeFilter.cpp
@@ -83,6 +83,12 @@
     return ::ndk::ScopedAStatus::ok();
 }
 
+binder_status_t TimeFilter::dump(int fd, const char** /* args */, uint32_t /* numArgs */) {
+    dprintf(fd, "    TimeFilter:\n");
+    dprintf(fd, "      mTimeStamp: %" PRIu64 "\n", mTimeStamp);
+    return STATUS_OK;
+}
+
 }  // namespace tuner
 }  // namespace tv
 }  // namespace hardware
diff --git a/tv/tuner/aidl/default/TimeFilter.h b/tv/tuner/aidl/default/TimeFilter.h
index ff35c47..5f4c2d4 100644
--- a/tv/tuner/aidl/default/TimeFilter.h
+++ b/tv/tuner/aidl/default/TimeFilter.h
@@ -44,8 +44,10 @@
     ::ndk::ScopedAStatus getSourceTime(int64_t* _aidl_return) override;
     ::ndk::ScopedAStatus close() override;
 
+    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
   private:
-    std::shared_ptr<Demux> mDemux;
+    ::std::shared_ptr<Demux> mDemux;
     uint64_t mTimeStamp = INVALID_TIME_STAMP;
     time_t mBeginTime;
 };
diff --git a/tv/tuner/aidl/default/Tuner.cpp b/tv/tuner/aidl/default/Tuner.cpp
index badb08f..96e83bb 100644
--- a/tv/tuner/aidl/default/Tuner.cpp
+++ b/tv/tuner/aidl/default/Tuner.cpp
@@ -55,9 +55,13 @@
     capsIsdbs.set<FrontendCapabilities::Tag::isdbsCaps>(FrontendIsdbsCapabilities());
     mFrontendCaps[0] = capsIsdbs;
     statusCaps = {
-            FrontendStatusType::DEMOD_LOCK,  FrontendStatusType::SNR,
-            FrontendStatusType::FEC,         FrontendStatusType::MODULATION,
-            FrontendStatusType::MODULATIONS, FrontendStatusType::ROLL_OFF,
+            FrontendStatusType::DEMOD_LOCK,
+            FrontendStatusType::SNR,
+            FrontendStatusType::FEC,
+            FrontendStatusType::MODULATION,
+            FrontendStatusType::MODULATIONS,
+            FrontendStatusType::ROLL_OFF,
+            FrontendStatusType::STREAM_ID_LIST,
     };
     mFrontendStatusCaps[0] = statusCaps;
 
@@ -169,7 +173,7 @@
     statusCaps = {
             FrontendStatusType::DEMOD_LOCK,      FrontendStatusType::MODULATION,
             FrontendStatusType::MODULATIONS,     FrontendStatusType::ROLL_OFF,
-            FrontendStatusType::IS_SHORT_FRAMES,
+            FrontendStatusType::IS_SHORT_FRAMES, FrontendStatusType::STREAM_ID_LIST,
     };
     mFrontendStatusCaps[8] = statusCaps;
 
@@ -313,6 +317,33 @@
     return ::ndk::ScopedAStatus::ok();
 }
 
+binder_status_t Tuner::dump(int fd, const char** args, uint32_t numArgs) {
+    ALOGV("%s", __FUNCTION__);
+    {
+        dprintf(fd, "Frontends:\n");
+        for (int i = 0; i < mFrontendSize; i++) {
+            mFrontends[i]->dump(fd, args, numArgs);
+            for (int j = 0; j < mFrontendStatusCaps[i].size(); j++) {
+                dprintf(fd, "    statusCap: %d\n", mFrontendStatusCaps[i][j]);
+            }
+        }
+    }
+    {
+        dprintf(fd, "Demuxs:\n");
+        map<int32_t, std::shared_ptr<Demux>>::iterator it;
+        for (it = mDemuxes.begin(); it != mDemuxes.end(); it++) {
+            it->second->dump(fd, args, numArgs);
+        }
+    }
+    {
+        dprintf(fd, "Lnbs:\n");
+        for (int i = 0; i < mLnbs.size(); i++) {
+            mLnbs[i]->dump(fd, args, numArgs);
+        }
+    }
+    return STATUS_OK;
+}
+
 void Tuner::setFrontendAsDemuxSource(int32_t frontendId, int32_t demuxId) {
     mFrontendToDemux[frontendId] = demuxId;
     if (mFrontends[frontendId] != nullptr && mFrontends[frontendId]->isLocked()) {
@@ -332,6 +363,10 @@
 }
 
 void Tuner::removeFrontend(int32_t frontendId) {
+    map<int32_t, int32_t>::iterator it = mFrontendToDemux.find(frontendId);
+    if (it != mFrontendToDemux.end()) {
+        mDemuxes.erase(it->second);
+    }
     mFrontendToDemux.erase(frontendId);
 }
 
diff --git a/tv/tuner/aidl/default/Tuner.h b/tv/tuner/aidl/default/Tuner.h
index 7af7ab8..682496c 100644
--- a/tv/tuner/aidl/default/Tuner.h
+++ b/tv/tuner/aidl/default/Tuner.h
@@ -57,6 +57,8 @@
                                        std::vector<int32_t>* out_lnbId,
                                        std::shared_ptr<ILnb>* _aidl_return) override;
 
+    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
     std::shared_ptr<Frontend> getFrontendById(int32_t frontendId);
     void setFrontendAsDemuxSource(int32_t frontendId, int32_t demuxId);
     void frontendStartTune(int32_t frontendId);
diff --git a/tv/tuner/aidl/vts/functional/FilterTests.cpp b/tv/tuner/aidl/vts/functional/FilterTests.cpp
index a5acdc1..53afef7 100644
--- a/tv/tuner/aidl/vts/functional/FilterTests.cpp
+++ b/tv/tuner/aidl/vts/functional/FilterTests.cpp
@@ -17,6 +17,7 @@
 #include "FilterTests.h"
 
 #include <inttypes.h>
+#include <algorithm>
 
 #include <aidl/android/hardware/tv/tuner/DemuxFilterMonitorEventType.h>
 #include <aidlcommonsupport/NativeHandle.h>
@@ -31,23 +32,24 @@
     mPidFilterOutputCount++;
     mMsgCondition.signal();
 
-    // HACK: we need to cast the const away as DemuxFilterEvent contains a ScopedFileDescriptor
-    // that cannot be copied.
-    for (auto&& e : const_cast<std::vector<DemuxFilterEvent>&>(events)) {
-        auto it = mFilterEventPromises.find(e.getTag());
-        if (it != mFilterEventPromises.cend()) {
-            it->second.set_value(std::move(e));
-            mFilterEventPromises.erase(it);
+    for (auto it = mFilterCallbackVerifiers.begin(); it != mFilterCallbackVerifiers.end();) {
+        auto& [verifier, promise] = *it;
+        if (verifier(events)) {
+            promise.set_value();
+            it = mFilterCallbackVerifiers.erase(it);
+        } else {
+            ++it;
         }
-    }
+    };
 
     return ::ndk::ScopedAStatus::ok();
 }
 
-std::future<DemuxFilterEvent> FilterCallback::getNextFilterEventWithTag(DemuxFilterEvent::Tag tag) {
-    // Note: this currently only supports one future per DemuxFilterEvent::Tag.
-    mFilterEventPromises[tag] = std::promise<DemuxFilterEvent>();
-    return mFilterEventPromises[tag].get_future();
+std::future<void> FilterCallback::verifyFilterCallback(FilterCallbackVerifier&& verifier) {
+    std::promise<void> promise;
+    auto future = promise.get_future();
+    mFilterCallbackVerifiers.emplace_back(std::move(verifier), std::move(promise));
+    return future;
 }
 
 void FilterCallback::testFilterDataOutput() {
diff --git a/tv/tuner/aidl/vts/functional/FilterTests.h b/tv/tuner/aidl/vts/functional/FilterTests.h
index 6258bac..f579441 100644
--- a/tv/tuner/aidl/vts/functional/FilterTests.h
+++ b/tv/tuner/aidl/vts/functional/FilterTests.h
@@ -60,9 +60,18 @@
 
 class FilterCallback : public BnFilterCallback {
   public:
+    /**
+     * A FilterCallbackVerifier is used to test and verify filter callbacks.
+     * The function should return true when a callback has been handled by this
+     * filter verifier. This will cause the associated future to be unblocked.
+     * If the function returns false, we continue to wait for future callbacks
+     * (the future remains blocked).
+     */
+    using FilterCallbackVerifier = std::function<bool(const std::vector<DemuxFilterEvent>&)>;
+
     virtual ::ndk::ScopedAStatus onFilterEvent(const vector<DemuxFilterEvent>& events) override;
 
-    std::future<DemuxFilterEvent> getNextFilterEventWithTag(DemuxFilterEvent::Tag tag);
+    std::future<void> verifyFilterCallback(FilterCallbackVerifier&& verifier);
 
     virtual ::ndk::ScopedAStatus onFilterStatus(const DemuxFilterStatus /*status*/) override {
         return ::ndk::ScopedAStatus::ok();
@@ -85,7 +94,7 @@
     int32_t mFilterId;
     std::shared_ptr<IFilter> mFilter;
 
-    std::unordered_map<DemuxFilterEvent::Tag, std::promise<DemuxFilterEvent>> mFilterEventPromises;
+    std::vector<std::pair<FilterCallbackVerifier, std::promise<void>>> mFilterCallbackVerifiers;
     native_handle_t* mAvSharedHandle = nullptr;
     uint64_t mAvSharedMemSize = -1;
 
diff --git a/tv/tuner/aidl/vts/functional/FrontendTests.cpp b/tv/tuner/aidl/vts/functional/FrontendTests.cpp
index 6204803..12b1f33 100644
--- a/tv/tuner/aidl/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/aidl/vts/functional/FrontendTests.cpp
@@ -398,6 +398,13 @@
                             expectStatuses[i].get<FrontendStatus::Tag::partialReceptionFlag>());
                 break;
             }
+            case FrontendStatusType::STREAM_ID_LIST: {
+                ASSERT_TRUE(std::equal(
+                        realStatuses[i].get<FrontendStatus::Tag::streamIdList>().begin(),
+                        realStatuses[i].get<FrontendStatus::Tag::streamIdList>().end(),
+                        expectStatuses[i].get<FrontendStatus::Tag::streamIdList>().begin()));
+                break;
+            }
             default: {
                 continue;
             }
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
index 88890e4..89e42df 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
@@ -640,10 +640,51 @@
     testTimeFilter(timeFilterMap[timeFilter.timeFilterId]);
 }
 
-// TODO: move boilerplate into text fixture
-TEST_P(TunerFilterAidlTest, FilterTimeDelayHintTest) {
-    description("Test filter delay hint.");
+static bool isMediaFilter(const FilterConfig& filterConfig) {
+    switch (filterConfig.type.mainType) {
+        case DemuxFilterMainType::TS: {
+            // TS Audio and Video filters are media filters
+            auto tsFilterType =
+                    filterConfig.type.subType.get<DemuxFilterSubType::Tag::tsFilterType>();
+            return (tsFilterType == DemuxTsFilterType::AUDIO ||
+                    tsFilterType == DemuxTsFilterType::VIDEO);
+        }
+        case DemuxFilterMainType::MMTP: {
+            // MMTP Audio and Video filters are media filters
+            auto mmtpFilterType =
+                    filterConfig.type.subType.get<DemuxFilterSubType::Tag::mmtpFilterType>();
+            return (mmtpFilterType == DemuxMmtpFilterType::AUDIO ||
+                    mmtpFilterType == DemuxMmtpFilterType::VIDEO);
+        }
+        default:
+            return false;
+    }
+}
 
+static int getDemuxFilterEventDataLength(const DemuxFilterEvent& event) {
+    switch (event.getTag()) {
+        case DemuxFilterEvent::Tag::section:
+            return event.get<DemuxFilterEvent::Tag::section>().dataLength;
+        case DemuxFilterEvent::Tag::media:
+            return event.get<DemuxFilterEvent::Tag::media>().dataLength;
+        case DemuxFilterEvent::Tag::pes:
+            return event.get<DemuxFilterEvent::Tag::pes>().dataLength;
+        case DemuxFilterEvent::Tag::download:
+            return event.get<DemuxFilterEvent::Tag::download>().dataLength;
+        case DemuxFilterEvent::Tag::ipPayload:
+            return event.get<DemuxFilterEvent::Tag::ipPayload>().dataLength;
+
+        case DemuxFilterEvent::Tag::tsRecord:
+        case DemuxFilterEvent::Tag::mmtpRecord:
+        case DemuxFilterEvent::Tag::temi:
+        case DemuxFilterEvent::Tag::monitorEvent:
+        case DemuxFilterEvent::Tag::startId:
+            return 0;
+    }
+}
+
+// TODO: move boilerplate into text fixture
+void TunerFilterAidlTest::testDelayHint(const FilterConfig& filterConf) {
     int32_t feId;
     int32_t demuxId;
     std::shared_ptr<IDemux> demux;
@@ -657,40 +698,87 @@
     ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
     mFilterTests.setDemux(demux);
 
-    const auto& filterConf = filterMap[live.ipFilterId];
     ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
-    ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
-    ASSERT_TRUE(mFilterTests.configIpFilterCid(filterConf.ipCid, filterId));
 
+    bool mediaFilter = isMediaFilter(filterConf);
     auto filter = mFilterTests.getFilterById(filterId);
 
-    auto delayValue = std::chrono::milliseconds(5000);
-    FilterDelayHint delayHint;
-    delayHint.hintType = FilterDelayHintType::TIME_DELAY_IN_MS;
-    delayHint.hintValue = delayValue.count();
+    auto timeDelayInMs = std::chrono::milliseconds(filterConf.timeDelayInMs);
+    if (timeDelayInMs.count() > 0) {
+        FilterDelayHint delayHint;
+        delayHint.hintType = FilterDelayHintType::TIME_DELAY_IN_MS;
+        delayHint.hintValue = timeDelayInMs.count();
 
-    auto status = filter->setDelayHint(delayHint);
-    ASSERT_TRUE(status.isOk());
+        // setDelayHint should fail for media filters.
+        ASSERT_EQ(filter->setDelayHint(delayHint).isOk(), !mediaFilter);
+    }
 
-    auto startTime = std::chrono::steady_clock::now();
-    ASSERT_TRUE(mFilterTests.startFilter(filterId));
+    int dataDelayInBytes = filterConf.dataDelayInBytes;
+    if (dataDelayInBytes > 0) {
+        FilterDelayHint delayHint;
+        delayHint.hintType = FilterDelayHintType::DATA_SIZE_DELAY_IN_BYTES;
+        delayHint.hintValue = dataDelayInBytes;
 
-    auto cb = mFilterTests.getFilterCallbacks().at(filterId);
-    auto future = cb->getNextFilterEventWithTag(DemuxFilterEvent::Tag::ipPayload);
+        // setDelayHint should fail for media filters.
+        ASSERT_EQ(filter->setDelayHint(delayHint).isOk(), !mediaFilter);
+    }
 
-    // block and wait for callback to be received.
-    ASSERT_EQ(future.wait_for(std::chrono::seconds(10)), std::future_status::ready);
-    auto duration = std::chrono::steady_clock::now() - startTime;
-    ASSERT_GE(duration, delayValue);
+    // start and stop filter in order to circumvent callback scheduler race
+    // conditions after adjusting filter delays.
+    mFilterTests.startFilter(filterId);
+    mFilterTests.stopFilter(filterId);
 
-    // cleanup
-    ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+    if (!mediaFilter) {
+        auto cb = mFilterTests.getFilterCallbacks().at(filterId);
+        int callbackSize = 0;
+        auto future = cb->verifyFilterCallback(
+                [&callbackSize](const std::vector<DemuxFilterEvent>& events) {
+                    for (const auto& event : events) {
+                        callbackSize += getDemuxFilterEventDataLength(event);
+                    }
+                    return true;
+                });
+
+        // The configure stage can also produce events, so we should set the delay
+        // hint beforehand.
+        ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+
+        auto startTime = std::chrono::steady_clock::now();
+        ASSERT_TRUE(mFilterTests.startFilter(filterId));
+
+        // block and wait for callback to be received.
+        auto timeout = std::chrono::seconds(30);
+        ASSERT_EQ(future.wait_for(timeout), std::future_status::ready);
+        auto duration = std::chrono::steady_clock::now() - startTime;
+
+        bool delayHintTest = duration >= timeDelayInMs;
+        bool dataSizeTest = callbackSize >= dataDelayInBytes;
+
+        if (timeDelayInMs.count() > 0 && dataDelayInBytes > 0) {
+            ASSERT_TRUE(delayHintTest || dataSizeTest);
+        } else {
+            // if only one of time delay / data delay is configured, one of them
+            // holds true by default, so we want both assertions to be true.
+            ASSERT_TRUE(delayHintTest && dataSizeTest);
+        }
+
+        ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+    }
+
     ASSERT_TRUE(mFilterTests.closeFilter(filterId));
     ASSERT_TRUE(mDemuxTests.closeDemux());
     ASSERT_TRUE(mFrontendTests.closeFrontend());
 }
 
+TEST_P(TunerFilterAidlTest, FilterDelayHintTest) {
+    description("Test filter time delay hint.");
+
+    for (const auto& obj : filterMap) {
+        testDelayHint(obj.second);
+    }
+}
+
 TEST_P(TunerPlaybackAidlTest, PlaybackDataFlowWithTsSectionFilterTest) {
     description("Feed ts data from playback and configure Ts section filter to get output");
     if (!playback.support || playback.sectionFilterId.compare(emptyHardwareId) == 0) {
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
index 13c5a80..7f80d90 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
@@ -140,6 +140,7 @@
     void reconfigSingleFilterInDemuxTest(FilterConfig filterConf, FilterConfig filterReconf,
                                          FrontendConfig frontendConf);
     void testTimeFilter(TimeFilterConfig filterConf);
+    void testDelayHint(const FilterConfig& filterConf);
 
     DemuxFilterType getLinkageFilterType(int bit) {
         DemuxFilterType type;
diff --git a/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h b/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h
index 7ccf31a..b6cc5f8 100644
--- a/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h
+++ b/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h
@@ -96,6 +96,8 @@
     AvStreamType streamType;
     int32_t ipCid;
     int32_t monitorEventTypes;
+    int timeDelayInMs = 0;
+    int dataDelayInBytes = 0;
 
     bool operator<(const FilterConfig& /*c*/) const { return false; }
 };
@@ -336,6 +338,12 @@
                 if (filterConfig.hasMonitorEventTypes()) {
                     filterMap[id].monitorEventTypes = (int32_t)filterConfig.getMonitorEventTypes();
                 }
+                if (filterConfig.hasTimeDelayInMs()) {
+                    filterMap[id].timeDelayInMs = filterConfig.getTimeDelayInMs();
+                }
+                if (filterConfig.hasDataDelayInBytes()) {
+                    filterMap[id].dataDelayInBytes = filterConfig.getDataDelayInBytes();
+                }
                 if (filterConfig.hasAvFilterSettings_optional()) {
                     auto av = filterConfig.getFirstAvFilterSettings_optional();
                     if (av->hasAudioStreamType_optional()) {
diff --git a/tv/tuner/config/api/current.txt b/tv/tuner/config/api/current.txt
index 6c637a4..db1d076 100644
--- a/tv/tuner/config/api/current.txt
+++ b/tv/tuner/config/api/current.txt
@@ -256,6 +256,7 @@
     ctor public Filter();
     method @Nullable public android.media.tuner.testing.configuration.V1_0.AvFilterSettings getAvFilterSettings_optional();
     method @Nullable public java.math.BigInteger getBufferSize();
+    method @Nullable public java.math.BigInteger getDataDelayInBytes();
     method @Nullable public String getId();
     method @Nullable public android.media.tuner.testing.configuration.V1_0.IpFilterConfig getIpFilterConfig_optional();
     method @Nullable public android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum getMainType();
@@ -264,9 +265,11 @@
     method @Nullable public android.media.tuner.testing.configuration.V1_0.RecordFilterSettings getRecordFilterSettings_optional();
     method @Nullable public android.media.tuner.testing.configuration.V1_0.SectionFilterSettings getSectionFilterSettings_optional();
     method @Nullable public android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum getSubType();
+    method @Nullable public java.math.BigInteger getTimeDelayInMs();
     method @Nullable public boolean getUseFMQ();
     method public void setAvFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.AvFilterSettings);
     method public void setBufferSize(@Nullable java.math.BigInteger);
+    method public void setDataDelayInBytes(@Nullable java.math.BigInteger);
     method public void setId(@Nullable String);
     method public void setIpFilterConfig_optional(@Nullable android.media.tuner.testing.configuration.V1_0.IpFilterConfig);
     method public void setMainType(@Nullable android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum);
@@ -275,6 +278,7 @@
     method public void setRecordFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.RecordFilterSettings);
     method public void setSectionFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.SectionFilterSettings);
     method public void setSubType(@Nullable android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum);
+    method public void setTimeDelayInMs(@Nullable java.math.BigInteger);
     method public void setUseFMQ(@Nullable boolean);
   }
 
diff --git a/tv/tuner/config/sample_tuner_vts_config_aidl_V1.xml b/tv/tuner/config/sample_tuner_vts_config_aidl_V1.xml
index 8a6229e..da77200 100644
--- a/tv/tuner/config/sample_tuner_vts_config_aidl_V1.xml
+++ b/tv/tuner/config/sample_tuner_vts_config_aidl_V1.xml
@@ -101,7 +101,7 @@
                     bufferSize="16777216" pid="257" useFMQ="false">
                 <recordFilterSettings tsIndexMask="1" scIndexType="NONE"/>
             </filter>
-            <filter id="FILTER_IP_IP_0" mainType="IP" subType="IP" bufferSize="16777216" useFMQ="false">
+            <filter id="FILTER_IP_IP_0" mainType="IP" subType="IP" bufferSize="16777216" useFMQ="false" timeDelayInMs="5000">
                 <ipFilterConfig ipCid="1">
                     <srcIpAddress isIpV4="true" ip="192 168 1 1"/>
                     <destIpAddress isIpV4="true" ip="192 168 1 1"/>
diff --git a/tv/tuner/config/tuner_testing_dynamic_configuration.xsd b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
index fc2827f..54cedfc 100644
--- a/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
+++ b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
@@ -243,6 +243,10 @@
                     "bufferSize": the buffer size of the filter in hex.
                     "pid": the pid that would be used to configure the filter.
                     "useFMQ": if the filter uses FMQ.
+                    "timeDelayInMs": the filter's time delay hint. 0 by default.  Must not be
+                        longer than 30 seconds.
+                    "dataDelayInBytes": the filter's data delay hint. 0 by default. Configured data
+                        size must be received within 30 seconds.
 
                 Each filter element also contains at most one type-related "filterSettings".
                     - The settings type should match the filter "subType" attribute.
@@ -274,6 +278,8 @@
         <xs:attribute name="pid" type="xs:nonNegativeInteger" use="optional"/>
         <xs:attribute name="useFMQ" type="xs:boolean" use="required"/>
         <xs:attribute name="monitorEventTypes" type="monitoEvents" use="optional"/>
+        <xs:attribute name="timeDelayInMs" type="xs:nonNegativeInteger" use="optional"/>
+        <xs:attribute name="dataDelayInBytes" type="xs:nonNegativeInteger" use="optional"/>
     </xs:complexType>
 
     <!-- DVR SESSION -->
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/IUwbChip.aidl b/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/IUwbChip.aidl
index c4cb47b..c7708f1 100644
--- a/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/IUwbChip.aidl
+++ b/uwb/aidl/aidl_api/android.hardware.uwb/current/android/hardware/uwb/IUwbChip.aidl
@@ -40,6 +40,7 @@
   void open(in android.hardware.uwb.IUwbClientCallback clientCallback);
   void close();
   void coreInit();
+  void sessionInit(int sessionId);
   int getSupportedAndroidUciVersion();
   long getSupportedAndroidCapabilities();
   int sendUciMessage(in byte[] data);
diff --git a/uwb/aidl/android/hardware/uwb/IUwbChip.aidl b/uwb/aidl/android/hardware/uwb/IUwbChip.aidl
index 0c98611..f2bb0f1 100644
--- a/uwb/aidl/android/hardware/uwb/IUwbChip.aidl
+++ b/uwb/aidl/android/hardware/uwb/IUwbChip.aidl
@@ -50,6 +50,14 @@
     void coreInit();
 
     /**
+     * Perform any necessary UWB session initializations.
+     * This must be invoked by the framework at the beginging of every new ranging session.
+     *
+     * @param sessionId Session identifier as defined in the UCI specification.
+     */
+    void sessionInit(int sessionId);
+
+    /**
      * Supported version of vendor UCI specification.
      *
      * @return Returns the version of the "android.hardware.uwb.fira_android" types-only
diff --git a/uwb/aidl/default/uwb_chip.cpp b/uwb/aidl/default/uwb_chip.cpp
index 10dbdb6..a5a3f4a 100644
--- a/uwb/aidl/default/uwb_chip.cpp
+++ b/uwb/aidl/default/uwb_chip.cpp
@@ -51,6 +51,10 @@
     return ndk::ScopedAStatus::ok();
 }
 
+::ndk::ScopedAStatus UwbChip::sessionInit(int /* sessionId */) {
+    return ndk::ScopedAStatus::ok();
+}
+
 ::ndk::ScopedAStatus UwbChip::getSupportedAndroidUciVersion(int32_t* version) {
     *version = kAndroidUciVersion;
     return ndk::ScopedAStatus::ok();
diff --git a/uwb/aidl/default/uwb_chip.h b/uwb/aidl/default/uwb_chip.h
index ca97120..46cecd4 100644
--- a/uwb/aidl/default/uwb_chip.h
+++ b/uwb/aidl/default/uwb_chip.h
@@ -37,6 +37,7 @@
     ::ndk::ScopedAStatus open(const std::shared_ptr<IUwbClientCallback>& clientCallback) override;
     ::ndk::ScopedAStatus close() override;
     ::ndk::ScopedAStatus coreInit() override;
+    ::ndk::ScopedAStatus sessionInit(int sesionId) override;
     ::ndk::ScopedAStatus getSupportedAndroidUciVersion(int32_t* version) override;
     ::ndk::ScopedAStatus getSupportedAndroidCapabilities(int64_t* capabilities) override;
     ::ndk::ScopedAStatus sendUciMessage(const std::vector<uint8_t>& data,
diff --git a/uwb/aidl/vts/VtsHalUwbTargetTest.cpp b/uwb/aidl/vts/VtsHalUwbTargetTest.cpp
index 3820c0f..1da4432 100644
--- a/uwb/aidl/vts/VtsHalUwbTargetTest.cpp
+++ b/uwb/aidl/vts/VtsHalUwbTargetTest.cpp
@@ -166,6 +166,11 @@
     EXPECT_TRUE(iuwb_chip->coreInit().isOk());
 }
 
+TEST_P(UwbAidl, ChipSessionInit) {
+    const auto iuwb_chip = getAnyChipAndOpen();
+    EXPECT_TRUE(iuwb_chip->sessionInit(0).isOk());
+}
+
 TEST_P(UwbAidl, ChipGetSupportedAndroidUciVersion) {
     const auto iuwb_chip = getAnyChipAndOpen();
     EXPECT_TRUE(iuwb_chip->coreInit().isOk());
diff --git a/weaver/aidl/default/Weaver.cpp b/weaver/aidl/default/Weaver.cpp
index 56d9c4d..6b77924 100644
--- a/weaver/aidl/default/Weaver.cpp
+++ b/weaver/aidl/default/Weaver.cpp
@@ -15,30 +15,52 @@
  */
 
 #include "Weaver.h"
+#include <array>
 
 namespace aidl {
 namespace android {
 namespace hardware {
 namespace weaver {
 
+struct Slotinfo {
+    int slot_id;
+    std::vector<uint8_t> key;
+    std::vector<uint8_t> value;
+};
+
+std::array<struct Slotinfo, 16> slot_array;
 // Methods from ::android::hardware::weaver::IWeaver follow.
 
 ::ndk::ScopedAStatus Weaver::getConfig(WeaverConfig* out_config) {
-    (void)out_config;
+    *out_config = {16, 16, 16};
     return ::ndk::ScopedAStatus::ok();
 }
 
 ::ndk::ScopedAStatus Weaver::read(int32_t in_slotId, const std::vector<uint8_t>& in_key, WeaverReadResponse* out_response) {
-    (void)in_slotId;
-    (void)in_key;
-    (void)out_response;
+
+    if (in_slotId > 15 || in_key.size() > 16) {
+        *out_response = {0, {}};
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(Weaver::STATUS_FAILED));
+    }
+
+    if (slot_array[in_slotId].key != in_key) {
+        *out_response = {0, {}};
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(Weaver::STATUS_INCORRECT_KEY));
+    }
+
+    *out_response = {0, slot_array[in_slotId].value};
+
     return ::ndk::ScopedAStatus::ok();
 }
 
 ::ndk::ScopedAStatus Weaver::write(int32_t in_slotId, const std::vector<uint8_t>& in_key, const std::vector<uint8_t>& in_value) {
-    (void)in_slotId;
-    (void)in_key;
-    (void)in_value;
+
+    if (in_slotId > 15 || in_key.size() > 16 || in_value.size() > 16)
+        return ::ndk::ScopedAStatus::fromStatus(STATUS_FAILED_TRANSACTION);
+
+    slot_array[in_slotId].key = in_key;
+    slot_array[in_slotId].value = in_value;
+
     return ::ndk::ScopedAStatus::ok();
 }
 
diff --git a/wifi/netlinkinterceptor/aidl/Android.bp b/wifi/netlinkinterceptor/aidl/Android.bp
new file mode 100644
index 0000000..924edee
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/Android.bp
@@ -0,0 +1,36 @@
+//
+// 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.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+    name: "android.hardware.net.nlinterceptor",
+    vendor_available: true,
+    srcs: ["android/hardware/net/nlinterceptor/*.aidl"],
+    stability: "vintf",
+    backend: {
+        java: {
+            enabled: false,
+        },
+    },
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl b/wifi/netlinkinterceptor/aidl/aidl_api/NetlinkInterceptor/current/android/hardware/net/nlinterceptor/IInterceptor.aidl
similarity index 76%
copy from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl
copy to wifi/netlinkinterceptor/aidl/aidl_api/NetlinkInterceptor/current/android/hardware/net/nlinterceptor/IInterceptor.aidl
index 5e6d212..249b343 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl
+++ b/wifi/netlinkinterceptor/aidl/aidl_api/NetlinkInterceptor/current/android/hardware/net/nlinterceptor/IInterceptor.aidl
@@ -1,11 +1,11 @@
-/**
- * Copyright (c) 2021, The Android Open Source Project
+/*
+ * 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
+ *      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,
@@ -31,8 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.net.nlinterceptor;
 @VintfStability
-parcelable ParcelableBlendMode {
-  android.hardware.graphics.common.BlendMode blendMode;
+interface IInterceptor {
+  int createSocket(in int nlFamily, in int clientNlPid, in String clientName);
+  void closeSocket(in int nlFamily, in int interceptorNlPid);
+  void subscribeGroup(in int nlFamily, in int interceptorNlPid, in int nlGroup);
+  void unsubscribeGroup(in int nlFamily, in int interceptorNlPid, in int nlGroup);
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl b/wifi/netlinkinterceptor/aidl/aidl_api/android.hardware.net.nlinterceptor/current/android/hardware/net/nlinterceptor/IInterceptor.aidl
similarity index 72%
copy from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl
copy to wifi/netlinkinterceptor/aidl/aidl_api/android.hardware.net.nlinterceptor/current/android/hardware/net/nlinterceptor/IInterceptor.aidl
index 5e6d212..3d0f955 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/ParcelableBlendMode.aidl
+++ b/wifi/netlinkinterceptor/aidl/aidl_api/android.hardware.net.nlinterceptor/current/android/hardware/net/nlinterceptor/IInterceptor.aidl
@@ -1,11 +1,11 @@
-/**
- * Copyright (c) 2021, The Android Open Source Project
+/*
+ * 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
+ *      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,
@@ -31,8 +31,11 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.net.nlinterceptor;
 @VintfStability
-parcelable ParcelableBlendMode {
-  android.hardware.graphics.common.BlendMode blendMode;
+interface IInterceptor {
+  android.hardware.net.nlinterceptor.InterceptedSocket createSocket(in int nlFamily, in int clientNlPid, in String clientName);
+  void closeSocket(in android.hardware.net.nlinterceptor.InterceptedSocket handle);
+  void subscribeGroup(in android.hardware.net.nlinterceptor.InterceptedSocket handle, in int nlGroup);
+  void unsubscribeGroup(in android.hardware.net.nlinterceptor.InterceptedSocket handle, in int nlGroup);
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/WhitePointNits.aidl b/wifi/netlinkinterceptor/aidl/aidl_api/android.hardware.net.nlinterceptor/current/android/hardware/net/nlinterceptor/InterceptedSocket.aidl
similarity index 87%
copy from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/WhitePointNits.aidl
copy to wifi/netlinkinterceptor/aidl/aidl_api/android.hardware.net.nlinterceptor/current/android/hardware/net/nlinterceptor/InterceptedSocket.aidl
index 2b25167..b679be5 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/command/WhitePointNits.aidl
+++ b/wifi/netlinkinterceptor/aidl/aidl_api/android.hardware.net.nlinterceptor/current/android/hardware/net/nlinterceptor/InterceptedSocket.aidl
@@ -1,11 +1,11 @@
-/**
- * Copyright (c) 2021, The Android Open Source Project
+/*
+ * 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
+ *      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,
@@ -31,8 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.net.nlinterceptor;
 @VintfStability
-parcelable WhitePointNits {
-  float nits;
+parcelable InterceptedSocket {
+  int nlFamily;
+  int portId;
 }
diff --git a/wifi/netlinkinterceptor/aidl/android/hardware/net/nlinterceptor/IInterceptor.aidl b/wifi/netlinkinterceptor/aidl/android/hardware/net/nlinterceptor/IInterceptor.aidl
new file mode 100644
index 0000000..c222a1e
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/android/hardware/net/nlinterceptor/IInterceptor.aidl
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+package android.hardware.net.nlinterceptor;
+
+import android.hardware.net.nlinterceptor.InterceptedSocket;
+
+/**
+ * Netlink Interceptor
+ *
+ * This HAL provides a way for Android services to route their Netlink traffic to a location other
+ * than the Kernel. One might want to do this for a variety of reasons:
+ * -> Route Netlink traffic to a different host.
+ * -> Route Netlink traffic to a different VM.
+ * -> Convert Netlink commands into proprietary vendor hardware commands.
+ *
+ * Some important notes regarding Netlink Interceptor.
+ * -> All int values are treated as unsigned.
+ * -> Users of Netlink Interceptor must close their sockets with closeSocket manually.
+ * -> PID != process ID. In this case, it is "port ID", a unique number assigned by the kernel to a
+ *    given Netlink socket.
+ * -> Netlink PIDs are only unique per family. This means that for all NETLINK_GENERIC sockets,
+ *    there can only be one socket with PID "1234". HOWEVER, there can ALSO be a Netlink socket
+ *    using NETLINK_ROUTE which has a PID of "1234". Hence, in order to uniquely identify a Netlink
+ *    socket, both the PID and Netlink Family are required.
+ */
+@VintfStability
+interface IInterceptor {
+    /**
+     * Creates a Netlink socket on both the HU and TCU, and a bi-directional gRPC stream to carry
+     * data between them. This must be closed by the caller with closeSocket().
+     *
+     * @param nlFamily - Netlink Family. Support for families other than NETLINK_GENERIC is still
+     * experimental.
+     * @param clientNlPid - Port ID of the caller's Netlink socket.
+     * @param clientName - Human readable name of the caller. Used for debugging.
+     *
+     * @return InterceptedSocket identifying the socket on the HU allocated for the caller.
+     */
+    InterceptedSocket createSocket(in int nlFamily, in int clientNlPid, in String clientName);
+
+    /**
+     * Closes a socket and gRPC stream given the socket's identifier. This must be invoked manually
+     * by the caller of createSocket().
+     *
+     * @param handle - unique identifier for a socket returned by createSocket.
+     */
+    void closeSocket(in InterceptedSocket handle);
+
+    /**
+     * Subscribes a socket on the TCU to a Netlink multicast group.
+     *
+     * @param handle - unique identifier for a socket returned by createSocket.
+     * @param nlGroup - A single Netlink multicast group that the caller wants to subscribe to.
+     */
+    void subscribeGroup(in InterceptedSocket handle, in int nlGroup);
+
+    /**
+     * Unsubscribes a socket on the TCU from a Netlink multicast group.
+     *
+     * @param handle - unique identifier for a socket returned by createSocket.
+     * @param nlGroup - A single Netlink multicast group that the caller wants to unsubscribe from.
+     */
+    void unsubscribeGroup(in InterceptedSocket handle, in int nlGroup);
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/command/Error.aidl b/wifi/netlinkinterceptor/aidl/android/hardware/net/nlinterceptor/InterceptedSocket.aidl
similarity index 60%
copy from graphics/composer/aidl/android/hardware/graphics/composer3/command/Error.aidl
copy to wifi/netlinkinterceptor/aidl/android/hardware/net/nlinterceptor/InterceptedSocket.aidl
index 19843b9..d74a556 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/command/Error.aidl
+++ b/wifi/netlinkinterceptor/aidl/android/hardware/net/nlinterceptor/InterceptedSocket.aidl
@@ -1,11 +1,11 @@
-/**
- * Copyright (c) 2021, The Android Open Source Project
+/*
+ * 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
+ *      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,
@@ -14,16 +14,20 @@
  * limitations under the License.
  */
 
-package android.hardware.graphics.composer3.command;
+package android.hardware.net.nlinterceptor;
 
+/**
+ * Unique identifier for a Netlink socket.
+ */
 @VintfStability
-parcelable Error {
+parcelable InterceptedSocket {
     /**
-     * The index in the command payload array.
+     * Netlink family of the identified socket
      */
-    int commandIndex;
+    int nlFamily;
+
     /**
-     * The error generated by the command. Can be one of the IComposerClient.EX_*
+     * Netlink port ID of the identified socket.
      */
-    int errorCode;
+    int portId;
 }
diff --git a/wifi/netlinkinterceptor/aidl/default/Android.bp b/wifi/netlinkinterceptor/aidl/default/Android.bp
new file mode 100644
index 0000000..5227e51
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/Android.bp
@@ -0,0 +1,48 @@
+//
+// 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.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_binary {
+    name: "android.hardware.net.nlinterceptor-service.default",
+    init_rc: ["nlinterceptor-default.rc"],
+    vintf_fragments: ["nlinterceptor-default.xml"],
+    vendor: true,
+    relative_install_path: "hw",
+    defaults: ["nlinterceptor@defaults"],
+    shared_libs: [
+        "android.hardware.net.nlinterceptor-V1-ndk",
+        "libbase",
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "libnlinterceptor",
+        "libnl++",
+    ],
+    srcs: [
+        "InterceptorRelay.cpp",
+        "NetlinkInterceptor.cpp",
+        "service.cpp",
+        "util.cpp",
+    ],
+}
diff --git a/wifi/netlinkinterceptor/aidl/default/InterceptorRelay.cpp b/wifi/netlinkinterceptor/aidl/default/InterceptorRelay.cpp
new file mode 100644
index 0000000..ded9122
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/InterceptorRelay.cpp
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+#include "InterceptorRelay.h"
+
+#include <android-base/logging.h>
+#include <libnl++/printer.h>
+#include <poll.h>
+
+#include <chrono>
+
+#include "util.h"
+
+namespace android::nlinterceptor {
+using namespace std::chrono_literals;
+
+static constexpr std::chrono::milliseconds kPollTimeout = 300ms;
+static constexpr bool kSuperVerbose = true;
+
+InterceptorRelay::InterceptorRelay(uint32_t nlFamily, uint32_t clientNlPid,
+                                   const std::string& clientName)
+    : mClientName(clientName),
+      mNlSocket(std::make_optional<nl::Socket>(nlFamily, 0, 0)),
+      mClientNlPid(clientNlPid) {}
+
+InterceptorRelay::~InterceptorRelay() {
+    mRunning = false;
+    if (mRelayThread.joinable()) mRelayThread.join();
+}
+
+uint32_t InterceptorRelay::getPid() {
+    auto pidMaybe = mNlSocket->getPid();
+    CHECK(pidMaybe.has_value()) << "Failed to get pid of nl::Socket!";
+    return *pidMaybe;
+}
+
+void InterceptorRelay::relayMessages() {
+    pollfd fds[] = {
+        mNlSocket->preparePoll(POLLIN),
+    };
+    while (mRunning) {
+        if (poll(fds, countof(fds), kPollTimeout.count()) < 0) {
+            PLOG(FATAL) << "poll failed";
+            return;
+        }
+        const auto nlsockEvents = fds[0].revents;
+
+        if (isSocketBad(nlsockEvents)) {
+            LOG(ERROR) << "Netlink socket is bad";
+            mRunning = false;
+            return;
+        }
+        if (!isSocketReadable(nlsockEvents)) continue;
+
+        const auto [msgMaybe, sa] = mNlSocket->receiveFrom();
+        if (!msgMaybe.has_value()) {
+            LOG(ERROR) << "Failed to receive Netlink data!";
+            mRunning = false;
+            return;
+        }
+        const auto msg = *msgMaybe;
+        if (!msg.firstOk()) {
+            LOG(ERROR) << "Netlink packet is malformed!";
+            // Test messages might be empty, this isn't fatal.
+            continue;
+        }
+        if constexpr (kSuperVerbose) {
+            LOG(VERBOSE) << "[" << mClientName
+                         << "] nlMsg: " << nl::toString(msg, NETLINK_GENERIC);
+        }
+
+        uint32_t destinationPid = 0;
+        if (sa.nl_pid == 0) {
+            destinationPid = mClientNlPid;
+        }
+
+        if (!mNlSocket->send(msg, destinationPid)) {
+            LOG(ERROR) << "Failed to send Netlink message!";
+            mRunning = false;
+            return;
+        }
+    }
+    LOG(VERBOSE) << "[" << mClientName << "] Exiting relay thread!";
+}
+
+bool InterceptorRelay::start() {
+    if (mRunning) {
+        LOG(ERROR)
+            << "Can't relay messages: InterceptorRelay is already running!";
+        return false;
+    }
+    if (mRelayThread.joinable()) {
+        LOG(ERROR) << "relay thread is already running!";
+        return false;
+    }
+    if (!mNlSocket.has_value()) {
+        LOG(ERROR) << "Netlink socket not initialized!";
+        return false;
+    }
+
+    mRunning = true;
+    mRelayThread = std::thread(&InterceptorRelay::relayMessages, this);
+
+    LOG(VERBOSE) << "Relay threads initialized";
+    return true;
+}
+
+bool InterceptorRelay::subscribeGroup(uint32_t nlGroup) {
+    return mNlSocket->addMembership(nlGroup);
+}
+
+bool InterceptorRelay::unsubscribeGroup(uint32_t nlGroup) {
+    return mNlSocket->dropMembership(nlGroup);
+}
+
+}  // namespace android::nlinterceptor
diff --git a/wifi/netlinkinterceptor/aidl/default/InterceptorRelay.h b/wifi/netlinkinterceptor/aidl/default/InterceptorRelay.h
new file mode 100644
index 0000000..0178c90
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/InterceptorRelay.h
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <libnl++/Socket.h>
+
+#include <mutex>
+#include <thread>
+
+namespace android::nlinterceptor {
+
+class InterceptorRelay {
+   public:
+    /**
+     * Wrapper around the netlink socket and thread which relays messages.
+     *
+     * \param nlFamily - netlink family to use for the netlink socket.
+     * \param clientNlPid - pid of the client netlink socket.
+     * \param clientName - name of the client to be used for debugging.
+     */
+    InterceptorRelay(uint32_t nlFamily, uint32_t clientNlPid,
+                     const std::string& clientName);
+
+    /**
+     * Stops the relay thread if running and destroys itself.
+     */
+    ~InterceptorRelay();
+
+    /**
+     * Returns the PID of the internal Netlink socket.
+     *
+     * \return value of PID,
+     */
+    uint32_t getPid();
+
+    /**
+     * Spawns relay thread.
+     */
+    bool start();
+
+    /**
+     * Subscribes the internal socket to a single Netlink multicast group.
+     *
+     * \param nlGroup - Netlink group to subscribe to.
+     * \returns - true for success, false for failure.
+     */
+    bool subscribeGroup(uint32_t nlGroup);
+
+    /**
+     * Unsubscribes the internal socket from a single Netlink multicast group.
+     *
+     * \param nlGroup - Netlink group to unsubscribe from.
+     * \returns - true for success, false for failure.
+     */
+    bool unsubscribeGroup(uint32_t nlGroup);
+
+   private:
+    std::string mClientName;  ///< Name of client (Wificond, for example).
+    std::optional<nl::Socket> mNlSocket;
+    const uint32_t mClientNlPid = 0;  ///< pid of client NL socket.
+
+    /**
+     * If set to true, the relay thread should be running. Setting this to false
+     * stops the relay thread.
+     */
+    std::atomic_bool mRunning = false;
+
+    /**
+     * Reads incoming Netlink messages destined for mNlSocket. If from the
+     * kernel, the message is relayed to the client specified in the
+     * constructor. Otherwise, the message is relayed to the kernel. This will
+     * run as long as mRunning is set to true.
+     */
+    void relayMessages();
+
+    std::thread mRelayThread;
+};
+
+}  // namespace android::nlinterceptor
diff --git a/wifi/netlinkinterceptor/aidl/default/NetlinkInterceptor.cpp b/wifi/netlinkinterceptor/aidl/default/NetlinkInterceptor.cpp
new file mode 100644
index 0000000..908ecf2
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/NetlinkInterceptor.cpp
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+#include "NetlinkInterceptor.h"
+
+#include <android-base/logging.h>
+#include <libnl++/Socket.h>
+
+namespace android::nlinterceptor {
+
+ndk::ScopedAStatus NetlinkInterceptor::createSocket(
+    int32_t nlFamilyAidl, int32_t clientNlPidAidl,
+    const std::string& clientName, AidlInterceptedSocket* interceptedSocket) {
+    auto nlFamily = static_cast<uint32_t>(nlFamilyAidl);
+    auto clientNlPid = static_cast<uint32_t>(clientNlPidAidl);
+    uint32_t interceptorNlPid = 0;
+
+    std::unique_ptr<InterceptorRelay> interceptor =
+        std::make_unique<InterceptorRelay>(nlFamily, clientNlPid, clientName);
+
+    interceptorNlPid = interceptor->getPid();
+
+    if (interceptorNlPid == 0) {
+        LOG(ERROR) << "Failed to create a Netlink socket for " << clientName
+                   << ", " << nlFamily << ":" << clientNlPid;
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+
+    if (mClientMap.find({nlFamily, interceptorNlPid}) != mClientMap.end()) {
+        LOG(ERROR) << "A socket with pid " << interceptorNlPid
+                   << " already exists!";
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+
+    if (!interceptor->start()) {
+        LOG(ERROR) << "Failed to start interceptor thread!";
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+
+    if (!mClientMap
+             .emplace(InterceptedSocket(nlFamily, interceptorNlPid),
+                      std::move(interceptor))
+             .second) {
+        // If this happens, it is very bad.
+        LOG(FATAL) << "Failed to insert interceptor instance with pid "
+                   << interceptorNlPid << " into map!";
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+
+    interceptedSocket->nlFamily = nlFamily;
+    interceptedSocket->portId = interceptorNlPid;
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus NetlinkInterceptor::closeSocket(
+    const AidlInterceptedSocket& interceptedSocket) {
+    InterceptedSocket sock(interceptedSocket);
+
+    auto interceptorIt = mClientMap.find(sock);
+    if (interceptorIt == mClientMap.end()) {
+        LOG(ERROR) << "closeSocket Failed! No such socket " << sock;
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+    mClientMap.erase(interceptorIt);
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus NetlinkInterceptor::subscribeGroup(
+    const AidlInterceptedSocket& interceptedSocket, int32_t nlGroupAidl) {
+    InterceptedSocket sock(interceptedSocket);
+    auto nlGroup = static_cast<uint32_t>(nlGroupAidl);
+
+    auto interceptorIt = mClientMap.find(sock);
+    if (interceptorIt == mClientMap.end()) {
+        LOG(ERROR) << "subscribeGroup failed! No such socket " << sock;
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+
+    auto& interceptor = interceptorIt->second;
+    if (!interceptor->subscribeGroup(nlGroup)) {
+        LOG(ERROR) << "Failed to subscribe " << sock << " to " << nlGroup;
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus NetlinkInterceptor::unsubscribeGroup(
+    const AidlInterceptedSocket& interceptedSocket, int32_t nlGroupAidl) {
+    InterceptedSocket sock(interceptedSocket);
+    auto nlGroup = static_cast<uint32_t>(nlGroupAidl);
+
+    auto interceptorIt = mClientMap.find(sock);
+    if (interceptorIt == mClientMap.end()) {
+        LOG(ERROR) << "unsubscribeGroup failed! No such socket " << sock;
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+
+    auto& interceptor = interceptorIt->second;
+    if (!interceptor->unsubscribeGroup(nlGroup)) {
+        LOG(ERROR) << "Failed to unsubscribe " << sock << " from " << nlGroup;
+        return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
+    }
+    return ndk::ScopedAStatus::ok();
+}
+}  // namespace android::nlinterceptor
diff --git a/wifi/netlinkinterceptor/aidl/default/NetlinkInterceptor.h b/wifi/netlinkinterceptor/aidl/default/NetlinkInterceptor.h
new file mode 100644
index 0000000..8345654
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/NetlinkInterceptor.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/net/nlinterceptor/BnInterceptor.h>
+#include <libnlinterceptor/libnlinterceptor.h>
+
+#include <map>
+
+#include "InterceptorRelay.h"
+
+namespace android::nlinterceptor {
+
+class NetlinkInterceptor
+    : public ::aidl::android::hardware::net::nlinterceptor::BnInterceptor {
+    using ClientMap =
+        std::map<::android::nlinterceptor::InterceptedSocket,
+                 std::unique_ptr<::android::nlinterceptor::InterceptorRelay>>;
+
+    using AidlInterceptedSocket =
+        ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket;
+
+   public:
+    ndk::ScopedAStatus createSocket(
+        int32_t nlFamily, int32_t clientNlPid, const std::string& clientName,
+        AidlInterceptedSocket* interceptedSocket) override;
+
+    ndk::ScopedAStatus closeSocket(
+        const AidlInterceptedSocket& interceptedSocket) override;
+
+    ndk::ScopedAStatus subscribeGroup(
+        const AidlInterceptedSocket& interceptedSocket,
+        int32_t nlGroup) override;
+
+    ndk::ScopedAStatus unsubscribeGroup(
+        const AidlInterceptedSocket& interceptedSocket,
+        int32_t nlGroup) override;
+
+   private:
+    ClientMap mClientMap;
+};
+
+}  // namespace android::nlinterceptor
diff --git a/wifi/netlinkinterceptor/aidl/default/OWNERS b/wifi/netlinkinterceptor/aidl/default/OWNERS
new file mode 100644
index 0000000..b738dac
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/OWNERS
@@ -0,0 +1,2 @@
+chrisweir@google.com
+twasilczyk@google.com
diff --git a/wifi/netlinkinterceptor/aidl/default/nlinterceptor-default.rc b/wifi/netlinkinterceptor/aidl/default/nlinterceptor-default.rc
new file mode 100644
index 0000000..353cb27
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/nlinterceptor-default.rc
@@ -0,0 +1,4 @@
+service nlinterceptor /vendor/bin/hw/android.hardware.net.nlinterceptor-service.default
+    class hal
+    user root
+    group system inet
diff --git a/wifi/netlinkinterceptor/aidl/default/nlinterceptor-default.xml b/wifi/netlinkinterceptor/aidl/default/nlinterceptor-default.xml
new file mode 100644
index 0000000..d7d257e
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/nlinterceptor-default.xml
@@ -0,0 +1,9 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.net.nlinterceptor</name>
+        <interface>
+            <name>IInterceptor</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/wifi/netlinkinterceptor/aidl/default/service.cpp b/wifi/netlinkinterceptor/aidl/default/service.cpp
new file mode 100644
index 0000000..2aec3a5
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/service.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include "NetlinkInterceptor.h"
+
+namespace android::nlinterceptor {
+using namespace std::string_literals;
+
+static void service() {
+    base::SetDefaultTag("nlinterceptor");
+    base::SetMinimumLogSeverity(base::VERBOSE);
+    LOG(DEBUG) << "Netlink Interceptor service starting...";
+
+    // TODO(202549296): Sometimes this causes an Address Sanitizer error.
+    auto interceptor = ndk::SharedRefBase::make<NetlinkInterceptor>();
+    const auto instance = NetlinkInterceptor::descriptor + "/default"s;
+    const auto status = AServiceManager_addService(
+        interceptor->asBinder().get(), instance.c_str());
+    CHECK(status == STATUS_OK);
+
+    ABinderProcess_joinThreadPool();
+    LOG(FATAL) << "Netlink Interceptor has stopped";
+}
+
+}  // namespace android::nlinterceptor
+
+int main() {
+    ::android::nlinterceptor::service();
+    return 0;
+}
diff --git a/wifi/netlinkinterceptor/aidl/default/util.cpp b/wifi/netlinkinterceptor/aidl/default/util.cpp
new file mode 100644
index 0000000..c734747
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/util.cpp
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+#include "util.h"
+
+#include <poll.h>
+
+namespace android::nlinterceptor {
+
+bool isSocketReadable(const short revents) { return 0 != (revents & POLLIN); }
+
+bool isSocketBad(const short revents) {
+    return 0 != (revents & (POLLERR | POLLHUP | POLLNVAL));
+}
+
+}  // namespace android::nlinterceptor
diff --git a/wifi/netlinkinterceptor/aidl/default/util.h b/wifi/netlinkinterceptor/aidl/default/util.h
new file mode 100644
index 0000000..9b8ec63
--- /dev/null
+++ b/wifi/netlinkinterceptor/aidl/default/util.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android-base/macros.h>
+
+#include <functional>
+
+namespace android::nlinterceptor {
+
+/**
+ * Handy-dandy helper to get the size of a statically initialized array.
+ *
+ * \param N the array to get the size of.
+ * \return the size of the array.
+ */
+template <typename T, size_t N>
+size_t countof(T (&)[N]) {
+    return N;
+}
+
+/**
+ * Helper to check if socket is readable (POLLIN is set).
+ *
+ * \param revents pollfd.revents value to check.
+ * \return true if socket is ready to read.
+ */
+bool isSocketReadable(short revents);
+
+/**
+ * Helper to check if socket is bad (POLLERR, POLLHUP or POLLNVAL is set).
+ *
+ * \param revents pollfd.revents value to check.
+ * \return true if socket is bad.
+ */
+bool isSocketBad(short revents);
+
+}  // namespace android::nlinterceptor
diff --git a/wifi/netlinkinterceptor/libnlinterceptor/Android.bp b/wifi/netlinkinterceptor/libnlinterceptor/Android.bp
new file mode 100644
index 0000000..00cae32
--- /dev/null
+++ b/wifi/netlinkinterceptor/libnlinterceptor/Android.bp
@@ -0,0 +1,65 @@
+//
+// 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.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_defaults {
+    name: "nlinterceptor@defaults",
+    cpp_std: "experimental",
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Wsuggest-override",
+        "-Werror",
+    ],
+    shared_libs: [
+        "libbase",
+        "libutils",
+    ],
+    sanitize: {
+        address: true,
+        undefined: true,
+        all_undefined: true,
+        fuzzer: true,
+        cfi: true,
+        integer_overflow: true,
+        scs: true,
+    },
+    strip: {
+        keep_symbols_and_debug_frame: true,
+    },
+}
+
+cc_library_static {
+    name: "libnlinterceptor",
+    defaults: ["nlinterceptor@defaults"],
+    vendor_available: true,
+    shared_libs: [
+        "android.hardware.net.nlinterceptor-V1-ndk",
+        "libbinder_ndk",
+    ],
+    srcs: [
+        "libnlinterceptor.cpp",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/wifi/netlinkinterceptor/libnlinterceptor/include/libnlinterceptor/libnlinterceptor.h b/wifi/netlinkinterceptor/libnlinterceptor/include/libnlinterceptor/libnlinterceptor.h
new file mode 100644
index 0000000..ac8653e
--- /dev/null
+++ b/wifi/netlinkinterceptor/libnlinterceptor/include/libnlinterceptor/libnlinterceptor.h
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+
+#include <aidl/android/hardware/net/nlinterceptor/InterceptedSocket.h>
+#include <android-base/unique_fd.h>
+#include <linux/netlink.h>
+
+#include <optional>
+#include <string>
+
+namespace android::nlinterceptor {
+
+/**
+ * Wrapper structure to uniquely identifies a socket that Netlink Interceptor
+ * has allocated for us.
+ */
+struct InterceptedSocket {
+    uint32_t nlFamily;
+    uint32_t portId;
+
+    InterceptedSocket(
+        ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket sock);
+    InterceptedSocket(uint32_t nlFamily, uint32_t portId);
+
+    bool operator<(const InterceptedSocket& other) const;
+    operator sockaddr_nl() const;
+    operator ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket()
+        const;
+};
+
+/**
+ * Output stream operator for InterceptedSocket
+ */
+std::ostream& operator<<(std::ostream& os, const InterceptedSocket& sock);
+
+/**
+ * Checks if an instance Netlink Interceptor exists.
+ *
+ * \return true if supported, false if not.
+ */
+bool isEnabled();
+
+/**
+ * Asks Netlink Interceptor to allocate a socket to which we can send Netlink
+ * traffic.
+ *
+ * \param clientSocket - File descriptor for the client's Netlink socket.
+ * \param clientName - Human readable name of the client application.
+ * \return Identifier for the socket created by Netlink Interceptor, nullopt on
+ * error.
+ */
+std::optional<InterceptedSocket> createSocket(base::borrowed_fd clientSocket,
+                                              const std::string& clientName);
+
+/**
+ * Asks Netlink Interceptor to close a socket that it created for us previously,
+ * if it exists.
+ *
+ * \param sock - Identifier for the socket created by Netlink Interceptor.
+ */
+void closeSocket(const InterceptedSocket& sock);
+
+/**
+ * Asks Netlink Interceptor to subscribe a socket that it created for us
+ * previously to a specified multicast group.
+ *
+ * \param sock - Identifier for the socket created by Netlink Interceptor.
+ * \param group - A single Netlink multicast group for which we would like to
+ * receive events.
+ * \return true for success, false if something went wrong.
+ */
+bool subscribe(const InterceptedSocket& sock, uint32_t group);
+
+/**
+ * Asks Netlink Interceptor to unsubscribe a socket that it created for us
+ * previously from a specified multicast group.
+ *
+ * \param sock - Identifier for the socket created by Netlink Interceptor.
+ * \param group - A single Netlink multicast group for which we no longer wish
+ * to receive events.
+ * \return true for success, false if something went wrong.
+ */
+bool unsubscribe(const InterceptedSocket& sock, uint32_t group);
+}  // namespace android::nlinterceptor
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// C wrappers for libnlinterceptor
+struct android_nlinterceptor_InterceptedSocket {
+    uint32_t nlFamily;
+    uint32_t portId;
+};
+
+bool android_nlinterceptor_isEnabled();
+
+bool android_nlinterceptor_createSocket(
+    int clientSocketFd, const char* clientName,
+    struct android_nlinterceptor_InterceptedSocket* interceptedSocket);
+
+void android_nlinterceptor_closeSocket(
+    const struct android_nlinterceptor_InterceptedSocket* sock);
+
+bool android_nlinterceptor_subscribe(
+    const struct android_nlinterceptor_InterceptedSocket* sock, uint32_t group);
+
+bool android_nlinterceptor_unsubscribe(
+    const struct android_nlinterceptor_InterceptedSocket* sock, uint32_t group);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/wifi/netlinkinterceptor/libnlinterceptor/libnlinterceptor.cpp b/wifi/netlinkinterceptor/libnlinterceptor/libnlinterceptor.cpp
new file mode 100644
index 0000000..575f900
--- /dev/null
+++ b/wifi/netlinkinterceptor/libnlinterceptor/libnlinterceptor.cpp
@@ -0,0 +1,174 @@
+/*
+ * 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.
+ */
+
+#include <aidl/android/hardware/net/nlinterceptor/IInterceptor.h>
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <android/binder_manager.h>
+#include <libnlinterceptor/libnlinterceptor.h>
+#include <linux/netlink.h>
+
+#include <mutex>
+
+namespace android::nlinterceptor {
+using namespace std::string_literals;
+using namespace ::aidl::android::hardware::net::nlinterceptor;
+using base::borrowed_fd;
+using AidlInterceptedSocket =
+    ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket;
+
+static const auto kServiceName = IInterceptor::descriptor + "/default"s;
+
+InterceptedSocket::InterceptedSocket(
+    ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket sock)
+    : nlFamily(sock.nlFamily), portId(sock.portId) {}
+
+InterceptedSocket::InterceptedSocket(uint32_t nlFamily, uint32_t portId)
+    : nlFamily(nlFamily), portId(portId) {}
+
+std::ostream& operator<<(std::ostream& os, const InterceptedSocket& sock) {
+    return os << "family: " << sock.nlFamily << ", portId: " << sock.portId;
+}
+
+bool InterceptedSocket::operator<(const InterceptedSocket& other) const {
+    if (nlFamily != other.nlFamily) {
+        return nlFamily < other.nlFamily;
+    }
+    return portId < other.portId;
+}
+
+InterceptedSocket::operator sockaddr_nl() const {
+    return {
+        .nl_family = AF_NETLINK,
+        .nl_pad = 0,
+        .nl_pid = portId,
+        .nl_groups = 0,
+    };
+}
+
+InterceptedSocket::operator AidlInterceptedSocket() const {
+    return {
+        .nlFamily = static_cast<int32_t>(nlFamily),
+        .portId = static_cast<int32_t>(portId),
+    };
+}
+
+bool isEnabled() {
+    static std::mutex supportedMutex;
+    static std::optional<bool> interceptorSupported;
+    // Avoid querying service manager when we can cache the result.
+    if (interceptorSupported.has_value()) return *interceptorSupported;
+    std::lock_guard lock(supportedMutex);
+    if (interceptorSupported.has_value()) return *interceptorSupported;
+
+    if (!AServiceManager_isDeclared(kServiceName.c_str())) {
+        interceptorSupported = false;
+        return false;
+    }
+    interceptorSupported = true;
+    return true;
+}
+
+static IInterceptor& getInstance() {
+    static std::mutex instanceMutex;
+    static std::shared_ptr<IInterceptor> interceptorInstance;
+    CHECK(isEnabled()) << "Can't getInstance! Interceptor not supported!";
+    // Don't overwrite the pointer once we've acquired it.
+    if (interceptorInstance != nullptr) return *interceptorInstance;
+    std::lock_guard lock(instanceMutex);
+    if (interceptorInstance != nullptr) return *interceptorInstance;
+    interceptorInstance = IInterceptor::fromBinder(
+        ndk::SpAIBinder(AServiceManager_waitForService(kServiceName.c_str())));
+    CHECK(interceptorInstance != nullptr)
+        << "Failed to get Netlink Interceptor service!";
+    return *interceptorInstance;
+}
+
+std::optional<InterceptedSocket> createSocket(borrowed_fd clientSocket,
+                                              const std::string& clientName) {
+    sockaddr_nl nladdr = {};
+    socklen_t nlsize = sizeof(nladdr);
+    if (getsockname(clientSocket.get(), reinterpret_cast<sockaddr*>(&nladdr),
+                    &nlsize) < 0) {
+        PLOG(ERROR) << "Failed to get pid of fd passed by " << clientName;
+        return std::nullopt;
+    }
+
+    ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket
+        interceptedSocket;
+    auto aidlStatus = getInstance().createSocket(
+        nladdr.nl_family, nladdr.nl_pid, clientName, &interceptedSocket);
+    if (!aidlStatus.isOk()) {
+        return std::nullopt;
+    }
+
+    return InterceptedSocket{nladdr.nl_family,
+                             uint32_t(interceptedSocket.portId)};
+}
+
+void closeSocket(const InterceptedSocket& sock) {
+    auto aidlStatus = getInstance().closeSocket(sock);
+    if (!aidlStatus.isOk()) {
+        LOG(ERROR) << "Failed to close socket with pid = " << sock.portId;
+    }
+}
+
+bool subscribe(const InterceptedSocket& sock, uint32_t group) {
+    auto aidlStatus = getInstance().subscribeGroup(sock, group);
+    return aidlStatus.isOk();
+}
+
+bool unsubscribe(const InterceptedSocket& sock, uint32_t group) {
+    auto aidlStatus = getInstance().unsubscribeGroup(sock, group);
+    return aidlStatus.isOk();
+}
+
+extern "C" bool android_nlinterceptor_isEnabled() { return isEnabled(); }
+
+extern "C" bool android_nlinterceptor_createSocket(
+    int clientSocketFd, const char* clientName,
+    android_nlinterceptor_InterceptedSocket* interceptedSocket) {
+    if (!clientName || clientSocketFd <= 0) return false;
+    const auto maybeSocket =
+        createSocket(borrowed_fd(clientSocketFd), clientName);
+    if (!maybeSocket) return false;
+    *interceptedSocket = {.nlFamily = maybeSocket->nlFamily,
+                          .portId = maybeSocket->portId};
+    return true;
+}
+
+extern "C" void android_nlinterceptor_closeSocket(
+    const android_nlinterceptor_InterceptedSocket* sock) {
+    if (!sock) {
+        LOG(ERROR) << "Can't close socket identified by a null pointer!";
+        return;
+    }
+    closeSocket({sock->nlFamily, sock->portId});
+}
+
+extern "C" bool android_nlinterceptor_subscribe(
+    const android_nlinterceptor_InterceptedSocket* sock, uint32_t group) {
+    if (!sock) return false;
+    return subscribe({sock->nlFamily, sock->portId}, group);
+}
+
+extern "C" bool android_nlinterceptor_unsubscribe(
+    const android_nlinterceptor_InterceptedSocket* sock, uint32_t group) {
+    if (!sock) return false;
+    return unsubscribe({sock->nlFamily, sock->portId}, group);
+}
+
+}  // namespace android::nlinterceptor
diff --git a/wifi/netlinkinterceptor/vts/OWNERS b/wifi/netlinkinterceptor/vts/OWNERS
new file mode 100644
index 0000000..b738dac
--- /dev/null
+++ b/wifi/netlinkinterceptor/vts/OWNERS
@@ -0,0 +1,2 @@
+chrisweir@google.com
+twasilczyk@google.com
diff --git a/wifi/netlinkinterceptor/vts/functional/Android.bp b/wifi/netlinkinterceptor/vts/functional/Android.bp
new file mode 100644
index 0000000..33284e8
--- /dev/null
+++ b/wifi/netlinkinterceptor/vts/functional/Android.bp
@@ -0,0 +1,51 @@
+//
+// 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.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+    name: "VtsHalNetlinkInterceptorV1_0Test",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    cpp_std: "experimental",
+    srcs: [
+        "interceptor_aidl_test.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.net.nlinterceptor-V1-ndk",
+        "libbase",
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "libgmock",
+        "android.hardware.automotive.can@libnetdevice",
+        "libnl++",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+    disable_framework: true,
+}
diff --git a/wifi/netlinkinterceptor/vts/functional/interceptor_aidl_test.cpp b/wifi/netlinkinterceptor/vts/functional/interceptor_aidl_test.cpp
new file mode 100644
index 0000000..b26d8ec
--- /dev/null
+++ b/wifi/netlinkinterceptor/vts/functional/interceptor_aidl_test.cpp
@@ -0,0 +1,195 @@
+/*
+ * 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.
+ */
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/net/nlinterceptor/IInterceptor.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <gtest/gtest.h>
+#include <libnetdevice/libnetdevice.h>
+#include <libnl++/MessageFactory.h>
+#include <libnl++/Socket.h>
+#include <libnl++/printer.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+#include <chrono>
+#include <thread>
+
+using aidl::android::hardware::net::nlinterceptor::IInterceptor;
+using AidlInterceptedSocket =
+    ::aidl::android::hardware::net::nlinterceptor::InterceptedSocket;
+using namespace std::chrono_literals;
+using namespace std::string_literals;
+
+class InterceptorAidlTest : public ::testing::TestWithParam<std::string> {
+   public:
+    virtual void SetUp() override {
+        android::base::SetDefaultTag("InterceptorAidlTest");
+        android::base::SetMinimumLogSeverity(android::base::VERBOSE);
+        const auto instance = IInterceptor::descriptor + "/default"s;
+        mNlInterceptorService = IInterceptor::fromBinder(
+            ndk::SpAIBinder(AServiceManager_getService(instance.c_str())));
+
+        ASSERT_NE(mNlInterceptorService, nullptr);
+        mSocket = std::make_unique<android::nl::Socket>(NETLINK_ROUTE);
+        ASSERT_TRUE(mSocket->getPid().has_value());
+
+        // If the test broke last run, clean up our mess, don't worry about "no
+        // such device".
+        if (android::netdevice::del(mTestIfaceName)) {
+            LOG(WARNING) << "Test interface wasn't cleaned up on previous run!";
+        }
+    }
+
+    void multicastReceiver();
+
+    std::shared_ptr<IInterceptor> mNlInterceptorService;
+    std::unique_ptr<android::nl::Socket> mSocket;
+    bool mRunning;
+    bool mGotMulticast;
+    const std::string mTestIfaceName = "interceptorvts0";
+};
+
+TEST_P(InterceptorAidlTest, createSocketTest) {
+    // Ask IInterceptor for a socket.
+    AidlInterceptedSocket interceptedSocket;
+    auto aidlStatus = mNlInterceptorService->createSocket(
+        NETLINK_ROUTE, *(mSocket->getPid()), "createSocketTest",
+        &interceptedSocket);
+    ASSERT_TRUE(aidlStatus.isOk());
+    ASSERT_NE(interceptedSocket.portId, 0);
+    uint32_t interceptorPid = interceptedSocket.portId;
+
+    // Ask the kernel to tell us what interfaces are available.
+    android::nl::MessageFactory<rtgenmsg> req(RTM_GETLINK,
+                                              NLM_F_REQUEST | NLM_F_DUMP);
+    req->rtgen_family = AF_PACKET;
+    sockaddr_nl sa = {.nl_family = AF_NETLINK,
+                      .nl_pad = 0,
+                      .nl_pid = interceptorPid,
+                      .nl_groups = 0};
+    EXPECT_TRUE(mSocket->send(req, sa));
+
+    // We'll likely get back several messages, as indicated by the MULTI flag.
+    unsigned received = 0;
+    for (const auto msg : *mSocket) {
+        ASSERT_NE(msg->nlmsg_type, NLMSG_ERROR);
+        ++received;
+        break;
+        if (msg->nlmsg_type == NLMSG_DONE) {
+            // TODO(202548749): NLMSG_DONE on NETLINK_ROUTE doesn't work?
+            break;
+        }
+    }
+    ASSERT_GE(received, 1);
+
+    // Close the socket and make sure it's stopped working.
+    aidlStatus = mNlInterceptorService->closeSocket(interceptedSocket);
+    EXPECT_TRUE(aidlStatus.isOk());
+    EXPECT_FALSE(mSocket->send(req, sa));
+}
+
+static bool isSocketReadable(const short revents) {
+    return 0 != (revents & POLLIN);
+}
+
+static bool isSocketBad(const short revents) {
+    return 0 != (revents & (POLLERR | POLLHUP | POLLNVAL));
+}
+
+void InterceptorAidlTest::multicastReceiver() {
+    pollfd fds[] = {
+        mSocket->preparePoll(POLLIN),
+    };
+    while (mRunning) {
+        if (poll(fds, 1, 300) < 0) {
+            PLOG(FATAL) << "poll failed";
+            return;
+        }
+        const auto nlsockEvents = fds[0].revents;
+        ASSERT_FALSE(isSocketBad(nlsockEvents));
+        if (!isSocketReadable(nlsockEvents)) continue;
+
+        const auto [msgMaybe, sa] = mSocket->receiveFrom();
+        ASSERT_TRUE(msgMaybe.has_value());
+        auto msg = *msgMaybe;
+
+        // Multicast messages have 0 for their pid and sequence number.
+        if (msg->nlmsg_pid == 0 && msg->nlmsg_seq == 0) {
+            mGotMulticast = true;
+        }
+    }
+}
+
+TEST_P(InterceptorAidlTest, subscribeGroupTest) {
+    // Ask IInterceptor for a socket.
+    AidlInterceptedSocket interceptedSocket;
+    auto aidlStatus = mNlInterceptorService->createSocket(
+        NETLINK_ROUTE, *(mSocket->getPid()), "subscribeGroupTest",
+        &interceptedSocket);
+    ASSERT_TRUE(aidlStatus.isOk());
+    ASSERT_TRUE(interceptedSocket.portId != 0);
+
+    // Listen for interface up/down events.
+    aidlStatus =
+        mNlInterceptorService->subscribeGroup(interceptedSocket, RTNLGRP_LINK);
+    ASSERT_TRUE(aidlStatus.isOk());
+
+    // Start a thread to receive a multicast
+    mRunning = true;
+    mGotMulticast = false;
+    std::thread successfulReceiver(&InterceptorAidlTest::multicastReceiver,
+                                   this);
+
+    // TODO(201695162): use futures with wait_for instead of a sleep_for().
+    std::this_thread::sleep_for(50ms);
+    // create a network interface and bring it up to trigger a multicast event.
+    ASSERT_TRUE(android::netdevice::add(mTestIfaceName, /*type=*/"dummy"));
+    ASSERT_TRUE(android::netdevice::up(mTestIfaceName));
+    std::this_thread::sleep_for(50ms);
+    EXPECT_TRUE(mGotMulticast);
+    mRunning = false;
+    successfulReceiver.join();
+
+    // Stop listening to interface up/down events.
+    aidlStatus = mNlInterceptorService->unsubscribeGroup(interceptedSocket,
+                                                         RTNLGRP_LINK);
+    ASSERT_TRUE(aidlStatus.isOk());
+
+    // This time, we should hear nothing.
+    mGotMulticast = false;
+    mRunning = true;
+    std::thread unsuccessfulReceiver(&InterceptorAidlTest::multicastReceiver,
+                                     this);
+    std::this_thread::sleep_for(50ms);
+    ASSERT_TRUE(android::netdevice::down(mTestIfaceName));
+    ASSERT_TRUE(android::netdevice::del(mTestIfaceName));
+    std::this_thread::sleep_for(50ms);
+    EXPECT_FALSE(mGotMulticast);
+    mRunning = false;
+    unsuccessfulReceiver.join();
+
+    aidlStatus = mNlInterceptorService->closeSocket(interceptedSocket);
+    EXPECT_TRUE(aidlStatus.isOk());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InterceptorAidlTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, InterceptorAidlTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             IInterceptor::descriptor)),
+                         android::PrintInstanceNameToString);