Merge "Use explicit requirements from APEX" into main
diff --git a/audio/aidl/default/Configuration.cpp b/audio/aidl/default/Configuration.cpp
index 635a25b..3c3dadb 100644
--- a/audio/aidl/default/Configuration.cpp
+++ b/audio/aidl/default/Configuration.cpp
@@ -105,15 +105,11 @@
     return port;
 }
 
-static AudioPortConfig createPortConfig(int32_t id, int32_t portId, PcmType pcmType, int32_t layout,
-                                        int32_t sampleRate, int32_t flags, bool isInput,
-                                        const AudioPortExt& ext) {
+static AudioPortConfig createDynamicPortConfig(int32_t id, int32_t portId, int32_t flags,
+                                               bool isInput, const AudioPortExt& ext) {
     AudioPortConfig config;
     config.id = id;
     config.portId = portId;
-    config.sampleRate = Int{.value = sampleRate};
-    config.channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout);
-    config.format = AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = pcmType};
     config.gain = AudioGainConfig();
     config.flags = isInput ? AudioIoFlags::make<AudioIoFlags::Tag::input>(flags)
                            : AudioIoFlags::make<AudioIoFlags::Tag::output>(flags);
@@ -121,6 +117,16 @@
     return config;
 }
 
+static AudioPortConfig createPortConfig(int32_t id, int32_t portId, PcmType pcmType, int32_t layout,
+                                        int32_t sampleRate, int32_t flags, bool isInput,
+                                        const AudioPortExt& ext) {
+    AudioPortConfig config = createDynamicPortConfig(id, portId, flags, isInput, ext);
+    config.sampleRate = Int{.value = sampleRate};
+    config.channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout);
+    config.format = AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = pcmType};
+    return config;
+}
+
 static AudioRoute createRoute(const std::vector<AudioPort>& sources, const AudioPort& sink) {
     AudioRoute route;
     route.sinkPortId = sink.id;
@@ -147,8 +153,7 @@
 //  * "primary output", PRIMARY, 1 max open, 1 max active stream
 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
 //  * "primary input", 1 max open, 1 max active stream
-//    - profile PCM 16-bit; MONO, STEREO;
-//        8000, 11025, 16000, 32000, 44100, 48000
+//    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
 //  * "telephony_tx", 1 max open, 1 max active stream
 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
 //  * "telephony_rx", 1 max open, 1 max active stream
@@ -164,11 +169,11 @@
 //  "FM Tuner" -> "fm_tuner"
 //
 // Initial port configs:
-//  * "Speaker" device port: PCM 16-bit; STEREO; 48000
-//  * "Built-In Mic" device port: PCM 16-bit; MONO; 48000
-//  * "Telephony Tx" device port: PCM 16-bit; MONO; 48000
-//  * "Telephony Rx" device port: PCM 16-bit; MONO; 48000
-//  * "FM Tuner" device port: PCM 16-bit; STEREO; 48000
+//  * "Speaker" device port: dynamic configuration
+//  * "Built-In Mic" device port: dynamic configuration
+//  * "Telephony Tx" device port: dynamic configuration
+//  * "Telephony Rx" device port: dynamic configuration
+//  * "FM Tuner" device port: dynamic configuration
 //
 std::unique_ptr<Configuration> getPrimaryConfiguration() {
     static const Configuration configuration = []() {
@@ -186,9 +191,8 @@
                                            1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
         c.ports.push_back(speakerOutDevice);
         c.initialConfigs.push_back(
-                createPortConfig(speakerOutDevice.id, speakerOutDevice.id, PcmType::INT_16_BIT,
-                                 AudioChannelLayout::LAYOUT_STEREO, 48000, 0, false,
-                                 createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0)));
+                createDynamicPortConfig(speakerOutDevice.id, speakerOutDevice.id, 0, false,
+                                        createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0)));
 
         AudioPort micInDevice =
                 createPort(c.nextPortId++, "Built-In Mic", 0, true,
@@ -196,35 +200,31 @@
                                            1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
         c.ports.push_back(micInDevice);
         c.initialConfigs.push_back(
-                createPortConfig(micInDevice.id, micInDevice.id, PcmType::INT_16_BIT,
-                                 AudioChannelLayout::LAYOUT_MONO, 48000, 0, true,
-                                 createDeviceExt(AudioDeviceType::IN_MICROPHONE, 0)));
+                createDynamicPortConfig(micInDevice.id, micInDevice.id, 0, true,
+                                        createDeviceExt(AudioDeviceType::IN_MICROPHONE, 0)));
 
         AudioPort telephonyTxOutDevice =
                 createPort(c.nextPortId++, "Telephony Tx", 0, false,
                            createDeviceExt(AudioDeviceType::OUT_TELEPHONY_TX, 0));
         c.ports.push_back(telephonyTxOutDevice);
         c.initialConfigs.push_back(
-                createPortConfig(telephonyTxOutDevice.id, telephonyTxOutDevice.id,
-                                 PcmType::INT_16_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
-                                 false, createDeviceExt(AudioDeviceType::OUT_TELEPHONY_TX, 0)));
+                createDynamicPortConfig(telephonyTxOutDevice.id, telephonyTxOutDevice.id, 0, false,
+                                        createDeviceExt(AudioDeviceType::OUT_TELEPHONY_TX, 0)));
 
         AudioPort telephonyRxInDevice =
                 createPort(c.nextPortId++, "Telephony Rx", 0, true,
                            createDeviceExt(AudioDeviceType::IN_TELEPHONY_RX, 0));
         c.ports.push_back(telephonyRxInDevice);
         c.initialConfigs.push_back(
-                createPortConfig(telephonyRxInDevice.id, telephonyRxInDevice.id,
-                                 PcmType::INT_16_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
-                                 true, createDeviceExt(AudioDeviceType::IN_TELEPHONY_RX, 0)));
+                createDynamicPortConfig(telephonyRxInDevice.id, telephonyRxInDevice.id, 0, true,
+                                        createDeviceExt(AudioDeviceType::IN_TELEPHONY_RX, 0)));
 
         AudioPort fmTunerInDevice = createPort(c.nextPortId++, "FM Tuner", 0, true,
                                                createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0));
         c.ports.push_back(fmTunerInDevice);
         c.initialConfigs.push_back(
-                createPortConfig(fmTunerInDevice.id, fmTunerInDevice.id, PcmType::INT_16_BIT,
-                                 AudioChannelLayout::LAYOUT_STEREO, 48000, 0, true,
-                                 createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0)));
+                createDynamicPortConfig(fmTunerInDevice.id, fmTunerInDevice.id, 0, true,
+                                        createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0)));
 
         // Mix ports
 
@@ -287,13 +287,15 @@
 
 // Note: When transitioning to loading of XML configs, either keep the configuration
 // of the remote submix sources from this static configuration, or update the XML
-// config to match it. There are two reasons for that:
-//   1. The canonical r_submix configuration only lists 'STEREO' and '48000',
+// config to match it. There are several reasons for that:
+//   1. The "Remote Submix In" device is listed in the XML config as "attached",
+//      however in the AIDL scheme its device type has a "virtual" connection.
+//   2. The canonical r_submix configuration only lists 'STEREO' and '48000',
 //      however the framework attempts to open streams for other sample rates
 //      as well. The legacy r_submix implementation allowed that, but libaudiohal@aidl
 //      will not find a mix port to use. Because of that, list all channel
 //      masks and sample rates that the legacy implementation allowed.
-//   2. The legacy implementation had a hard limit on the number of routes (10),
+//   3. The legacy implementation had a hard limit on the number of routes (10),
 //      and this is checked indirectly by AudioPlaybackCaptureTest#testPlaybackCaptureDoS
 //      CTS test. Instead of hardcoding the number of routes, we can use
 //      "maxOpen/ActiveStreamCount" to enforce a similar limit. However, the canonical
@@ -331,15 +333,15 @@
                 createPort(c.nextPortId++, "Remote Submix Out", 0, false,
                            createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0,
                                            AudioDeviceDescription::CONNECTION_VIRTUAL));
-        rsubmixOutDevice.profiles = standardPcmAudioProfiles;
         c.ports.push_back(rsubmixOutDevice);
+        c.connectedProfiles[rsubmixOutDevice.id] = standardPcmAudioProfiles;
 
         AudioPort rsubmixInDevice =
                 createPort(c.nextPortId++, "Remote Submix In", 0, true,
                            createDeviceExt(AudioDeviceType::IN_SUBMIX, 0,
                                            AudioDeviceDescription::CONNECTION_VIRTUAL));
-        rsubmixInDevice.profiles = standardPcmAudioProfiles;
         c.ports.push_back(rsubmixInDevice);
+        c.connectedProfiles[rsubmixInDevice.id] = standardPcmAudioProfiles;
 
         // Mix ports
 
@@ -384,7 +386,7 @@
 //  * "usb_device output" -> "USB Headset Out"
 //  * "USB Device In", "USB Headset In" -> "usb_device input"
 //
-// Profiles for device port connected state:
+// Profiles for device port connected state (when simulating connections):
 //  * "USB Device Out", "USB Headset Out":
 //    - profile PCM 16-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000
 //    - profile PCM 24-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000
@@ -461,9 +463,9 @@
 //  * "Test In", IN_AFE_PROXY
 //    - no profiles specified
 //  * "Wired Headset", OUT_HEADSET
-//    - profile PCM 24-bit; STEREO; 48000
+//    - no profiles specified
 //  * "Wired Headset Mic", IN_HEADSET
-//    - profile PCM 24-bit; MONO; 48000
+//    - no profiles specified
 //
 // Mix ports:
 //  * "test output", 1 max open, 1 max active stream
@@ -486,6 +488,10 @@
 //  * "Test Out" device port: PCM 24-bit; STEREO; 48000
 //  * "Test In" device port: PCM 24-bit; MONO; 48000
 //
+// Profiles for device port connected state (when simulating connections):
+//  * "Wired Headset": dynamic profiles
+//  * "Wired Headset Mic": dynamic profiles
+//
 std::unique_ptr<Configuration> getStubConfiguration() {
     static const Configuration configuration = []() {
         Configuration c;
@@ -504,8 +510,6 @@
                 createPort(c.nextPortId++, "Wired Headset", 0, false,
                            createDeviceExt(AudioDeviceType::OUT_HEADSET, 0,
                                            AudioDeviceDescription::CONNECTION_ANALOG));
-        headsetOutDevice.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
         c.ports.push_back(headsetOutDevice);
 
         AudioPort testInDevice = createPort(c.nextPortId++, "Test In", 0, true,
@@ -520,8 +524,6 @@
                 createPort(c.nextPortId++, "Wired Headset Mic", 0, true,
                            createDeviceExt(AudioDeviceType::IN_HEADSET, 0,
                                            AudioDeviceDescription::CONNECTION_ANALOG));
-        headsetInDevice.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_MONO}, {48000}));
         c.ports.push_back(headsetInDevice);
 
         // Mix ports
@@ -553,24 +555,24 @@
                               {44100, 48000}));
         c.ports.push_back(compressedOffloadOutMix);
 
-        AudioPort testInMIx =
+        AudioPort testInMix =
                 createPort(c.nextPortId++, "test input", 0, true, createPortMixExt(2, 2));
-        testInMIx.profiles.push_back(
+        testInMix.profiles.push_back(
                 createProfile(PcmType::INT_16_BIT,
                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
                                AudioChannelLayout::LAYOUT_FRONT_BACK},
                               {8000, 11025, 16000, 22050, 32000, 44100, 48000}));
-        testInMIx.profiles.push_back(
+        testInMix.profiles.push_back(
                 createProfile(PcmType::INT_24_BIT,
                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
                                AudioChannelLayout::LAYOUT_FRONT_BACK},
                               {8000, 11025, 16000, 22050, 32000, 44100, 48000}));
-        c.ports.push_back(testInMIx);
+        c.ports.push_back(testInMix);
 
         c.routes.push_back(
                 createRoute({testOutMix, testFastOutMix, compressedOffloadOutMix}, testOutDevice));
         c.routes.push_back(createRoute({testOutMix}, headsetOutDevice));
-        c.routes.push_back(createRoute({testInDevice, headsetInDevice}, testInMIx));
+        c.routes.push_back(createRoute({testInDevice, headsetInDevice}, testInMix));
 
         c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
 
@@ -603,11 +605,19 @@
 //  "a2dp output" -> "BT A2DP Speaker"
 //  "hearing aid output" -> "BT Hearing Aid Out"
 //
+// Profiles for device port connected state (when simulating connections):
+//  * "BT A2DP Out", "BT A2DP Headphones", "BT A2DP Speaker":
+//    - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
+//  * "BT Hearing Aid Out":
+//    - profile PCM 16-bit; STEREO; 16000, 24000
+//
 std::unique_ptr<Configuration> getBluetoothConfiguration() {
     static const Configuration configuration = []() {
         const std::vector<AudioProfile> standardPcmAudioProfiles = {
                 createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO},
                               {44100, 48000, 88200, 96000})};
+        const std::vector<AudioProfile> hearingAidAudioProfiles = {createProfile(
+                PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {16000, 24000})};
         Configuration c;
 
         // Device ports
@@ -645,8 +655,7 @@
                            createDeviceExt(AudioDeviceType::OUT_HEARING_AID, 0,
                                            AudioDeviceDescription::CONNECTION_WIRELESS));
         c.ports.push_back(btOutHearingAid);
-        c.connectedProfiles[btOutHearingAid.id] = std::vector<AudioProfile>(
-                {createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {16000})});
+        c.connectedProfiles[btOutHearingAid.id] = hearingAidAudioProfiles;
 
         // Mix ports
         AudioPort btOutMix =
@@ -655,8 +664,7 @@
 
         AudioPort btHearingOutMix =
                 createPort(c.nextPortId++, "hearing aid output", 0, false, createPortMixExt(1, 1));
-        btHearingOutMix.profiles.push_back(createProfile(
-                PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {16000, 24000}));
+        btHearingOutMix.profiles = hearingAidAudioProfiles;
         c.ports.push_back(btHearingOutMix);
 
         c.routes.push_back(createRoute({btOutMix}, btOutDevice));
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 76132b3..d721b32 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -65,32 +65,56 @@
 
 namespace {
 
+inline bool hasDynamicChannelMasks(const std::vector<AudioChannelLayout>& channelMasks) {
+    return channelMasks.empty() ||
+           std::all_of(channelMasks.begin(), channelMasks.end(),
+                       [](const auto& channelMask) { return channelMask == AudioChannelLayout{}; });
+}
+
+inline bool hasDynamicFormat(const AudioFormatDescription& format) {
+    return format == AudioFormatDescription{};
+}
+
+inline bool hasDynamicSampleRates(const std::vector<int32_t>& sampleRates) {
+    return sampleRates.empty() ||
+           std::all_of(sampleRates.begin(), sampleRates.end(),
+                       [](const auto& sampleRate) { return sampleRate == 0; });
+}
+
+inline bool isDynamicProfile(const AudioProfile& profile) {
+    return hasDynamicFormat(profile.format) || hasDynamicChannelMasks(profile.channelMasks) ||
+           hasDynamicSampleRates(profile.sampleRates);
+}
+
+bool hasDynamicProfilesOnly(const std::vector<AudioProfile>& profiles) {
+    if (profiles.empty()) return true;
+    return std::all_of(profiles.begin(), profiles.end(), isDynamicProfile);
+}
+
+// Note: does not assign an ID to the config.
 bool generateDefaultPortConfig(const AudioPort& port, AudioPortConfig* config) {
+    const bool allowDynamicConfig = port.ext.getTag() == AudioPortExt::device;
     *config = {};
     config->portId = port.id;
-    if (port.profiles.empty()) {
-        LOG(ERROR) << __func__ << ": port " << port.id << " has no profiles";
-        return false;
+    for (const auto& profile : port.profiles) {
+        if (isDynamicProfile(profile)) continue;
+        config->format = profile.format;
+        config->channelMask = *profile.channelMasks.begin();
+        config->sampleRate = Int{.value = *profile.sampleRates.begin()};
+        config->flags = port.flags;
+        config->ext = port.ext;
+        return true;
     }
-    const auto& profile = port.profiles.begin();
-    config->format = profile->format;
-    if (profile->channelMasks.empty()) {
-        LOG(ERROR) << __func__ << ": the first profile in port " << port.id
-                   << " has no channel masks";
-        return false;
+    if (allowDynamicConfig) {
+        config->format = AudioFormatDescription{};
+        config->channelMask = AudioChannelLayout{};
+        config->sampleRate = Int{.value = 0};
+        config->flags = port.flags;
+        config->ext = port.ext;
+        return true;
     }
-    config->channelMask = *profile->channelMasks.begin();
-    if (profile->sampleRates.empty()) {
-        LOG(ERROR) << __func__ << ": the first profile in port " << port.id
-                   << " has no sample rates";
-        return false;
-    }
-    Int sampleRate;
-    sampleRate.value = *profile->sampleRates.begin();
-    config->sampleRate = sampleRate;
-    config->flags = port.flags;
-    config->ext = port.ext;
-    return true;
+    LOG(ERROR) << __func__ << ": port " << port.id << " only has dynamic profiles";
+    return false;
 }
 
 bool findAudioProfile(const AudioPort& port, const AudioFormatDescription& format,
@@ -314,6 +338,18 @@
     return config;
 }
 
+std::vector<AudioRoute*> Module::getAudioRoutesForAudioPortImpl(int32_t portId) {
+    std::vector<AudioRoute*> result;
+    auto& routes = getConfig().routes;
+    for (auto& r : routes) {
+        const auto& srcs = r.sourcePortIds;
+        if (r.sinkPortId == portId || std::find(srcs.begin(), srcs.end(), portId) != srcs.end()) {
+            result.push_back(&r);
+        }
+    }
+    return result;
+}
+
 internal::Configuration& Module::getConfig() {
     if (!mConfig) {
         mConfig = std::move(initializeConfig());
@@ -321,6 +357,24 @@
     return *mConfig;
 }
 
+std::set<int32_t> Module::getRoutableAudioPortIds(int32_t portId,
+                                                  std::vector<AudioRoute*>* routes) {
+    std::vector<AudioRoute*> routesStorage;
+    if (routes == nullptr) {
+        routesStorage = getAudioRoutesForAudioPortImpl(portId);
+        routes = &routesStorage;
+    }
+    std::set<int32_t> result;
+    for (AudioRoute* r : *routes) {
+        if (r->sinkPortId == portId) {
+            result.insert(r->sourcePortIds.begin(), r->sourcePortIds.end());
+        } else {
+            result.insert(r->sinkPortId);
+        }
+    }
+    return result;
+}
+
 void Module::registerPatch(const AudioPatch& patch) {
     auto& configs = getConfig().portConfigs;
     auto do_insert = [&](const std::vector<int32_t>& portConfigIds) {
@@ -510,7 +564,31 @@
         }
     }
 
-    if (connectedPort.profiles.empty()) {
+    // Two main cases are considered with regard to the profiles of the connected device port:
+    //
+    //  1. If the template device port has dynamic profiles, and at least one routable mix
+    //     port also has dynamic profiles, it means that after connecting the device, the
+    //     connected device port must have profiles populated with actual capabilities of
+    //     the connected device, and dynamic of routable mix ports will be filled
+    //     according to these capabilities. An example of this case is connection of an
+    //     HDMI or USB device. For USB handled by ADSP, there can be mix ports with static
+    //     profiles, and one dedicated mix port for "hi-fi" playback. The latter is left with
+    //     dynamic profiles so that they can be populated with actual capabilities of
+    //     the connected device.
+    //
+    //  2. If the template device port has dynamic profiles, while all routable mix ports
+    //     have static profiles, it means that after connecting the device, the connected
+    //     device port can be left with dynamic profiles, and profiles of mix ports are
+    //     left untouched. An example of this case is connection of an analog wired
+    //     headset, it should be treated in the same way as a speaker.
+    //
+    //  Yet another possible case is when both the template device port and all routable
+    //  mix ports have static profiles. This is allowed and handled correctly, however, it
+    //  is not very practical, since these profiles are likely duplicates of each other.
+
+    std::vector<AudioRoute*> routesToMixPorts = getAudioRoutesForAudioPortImpl(templateId);
+    std::set<int32_t> routableMixPortIds = getRoutableAudioPortIds(templateId, &routesToMixPorts);
+    if (hasDynamicProfilesOnly(connectedPort.profiles)) {
         if (!mDebug.simulateDeviceConnections) {
             RETURN_STATUS_IF_ERROR(populateConnectedDevicePort(&connectedPort));
         } else {
@@ -520,23 +598,22 @@
                 connectedPort.profiles = connectedProfilesIt->second;
             }
         }
-        if (connectedPort.profiles.empty()) {
-            LOG(ERROR) << __func__
-                       << ": profiles of a connected port still empty after connecting external "
-                          "device "
-                       << connectedPort.toString();
-            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
-        }
-    }
-
-    for (auto profile : connectedPort.profiles) {
-        if (profile.channelMasks.empty()) {
-            LOG(ERROR) << __func__ << ": the profile " << profile.name << " has no channel masks";
-            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
-        }
-        if (profile.sampleRates.empty()) {
-            LOG(ERROR) << __func__ << ": the profile " << profile.name << " has no sample rates";
-            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+        if (hasDynamicProfilesOnly(connectedPort.profiles)) {
+            // Possible case 2. Check if all routable mix ports have static profiles.
+            if (auto dynamicMixPortIt = std::find_if(ports.begin(), ports.end(),
+                                                     [&routableMixPortIds](const auto& p) {
+                                                         return routableMixPortIds.count(p.id) >
+                                                                        0 &&
+                                                                hasDynamicProfilesOnly(p.profiles);
+                                                     });
+                dynamicMixPortIt != ports.end()) {
+                LOG(ERROR) << __func__
+                           << ": connected port only has dynamic profiles after connecting "
+                           << "external device " << connectedPort.toString() << ", and there exist "
+                           << "a routable mix port with dynamic profiles: "
+                           << dynamicMixPortIt->toString();
+                return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+            }
         }
     }
 
@@ -548,44 +625,36 @@
     ports.push_back(connectedPort);
     onExternalDeviceConnectionChanged(connectedPort, true /*connected*/);
 
-    std::vector<int32_t> routablePortIds;
+    // For routes where the template port is a source, add the connected port to sources,
+    // otherwise, create a new route by copying from the route for the template port.
     std::vector<AudioRoute> newRoutes;
-    auto& routes = getConfig().routes;
-    for (auto& r : routes) {
-        if (r.sinkPortId == templateId) {
-            AudioRoute newRoute;
-            newRoute.sourcePortIds = r.sourcePortIds;
-            newRoute.sinkPortId = connectedPort.id;
-            newRoute.isExclusive = r.isExclusive;
-            newRoutes.push_back(std::move(newRoute));
-            routablePortIds.insert(routablePortIds.end(), r.sourcePortIds.begin(),
-                                   r.sourcePortIds.end());
+    for (AudioRoute* r : routesToMixPorts) {
+        if (r->sinkPortId == templateId) {
+            newRoutes.push_back(AudioRoute{.sourcePortIds = r->sourcePortIds,
+                                           .sinkPortId = connectedPort.id,
+                                           .isExclusive = r->isExclusive});
         } else {
-            auto& srcs = r.sourcePortIds;
-            if (std::find(srcs.begin(), srcs.end(), templateId) != srcs.end()) {
-                srcs.push_back(connectedPort.id);
-                routablePortIds.push_back(r.sinkPortId);
-            }
+            r->sourcePortIds.push_back(connectedPort.id);
         }
     }
+    auto& routes = getConfig().routes;
     routes.insert(routes.end(), newRoutes.begin(), newRoutes.end());
 
-    // Note: this is a simplistic approach assuming that a mix port can only be populated
-    // from a single device port. Implementing support for stuffing dynamic profiles with a superset
-    // of all profiles from all routable dynamic device ports would be more involved.
-    for (const auto mixPortId : routablePortIds) {
-        auto portsIt = findById<AudioPort>(ports, mixPortId);
-        if (portsIt != ports.end()) {
-            if (portsIt->profiles.empty()) {
-                portsIt->profiles = connectedPort.profiles;
-                connectedPortsIt->second.insert(portsIt->id);
+    if (!hasDynamicProfilesOnly(connectedPort.profiles) && !routableMixPortIds.empty()) {
+        // Note: this is a simplistic approach assuming that a mix port can only be populated
+        // from a single device port. Implementing support for stuffing dynamic profiles with
+        // a superset of all profiles from all routable dynamic device ports would be more involved.
+        for (auto& port : ports) {
+            if (routableMixPortIds.count(port.id) == 0) continue;
+            if (hasDynamicProfilesOnly(port.profiles)) {
+                port.profiles = connectedPort.profiles;
+                connectedPortsIt->second.insert(port.id);
             } else {
-                // Check if profiles are non empty because they were populated by
-                // a previous connection. Otherwise, it means that they are not empty because
-                // the mix port has static profiles.
-                for (const auto cp : mConnectedDevicePorts) {
-                    if (cp.second.count(portsIt->id) > 0) {
-                        connectedPortsIt->second.insert(portsIt->id);
+                // Check if profiles are not all dynamic because they were populated by
+                // a previous connection. Otherwise, it means that they are actually static.
+                for (const auto& cp : mConnectedDevicePorts) {
+                    if (cp.second.count(port.id) > 0) {
+                        connectedPortsIt->second.insert(port.id);
                         break;
                     }
                 }
@@ -705,13 +774,9 @@
         LOG(ERROR) << __func__ << ": port id " << in_portId << " not found";
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
-    auto& routes = getConfig().routes;
-    std::copy_if(routes.begin(), routes.end(), std::back_inserter(*_aidl_return),
-                 [&](const auto& r) {
-                     const auto& srcs = r.sourcePortIds;
-                     return r.sinkPortId == in_portId ||
-                            std::find(srcs.begin(), srcs.end(), in_portId) != srcs.end();
-                 });
+    std::vector<AudioRoute*> routes = getAudioRoutesForAudioPortImpl(in_portId);
+    std::transform(routes.begin(), routes.end(), std::back_inserter(*_aidl_return),
+                   [](auto rptr) { return *rptr; });
     return ndk::ScopedAStatus::ok();
 }
 
@@ -925,13 +990,14 @@
 
     const int portId = existing != configs.end() ? existing->portId : in_requested.portId;
     if (portId == 0) {
-        LOG(ERROR) << __func__ << ": input port config does not specify portId";
+        LOG(ERROR) << __func__ << ": requested port config does not specify portId";
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
     auto& ports = getConfig().ports;
     auto portIt = findById<AudioPort>(ports, portId);
     if (portIt == ports.end()) {
-        LOG(ERROR) << __func__ << ": input port config points to non-existent portId " << portId;
+        LOG(ERROR) << __func__ << ": requested port config points to non-existent portId "
+                   << portId;
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
     if (existing != configs.end()) {
@@ -949,6 +1015,10 @@
     // or a new generated config. Now attempt to update it according to the specified
     // fields of 'in_requested'.
 
+    // Device ports with only dynamic profiles are used for devices that are connected via ADSP,
+    // which takes care of their actual configuration automatically.
+    const bool allowDynamicConfig = portIt->ext.getTag() == AudioPortExt::device &&
+                                    hasDynamicProfilesOnly(portIt->profiles);
     bool requestedIsValid = true, requestedIsFullySpecified = true;
 
     AudioIoFlags portFlags = portIt->flags;
@@ -966,17 +1036,19 @@
     AudioProfile portProfile;
     if (in_requested.format.has_value()) {
         const auto& format = in_requested.format.value();
-        if (findAudioProfile(*portIt, format, &portProfile)) {
+        if ((format == AudioFormatDescription{} && allowDynamicConfig) ||
+            findAudioProfile(*portIt, format, &portProfile)) {
             out_suggested->format = format;
         } else {
             LOG(WARNING) << __func__ << ": requested format " << format.toString()
-                         << " is not found in port's " << portId << " profiles";
+                         << " is not found in the profiles of port " << portId;
             requestedIsValid = false;
         }
     } else {
         requestedIsFullySpecified = false;
     }
-    if (!findAudioProfile(*portIt, out_suggested->format.value(), &portProfile)) {
+    if (!(out_suggested->format.value() == AudioFormatDescription{} && allowDynamicConfig) &&
+        !findAudioProfile(*portIt, out_suggested->format.value(), &portProfile)) {
         LOG(ERROR) << __func__ << ": port " << portId << " does not support format "
                    << out_suggested->format.value().toString() << " anymore";
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
@@ -984,8 +1056,9 @@
 
     if (in_requested.channelMask.has_value()) {
         const auto& channelMask = in_requested.channelMask.value();
-        if (find(portProfile.channelMasks.begin(), portProfile.channelMasks.end(), channelMask) !=
-            portProfile.channelMasks.end()) {
+        if ((channelMask == AudioChannelLayout{} && allowDynamicConfig) ||
+            find(portProfile.channelMasks.begin(), portProfile.channelMasks.end(), channelMask) !=
+                    portProfile.channelMasks.end()) {
             out_suggested->channelMask = channelMask;
         } else {
             LOG(WARNING) << __func__ << ": requested channel mask " << channelMask.toString()
@@ -999,7 +1072,8 @@
 
     if (in_requested.sampleRate.has_value()) {
         const auto& sampleRate = in_requested.sampleRate.value();
-        if (find(portProfile.sampleRates.begin(), portProfile.sampleRates.end(),
+        if ((sampleRate.value == 0 && allowDynamicConfig) ||
+            find(portProfile.sampleRates.begin(), portProfile.sampleRates.end(),
                  sampleRate.value) != portProfile.sampleRates.end()) {
             out_suggested->sampleRate = sampleRate;
         } else {
@@ -1397,7 +1471,18 @@
     return mIsMmapSupported.value();
 }
 
-ndk::ScopedAStatus Module::populateConnectedDevicePort(AudioPort* audioPort __unused) {
+ndk::ScopedAStatus Module::populateConnectedDevicePort(AudioPort* audioPort) {
+    if (audioPort->ext.getTag() != AudioPortExt::device) {
+        LOG(ERROR) << __func__ << ": not a device port: " << audioPort->toString();
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    const auto& devicePort = audioPort->ext.get<AudioPortExt::device>();
+    if (!devicePort.device.type.connection.empty()) {
+        LOG(ERROR) << __func__
+                   << ": module implementation must override 'populateConnectedDevicePort' "
+                   << "to handle connection of external devices.";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
     LOG(VERBOSE) << __func__ << ": do nothing and return ok";
     return ndk::ScopedAStatus::ok();
 }
diff --git a/audio/aidl/default/bluetooth/ModuleBluetooth.cpp b/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
index bfe7ca0..3c33207 100644
--- a/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
+++ b/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
@@ -18,15 +18,23 @@
 
 #include <android-base/logging.h>
 
+#include "BluetoothAudioSessionControl.h"
 #include "core-impl/ModuleBluetooth.h"
 #include "core-impl/StreamBluetooth.h"
 
 namespace aidl::android::hardware::audio::core {
 
-using aidl::android::hardware::audio::common::SinkMetadata;
-using aidl::android::hardware::audio::common::SourceMetadata;
-using aidl::android::media::audio::common::AudioOffloadInfo;
-using aidl::android::media::audio::common::MicrophoneInfo;
+using ::aidl::android::hardware::audio::common::SinkMetadata;
+using ::aidl::android::hardware::audio::common::SourceMetadata;
+using ::aidl::android::hardware::bluetooth::audio::BluetoothAudioSession;
+using ::aidl::android::media::audio::common::AudioDeviceDescription;
+using ::aidl::android::media::audio::common::AudioDeviceType;
+using ::aidl::android::media::audio::common::AudioOffloadInfo;
+using ::aidl::android::media::audio::common::AudioPort;
+using ::aidl::android::media::audio::common::AudioPortExt;
+using ::aidl::android::media::audio::common::MicrophoneInfo;
+using ::android::bluetooth::audio::aidl::BluetoothAudioPortAidl;
+using ::android::bluetooth::audio::aidl::BluetoothAudioPortAidlOut;
 
 ndk::ScopedAStatus ModuleBluetooth::getBluetoothA2dp(
         std::shared_ptr<IBluetoothA2dp>* _aidl_return) {
@@ -80,6 +88,49 @@
                                                     offloadInfo, getBtProfileManagerHandles());
 }
 
+ndk::ScopedAStatus ModuleBluetooth::populateConnectedDevicePort(AudioPort* audioPort) {
+    if (audioPort->ext.getTag() != AudioPortExt::device) {
+        LOG(ERROR) << __func__ << ": not a device port: " << audioPort->toString();
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    const auto& devicePort = audioPort->ext.get<AudioPortExt::device>();
+    const auto& description = devicePort.device.type;
+    // Since the configuration of the BT module is static, there is nothing to populate here.
+    // However, this method must return an error when the device can not be connected,
+    // this is determined by the status of BT profiles.
+    if (description.connection == AudioDeviceDescription::CONNECTION_BT_A2DP) {
+        bool isA2dpEnabled = false;
+        if (!!mBluetoothA2dp) {
+            RETURN_STATUS_IF_ERROR(mBluetoothA2dp.getInstance()->isEnabled(&isA2dpEnabled));
+        }
+        return isA2dpEnabled ? ndk::ScopedAStatus::ok()
+                             : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    } else if (description.connection == AudioDeviceDescription::CONNECTION_BT_LE) {
+        bool isLeEnabled = false;
+        if (!!mBluetoothLe) {
+            RETURN_STATUS_IF_ERROR(mBluetoothLe.getInstance()->isEnabled(&isLeEnabled));
+        }
+        return isLeEnabled ? ndk::ScopedAStatus::ok()
+                           : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    } else if (description.connection == AudioDeviceDescription::CONNECTION_WIRELESS &&
+               description.type == AudioDeviceType::OUT_HEARING_AID) {
+        // Hearing aids can use a number of profiles, thus the only way to check
+        // connectivity is to try to talk to the BT HAL.
+        if (!BluetoothAudioSession::IsAidlAvailable()) {
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+        }
+        std::shared_ptr<BluetoothAudioPortAidl> proxy = std::shared_ptr<BluetoothAudioPortAidl>(
+                std::make_shared<BluetoothAudioPortAidlOut>());
+        if (proxy->registerPort(description)) {
+            proxy->unregisterPort();
+            return ndk::ScopedAStatus::ok();
+        }
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    LOG(ERROR) << __func__ << ": unsupported device type: " << audioPort->toString();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+}
+
 ndk::ScopedAStatus ModuleBluetooth::onMasterMuteChanged(bool) {
     LOG(DEBUG) << __func__ << ": is not supported";
     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index bfdab51..da94815 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -202,6 +202,7 @@
     std::set<int32_t> findConnectedPortConfigIds(int32_t portConfigId);
     ndk::ScopedAStatus findPortIdForNewStream(
             int32_t in_portConfigId, ::aidl::android::media::audio::common::AudioPort** port);
+    std::vector<AudioRoute*> getAudioRoutesForAudioPortImpl(int32_t portId);
     virtual BtProfileHandles getBtProfileManagerHandles();
     internal::Configuration& getConfig();
     const ConnectedDevicePorts& getConnectedDevicePorts() const { return mConnectedDevicePorts; }
@@ -209,6 +210,8 @@
     bool getMasterVolume() const { return mMasterVolume; }
     bool getMicMute() const { return mMicMute; }
     const Patches& getPatches() const { return mPatches; }
+    std::set<int32_t> getRoutableAudioPortIds(int32_t portId,
+                                              std::vector<AudioRoute*>* routes = nullptr);
     const Streams& getStreams() const { return mStreams; }
     Type getType() const { return mType; }
     bool isMmapSupported();
diff --git a/audio/aidl/default/include/core-impl/ModuleBluetooth.h b/audio/aidl/default/include/core-impl/ModuleBluetooth.h
index 68b4e6b..526a809 100644
--- a/audio/aidl/default/include/core-impl/ModuleBluetooth.h
+++ b/audio/aidl/default/include/core-impl/ModuleBluetooth.h
@@ -44,6 +44,8 @@
             const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
                     offloadInfo,
             std::shared_ptr<StreamOut>* result) override;
+    ndk::ScopedAStatus populateConnectedDevicePort(
+            ::aidl::android::media::audio::common::AudioPort* audioPort) override;
     ndk::ScopedAStatus onMasterMuteChanged(bool mute) override;
     ndk::ScopedAStatus onMasterVolumeChanged(float volume) override;
 
@@ -51,4 +53,4 @@
     ChildInterface<IBluetoothLe> mBluetoothLe;
 };
 
-}  // namespace aidl::android::hardware::audio::core
\ No newline at end of file
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
index adea877..f8c775f 100644
--- a/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
+++ b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
@@ -59,23 +59,22 @@
 
 ndk::ScopedAStatus ModuleRemoteSubmix::populateConnectedDevicePort(AudioPort* audioPort) {
     // Find the corresponding mix port and copy its profiles.
-    std::vector<AudioRoute> routes;
     // At this moment, the port has the same ID as the template port, see connectExternalDevice.
-    RETURN_STATUS_IF_ERROR(getAudioRoutesForAudioPort(audioPort->id, &routes));
+    std::vector<AudioRoute*> routes = getAudioRoutesForAudioPortImpl(audioPort->id);
     if (routes.empty()) {
         LOG(ERROR) << __func__ << ": no routes found for the port " << audioPort->toString();
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
     const auto& route = *routes.begin();
     AudioPort mixPort;
-    if (route.sinkPortId == audioPort->id) {
-        if (route.sourcePortIds.empty()) {
-            LOG(ERROR) << __func__ << ": invalid route " << route.toString();
+    if (route->sinkPortId == audioPort->id) {
+        if (route->sourcePortIds.empty()) {
+            LOG(ERROR) << __func__ << ": invalid route " << route->toString();
             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
         }
-        RETURN_STATUS_IF_ERROR(getAudioPort(*route.sourcePortIds.begin(), &mixPort));
+        RETURN_STATUS_IF_ERROR(getAudioPort(*route->sourcePortIds.begin(), &mixPort));
     } else {
-        RETURN_STATUS_IF_ERROR(getAudioPort(route.sinkPortId, &mixPort));
+        RETURN_STATUS_IF_ERROR(getAudioPort(route->sinkPortId, &mixPort));
     }
     audioPort->profiles = mixPort.profiles;
     return ndk::ScopedAStatus::ok();
diff --git a/audio/aidl/vts/ModuleConfig.cpp b/audio/aidl/vts/ModuleConfig.cpp
index af3597d..8f19547 100644
--- a/audio/aidl/vts/ModuleConfig.cpp
+++ b/audio/aidl/vts/ModuleConfig.cpp
@@ -281,6 +281,22 @@
     return {};
 }
 
+std::vector<AudioPort> ModuleConfig::getRoutableMixPortsForDevicePort(const AudioPort& port) const {
+    std::set<int32_t> portIds;
+    for (const auto& route : mRoutes) {
+        if (port.id == route.sinkPortId) {
+            portIds.insert(route.sourcePortIds.begin(), route.sourcePortIds.end());
+        } else if (auto it = std::find(route.sourcePortIds.begin(), route.sourcePortIds.end(),
+                                       port.id);
+                   it != route.sourcePortIds.end()) {
+            portIds.insert(route.sinkPortId);
+        }
+    }
+    const bool isInput = port.flags.getTag() == AudioIoFlags::input;
+    return findMixPorts(isInput, false /*connectedOnly*/, false /*singlePort*/,
+                        [&portIds](const AudioPort& p) { return portIds.count(p.id) > 0; });
+}
+
 std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getNonRoutableSrcSinkPair(
         bool isInput) const {
     const auto mixPorts = getMixPorts(isInput, false /*connectedOnly*/);
diff --git a/audio/aidl/vts/ModuleConfig.h b/audio/aidl/vts/ModuleConfig.h
index 0cbf24d..b89adc0 100644
--- a/audio/aidl/vts/ModuleConfig.h
+++ b/audio/aidl/vts/ModuleConfig.h
@@ -103,6 +103,9 @@
     std::optional<aidl::android::media::audio::common::AudioPort>
     getSourceMixPortForConnectedDevice() const;
 
+    std::vector<aidl::android::media::audio::common::AudioPort> getRoutableMixPortsForDevicePort(
+            const aidl::android::media::audio::common::AudioPort& port) const;
+
     std::optional<SrcSinkPair> getNonRoutableSrcSinkPair(bool isInput) const;
     std::optional<SrcSinkPair> getRoutableSrcSinkPair(bool isInput) const;
     std::vector<SrcSinkGroup> getRoutableSrcSinkGroups(bool isInput) const;
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 621d200..9c52d19 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -1501,8 +1501,25 @@
                 << "port ID " << connectedPortId;
         EXPECT_EQ(portConnected.get(), connectedPort);
         const auto& portProfiles = connectedPort.profiles;
-        EXPECT_NE(0UL, portProfiles.size())
-                << "Connected port has no profiles: " << connectedPort.toString();
+        if (portProfiles.empty()) {
+            const auto routableMixPorts =
+                    moduleConfig->getRoutableMixPortsForDevicePort(connectedPort);
+            bool hasMixPortWithStaticProfile = false;
+            for (const auto& mixPort : routableMixPorts) {
+                const auto& mixPortProfiles = mixPort.profiles;
+                if (!mixPortProfiles.empty() &&
+                    !std::all_of(mixPortProfiles.begin(), mixPortProfiles.end(),
+                                 [](const auto& profile) {
+                                     return profile.format.type == AudioFormatType::DEFAULT;
+                                 })) {
+                    hasMixPortWithStaticProfile = true;
+                    break;
+                }
+            }
+            EXPECT_TRUE(hasMixPortWithStaticProfile)
+                    << "Connected port has no profiles and no routable mix ports with profiles: "
+                    << connectedPort.toString();
+        }
         const auto dynamicProfileIt =
                 std::find_if(portProfiles.begin(), portProfiles.end(), [](const auto& profile) {
                     return profile.format.type == AudioFormatType::DEFAULT;
@@ -1586,7 +1603,8 @@
         EXPECT_NE(portConfigsAfter.end(), afterIt)
                 << " port config ID " << c.id << " was removed by reset";
         if (afterIt != portConfigsAfter.end()) {
-            EXPECT_EQ(c, *afterIt);
+            EXPECT_TRUE(c == *afterIt)
+                    << "Expected: " << c.toString() << "; Actual: " << afterIt->toString();
         }
     }
 }
diff --git a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
index 8bcad1e..910ae7c 100644
--- a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
+++ b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
@@ -115,6 +115,9 @@
 };
 
 class VtsHalAutomotiveVehicleTargetTest : public testing::TestWithParam<ServiceDescriptor> {
+  protected:
+    bool checkIsSupported(int32_t propertyId);
+
   public:
     void verifyProperty(VehicleProperty propId, VehiclePropertyAccess access,
                         VehiclePropertyChangeMode changeMode, VehiclePropertyGroup group,
@@ -155,7 +158,7 @@
     }
 }
 
-// Test getAllPropConfig() returns at least 4 property configs.
+// Test getAllPropConfigs() returns at least 1 property configs.
 TEST_P(VtsHalAutomotiveVehicleTargetTest, getAllPropConfigs) {
     ALOGD("VtsHalAutomotiveVehicleTargetTest::getAllPropConfigs");
 
@@ -163,25 +166,31 @@
 
     ASSERT_TRUE(result.ok()) << "Failed to get all property configs, error: "
                              << result.error().message();
-    ASSERT_GE(result.value().size(), 4u) << StringPrintf(
-            "Expect to get at least 4 property configs, got %zu", result.value().size());
+    ASSERT_GE(result.value().size(), 1u)
+          << StringPrintf("Expect to get at least 1 property config, got %zu",
+                          result.value().size());
 }
 
-// Test getPropConfigs() can query all properties listed in CDD.
-TEST_P(VtsHalAutomotiveVehicleTargetTest, getRequiredPropConfigs) {
+// Test getPropConfigs() can query properties returned by getAllPropConfigs.
+TEST_P(VtsHalAutomotiveVehicleTargetTest, getPropConfigsWithValidProps) {
     ALOGD("VtsHalAutomotiveVehicleTargetTest::getRequiredPropConfigs");
 
-    // Check the properties listed in CDD
-    std::vector<int32_t> properties = {
-            toInt(VehicleProperty::GEAR_SELECTION), toInt(VehicleProperty::NIGHT_MODE),
-            toInt(VehicleProperty::PARKING_BRAKE_ON), toInt(VehicleProperty::PERF_VEHICLE_SPEED)};
+    std::vector<int32_t> properties;
+    auto result = mVhalClient->getAllPropConfigs();
 
-    auto result = mVhalClient->getPropConfigs(properties);
+    ASSERT_TRUE(result.ok()) << "Failed to get all property configs, error: "
+                             << result.error().message();
+    for (const auto& cfgPtr : result.value()) {
+        properties.push_back(cfgPtr->getPropId());
+    }
+
+    result = mVhalClient->getPropConfigs(properties);
 
     ASSERT_TRUE(result.ok()) << "Failed to get required property config, error: "
                              << result.error().message();
-    ASSERT_EQ(result.value().size(), 4u)
-            << StringPrintf("Expect to get exactly 4 configs, got %zu", result.value().size());
+    ASSERT_EQ(result.value().size(), properties.size())
+          << StringPrintf("Expect to get exactly %zu configs, got %zu",
+                          properties.size(), result.value().size());
 }
 
 // Test getPropConfig() with an invalid propertyId returns an error code.
@@ -200,6 +209,9 @@
     ALOGD("VtsHalAutomotiveVehicleTargetTest::get");
 
     int32_t propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
+    if (!checkIsSupported(propId)) {
+        GTEST_SKIP() << "Property: " << propId << " is not supported, skip the test";
+    }
     auto result = mVhalClient->getValueSync(*mVhalClient->createHalPropValue(propId));
 
     ASSERT_TRUE(result.ok()) << StringPrintf("Failed to get value for property: %" PRId32
@@ -285,6 +297,10 @@
     ALOGD("VtsHalAutomotiveVehicleTargetTest::setNotWritableProp");
 
     int32_t propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
+    if (!checkIsSupported(propId)) {
+        GTEST_SKIP() << "Property: " << propId << " is not supported, skip the test";
+    }
+
     auto getValueResult = mVhalClient->getValueSync(*mVhalClient->createHalPropValue(propId));
     ASSERT_TRUE(getValueResult.ok())
             << StringPrintf("Failed to get value for property: %" PRId32 ", error: %s", propId,
@@ -325,6 +341,9 @@
     ALOGD("VtsHalAutomotiveVehicleTargetTest::subscribeAndUnsubscribe");
 
     int32_t propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
+    if (!checkIsSupported(propId)) {
+        GTEST_SKIP() << "Property: " << propId << " is not supported, skip the test";
+    }
 
     auto propConfigsResult = mVhalClient->getPropConfigs({propId});
 
@@ -414,6 +433,9 @@
     }
 
     int32_t propId = toInt(VehicleProperty::PARKING_BRAKE_ON);
+    if (!checkIsSupported(propId)) {
+        GTEST_SKIP() << "Property: " << propId << " is not supported, skip the test";
+    }
     auto prop = mVhalClient->createHalPropValue(propId);
 
     auto result = mVhalClient->getValueSync(*prop);
@@ -865,6 +887,11 @@
                    VehicleArea::GLOBAL, VehiclePropertyType::INT32);
 }
 
+bool VtsHalAutomotiveVehicleTargetTest::checkIsSupported(int32_t propertyId) {
+    auto result = mVhalClient->getPropConfigs({propertyId});
+    return result.ok();
+}
+
 std::vector<ServiceDescriptor> getDescriptors() {
     std::vector<ServiceDescriptor> descriptors;
     for (std::string name : getAidlHalInstanceNames(IVehicle::descriptor)) {
diff --git a/compatibility_matrices/compatibility_matrix.8.xml b/compatibility_matrices/compatibility_matrix.8.xml
index 3d55da9..99dcdbb 100644
--- a/compatibility_matrices/compatibility_matrix.8.xml
+++ b/compatibility_matrices/compatibility_matrix.8.xml
@@ -360,6 +360,18 @@
             <instance>software</instance>
         </interface>
     </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.media.omx</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOmx</name>
+            <instance>default</instance>
+        </interface>
+        <interface>
+            <name>IOmxStore</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.memtrack</name>
         <version>1</version>
diff --git a/media/OWNERS b/media/OWNERS
index 71a53ef..01b440a 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -1,7 +1,6 @@
 # Bug component: 25690
 
 # Media team
-jgus@google.com
 lajos@google.com
 taklee@google.com
 wonsik@google.com
diff --git a/nfc/1.0/Android.bp b/nfc/1.0/Android.bp
index 55c8639..ef12c7c 100644
--- a/nfc/1.0/Android.bp
+++ b/nfc/1.0/Android.bp
@@ -22,4 +22,8 @@
     ],
     gen_java: true,
     gen_java_constants: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.nfcservices",
+    ],
 }
diff --git a/nfc/1.1/Android.bp b/nfc/1.1/Android.bp
index a8463cf..65da2a0 100644
--- a/nfc/1.1/Android.bp
+++ b/nfc/1.1/Android.bp
@@ -22,4 +22,8 @@
         "android.hidl.base@1.0",
     ],
     gen_java: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.nfcservices",
+    ],
 }
diff --git a/nfc/1.2/Android.bp b/nfc/1.2/Android.bp
index 4831ab9..8ad93f9 100644
--- a/nfc/1.2/Android.bp
+++ b/nfc/1.2/Android.bp
@@ -22,4 +22,8 @@
         "android.hidl.base@1.0",
     ],
     gen_java: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.nfcservices",
+    ],
 }
diff --git a/nfc/aidl/Android.bp b/nfc/aidl/Android.bp
index 08ec5fe..dae9f29 100644
--- a/nfc/aidl/Android.bp
+++ b/nfc/aidl/Android.bp
@@ -34,6 +34,13 @@
             sdk_version: "module_current",
             enabled: false,
         },
+	ndk: {
+            enabled: true,
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.nfcservices",
+            ],
+        },
         rust: {
             enabled: true,
         },
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 3a8a1e8..822770d 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -79,7 +79,8 @@
 typedef KeyMintAidlTestBase::KeyData KeyData;
 // Predicate for testing basic characteristics validity in generation or import.
 bool KeyCharacteristicsBasicallyValid(SecurityLevel secLevel,
-                                      const vector<KeyCharacteristics>& key_characteristics) {
+                                      const vector<KeyCharacteristics>& key_characteristics,
+                                      int32_t aidl_version) {
     if (key_characteristics.empty()) return false;
 
     std::unordered_set<SecurityLevel> levels_seen;
@@ -89,7 +90,12 @@
             return false;
         }
 
-        EXPECT_EQ(count_tag_invalid_entries(entry.authorizations), 0);
+        // There was no test to assert that INVALID tag should not present in authorization list
+        // before Keymint V3, so there are some Keymint implementations where asserting for INVALID
+        // tag fails(b/297306437), hence skipping for Keymint < 3.
+        if (aidl_version >= 3) {
+            EXPECT_EQ(count_tag_invalid_entries(entry.authorizations), 0);
+        }
 
         // Just ignore the SecurityLevel::KEYSTORE as the KM won't do any enforcement on this.
         if (entry.securityLevel == SecurityLevel::KEYSTORE) continue;
@@ -264,7 +270,7 @@
     vendor_patch_level_ = getVendorPatchlevel();
 }
 
-int32_t KeyMintAidlTestBase::AidlVersion() {
+int32_t KeyMintAidlTestBase::AidlVersion() const {
     int32_t version = 0;
     auto status = keymint_->getInterfaceVersion(&version);
     if (!status.isOk()) {
@@ -294,8 +300,8 @@
     KeyCreationResult creationResult;
     Status result = keymint_->generateKey(key_desc.vector_data(), attest_key, &creationResult);
     if (result.isOk()) {
-        EXPECT_PRED2(KeyCharacteristicsBasicallyValid, SecLevel(),
-                     creationResult.keyCharacteristics);
+        EXPECT_PRED3(KeyCharacteristicsBasicallyValid, SecLevel(),
+                     creationResult.keyCharacteristics, AidlVersion());
         EXPECT_GT(creationResult.keyBlob.size(), 0);
         *key_blob = std::move(creationResult.keyBlob);
         *key_characteristics = std::move(creationResult.keyCharacteristics);
@@ -367,8 +373,8 @@
                                  {} /* attestationSigningKeyBlob */, &creationResult);
 
     if (result.isOk()) {
-        EXPECT_PRED2(KeyCharacteristicsBasicallyValid, SecLevel(),
-                     creationResult.keyCharacteristics);
+        EXPECT_PRED3(KeyCharacteristicsBasicallyValid, SecLevel(),
+                     creationResult.keyCharacteristics, AidlVersion());
         EXPECT_GT(creationResult.keyBlob.size(), 0);
 
         *key_blob = std::move(creationResult.keyBlob);
@@ -411,8 +417,8 @@
             unwrapping_params.vector_data(), password_sid, biometric_sid, &creationResult);
 
     if (result.isOk()) {
-        EXPECT_PRED2(KeyCharacteristicsBasicallyValid, SecLevel(),
-                     creationResult.keyCharacteristics);
+        EXPECT_PRED3(KeyCharacteristicsBasicallyValid, SecLevel(),
+                     creationResult.keyCharacteristics, AidlVersion());
         EXPECT_GT(creationResult.keyBlob.size(), 0);
 
         key_blob_ = std::move(creationResult.keyBlob);
@@ -2068,27 +2074,36 @@
     return retval;
 }
 
-void assert_mgf_digests_present_in_key_characteristics(
+void KeyMintAidlTestBase::assert_mgf_digests_present_or_not_in_key_characteristics(
+        std::vector<android::hardware::security::keymint::Digest>& expected_mgf_digests,
+        bool is_mgf_digest_expected) const {
+    assert_mgf_digests_present_or_not_in_key_characteristics(
+            key_characteristics_, expected_mgf_digests, is_mgf_digest_expected);
+}
+
+void KeyMintAidlTestBase::assert_mgf_digests_present_or_not_in_key_characteristics(
         const vector<KeyCharacteristics>& key_characteristics,
-        std::vector<android::hardware::security::keymint::Digest>& expected_mgf_digests) {
+        std::vector<android::hardware::security::keymint::Digest>& expected_mgf_digests,
+        bool is_mgf_digest_expected) const {
+    // There was no test to assert that MGF1 digest was present in generated/imported key
+    // characteristics before Keymint V3, so there are some Keymint implementations where
+    // asserting for MGF1 digest fails(b/297306437), hence skipping for Keymint < 3.
+    if (AidlVersion() < 3) {
+        return;
+    }
     AuthorizationSet auths;
     for (auto& entry : key_characteristics) {
         auths.push_back(AuthorizationSet(entry.authorizations));
     }
     for (auto digest : expected_mgf_digests) {
-        ASSERT_TRUE(auths.Contains(TAG_RSA_OAEP_MGF_DIGEST, digest));
+        if (is_mgf_digest_expected) {
+            ASSERT_TRUE(auths.Contains(TAG_RSA_OAEP_MGF_DIGEST, digest));
+        } else {
+            ASSERT_FALSE(auths.Contains(TAG_RSA_OAEP_MGF_DIGEST, digest));
+        }
     }
 }
 
-bool is_mgf_digest_present(const vector<KeyCharacteristics>& key_characteristics,
-                           android::hardware::security::keymint::Digest expected_mgf_digest) {
-    AuthorizationSet auths;
-    for (auto& entry : key_characteristics) {
-        auths.push_back(AuthorizationSet(entry.authorizations));
-    }
-    return auths.Contains(TAG_RSA_OAEP_MGF_DIGEST, expected_mgf_digest);
-}
-
 namespace {
 
 void check_cose_key(const vector<uint8_t>& data, bool testMode) {
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 9778b3d..4fb711c 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -95,7 +95,7 @@
 
     void InitializeKeyMint(std::shared_ptr<IKeyMintDevice> keyMint);
     IKeyMintDevice& keyMint() { return *keymint_; }
-    int32_t AidlVersion();
+    int32_t AidlVersion() const;
     uint32_t os_version() { return os_version_; }
     uint32_t os_patch_level() { return os_patch_level_; }
     uint32_t vendor_patch_level() { return vendor_patch_level_; }
@@ -373,6 +373,15 @@
     bool shouldSkipAttestKeyTest(void) const;
     void skipAttestKeyTest(void) const;
 
+    void assert_mgf_digests_present_or_not_in_key_characteristics(
+            const vector<KeyCharacteristics>& key_characteristics,
+            std::vector<android::hardware::security::keymint::Digest>& expected_mgf_digests,
+            bool is_mgf_digest_expected) const;
+
+    void assert_mgf_digests_present_or_not_in_key_characteristics(
+            std::vector<android::hardware::security::keymint::Digest>& expected_mgf_digests,
+            bool is_mgf_digest_expected) const;
+
   protected:
     std::shared_ptr<IKeyMintDevice> keymint_;
     uint32_t os_version_;
@@ -430,11 +439,6 @@
 X509_Ptr parse_cert_blob(const vector<uint8_t>& blob);
 ASN1_OCTET_STRING* get_attestation_record(X509* certificate);
 vector<uint8_t> make_name_from_str(const string& name);
-void assert_mgf_digests_present_in_key_characteristics(
-        const vector<KeyCharacteristics>& key_characteristics,
-        std::vector<android::hardware::security::keymint::Digest>& expected_mgf_digests);
-bool is_mgf_digest_present(const vector<KeyCharacteristics>& key_characteristics,
-                           android::hardware::security::keymint::Digest expected_mgf_digest);
 void check_maced_pubkey(const MacedPublicKey& macedPubKey, bool testMode,
                         vector<uint8_t>* payload_value);
 void p256_pub_key(const vector<uint8_t>& coseKeyData, EVP_PKEY_Ptr* signingKey);
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index de563c4..a8f17dd 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -4743,6 +4743,12 @@
  * should have the correct characteristics.
  */
 TEST_P(ImportKeyTest, RsaOaepMGFDigestSuccess) {
+    // There was no test to assert that MGF1 digest was present in generated/imported key
+    // characteristics before Keymint V3, so there are some Keymint implementations where
+    // this test case fails(b/297306437), hence this test is skipped for Keymint < 3.
+    if (AidlVersion() < 3) {
+        GTEST_SKIP() << "Test not applicable to Keymint < V3";
+    }
     auto mgf_digests = ValidDigests(false /* withNone */, true /* withMD5 */);
     size_t key_size = 2048;
 
@@ -4763,7 +4769,7 @@
     CheckOrigin();
 
     // Make sure explicitly specified mgf-digests exist in key characteristics.
-    assert_mgf_digests_present_in_key_characteristics(key_characteristics_, mgf_digests);
+    assert_mgf_digests_present_or_not_in_key_characteristics(mgf_digests, true);
 
     string message = "Hello";
 
@@ -4827,8 +4833,9 @@
     CheckCryptoParam(TAG_PADDING, PaddingMode::RSA_OAEP);
     CheckOrigin();
 
+    vector defaultDigest = {Digest::SHA1};
     // Make sure default mgf-digest (SHA1) is not included in Key characteristics.
-    ASSERT_FALSE(is_mgf_digest_present(key_characteristics_, Digest::SHA1));
+    assert_mgf_digests_present_or_not_in_key_characteristics(defaultDigest, false);
 }
 
 INSTANTIATE_KEYMINT_AIDL_TEST(ImportKeyTest);
@@ -5256,7 +5263,7 @@
  */
 TEST_P(EncryptionOperationsTest, RsaOaepSuccess) {
     auto digests = ValidDigests(false /* withNone */, true /* withMD5 */);
-    auto mgf_digest = Digest::SHA1;
+    auto mgf_digest = vector{Digest::SHA1};
 
     size_t key_size = 2048;  // Need largish key for SHA-512 test.
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
@@ -5264,11 +5271,11 @@
                                                  .RsaEncryptionKey(key_size, 65537)
                                                  .Padding(PaddingMode::RSA_OAEP)
                                                  .Digest(digests)
-                                                 .Authorization(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest)
+                                                 .OaepMGFDigest(mgf_digest)
                                                  .SetDefaultValidity()));
 
     // Make sure explicitly specified mgf-digest exist in key characteristics.
-    ASSERT_TRUE(is_mgf_digest_present(key_characteristics_, mgf_digest));
+    assert_mgf_digests_present_or_not_in_key_characteristics(mgf_digest, true);
 
     string message = "Hello";
 
@@ -5393,21 +5400,21 @@
                                                  .Padding(PaddingMode::RSA_OAEP)
                                                  .Digest(Digest::SHA_2_256)
                                                  .SetDefaultValidity()));
+    if (AidlVersion() >= 3) {
+        std::vector<Digest> mgf1DigestsInAuths;
+        mgf1DigestsInAuths.reserve(digests.size());
+        const auto& hw_auths = SecLevelAuthorizations(key_characteristics_);
+        std::for_each(hw_auths.begin(), hw_auths.end(), [&](auto& param) {
+            if (param.tag == Tag::RSA_OAEP_MGF_DIGEST) {
+                KeyParameterValue value = param.value;
+                mgf1DigestsInAuths.push_back(param.value.template get<KeyParameterValue::digest>());
+            }
+        });
 
-    std::vector<Digest> mgf1DigestsInAuths;
-    mgf1DigestsInAuths.reserve(digests.size());
-    const auto& hw_auths = SecLevelAuthorizations(key_characteristics_);
-    std::for_each(hw_auths.begin(), hw_auths.end(), [&](auto& param) {
-        if (param.tag == Tag::RSA_OAEP_MGF_DIGEST) {
-            KeyParameterValue value = param.value;
-            mgf1DigestsInAuths.push_back(param.value.template get<KeyParameterValue::digest>());
-        }
-    });
-
-    std::sort(digests.begin(), digests.end());
-    std::sort(mgf1DigestsInAuths.begin(), mgf1DigestsInAuths.end());
-    EXPECT_EQ(digests, mgf1DigestsInAuths);
-
+        std::sort(digests.begin(), digests.end());
+        std::sort(mgf1DigestsInAuths.begin(), mgf1DigestsInAuths.end());
+        EXPECT_EQ(digests, mgf1DigestsInAuths);
+    }
     string message = "Hello";
 
     for (auto digest : digests) {
@@ -5462,8 +5469,9 @@
                                                  .Digest(Digest::SHA_2_256)
                                                  .SetDefaultValidity()));
 
+    vector defaultDigest = vector{Digest::SHA1};
     // Make sure default mgf-digest (SHA1) is not included in Key characteristics.
-    ASSERT_FALSE(is_mgf_digest_present(key_characteristics_, Digest::SHA1));
+    assert_mgf_digests_present_or_not_in_key_characteristics(defaultDigest, false);
 
     // Do local RSA encryption using the default MGF digest of SHA-1.
     string message = "Hello";
@@ -5499,19 +5507,20 @@
  */
 TEST_P(EncryptionOperationsTest, RsaOaepMGFDigestDefaultFail) {
     size_t key_size = 2048;
-    auto mgf_digest = Digest::SHA_2_256;
+    auto mgf_digest = vector{Digest::SHA_2_256};
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                                 .Authorization(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest)
+                                                 .OaepMGFDigest(mgf_digest)
                                                  .RsaEncryptionKey(key_size, 65537)
                                                  .Padding(PaddingMode::RSA_OAEP)
                                                  .Digest(Digest::SHA_2_256)
                                                  .SetDefaultValidity()));
 
     // Make sure explicitly specified mgf-digest exist in key characteristics.
-    ASSERT_TRUE(is_mgf_digest_present(key_characteristics_, mgf_digest));
+    assert_mgf_digests_present_or_not_in_key_characteristics(mgf_digest, true);
+    vector defaultDigest = vector{Digest::SHA1};
     // Make sure default mgf-digest is not included in key characteristics.
-    ASSERT_FALSE(is_mgf_digest_present(key_characteristics_, Digest::SHA1));
+    assert_mgf_digests_present_or_not_in_key_characteristics(defaultDigest, false);
 
     // Do local RSA encryption using the default MGF digest of SHA-1.
     string message = "Hello";
@@ -5535,16 +5544,17 @@
  * with incompatible MGF digest.
  */
 TEST_P(EncryptionOperationsTest, RsaOaepWithMGFIncompatibleDigest) {
-    auto mgf_digest = Digest::SHA_2_256;
+    auto mgf_digest = vector{Digest::SHA_2_256};
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                 .Authorization(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest)
+                                                 .OaepMGFDigest(mgf_digest)
                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
                                                  .RsaEncryptionKey(2048, 65537)
                                                  .Padding(PaddingMode::RSA_OAEP)
                                                  .Digest(Digest::SHA_2_256)
                                                  .SetDefaultValidity()));
+
     // Make sure explicitly specified mgf-digest exist in key characteristics.
-    ASSERT_TRUE(is_mgf_digest_present(key_characteristics_, mgf_digest));
+    assert_mgf_digests_present_or_not_in_key_characteristics(mgf_digest, true);
 
     string message = "Hello World!";
 
@@ -5562,16 +5572,17 @@
  * with unsupported MGF digest.
  */
 TEST_P(EncryptionOperationsTest, RsaOaepWithMGFUnsupportedDigest) {
-    auto mgf_digest = Digest::SHA_2_256;
+    auto mgf_digest = vector{Digest::SHA_2_256};
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                 .Authorization(TAG_RSA_OAEP_MGF_DIGEST, mgf_digest)
+                                                 .OaepMGFDigest(mgf_digest)
                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
                                                  .RsaEncryptionKey(2048, 65537)
                                                  .Padding(PaddingMode::RSA_OAEP)
                                                  .Digest(Digest::SHA_2_256)
                                                  .SetDefaultValidity()));
+
     // Make sure explicitly specified mgf-digest exist in key characteristics.
-    ASSERT_TRUE(is_mgf_digest_present(key_characteristics_, mgf_digest));
+    assert_mgf_digests_present_or_not_in_key_characteristics(mgf_digest, true);
 
     string message = "Hello World!";
 
diff --git a/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl b/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
index 15b0442..61404d4 100644
--- a/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
+++ b/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
@@ -101,17 +101,19 @@
     -4670545 : bstr,                         ; Code Hash
     ? -4670546 : bstr,                       ; Code Descriptor
     -4670547 : bstr,                         ; Configuration Hash
-    -4670548 : bstr .cbor {                  ; Configuration Descriptor
-        ? -70002 : tstr,                         ; Component name
-        ? -70003 : int / tstr,                   ; Component version
-        ? -70004 : null,                         ; Resettable
-        ? -70005 : uint,                         ; Security version
-    },
+    -4670548 : bstr .cbor ConfigurationDescriptor,
     -4670549 : bstr,                         ; Authority Hash
     ? -4670550 : bstr,                       ; Authority Descriptor
     -4670551 : bstr,                         ; Mode
 }
 
+ConfigurationDescriptor = {                  ; Configuration Descriptor
+    ? -70002 : tstr,                         ; Component name
+    ? -70003 : int / tstr,                   ; Component version
+    ? -70004 : null,                         ; Resettable
+    ? -70005 : uint,                         ; Security version
+}
+
 ; Each entry in the DICE chain is a DiceChainEntryPayload signed by the key from the previous
 ; entry in the DICE chain array.
 DiceChainEntry = [                            ; COSE_Sign1 (untagged), [RFC9052 s4.2]
diff --git a/thermal/2.0/default/Android.bp b/thermal/2.0/default/Android.bp
index f743ade..83afa97 100644
--- a/thermal/2.0/default/Android.bp
+++ b/thermal/2.0/default/Android.bp
@@ -22,23 +22,13 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-filegroup {
-    name: "android.hardware.thermal@2.0-service.xml",
-    srcs: ["android.hardware.thermal@2.0-service.xml"],
-}
-
-filegroup {
-    name: "android.hardware.thermal@2.0-service.rc",
-    srcs: ["android.hardware.thermal@2.0-service.rc"],
-}
-
 cc_binary {
     name: "android.hardware.thermal@2.0-service.mock",
     defaults: ["hidl_defaults"],
     relative_install_path: "hw",
     vendor: true,
-    init_rc: [":android.hardware.thermal@2.0-service.rc"],
-    vintf_fragments: [":android.hardware.thermal@2.0-service.xml"],
+    init_rc: ["android.hardware.thermal@2.0-service.rc"],
+    vintf_fragments: ["android.hardware.thermal@2.0-service.xml"],
     srcs: [
         "Thermal.cpp",
         "service.cpp",
diff --git a/thermal/2.0/default/apex/Android.bp b/thermal/2.0/default/apex/Android.bp
deleted file mode 100644
index 914a3a8..0000000
--- a/thermal/2.0/default/apex/Android.bp
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (C) 2022 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 {
-    default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
-apex_key {
-    name: "com.android.hardware.thermal.key",
-    public_key: "com.android.hardware.thermal.avbpubkey",
-    private_key: "com.android.hardware.thermal.pem",
-}
-
-android_app_certificate {
-    name: "com.android.hardware.thermal.certificate",
-    certificate: "com.android.hardware.thermal",
-}
-
-genrule {
-    name: "com.android.hardware.thermal.rc-gen",
-    srcs: [":android.hardware.thermal@2.0-service.rc"],
-    out: ["com.android.hardware.thermal.rc"],
-    cmd: "sed -E 's/\\/vendor/\\/apex\\/com.android.hardware.thermal.mock/' $(in) > $(out)",
-}
-
-prebuilt_etc {
-    name: "com.android.hardware.thermal.rc",
-    src: ":com.android.hardware.thermal.rc-gen",
-    installable: false,
-}
-
-apex {
-    name: "com.android.hardware.thermal.mock",
-    manifest: "manifest.json",
-    file_contexts: "file_contexts",
-    key: "com.android.hardware.thermal.key",
-    certificate: ":com.android.hardware.thermal.certificate",
-    use_vndk_as_stable: true,
-    updatable: false,
-    soc_specific: true,
-    binaries: ["android.hardware.thermal@2.0-service.mock"],
-    prebuilts: ["com.android.hardware.thermal.rc"],
-    vintf_fragments: [":android.hardware.thermal@2.0-service.xml"],
-}
diff --git a/thermal/2.0/default/apex/com.android.hardware.thermal.avbpubkey b/thermal/2.0/default/apex/com.android.hardware.thermal.avbpubkey
deleted file mode 100644
index 8f7cf72..0000000
--- a/thermal/2.0/default/apex/com.android.hardware.thermal.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/thermal/2.0/default/apex/com.android.hardware.thermal.pem b/thermal/2.0/default/apex/com.android.hardware.thermal.pem
deleted file mode 100644
index 4ea6e85..0000000
--- a/thermal/2.0/default/apex/com.android.hardware.thermal.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
diff --git a/thermal/2.0/default/apex/com.android.hardware.thermal.pk8 b/thermal/2.0/default/apex/com.android.hardware.thermal.pk8
deleted file mode 100644
index 3e5bf69..0000000
--- a/thermal/2.0/default/apex/com.android.hardware.thermal.pk8
+++ /dev/null
Binary files differ
diff --git a/thermal/2.0/default/apex/com.android.hardware.thermal.x509.pem b/thermal/2.0/default/apex/com.android.hardware.thermal.x509.pem
deleted file mode 100644
index 048e69a..0000000
--- a/thermal/2.0/default/apex/com.android.hardware.thermal.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF3TCCA8UCFFWeg2KJX/fyAqZPcKaFS61/a3GiMA0GCSqGSIb3DQEBCwUAMIGp
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTElMCMGA1UEAwwcY29t
-LmFuZHJvaWQuaGFyZHdhcmUudGhlcm1hbDAgFw0yMTExMTcxODE3MjRaGA80NzU5
-MTAxNDE4MTcyNFowgakxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
-MRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYD
-VQQLDAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29t
-MSUwIwYDVQQDDBxjb20uYW5kcm9pZC5oYXJkd2FyZS50aGVybWFsMIICIjANBgkq
-hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2W8QhCKX0WoS5jhIWbWBoKulD6XhKASA
-CL0oU6Uci0U6id2m++ou/T0aHSlliS9kT1NEABNwbLeTDa9h1qg1lbajRzXbvzEz
-EvZYT+dlgYFNZ9zaVCIlMapoiN+nrM/Rs24UBjJrZu1B39+IcE5ciQz69PgrLKWF
-vFEdYzxWI246azOVr3fvdelQg+CyPgiGObVAGOHhAidvsjg4FssKnADzn+JNlTt6
-b9P65xUQErut8hz9YdLtfZ096iwe8eEpsMOQwCNdKNXVCcNjQWkOwRaU+0awHoH1
-4mArvF7yyvJxqzkNaR03BPqXAHPIAPu6xdfA19+HVIiz6bLEZ1mfCM6edXByCWZu
-K8o54OZph71r15ncv4DVd+cnBjNvBvfdlJSeGjSreFkUo5NkfAwqdmLfZx6CedHI
-sLx7X8vPYolQnR4UEvaX6yeNN0gs8Dd6ePMqOEiwWFVASD+cbpcUrp09uzlDStGV
-1DPx/9J2kw8eXPMqOSGThkLWuUMUFojyh7bNlL16oYmEeZW6/OOXCOXzAQgJ7NIs
-DA1/H2w1HMHWgSfF4y+Es2CiqcgVFOIU/07b31Edw4v56pjx1CUpRpJZjDA1JJNo
-A4YCnpA6JWTxzUTmv21fEYyY+poA3CuzvCfZ80z9h/UFW98oM9GawGvK0i2pLudS
-RaZXWeil08cCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAj2gpn/IpAHQLDlI52WwL
-IDc5uzlf1BGseLZ8M8uuMiwvN00nOjunQQZEIbhH7+03GYyMzRhTTI3nWwmX4Fnq
-vC5sR68yNlu9gOAMXaAHo/Rw73ak7sv8xGbb2FeQsHaMKDQ2nqxP17SWdQ0xWa1u
-5qNurPOdAPOw77noZcT7yYX7lcrOKxPIekPJxyeOlp4bQSmabSRgYr70B7GybPlv
-K1gkgCBxl5RiVjVxLo+7ESHSAaGLy0S7F2v6PJ9oj15TovWQ0py2iBKZ6HReB7s/
-umnQqkwXDLudlNmoXIsgIYn8vKFTYpy1GSNJqhRSLfvLR6NtuU0iCTvg/X7oPmS1
-dWUdjVeO7ZVvIpO3gLLEe4maBEYF2sOlt3bRmzIHydORJtkfTt5tiZ4wR9RfJbkj
-iBiDbNiX010bZPTAXmgMbuJzQXZEXCBy0qKeS1cHwf9M8FDoiLajXepfZIp+6syt
-D4lZk4eAV141JL5PfABfdZWwT3cTgFIqCYpqrMQJIu+GHEjUwD2yNPi0I1/ydFCW
-CPDnzWjYCi6yVB8hss3ZFbvhfyJzdm3LivNVbLGK0+TG0EOAz6d2aQ0UjESgMD1A
-U8hLzQt7MiFSG0bt2cVx6SgCHeYUqMntbFELEAURWrhAfPLMJtAvFgKbEiZEAkkW
-pdDVh603aIp4LjVCfTYp/mQ=
------END CERTIFICATE-----
diff --git a/thermal/2.0/default/apex/file_contexts b/thermal/2.0/default/apex/file_contexts
deleted file mode 100644
index e0d87c7..0000000
--- a/thermal/2.0/default/apex/file_contexts
+++ /dev/null
@@ -1,5 +0,0 @@
-(/.*)?                                                    u:object_r:vendor_file:s0
-# Permission XMLs
-/etc/permissions(/.*)?                                    u:object_r:vendor_configs_file:s0
-# binary
-/bin/hw/android\.hardware\.thermal@2\.0-service\.mock     u:object_r:hal_thermal_default_exec:s0
diff --git a/thermal/2.0/default/apex/manifest.json b/thermal/2.0/default/apex/manifest.json
deleted file mode 100644
index ee44dc1..0000000
--- a/thermal/2.0/default/apex/manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name": "com.android.hardware.thermal.mock",
-  "version": 1
-}
diff --git a/threadnetwork/aidl/default/thread_chip.cpp b/threadnetwork/aidl/default/thread_chip.cpp
index 9358eba..ed34e63 100644
--- a/threadnetwork/aidl/default/thread_chip.cpp
+++ b/threadnetwork/aidl/default/thread_chip.cpp
@@ -32,23 +32,19 @@
 namespace threadnetwork {
 
 ThreadChip::ThreadChip(char* url) : mUrl(), mRxFrameBuffer(), mCallback(nullptr) {
-    static const char kHdlcProtocol[] = "spinel+hdlc";
-    static const char kSpiProtocol[] = "spinel+spi";
-    const char* protocol;
+    const char* interfaceName;
 
     CHECK_EQ(mUrl.Init(url), 0);
 
-    protocol = mUrl.GetProtocol();
-    CHECK_NE(protocol, nullptr);
+    interfaceName = mUrl.GetProtocol();
+    CHECK_NE(interfaceName, nullptr);
 
-    if (memcmp(protocol, kSpiProtocol, strlen(kSpiProtocol)) == 0) {
-        mSpinelInterface = std::make_shared<ot::Posix::SpiInterface>(handleReceivedFrameJump, this,
-                                                                     mRxFrameBuffer);
-    } else if (memcmp(protocol, kHdlcProtocol, strlen(kHdlcProtocol)) == 0) {
-        mSpinelInterface = std::make_shared<ot::Posix::HdlcInterface>(handleReceivedFrameJump, this,
-                                                                      mRxFrameBuffer);
+    if (ot::Posix::SpiInterface::IsInterfaceNameMatch(interfaceName)) {
+        mSpinelInterface = std::make_shared<ot::Posix::SpiInterface>(mUrl);
+    } else if (ot::Posix::HdlcInterface::IsInterfaceNameMatch(interfaceName)) {
+        mSpinelInterface = std::make_shared<ot::Posix::HdlcInterface>(mUrl);
     } else {
-        ALOGE("The protocol \"%s\" is not supported", protocol);
+        ALOGE("The interface \"%s\" is not supported", interfaceName);
         exit(EXIT_FAILURE);
     }
 
@@ -106,7 +102,8 @@
     if (in_callback == nullptr) {
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     } else if (mCallback == nullptr) {
-        if (mSpinelInterface->Init(mUrl) != OT_ERROR_NONE) {
+        if (mSpinelInterface->Init(handleReceivedFrameJump, this, mRxFrameBuffer) !=
+            OT_ERROR_NONE) {
             return errorStatus(ERROR_FAILED, "Failed to initialize the interface");
         }
 
diff --git a/threadnetwork/aidl/default/thread_chip.hpp b/threadnetwork/aidl/default/thread_chip.hpp
index 680580a..30046ef 100644
--- a/threadnetwork/aidl/default/thread_chip.hpp
+++ b/threadnetwork/aidl/default/thread_chip.hpp
@@ -20,6 +20,7 @@
 #include <aidl/android/hardware/threadnetwork/IThreadChipCallback.h>
 
 #include "lib/spinel/spinel_interface.hpp"
+#include "lib/url/url.hpp"
 #include "mainloop.hpp"
 
 #include <android/binder_auto_utils.h>
diff --git a/tv/OWNERS b/tv/OWNERS
index ee7f272..e051b28 100644
--- a/tv/OWNERS
+++ b/tv/OWNERS
@@ -9,4 +9,5 @@
 quxiangfang@google.com
 shubang@google.com
 yixiaoluo@google.com
+qingxun@google.com
 
diff --git a/tv/input/OWNERS b/tv/input/OWNERS
index e69de29..1252e4e 100644
--- a/tv/input/OWNERS
+++ b/tv/input/OWNERS
@@ -0,0 +1 @@
+# Bug component: 826094
diff --git a/usb/apex/Android.bp b/usb/apex/Android.bp
index 765aa21..789a3fc 100644
--- a/usb/apex/Android.bp
+++ b/usb/apex/Android.bp
@@ -16,26 +16,15 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-apex_key {
-    name: "com.android.hardware.usb.key",
-    public_key: "com.android.hardware.usb.avbpubkey",
-    private_key: "com.android.hardware.usb.pem",
-}
-
-android_app_certificate {
-    name: "com.android.hardware.usb.certificate",
-    certificate: "com.android.hardware.usb",
-}
-
 apex {
     name: "com.android.hardware.usb",
     manifest: "manifest.json",
     file_contexts: "file_contexts",
-    key: "com.android.hardware.usb.key",
-    certificate: ":com.android.hardware.usb.certificate",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
     updatable: false,
-    soc_specific: true,
-    use_vndk_as_stable: true,
+    vendor: true,
+
     binaries: ["android.hardware.usb-service.example"],
     prebuilts: [
         "com.android.hardware.usb.rc", // init .rc
@@ -50,7 +39,7 @@
     name: "com.android.hardware.usb.rc-gen",
     srcs: [":android.hardware.usb-service.example.rc"],
     out: ["com.android.hardware.usb.rc"],
-    cmd: "sed -E 's/\\/vendor/\\/apex\\/com.android.hardware.usb/' $(in) > $(out)",
+    cmd: "sed -E 's@/vendor/bin@/apex/com.android.hardware.usb/bin@' $(in) > $(out)",
 }
 
 prebuilt_etc {
diff --git a/usb/apex/com.android.hardware.usb.avbpubkey b/usb/apex/com.android.hardware.usb.avbpubkey
deleted file mode 100644
index 0302d63..0000000
--- a/usb/apex/com.android.hardware.usb.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/usb/apex/com.android.hardware.usb.pem b/usb/apex/com.android.hardware.usb.pem
deleted file mode 100644
index e1e57da..0000000
--- a/usb/apex/com.android.hardware.usb.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
diff --git a/usb/apex/com.android.hardware.usb.pk8 b/usb/apex/com.android.hardware.usb.pk8
deleted file mode 100644
index 9f3f39b..0000000
--- a/usb/apex/com.android.hardware.usb.pk8
+++ /dev/null
Binary files differ
diff --git a/usb/apex/com.android.hardware.usb.x509.pem b/usb/apex/com.android.hardware.usb.x509.pem
deleted file mode 100644
index 210c30d..0000000
--- a/usb/apex/com.android.hardware.usb.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF1TCCA70CFFEdsyLGoTRk+VIzqb6aDl1tXeuZMA0GCSqGSIb3DQEBCwUAMIGl
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEhMB8GA1UEAwwYY29t
-LmFuZHJvaWQuaGFyZHdhcmUudXNiMCAXDTIxMTExNzIyMzAwM1oYDzQ3NTkxMDE0
-MjIzMDAzWjCBpTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAU
-BgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0FuZHJvaWQxEDAOBgNVBAsM
-B0FuZHJvaWQxIjAgBgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5kcm9pZC5jb20xITAf
-BgNVBAMMGGNvbS5hbmRyb2lkLmhhcmR3YXJlLnVzYjCCAiIwDQYJKoZIhvcNAQEB
-BQADggIPADCCAgoCggIBAM2E0E9ubNU/or7r9UIcFrC4l7CeM0HwtwSjTUKV1Z9K
-7rPFoUPE3cQ+cResnWQay8IGnomLYptAIMe8sLCC83LwU1ucTihxX87qq2W3V14w
-U4AkqDzNvYqKiD3yz9WofKxcu7ut8+1O4Pvp11X8UXuy5kNzf8WGpGB04k6U6KtA
-q8+U8+4h9h1Uvhaa0AeG9Yp22LzRLTb3J+eCoGHJnjoXYsd9T/gvedyXKkuf0lWB
-b3Aor3/CQrpdCW2/iJbuASdBdfilpQShaagxy2wmQsYxnT8ZWf+tIDYjg3xqqVPl
-GChFwCQBdaTuLI/k9gbaXkSxuzRkp5wc/ELhYbkhIS25yefAF2C6num++AHQBh1+
-qO0fHztsK80c5cVoDPWu17/nP7y3QloRyLFUrL3hVW1RQaFwE2Hmv4H0UwVAsleU
-ZIsz2ifTjiSl/tnkFTx0I6BVk7T87QhO3WXN4v6VDYZKeD4gQYS0NfwplahejrFw
-s3EcwKgt6f0KlIpzoEQBmNQBXxsRgL31GWCwCszb7+VrTMzgUpO41R3PyewbeaZk
-S/SHyEOwyf0WIvnZhZ/5CNd9qirClu6jS8kdLvwC2qA25VqSPw126EX1e2xUqm02
-C/6c7JDVocuQhvsJOnnpZt68Iwgw9g/xLCLA9RszH9ccRctZqRnzHB1AjTrBOq0P
-AgMBAAEwDQYJKoZIhvcNAQELBQADggIBAELbSot2Io/JZIYLTxgeReI4lk1KUzf8
-fGlDNlRm+goxOHXWQgvXgiftwM9IOB+H+EtNHAA9Q6ojAmfRe6rZC4p0ZxWOamtR
-V+pQj0c6Zvx8HJPMQdyoHx538iNXM093s2wnf+QuACb3BnvkK7uuLGAlIzWdImtL
-DKKFN05nppViY04tGP5HgT57b7YGwdkEp6euCJcyWIKjlyEH/bwTWM8ws/Px6uhw
-+5W2K7KrBsdRKPBF7qwXoS8Ak8pS5de9Xd7mbGBLaUtjsZ0pJbq0aFpuT0GbLWUm
-wiD5Ljq3ea/2GZxbHGiXQ2yNjFSd/jpuxDnnm99t7+HGw1v5Jld+hUVqXXfVNhWe
-hUKIv5TOk1nttNdsaLyDtxyt22JX7NnoPM0MqrkYwA8Xqrbv0VC8D/CVjiBC9Tce
-crhpCISNfQSkdEn/c+q/naFUvQy8oYqXkg1TjeGlcxwJOpGliYbbYT6VAwuI/ssI
-yX3Fkr8f5KhfN2aFnOpidknmLp9EyL2j5bxAtSD9xAHtczMn10uCUdLELjRB1L4f
-1qY+EjpIgK0NIFuEt9K5uZXirXq3K3eixKeJFNji3x/X8NgDALSdnT8JIlSg4DMg
-iWupLrQ9CSHMlgh5P43ALamiRIHQNqEwgj8OIGzsvQTSLbRjbPWYcDZa+Q1hosiA
-Fv7vjDI6oySM
------END CERTIFICATE-----
diff --git a/vibrator/OWNERS b/vibrator/OWNERS
index 62a567e..c4de58a 100644
--- a/vibrator/OWNERS
+++ b/vibrator/OWNERS
@@ -1,8 +1,2 @@
 # Bug component: 345036
-
 include platform/frameworks/base:/services/core/java/com/android/server/vibrator/OWNERS
-
-chrispaulo@google.com
-michaelwr@google.com
-nathankulczak@google.com
-taikuo@google.com
diff --git a/vibrator/aidl/default/Android.bp b/vibrator/aidl/default/Android.bp
index 78bb4ed..fb71a82 100644
--- a/vibrator/aidl/default/Android.bp
+++ b/vibrator/aidl/default/Android.bp
@@ -32,9 +32,11 @@
     },
 }
 
-filegroup {
+prebuilt_etc {
     name: "android.hardware.vibrator.xml",
-    srcs: ["android.hardware.vibrator.xml"],
+    src: "android.hardware.vibrator.xml",
+    sub_dir: "vintf",
+    installable: false,
 }
 
 cc_binary {
diff --git a/vibrator/aidl/default/apex/Android.bp b/vibrator/aidl/default/apex/Android.bp
index 7949057..39626bf 100644
--- a/vibrator/aidl/default/apex/Android.bp
+++ b/vibrator/aidl/default/apex/Android.bp
@@ -2,17 +2,6 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-apex_key {
-    name: "com.android.hardware.vibrator.key",
-    public_key: "com.android.hardware.vibrator.avbpubkey",
-    private_key: "com.android.hardware.vibrator.pem",
-}
-
-android_app_certificate {
-    name: "com.android.hardware.vibrator.certificate",
-    certificate: "com.android.hardware.vibrator",
-}
-
 prebuilt_etc {
     name: "com.android.hardware.vibrator.rc",
     src: "com.android.hardware.vibrator.rc",
@@ -22,20 +11,19 @@
 apex {
     name: "com.android.hardware.vibrator",
     manifest: "apex_manifest.json",
-    key: "com.android.hardware.vibrator.key",
-    certificate: ":com.android.hardware.vibrator.certificate",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
     file_contexts: "file_contexts",
-    use_vndk_as_stable: true,
     updatable: false,
-    // Install the apex in /vendor/apex
-    soc_specific: true,
+    vendor: true,
+
     binaries: [
         "android.hardware.vibrator-service.example",
     ],
     prebuilts: [
         "com.android.hardware.vibrator.rc",
+        "android.hardware.vibrator.xml",
     ],
-    vintf_fragments: [":android.hardware.vibrator.xml"],
     // vibrator.default.so is not needed by the AIDL service binary.
     overrides: ["vibrator.default"],
 }
diff --git a/vibrator/aidl/default/apex/com.android.hardware.vibrator.avbpubkey b/vibrator/aidl/default/apex/com.android.hardware.vibrator.avbpubkey
deleted file mode 100644
index a6ca630..0000000
--- a/vibrator/aidl/default/apex/com.android.hardware.vibrator.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/vibrator/aidl/default/apex/com.android.hardware.vibrator.pem b/vibrator/aidl/default/apex/com.android.hardware.vibrator.pem
deleted file mode 100644
index c0f5c50..0000000
--- a/vibrator/aidl/default/apex/com.android.hardware.vibrator.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
diff --git a/vibrator/aidl/default/apex/com.android.hardware.vibrator.pk8 b/vibrator/aidl/default/apex/com.android.hardware.vibrator.pk8
deleted file mode 100644
index d20cc33..0000000
--- a/vibrator/aidl/default/apex/com.android.hardware.vibrator.pk8
+++ /dev/null
Binary files differ
diff --git a/vibrator/aidl/default/apex/com.android.hardware.vibrator.x509.pem b/vibrator/aidl/default/apex/com.android.hardware.vibrator.x509.pem
deleted file mode 100644
index 993245b..0000000
--- a/vibrator/aidl/default/apex/com.android.hardware.vibrator.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF3zCCA8cCFBJmLB9vGtl8nENMVa8g51Y2vRhPMA0GCSqGSIb3DQEBCwUAMIGq
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEmMCQGA1UEAwwdY29t
-LmFuZHJvaWQuaGFyZHdhcmUudmlicmF0b3IwIBcNMjEwOTE2MTcyOTA5WhgPNDc1
-OTA4MTMxNzI5MDlaMIGqMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5p
-YTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4G
-A1UECwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNv
-bTEmMCQGA1UEAwwdY29tLmFuZHJvaWQuaGFyZHdhcmUudmlicmF0b3IwggIiMA0G
-CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDV857uzUSXWQNWIuiNRwt1zd/eSB8P
-iVNq0qTexlZvamXr6h5VwX45iJeDVCxlx3uktXXP2NH7U01A5gl8Hix6iodNe3sJ
-fFIhzUiqdMfAn+6RWcJcb3v6J58D6R+htgtaSgv8WOLkIZyhbmU3NToc7dNe2j0U
-wh6xfYhpj/s0RManSTZW19C2H8g5eNfhEZgDT+KOUIgepv/x6Y5IR147JPh8Ha7g
-vxM87ceErSvr3e8uXDWUZtQ6IDfF2NkxJJGJos4IAteXbkG60q76V8pmWLCqIsMM
-tRcIpTEJUIbnbxAqSu+crZqQowu9HrJMYnqunlmXASeluxXdl8VKOVNMZHy3ipj7
-HjoTUJoiEVDLYeT7db76k2lDFH/JRtnoe3BBinUEKvGT3rOjy55C4E2DSMSM1Laz
-zkRcJ4hlzFQLXD5/iwWgW6me1lmnOEqFJZolc1fEc+VfEdZdwJmZF6Clm5av2hDm
-Oq09qL02nXy0OyAoCI6IcrrAlFFolgel32nWp1R7c+N2+6vLMP3KR50TgSiwHNNQ
-weZhpP1GrXDyVj+ilL5T/2ionvjIvDBgOi8B0IwiqeHY7lqsSyMOuKTi5WPrJ86E
-GNJ+PlivA/P9MAatem4kzCT2t3DbVC+dtybiUAmVFb2Ls+dVK4nHcbGTW9AuBijD
-COEHQgi4Xs6lnwIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQDGvq99QUxMh+DaI2Pd
-s4fQ9MmYxGDxULhjqgGAjDbL3jQMG2FxPTu1Z2VJgg4n+PTNsgsqgn1JgQM3gvFp
-8FKhoxtzM5V8pPxphCG7U/f3ZsmXdLl69sbVkMRhorhQ8H54q0O/T3Ig/ULZgblE
-xCRT1REB693tUQOCYgWgnsOpvySfujYhNBirl48Hw9zrRmQNTsO20dKwkZUvkVow
-/pawucYrHibgwgKWz8kB3Dl4DODiLybek0hGzr59Joul9eMsxTuQsHAIUv0KO2Ny
-5WT7GIX6qYc+VrnXsO+PHtx5GTUjrJiue3aggoW6X7gu3Z6KuIOiVTVLVp6wSJtt
-VHv90HTu2lYxtPyPSOpFfwFOTicN+5VmLTQwPvPRqsnCaYc+K2iWyEhN/PnSfFNc
-t/TX9HT3ljXq9yfshQmQJ27pdUiYs9Avt7fEXpJjQ0Tn9w8jRS5gsrnTUXTG6HXf
-I4lsMSAApFZa112PwU7xAIIaipBauuMjQCabD/thBzB6d29Rlbz3cjBzoky9h2vb
-XNIVo5O2Jiz7OJQ/7mubvJqIBngiaDK78n2hSdYglI1hgcf0KaQIJUridzmjt0kp
-xXcwIz7nJxhNpbsYnDnqwqz9en8a4N+KeoQleYROo2kEtE434AJkzdABV4IKRafj
-cbPWuY6F2faWAjkSOEhBfGOKOw==
------END CERTIFICATE-----
diff --git a/vibrator/aidl/default/apex/file_contexts b/vibrator/aidl/default/apex/file_contexts
index f811656..f061caa 100644
--- a/vibrator/aidl/default/apex/file_contexts
+++ b/vibrator/aidl/default/apex/file_contexts
@@ -1,3 +1,4 @@
-(/.*)? 							u:object_r:vendor_file:s0
-/bin/hw/android\.hardware\.vibrator-service\.example	u:object_r:hal_vibrator_default_exec:s0
+(/.*)?                                                  u:object_r:vendor_file:s0
+/etc(/.*)?                                              u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.vibrator-service\.example    u:object_r:hal_vibrator_default_exec:s0
 
diff --git a/wifi/apex/Android.bp b/wifi/apex/Android.bp
index f8ba5c4..f8c8e6f 100644
--- a/wifi/apex/Android.bp
+++ b/wifi/apex/Android.bp
@@ -2,17 +2,6 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-apex_key {
-    name: "com.android.hardware.wifi.key",
-    public_key: "com.android.hardware.wifi.avbpubkey",
-    private_key: "com.android.hardware.wifi.pem",
-}
-
-android_app_certificate {
-    name: "com.android.hardware.wifi.certificate",
-    certificate: "com.android.hardware.wifi",
-}
-
 genrule {
     name: "gen-android.hardware.wifi.rc",
     srcs: [":default-android.hardware.wifi-service.rc"],
@@ -36,12 +25,12 @@
 apex {
     name: "com.android.hardware.wifi",
     manifest: "apex_manifest.json",
-    key: "com.android.hardware.wifi.key",
-    certificate: ":com.android.hardware.wifi.certificate",
+    key: "com.android.hardware.key",
+    certificate: ":com.android.hardware.certificate",
     file_contexts: "file_contexts",
-    use_vndk_as_stable: true,
     updatable: false,
-    soc_specific: true,
+    vendor: true,
+
     binaries: [
         "android.hardware.wifi-service",
     ],
diff --git a/wifi/apex/com.android.hardware.wifi.avbpubkey b/wifi/apex/com.android.hardware.wifi.avbpubkey
deleted file mode 100644
index 63fba77..0000000
--- a/wifi/apex/com.android.hardware.wifi.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/wifi/apex/com.android.hardware.wifi.pem b/wifi/apex/com.android.hardware.wifi.pem
deleted file mode 100644
index 9e589ac..0000000
--- a/wifi/apex/com.android.hardware.wifi.pem
+++ /dev/null
@@ -1,52 +0,0 @@
------BEGIN PRIVATE KEY-----
-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
-etEvMk8bJ4u7X89NWW/i2J+kQiDQg819
------END PRIVATE KEY-----
diff --git a/wifi/apex/com.android.hardware.wifi.pk8 b/wifi/apex/com.android.hardware.wifi.pk8
deleted file mode 100644
index f4481bf..0000000
--- a/wifi/apex/com.android.hardware.wifi.pk8
+++ /dev/null
Binary files differ
diff --git a/wifi/apex/com.android.hardware.wifi.x509.pem b/wifi/apex/com.android.hardware.wifi.x509.pem
deleted file mode 100644
index c942e71..0000000
--- a/wifi/apex/com.android.hardware.wifi.x509.pem
+++ /dev/null
@@ -1,36 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIGOzCCBCOgAwIBAgIUIEueuBFEoCFmLyEvXDsKVuZeH0EwDQYJKoZIhvcNAQEL
-BQAwgasxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
-DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
-b2lkMScwJQYDVQQDDB5jb20uYW5kcm9pZC5oYXJkd2FyZS53aWZpLmFwZXgxIjAg
-BgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5kcm9pZC5jb20wIBcNMjIxMDA2MTY1MDQy
-WhgPNDc2MDA5MDExNjUwNDJaMIGrMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2Fs
-aWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9p
-ZDEQMA4GA1UECwwHQW5kcm9pZDEnMCUGA1UEAwweY29tLmFuZHJvaWQuaGFyZHdh
-cmUud2lmaS5hcGV4MSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29t
-MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAo4N23iL0J42qG2lt4ysD
-t6XxAKdi4sTWB6ZjFWerBm11s3yLr1KBZV82z3j2o7+EOaWa/91Mgc+aoiGYUa1f
-IweugKTrnRmrzOvtq/Wp5PGqSxsmLPPvH3wyEB/CMgAn0pqDf0WyCWJ2kAlcCkmy
-qVNFupkGFyIE6gkoc+AmJGbSTquDlL07R/8XYDicqrcgeqy9ZaCJ5FLfmbnnRb2A
-vm4Un7e5dFz5+dPaOJXf4AOMUSPUd7fuBliGYFLzcZnYQbzMktXa4XnPuSlmerwy
-EwY767L2bjRjaSgPb0Js13gZ4S4ZHZe07AV7HPlt/EzbxV/jtMgHl4xn5p0WhVnK
-MPtLsO/e7FkDPAKpT02sgUK6pVKqgBGOWm27tmTB09lscMLQeVFqwpoFq2zMUrDn
-ipDFMWRBeLrEDKx41zF3gqdPmP+SMkQYJu4OATIXOndIeo7AN9iE+N6snHkckNyE
-saCwmnzyhVAbMn/epfIQZz3zcyljA9yfOpv5jctN4es+3i0htDnoNO9ij4M5fxuP
-jtNAP3EA61nKZ5+Js0/MMQKrfwCLogPl/4vCNuuGT2rhCkhq1CLYXmb9ghvVzcPe
-BOGXNDKdB+aUTxrQUOYlHf0cRDHdU6cchrz9+QhR7t9dlibtiyCZE34xgR3klmyz
-XJ3M1r/QRihjARH7exrrwiUCAwEAAaNTMFEwHQYDVR0OBBYEFGN9tMk+4SDk7twk
-MrLjM+nRxGDJMB8GA1UdIwQYMBaAFGN9tMk+4SDk7twkMrLjM+nRxGDJMA8GA1Ud
-EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAHoTfVBRG0rVE7gkV526gwR5
-/3mXyYA57lKJhZ21fu2qfTE6WYj4DsOTZKrPIAUFv/SnzZ6Rvv7W81XV5M/1m+5R
-/1wYvWwm3FBOvvt4VDUiel0Zfc9+nwynjz1seYdXU8fNIOzBcr9hutkYdRZDkNpc
-Zcl4NG04TzyedkQ/0SyHnygmq4ZY9OUEvrNaWBFHzw2SQhYvHh8jUrqpPvoJz0Px
-avKI8bOgXTJRJ+Pk7hjXDFQY/fbE0RGivorPMLs+XHaEIb+YPyXsX4OZwowG5KL8
-txyvUsH+qZToytdPk4LCuwYBobBlr+AAg7pxOtbDW1ITDhQ9n05UFK2iUwsJecgg
-VDA0K3GuCjmGVmkw7SFRYfToCyGWah8sQCUMCCcsof7gS+dMxuWeee+sRxRJcJY+
-xR2uySe8g4ohwNjQ0zLQv7PZOKQh91yEWxRXmhPYVpiVAjpSD2zH7Vd6CJ9xji//
-5S1UrxWwQ5igvu8v5veqNAW7uXGXADnxL69HVGTLm0XDIUUOAUIG8waiVkYUo3UU
-AzAFbF7ewYMKdg7ylUYcTaMRIsKYW/3/1t3NJv2z99W4V/p8e1kRCeWMPB5C+/Lo
-b/hSWj1NF9AJ30ukBndMh6bRprq+G5NLV6OaoCLp606CMdXdT8uw9lYCt7DbQHG9
-Hw3iw61svpUwcaWfN1hI
------END CERTIFICATE-----