Merge "Avoid multiple map lookups"
diff --git a/bluetooth/audio/2.2/default/OWNERS b/bluetooth/audio/2.2/default/OWNERS
new file mode 100644
index 0000000..17ea464
--- /dev/null
+++ b/bluetooth/audio/2.2/default/OWNERS
@@ -0,0 +1,4 @@
+include platform/packages/modules/Bluetooth:/OWNERS
+
+cheneyni@google.com
+aliceypkuo@google.com
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
index 7e49074..5a413e0 100644
--- a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
@@ -88,8 +88,9 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
   }
   *_aidl_return = data_mq_->dupeDesc();
+  auto desc = data_mq_->dupeDesc();
   BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
-                                                _aidl_return, *audio_config_);
+                                                &desc, *audio_config_);
   return ndk::ScopedAStatus::ok();
 }
 
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
index 8e6cee7..1e55a0b 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "BTAudioProvidersFactory"
+#define LOG_TAG "BTAudioProviderFactoryAIDL"
 
 #include "BluetoothAudioProviderFactory.h"
 
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h
index 96d888c..b38cfd2 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h
@@ -18,13 +18,6 @@
 
 #include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioProviderFactory.h>
 
-#include "A2dpOffloadAudioProvider.h"
-#include "A2dpSoftwareAudioProvider.h"
-#include "BluetoothAudioProvider.h"
-#include "HearingAidAudioProvider.h"
-#include "LeAudioOffloadAudioProvider.h"
-#include "LeAudioSoftwareAudioProvider.h"
-
 namespace aidl {
 namespace android {
 namespace hardware {
diff --git a/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp b/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
index a993059..66ce93b 100644
--- a/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
@@ -81,10 +81,10 @@
     *_aidl_return = DataMQDesc();
     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
   }
+  *_aidl_return = data_mq_->dupeDesc();
   auto desc = data_mq_->dupeDesc();
   BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
                                                 &desc, *audio_config_);
-  *_aidl_return = data_mq_->dupeDesc();
   return ndk::ScopedAStatus::ok();
 }
 
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
index 4078783..72ac9bd 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "BTAudioProviderLeAudioSW"
+#define LOG_TAG "BTAudioProviderLeAudioHW"
 
 #include "LeAudioOffloadAudioProvider.h"
 
diff --git a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
index f9962fd..67b7d60 100644
--- a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "BTAudioProviderLeAudioHW"
+#define LOG_TAG "BTAudioProviderLeAudioSW"
 
 #include "LeAudioSoftwareAudioProvider.h"
 
@@ -88,6 +88,16 @@
       channel_mode_to_channel_count(pcm_config.channelMode) *
       (pcm_config.bitsPerSample / 8) * (pcm_config.dataIntervalUs / 1000) *
       buffer_modifier;
+  if (data_mq_size <= 0) {
+    LOG(ERROR) << __func__ << "Unexpected audio buffer size: " << data_mq_size
+               << ", SampleRateHz: " << pcm_config.sampleRateHz
+               << ", ChannelMode: " << toString(pcm_config.channelMode)
+               << ", BitsPerSample: "
+               << static_cast<int>(pcm_config.bitsPerSample)
+               << ", DataIntervalUs: " << pcm_config.dataIntervalUs
+               << ", SessionType: " << toString(session_type_);
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
 
   LOG(INFO) << __func__ << " - size of audio buffer " << data_mq_size
             << " byte(s)";
@@ -113,8 +123,9 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
   }
   *_aidl_return = data_mq_->dupeDesc();
+  auto desc = data_mq_->dupeDesc();
   BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
-                                                _aidl_return, *audio_config_);
+                                                &desc, *audio_config_);
   return ndk::ScopedAStatus::ok();
 }
 
diff --git a/bluetooth/audio/aidl/default/OWNERS b/bluetooth/audio/aidl/default/OWNERS
new file mode 100644
index 0000000..17ea464
--- /dev/null
+++ b/bluetooth/audio/aidl/default/OWNERS
@@ -0,0 +1,4 @@
+include platform/packages/modules/Bluetooth:/OWNERS
+
+cheneyni@google.com
+aliceypkuo@google.com
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/vts/OWNERS b/bluetooth/audio/aidl/vts/OWNERS
new file mode 100644
index 0000000..17ea464
--- /dev/null
+++ b/bluetooth/audio/aidl/vts/OWNERS
@@ -0,0 +1,4 @@
+include platform/packages/modules/Bluetooth:/OWNERS
+
+cheneyni@google.com
+aliceypkuo@google.com
\ No newline at end of file
diff --git a/bluetooth/audio/utils/OWNERS b/bluetooth/audio/utils/OWNERS
index ed92847..17ea464 100644
--- a/bluetooth/audio/utils/OWNERS
+++ b/bluetooth/audio/utils/OWNERS
@@ -1,3 +1,4 @@
 include platform/packages/modules/Bluetooth:/OWNERS
 
-cheneyni@google.com
\ No newline at end of file
+cheneyni@google.com
+aliceypkuo@google.com
\ No newline at end of file
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
index 95e473e..8052b01 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -114,11 +114,6 @@
 const AudioConfiguration& BluetoothAudioSession::GetAudioConfig() {
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (!IsSessionReady()) {
-    if (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
-      return invalidOffloadAudioConfiguration;
-    } else {
-      return invalidSoftwareAudioConfiguration;
-    }
     switch (session_type_) {
       case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
         return invalidOffloadAudioConfiguration;
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
index 91e0238..284d0bb 100644
--- a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
@@ -761,6 +761,13 @@
       from_session_type_2_1(session_type));
 }
 
+void HidlToAidlMiddleware_2_2::UpdateTracksMetadata(
+    const SessionType_2_1& session_type,
+    const struct source_metadata* source_metadata) {
+  return BluetoothAudioSessionControl::UpdateSourceMetadata(
+      from_session_type_2_1(session_type), *source_metadata);
+}
+
 void HidlToAidlMiddleware_2_2::UpdateSinkMetadata(
     const SessionType_2_1& session_type,
     const struct sink_metadata* sink_metadata) {
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h
index 149e404..f6c3e5c 100644
--- a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h
@@ -54,6 +54,10 @@
 
   static void StopStream(const SessionType_2_1& session_type);
 
+  static void UpdateTracksMetadata(
+      const SessionType_2_1& session_type,
+      const struct source_metadata* source_metadata);
+
   static void UpdateSinkMetadata(const SessionType_2_1& session_type,
                                  const struct sink_metadata* sink_metadata);
 };
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
index 368939e..c270ef0 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
@@ -152,7 +152,7 @@
     std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
         BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
     if (session_ptr != nullptr) {
-      session_ptr->GetAudioSession()->UpdateTracksMetadata(source_metadata);
+      session_ptr->UpdateTracksMetadata(source_metadata);
     }
   }
 
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
index 4613ddc..ceb0662 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
@@ -31,9 +31,13 @@
 
 using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_0;
 using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_2;
+using ::android::hardware::audio::common::V5_0::AudioContentType;
 using ::android::hardware::audio::common::V5_0::AudioSource;
+using ::android::hardware::audio::common::V5_0::AudioUsage;
+using ::android::hardware::audio::common::V5_0::PlaybackTrackMetadata;
 using ::android::hardware::audio::common::V5_0::RecordTrackMetadata;
 using ::android::hardware::audio::common::V5_0::SinkMetadata;
+using ::android::hardware::audio::common::V5_0::SourceMetadata;
 using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
 using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
 using ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration;
@@ -128,6 +132,53 @@
   return audio_session_2_1;
 }
 
+void BluetoothAudioSession_2_2::UpdateTracksMetadata(
+    const struct source_metadata* source_metadata) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::UpdateTracksMetadata(raw_session_type_,
+                                                          source_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 = source_metadata->track_count;
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+            << ", " << track_count << " track(s)";
+
+  if (session_type_2_1_ == SessionType_2_1::UNKNOWN) {
+    audio_session->UpdateTracksMetadata(source_metadata);
+    return;
+  }
+
+  struct playback_track_metadata* track = source_metadata->tracks;
+  SourceMetadata sourceMetadata;
+  PlaybackTrackMetadata* halMetadata;
+
+  sourceMetadata.tracks.resize(track_count);
+  halMetadata = sourceMetadata.tracks.data();
+  while (track_count && track) {
+    halMetadata->usage = static_cast<AudioUsage>(track->usage);
+    halMetadata->contentType =
+        static_cast<AudioContentType>(track->content_type);
+    halMetadata->gain = track->gain;
+    LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+                 << ", usage=" << toString(halMetadata->usage)
+                 << ", content=" << toString(halMetadata->contentType)
+                 << ", gain=" << halMetadata->gain;
+    --track_count;
+    ++track;
+    ++halMetadata;
+  }
+  auto hal_retval = audio_session->stack_iface_->updateMetadata(sourceMetadata);
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_2_1_) << " failed";
+  }
+}
+
 void BluetoothAudioSession_2_2::UpdateSinkMetadata(
     const struct sink_metadata* sink_metadata) {
   if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
index b6f96ab..e04ad80 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
@@ -152,6 +152,7 @@
   const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
   GetAudioConfig();
 
+  void UpdateTracksMetadata(const struct source_metadata* source_metadata);
   void UpdateSinkMetadata(const struct sink_metadata* sink_metadata);
 
   static constexpr ::android::hardware::bluetooth::audio::V2_2::
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/Android.bp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/Android.bp
index 741572d..bd2c3b1 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/Android.bp
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/Android.bp
@@ -50,6 +50,7 @@
         "libgui",
         "libhidlbase",
         "libprocessgroup",
+        "libtinyxml2",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.1",
         "android.hardware.graphics.mapper@3.0",
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 e519221..3f1e703 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
@@ -24,10 +24,18 @@
 #include <composer-vts/include/ReadbackVts.h>
 #include <composer-vts/include/RenderEngineVts.h>
 #include <gtest/gtest.h>
+#include <ui/DisplayId.h>
+#include <ui/DisplayIdentification.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/PixelFormat.h>
 #include <ui/Rect.h>
+
+// tinyxml2 does implicit conversions >:(
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+#include <tinyxml2.h>
+#pragma clang diagnostic pop
 #include "composer-vts/include/GraphicsComposerCallback.h"
 
 namespace aidl::android::hardware::graphics::composer3::vts {
@@ -124,6 +132,76 @@
                 /*layerCount*/ 1u, usage, "VtsHalGraphicsComposer3_ReadbackTest");
     }
 
+    uint64_t getStableDisplayId(int64_t display) {
+        DisplayIdentification identification;
+        const auto error = mComposerClient->getDisplayIdentificationData(display, &identification);
+        EXPECT_TRUE(error.isOk());
+
+        if (const auto info = ::android::parseDisplayIdentificationData(
+                    static_cast<uint8_t>(identification.port), identification.data)) {
+            return info->id.value;
+        }
+
+        return ::android::PhysicalDisplayId::fromPort(static_cast<uint8_t>(identification.port))
+                .value;
+    }
+
+    // Gets the per-display XML config
+    std::unique_ptr<tinyxml2::XMLDocument> getDisplayConfigXml(int64_t display) {
+        std::stringstream pathBuilder;
+        pathBuilder << "/vendor/etc/displayconfig/display_id_" << getStableDisplayId(display)
+                    << ".xml";
+        const std::string path = pathBuilder.str();
+        auto document = std::make_unique<tinyxml2::XMLDocument>();
+        const tinyxml2::XMLError error = document->LoadFile(path.c_str());
+        if (error == tinyxml2::XML_SUCCESS) {
+            return document;
+        } else {
+            return nullptr;
+        }
+    }
+
+    // Gets the max display brightness for this display.
+    // If the display config xml does not exist, then assume that the display is not well-configured
+    // enough to provide a display brightness, so return nullopt.
+    std::optional<float> getMaxDisplayBrightnessNits(int64_t display) {
+        const auto document = getDisplayConfigXml(display);
+        if (!document) {
+            // Assume the device doesn't support display brightness
+            return std::nullopt;
+        }
+
+        const auto root = document->RootElement();
+        if (!root) {
+            // If there's somehow no root element, then this isn't a valid config
+            return std::nullopt;
+        }
+
+        const auto screenBrightnessMap = root->FirstChildElement("screenBrightnessMap");
+        if (!screenBrightnessMap) {
+            // A valid display config must have a screen brightness map
+            return std::nullopt;
+        }
+
+        auto point = screenBrightnessMap->FirstChildElement("point");
+        float maxNits = -1.f;
+        while (point != nullptr) {
+            const auto nits = point->FirstChildElement("nits");
+            if (nits) {
+                maxNits = std::max(maxNits, nits->FloatText(-1.f));
+            }
+            point = point->NextSiblingElement("point");
+        }
+
+        if (maxNits < 0.f) {
+            // If we got here, then there were no point elements containing a nit value, so this
+            // config isn't valid
+            return std::nullopt;
+        }
+
+        return maxNits;
+    }
+
     void writeLayers(const std::vector<std::shared_ptr<TestLayer>>& layers) {
         for (auto layer : layers) {
             layer->write(mWriter);
@@ -250,8 +328,8 @@
         std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
-                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         writeLayers(layers);
@@ -286,8 +364,8 @@
             return;
         }
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
-                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
@@ -363,8 +441,8 @@
         std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
-                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
@@ -389,8 +467,8 @@
         return;
     }
 
-    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer, mDisplayWidth,
-                                  mDisplayHeight, mPixelFormat, mDataspace);
+    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth, mDisplayHeight,
+                                  mPixelFormat, mDataspace);
 
     ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 }
@@ -419,8 +497,13 @@
         return;
     }
 
-    aidl::android::hardware::common::NativeHandle bufferHandle =
-            ::android::dupToAidl(mGraphicBuffer->handle);
+    aidl::android::hardware::common::NativeHandle bufferHandle;
+    {
+        ::android::sp<::android::GraphicBuffer> buffer = allocate();
+        ASSERT_EQ(::android::OK, mGraphicBuffer->initCheck());
+        ::android::makeToAidl(mGraphicBuffer->handle);
+    }
+
     ndk::ScopedFileDescriptor releaseFence = ndk::ScopedFileDescriptor(-1);
     const auto error =
             mComposerClient->setReadbackBuffer(mPrimaryDisplay, bufferHandle, releaseFence);
@@ -438,8 +521,9 @@
     ndk::ScopedFileDescriptor releaseFence;
     const auto error = mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &releaseFence);
 
-    EXPECT_TRUE(error.isOk());
+    ASSERT_FALSE(error.isOk());
     EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, error.getServiceSpecificError());
+    EXPECT_EQ(-1, releaseFence.get());
 }
 
 TEST_P(GraphicsCompositionTest, ClientComposition) {
@@ -474,8 +558,8 @@
 
         std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
-                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(layers);
         ASSERT_TRUE(mReader.takeErrors().empty());
@@ -553,8 +637,8 @@
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
                                        {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, RED);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
-                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         auto deviceLayer = std::make_shared<TestBufferLayer>(
@@ -657,8 +741,8 @@
 
         std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
-                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         writeLayers(layers);
@@ -720,8 +804,8 @@
 
         std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
-                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
 
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
@@ -781,8 +865,8 @@
         // update expected colors to match crop
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth,
                                        {0, 0, mDisplayWidth, mDisplayHeight}, BLUE);
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
-                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(layers);
         ASSERT_TRUE(mReader.takeErrors().empty());
@@ -834,8 +918,8 @@
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE);
         ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
-                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         writeLayers(layers);
@@ -876,6 +960,90 @@
     }
 }
 
+TEST_P(GraphicsCompositionTest, SetLayerWhitePointDims) {
+    std::vector<DisplayCapability> capabilities;
+    const auto error = mComposerClient->getDisplayCapabilities(mPrimaryDisplay, &capabilities);
+    ASSERT_TRUE(error.isOk());
+
+    const bool brightnessSupport = std::find(capabilities.begin(), capabilities.end(),
+                                             DisplayCapability::BRIGHTNESS) != capabilities.end();
+
+    if (!brightnessSupport) {
+        GTEST_SUCCEED() << "Cannot verify dimming behavior without brightness support";
+        return;
+    }
+
+    const std::optional<float> maxBrightnessNitsOptional =
+            getMaxDisplayBrightnessNits(mPrimaryDisplay);
+
+    ASSERT_TRUE(maxBrightnessNitsOptional.has_value());
+
+    const float maxBrightnessNits = *maxBrightnessNitsOptional;
+
+    // Preconditions to successfully run are knowing the max brightness and successfully applying
+    // the max brightness
+    ASSERT_GT(maxBrightnessNits, 0.f);
+    mWriter.setDisplayBrightness(mPrimaryDisplay, 1.f);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    for (ColorMode mode : mTestColorModes) {
+        ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode(mPrimaryDisplay, mode, RenderIntent::COLORIMETRIC));
+
+        if (!getHasReadbackBuffer()) {
+            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace for "
+                               "color mode: "
+                            << toString(mode);
+            continue;
+        }
+        const common::Rect redRect = {0, 0, mDisplayWidth, mDisplayHeight / 2};
+        const common::Rect dimmerRedRect = {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight};
+        const auto redLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+        redLayer->setColor(RED);
+        redLayer->setDisplayFrame(redRect);
+        redLayer->setWhitePointNits(maxBrightnessNits);
+
+        const auto dimmerRedLayer =
+                std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+        dimmerRedLayer->setColor(RED);
+        dimmerRedLayer->setDisplayFrame(dimmerRedRect);
+        // Intentionally use a small dimming ratio as some implementations may be more likely to
+        // kick into GPU composition to apply dithering when the dimming ratio is high.
+        static constexpr float kDimmingRatio = 0.9f;
+        dimmerRedLayer->setWhitePointNits(maxBrightnessNits * kDimmingRatio);
+
+        const std::vector<std::shared_ptr<TestLayer>> layers = {redLayer, dimmerRedLayer};
+        std::vector<Color> expectedColors(static_cast<size_t>(mDisplayWidth * mDisplayHeight));
+
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
+        ReadbackHelper::fillColorsArea(expectedColors, mDisplayWidth, dimmerRedRect, DIM_RED);
+
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+        writeLayers(layers);
+        ASSERT_TRUE(mReader.takeErrors().empty());
+        mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
+        execute();
+        if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
+            GTEST_SUCCEED()
+                    << "Readback verification not supported for GPU composition for color mode: "
+                    << toString(mode);
+            continue;
+        }
+        mWriter.presentDisplay(mPrimaryDisplay);
+        execute();
+        ASSERT_TRUE(mReader.takeErrors().empty());
+
+        ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+        mTestRenderEngine->setRenderLayers(layers);
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers());
+        ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors));
+    }
+}
+
 class GraphicsBlendModeCompositionTest
     : public GraphicsCompositionTestBase,
       public testing::WithParamInterface<std::tuple<std::string, std::string>> {
@@ -973,8 +1141,8 @@
         setUpLayers(BlendMode::NONE);
         setExpectedColors(expectedColors);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
-                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(mLayers);
         ASSERT_TRUE(mReader.takeErrors().empty());
@@ -1014,8 +1182,8 @@
         setUpLayers(BlendMode::COVERAGE);
         setExpectedColors(expectedColors);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
-                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(mLayers);
         ASSERT_TRUE(mReader.takeErrors().empty());
@@ -1050,8 +1218,8 @@
         setUpLayers(BlendMode::PREMULTIPLIED);
         setExpectedColors(expectedColors);
 
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
-                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         writeLayers(mLayers);
         ASSERT_TRUE(mReader.takeErrors().empty());
@@ -1120,8 +1288,8 @@
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
             return;
         }
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
-                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
         mLayer->setTransform(Transform::FLIP_H);
         mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
@@ -1161,8 +1329,8 @@
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
             return;
         }
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
-                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         mLayer->setTransform(Transform::FLIP_V);
@@ -1202,8 +1370,8 @@
             GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
             return;
         }
-        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGraphicBuffer,
-                                      mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace);
+        ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mDisplayWidth,
+                                      mDisplayHeight, mPixelFormat, mDataspace);
         ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
 
         mLayer->setTransform(Transform::ROT_180);
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 ff22817..1c75749 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
@@ -76,7 +76,10 @@
         ASSERT_NE(binder, nullptr);
         ASSERT_NO_FATAL_FAILURE(mComposer = IComposer::fromBinder(binder));
         ASSERT_NE(mComposer, nullptr);
-        ASSERT_NO_FATAL_FAILURE(mComposer->createClient(&mComposerClient));
+
+        ndk::ScopedAStatus status;
+        ASSERT_NO_FATAL_FAILURE(status = mComposer->createClient(&mComposerClient));
+        ASSERT_TRUE(status.isOk());
 
         mComposerCallback = ::ndk::SharedRefBase::make<GraphicsComposerCallback>();
         EXPECT_TRUE(mComposerClient->registerCallback(mComposerCallback).isOk());
@@ -1538,7 +1541,7 @@
     execute();
 
     const auto errors = mReader.takeErrors();
-    if (errors.size() == 1 && errors[0].errorCode == EX_UNSUPPORTED_OPERATION) {
+    if (errors.size() == 1 && errors[0].errorCode == IComposerClient::EX_UNSUPPORTED) {
         GTEST_SUCCEED() << "setLayerColorTransform is not supported";
         return;
     }
@@ -1555,7 +1558,7 @@
         execute();
         const auto errors = mReader.takeErrors();
         EXPECT_EQ(1, errors.size());
-        EXPECT_EQ(EX_UNSUPPORTED_OPERATION, errors[0].errorCode);
+        EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, errors[0].errorCode);
         GTEST_SUCCEED() << "SetDisplayBrightness is not supported";
         return;
     }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/ReadbackVts.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/ReadbackVts.cpp
index ee597a1..d99903d 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/ReadbackVts.cpp
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/ReadbackVts.cpp
@@ -41,6 +41,7 @@
     writer.setLayerTransform(mDisplay, mLayer, mTransform);
     writer.setLayerPlaneAlpha(mDisplay, mLayer, mAlpha);
     writer.setLayerBlendMode(mDisplay, mLayer, mBlendMode);
+    writer.setLayerWhitePointNits(mDisplay, mLayer, mWhitePointNits);
 }
 
 std::string ReadbackHelper::getColorModeString(ColorMode mode) {
@@ -103,6 +104,7 @@
             1.0f, 1.0f));
 
     layerSettings.geometry.positionTransform = scale * translation;
+    layerSettings.whitePointNits = mWhitePointNits;
 
     return layerSettings;
 }
@@ -186,7 +188,6 @@
             int offset = (row * stride + col) * bytesPerPixel;
             uint8_t* pixelColor = (uint8_t*)bufferData + offset;
             const Color expectedColor = expectedColors[static_cast<size_t>(pixel)];
-
             ASSERT_EQ(std::round(255.0f * expectedColor.r), pixelColor[0]);
             ASSERT_EQ(std::round(255.0f * expectedColor.g), pixelColor[1]);
             ASSERT_EQ(std::round(255.0f * expectedColor.b), pixelColor[2]);
@@ -195,13 +196,11 @@
 }
 
 ReadbackBuffer::ReadbackBuffer(int64_t display, const std::shared_ptr<IComposerClient>& client,
-                               const ::android::sp<::android::GraphicBuffer>& graphicBuffer,
                                int32_t width, int32_t height, common::PixelFormat pixelFormat,
                                common::Dataspace dataspace) {
     mDisplay = display;
 
     mComposerClient = client;
-    mGraphicBuffer = graphicBuffer;
 
     mPixelFormat = pixelFormat;
     mDataspace = dataspace;
@@ -235,6 +234,7 @@
 }
 
 void ReadbackBuffer::checkReadbackBuffer(std::vector<Color> expectedColors) {
+    ASSERT_NE(nullptr, mGraphicBuffer);
     // lock buffer for reading
     ndk::ScopedFileDescriptor fenceHandle;
     EXPECT_TRUE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle).isOk());
@@ -242,7 +242,8 @@
     int outBytesPerPixel;
     int outBytesPerStride;
     void* bufData = nullptr;
-    auto status = mGraphicBuffer->lockAsync(mUsage, mAccessRegion, &bufData, fenceHandle.get(),
+
+    auto status = mGraphicBuffer->lockAsync(mUsage, mAccessRegion, &bufData, dup(fenceHandle.get()),
                                             &outBytesPerPixel, &outBytesPerStride);
     EXPECT_EQ(::android::OK, status);
     ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888);
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/ReadbackVts.h b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/ReadbackVts.h
index 0fac2b3..8785513 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/ReadbackVts.h
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/ReadbackVts.h
@@ -43,6 +43,10 @@
 
 static const Color BLACK = {0.0f, 0.0f, 0.0f, 1.0f};
 static const Color RED = {1.0f, 0.0f, 0.0f, 1.0f};
+// DIM_RED is 90% dimmed from RED in linear space
+// hard-code as value 243 in 8-bit space here, as calculating it requires
+// oetf(eotf(value) * .9), which is a complex non-linear transformation
+static const Color DIM_RED = {243.f / 255.f, 0.0f, 0.0f, 1.0f};
 static const Color TRANSLUCENT_RED = {1.0f, 0.0f, 0.0f, 0.3f};
 static const Color GREEN = {0.0f, 1.0f, 0.0f, 1.0f};
 static const Color BLUE = {0.0f, 0.0f, 1.0f, 1.0f};
@@ -67,6 +71,7 @@
     void setDisplayFrame(Rect frame) { mDisplayFrame = frame; }
     void setSourceCrop(FRect crop) { mSourceCrop = crop; }
     void setZOrder(uint32_t z) { mZOrder = z; }
+    void setWhitePointNits(float whitePointNits) { mWhitePointNits = whitePointNits; }
 
     void setSurfaceDamage(std::vector<Rect> surfaceDamage) {
         mSurfaceDamage = std::move(surfaceDamage);
@@ -84,10 +89,13 @@
 
     int64_t getLayer() const { return mLayer; }
 
+    float getWhitePointNits() const { return mWhitePointNits; }
+
   protected:
     int64_t mDisplay;
     int64_t mLayer;
     Rect mDisplayFrame = {0, 0, 0, 0};
+    float mWhitePointNits = -1.f;
     std::vector<Rect> mSurfaceDamage;
     Transform mTransform = static_cast<Transform>(0);
     FRect mSourceCrop = {0, 0, 0, 0};
@@ -188,8 +196,7 @@
 
 class ReadbackBuffer {
   public:
-    ReadbackBuffer(int64_t display, const std::shared_ptr<IComposerClient>& client,
-                   const ::android::sp<::android::GraphicBuffer>& graphicBuffer, int32_t width,
+    ReadbackBuffer(int64_t display, const std::shared_ptr<IComposerClient>& client, int32_t width,
                    int32_t height, common::PixelFormat pixelFormat, common::Dataspace dataspace);
 
     void setReadbackBuffer();
diff --git a/sensors/1.0/default/convert.cpp b/sensors/1.0/default/convert.cpp
index 53ceb0d..43ee327 100644
--- a/sensors/1.0/default/convert.cpp
+++ b/sensors/1.0/default/convert.cpp
@@ -190,8 +190,6 @@
         }
 
         default: {
-            CHECK_GE((int32_t)dst->sensorType, (int32_t)SensorType::DEVICE_PRIVATE_BASE);
-
             memcpy(dst->u.data.data(), src.data, 16 * sizeof(float));
             break;
         }
@@ -330,9 +328,6 @@
         }
 
         default: {
-            CHECK_GE((int32_t)src.sensorType,
-                     (int32_t)SensorType::DEVICE_PRIVATE_BASE);
-
             memcpy(dst->data, src.u.data.data(), 16 * sizeof(float));
             break;
         }
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFrontend.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFrontend.aidl
index e7aa070..e240e40 100644
--- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFrontend.aidl
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFrontend.aidl
@@ -46,4 +46,5 @@
   int linkCiCam(in int ciCamId);
   void unlinkCiCam(in int ciCamId);
   String getHardwareInfo();
+  void removeOutputPid(int pid);
 }
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/IFrontend.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/IFrontend.aidl
index 5b3ce39..f8248e6 100644
--- a/tv/tuner/aidl/android/hardware/tv/tuner/IFrontend.aidl
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/IFrontend.aidl
@@ -146,4 +146,13 @@
      * @return the frontend hardware information.
      */
     String getHardwareInfo();
+
+    /**
+     * Filter out unnecessary PID from frontend output.
+     *
+     * @param pid specify the PID will be filtered out.
+     *
+     * @return UNAVAILABLE if the frontend doesn’t support PID filtering out.
+     */
+    void removeOutputPid(int pid);
 }
diff --git a/tv/tuner/aidl/default/Frontend.cpp b/tv/tuner/aidl/default/Frontend.cpp
index 445d2b6..f0bf001 100644
--- a/tv/tuner/aidl/default/Frontend.cpp
+++ b/tv/tuner/aidl/default/Frontend.cpp
@@ -773,6 +773,13 @@
     return ::ndk::ScopedAStatus::ok();
 }
 
+::ndk::ScopedAStatus Frontend::removeOutputPid(int32_t /* in_pid */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return ::ndk::ScopedAStatus::fromServiceSpecificError(
+            static_cast<int32_t>(Result::UNAVAILABLE));
+}
+
 FrontendType Frontend::getFrontendType() {
     return mType;
 }
diff --git a/tv/tuner/aidl/default/Frontend.h b/tv/tuner/aidl/default/Frontend.h
index fdedf1e..3df1aa1 100644
--- a/tv/tuner/aidl/default/Frontend.h
+++ b/tv/tuner/aidl/default/Frontend.h
@@ -50,6 +50,7 @@
     ::ndk::ScopedAStatus linkCiCam(int32_t in_ciCamId, int32_t* _aidl_return) override;
     ::ndk::ScopedAStatus unlinkCiCam(int32_t in_ciCamId) override;
     ::ndk::ScopedAStatus getHardwareInfo(std::string* _aidl_return) override;
+    ::ndk::ScopedAStatus removeOutputPid(int32_t in_pid) override;
 
     binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
 
diff --git a/tv/tuner/aidl/vts/functional/FrontendTests.cpp b/tv/tuner/aidl/vts/functional/FrontendTests.cpp
index a8799ab..62d9b74 100644
--- a/tv/tuner/aidl/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/aidl/vts/functional/FrontendTests.cpp
@@ -298,6 +298,13 @@
     return AssertionResult(status.isOk());
 }
 
+AssertionResult FrontendTests::removeOutputPid(int32_t removePid) {
+    ndk::ScopedAStatus status;
+    status = mFrontend->removeOutputPid(removePid);
+    return AssertionResult(status.isOk() || status.getServiceSpecificError() ==
+                                                    static_cast<int32_t>(Result::UNAVAILABLE));
+}
+
 AssertionResult FrontendTests::unlinkCiCam(int32_t ciCamId) {
     ndk::ScopedAStatus status = mFrontend->unlinkCiCam(ciCamId);
     return AssertionResult(status.isOk());
@@ -508,6 +515,7 @@
     ASSERT_TRUE(setFrontendCallback());
     if (frontendConf.canConnectToCiCam) {
         ASSERT_TRUE(linkCiCam(frontendConf.ciCamId));
+        ASSERT_TRUE(removeOutputPid(frontendConf.removePid));
         ASSERT_TRUE(unlinkCiCam(frontendConf.ciCamId));
     }
     ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
diff --git a/tv/tuner/aidl/vts/functional/FrontendTests.h b/tv/tuner/aidl/vts/functional/FrontendTests.h
index 1745f76..537c419 100644
--- a/tv/tuner/aidl/vts/functional/FrontendTests.h
+++ b/tv/tuner/aidl/vts/functional/FrontendTests.h
@@ -95,6 +95,7 @@
     AssertionResult linkCiCam(int32_t ciCamId);
     AssertionResult unlinkCiCam(int32_t ciCamId);
     AssertionResult verifyHardwareInfo();
+    AssertionResult removeOutputPid(int32_t removePid);
 
     void getFrontendIdByType(FrontendType feType, int32_t& feId);
     void tuneTest(FrontendConfig frontendConf);
diff --git a/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h b/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h
index b73d594..3009c4a 100644
--- a/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h
+++ b/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h
@@ -83,6 +83,7 @@
     FrontendType type;
     bool canConnectToCiCam;
     int32_t ciCamId;
+    int32_t removePid;
     FrontendSettings settings;
     vector<FrontendStatusType> tuneStatusTypes;
     vector<FrontendStatus> expectTuneStatuses;
@@ -304,7 +305,8 @@
                 // TODO: b/182519645 complete the tune status config
                 frontendMap[id].tuneStatusTypes = types;
                 frontendMap[id].expectTuneStatuses = statuses;
-                getCiCamInfo(feConfig, frontendMap[id].canConnectToCiCam, frontendMap[id].ciCamId);
+                getCiCamInfo(feConfig, frontendMap[id].canConnectToCiCam, frontendMap[id].ciCamId,
+                             frontendMap[id].removePid);
             }
         }
     }
@@ -1004,13 +1006,16 @@
         return recordSettings;
     }
 
-    static void getCiCamInfo(Frontend feConfig, bool& canConnectToCiCam, int32_t& ciCamId) {
+    static void getCiCamInfo(Frontend feConfig, bool& canConnectToCiCam, int32_t& ciCamId,
+                             int32_t& removePid) {
         if (!feConfig.hasConnectToCicamId()) {
             canConnectToCiCam = false;
             ciCamId = -1;
+            removePid = -1;
             return;
         }
         canConnectToCiCam = true;
         ciCamId = static_cast<int32_t>(feConfig.getConnectToCicamId());
+        removePid = static_cast<int32_t>(feConfig.getRemoveOutputPid());
     }
 };
diff --git a/tv/tuner/config/api/current.txt b/tv/tuner/config/api/current.txt
index 4d519d7..383d49f 100644
--- a/tv/tuner/config/api/current.txt
+++ b/tv/tuner/config/api/current.txt
@@ -317,6 +317,7 @@
     method @Nullable public java.math.BigInteger getFrequency();
     method @Nullable public String getId();
     method @Nullable public boolean getIsSoftwareFrontend();
+    method @Nullable public java.math.BigInteger getRemoveOutputPid();
     method @Nullable public android.media.tuner.testing.configuration.V1_0.FrontendTypeEnum getType();
     method public void setConnectToCicamId(@Nullable java.math.BigInteger);
     method public void setDvbsFrontendSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.DvbsFrontendSettings);
@@ -325,6 +326,7 @@
     method public void setFrequency(@Nullable java.math.BigInteger);
     method public void setId(@Nullable String);
     method public void setIsSoftwareFrontend(@Nullable boolean);
+    method public void setRemoveOutputPid(@Nullable java.math.BigInteger);
     method public void setType(@Nullable android.media.tuner.testing.configuration.V1_0.FrontendTypeEnum);
   }
 
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 da77200..fefe86e 100644
--- a/tv/tuner/config/sample_tuner_vts_config_aidl_V1.xml
+++ b/tv/tuner/config/sample_tuner_vts_config_aidl_V1.xml
@@ -42,6 +42,8 @@
                 "softwareFeInputPath": used as the source of the software frontend.
                 "connectToCicamId": if the device supports frontend connecting to cicam, the target
                     cicam id needs to be configured here. Supported in Tuner 1.1 or higher.
+                "removeOutputPid": the unnecessary PID will be filtered out from frontend
+                    output. Supported in Tuner 2.0 or higher.
                 "frequency": the frequency used to configure tune and scan.
                 "endFrequency": the end frequency of scan. Supported in Tuner 1.1 or higher.
 
@@ -53,11 +55,13 @@
         -->
         <frontends>
             <frontend id="FE_DEFAULT" type="DVBT" isSoftwareFrontend="true"
-                      connectToCicamId="0" frequency="578000000" endFrequency="800000000">
+                      connectToCicamId="0" removeOutputPid="10" frequency="578000000"
+                      endFrequency="800000000">
                 <dvbtFrontendSettings bandwidth="8" transmissionMode="128" isHighPriority="1"/>
             </frontend>
             <frontend id="FE_DVBS_0" type="DVBS" isSoftwareFrontend="true"
-                      connectToCicamId="0" frequency="578000000" endFrequency="800000000">
+                      connectToCicamId="0" removeOutputPid="10" frequency="578000000"
+                      endFrequency="800000000">
             </frontend>
         </frontends>
         <!-- Filter section:
diff --git a/tv/tuner/config/tuner_testing_dynamic_configuration.xsd b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
index 94f108b..59abd9a 100644
--- a/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
+++ b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
@@ -94,6 +94,8 @@
                     "connectToCicamId": if the device supports frontend connecting to cicam, the
                         target cicam id needs to be configured here. Supported in Tuner 1.1 or
                         higher.
+                    "removeOutputPid": the unnecessary PID will be filtered out from frontend
+                        output. Supported in Tuner 2.0 or higher.
                     "frequency": the frequency used to configure tune and scan.
                     "endFrequency": the end frequency of scan. Supported in Tuner 1.1 or higher.
 
@@ -125,6 +127,7 @@
         <xs:attribute name="isSoftwareFrontend" type="xs:boolean" use="required"/>
         <xs:attribute name="frequency" type="xs:nonNegativeInteger" use="required"/>
         <xs:attribute name="connectToCicamId" type="xs:nonNegativeInteger" use="optional"/>
+        <xs:attribute name="removeOutputPid" type="xs:nonNegativeInteger" use="optional"/>
         <xs:attribute name="endFrequency" type="xs:nonNegativeInteger" use="optional"/>
     </xs:complexType>
 
diff --git a/uwb/aidl/Android.bp b/uwb/aidl/Android.bp
index 99fd094..2cc1e6a 100755
--- a/uwb/aidl/Android.bp
+++ b/uwb/aidl/Android.bp
@@ -16,7 +16,7 @@
     stability: "vintf",
     backend: {
         java: {
-            sdk_version: "module_current",
+            sdk_version: "module_Tiramisu",
             enabled: false,
         },
         ndk: {
@@ -27,7 +27,7 @@
                 "//apex_available:platform",
                 "com.android.uwb",
             ],
-            min_sdk_version: "current",
+            min_sdk_version: "Tiramisu",
         },
         rust: {
             enabled: true,
@@ -35,7 +35,7 @@
                 "//apex_available:platform",
                 "com.android.uwb",
             ],
-            min_sdk_version: "current",
+            min_sdk_version: "Tiramisu",
         },
     },
 }
@@ -47,7 +47,7 @@
     stability: "vintf",
     backend: {
         java: {
-            sdk_version: "module_current",
+            sdk_version: "module_Tiramisu",
             enabled: true,
             apex_available: [
                 "com.android.uwb",
@@ -58,7 +58,7 @@
                 "//apex_available:platform",
                 "com.android.uwb",
             ],
-            min_sdk_version: "current",
+            min_sdk_version: "Tiramisu",
         },
     },
 }