Merge "[UWB HAL] Use AsyncFd to read the buffer only when it's readable." into main
diff --git a/audio/aidl/default/Configuration.cpp b/audio/aidl/default/Configuration.cpp
index 85e4e24..635a25b 100644
--- a/audio/aidl/default/Configuration.cpp
+++ b/audio/aidl/default/Configuration.cpp
@@ -237,7 +237,7 @@
         c.ports.push_back(primaryOutMix);
 
         AudioPort primaryInMix =
-                createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(0, 0));
+                createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(0, 1));
         primaryInMix.profiles.push_back(
                 createProfile(PcmType::INT_16_BIT,
                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
@@ -252,14 +252,14 @@
         c.ports.push_back(telephonyTxOutMix);
 
         AudioPort telephonyRxInMix =
-                createPort(c.nextPortId++, "telephony_rx", 0, true, createPortMixExt(1, 1));
+                createPort(c.nextPortId++, "telephony_rx", 0, true, createPortMixExt(0, 1));
         telephonyRxInMix.profiles.insert(telephonyRxInMix.profiles.begin(),
                                          standardPcmAudioProfiles.begin(),
                                          standardPcmAudioProfiles.end());
         c.ports.push_back(telephonyRxInMix);
 
         AudioPort fmTunerInMix =
-                createPort(c.nextPortId++, "fm_tuner", 0, true, createPortMixExt(1, 1));
+                createPort(c.nextPortId++, "fm_tuner", 0, true, createPortMixExt(0, 1));
         fmTunerInMix.profiles.insert(fmTunerInMix.profiles.begin(),
                                      standardPcmAudioProfiles.begin(),
                                      standardPcmAudioProfiles.end());
@@ -441,7 +441,7 @@
         c.ports.push_back(usbDeviceOutMix);
 
         AudioPort usbDeviceInMix =
-                createPort(c.nextPortId++, "usb_device input", 0, true, createPortMixExt(1, 1));
+                createPort(c.nextPortId++, "usb_device input", 0, true, createPortMixExt(0, 1));
         c.ports.push_back(usbDeviceInMix);
 
         c.routes.push_back(createRoute({usbDeviceOutMix}, usbOutDevice));
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 3117134..76132b3 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -340,21 +340,43 @@
 
 ndk::ScopedAStatus Module::updateStreamsConnectedState(const AudioPatch& oldPatch,
                                                        const AudioPatch& newPatch) {
-    // Streams from the old patch need to be disconnected, streams from the new
-    // patch need to be connected. If the stream belongs to both patches, no need
-    // to update it.
+    // Notify streams about the new set of devices they are connected to.
     auto maybeFailure = ndk::ScopedAStatus::ok();
-    std::set<int32_t> idsToDisconnect, idsToConnect, idsToDisconnectOnFailure;
-    idsToDisconnect.insert(oldPatch.sourcePortConfigIds.begin(),
-                           oldPatch.sourcePortConfigIds.end());
-    idsToDisconnect.insert(oldPatch.sinkPortConfigIds.begin(), oldPatch.sinkPortConfigIds.end());
-    idsToConnect.insert(newPatch.sourcePortConfigIds.begin(), newPatch.sourcePortConfigIds.end());
-    idsToConnect.insert(newPatch.sinkPortConfigIds.begin(), newPatch.sinkPortConfigIds.end());
-    std::for_each(idsToDisconnect.begin(), idsToDisconnect.end(), [&](const auto& portConfigId) {
-        if (idsToConnect.count(portConfigId) == 0 && mStreams.count(portConfigId) != 0) {
-            if (auto status = mStreams.setStreamConnectedDevices(portConfigId, {}); status.isOk()) {
+    using Connections =
+            std::map<int32_t /*mixPortConfigId*/, std::set<int32_t /*devicePortConfigId*/>>;
+    Connections oldConnections, newConnections;
+    auto fillConnectionsHelper = [&](Connections& connections,
+                                     const std::vector<int32_t>& mixPortCfgIds,
+                                     const std::vector<int32_t>& devicePortCfgIds) {
+        for (int32_t mixPortCfgId : mixPortCfgIds) {
+            connections[mixPortCfgId].insert(devicePortCfgIds.begin(), devicePortCfgIds.end());
+        }
+    };
+    auto fillConnections = [&](Connections& connections, const AudioPatch& patch) {
+        if (std::find_if(patch.sourcePortConfigIds.begin(), patch.sourcePortConfigIds.end(),
+                         [&](int32_t portConfigId) { return mStreams.count(portConfigId) > 0; }) !=
+            patch.sourcePortConfigIds.end()) {
+            // Sources are mix ports.
+            fillConnectionsHelper(connections, patch.sourcePortConfigIds, patch.sinkPortConfigIds);
+        } else if (std::find_if(patch.sinkPortConfigIds.begin(), patch.sinkPortConfigIds.end(),
+                                [&](int32_t portConfigId) {
+                                    return mStreams.count(portConfigId) > 0;
+                                }) != patch.sinkPortConfigIds.end()) {
+            // Sources are device ports.
+            fillConnectionsHelper(connections, patch.sinkPortConfigIds, patch.sourcePortConfigIds);
+        }  // Otherwise, there are no streams to notify.
+    };
+    fillConnections(oldConnections, oldPatch);
+    fillConnections(newConnections, newPatch);
+
+    std::for_each(oldConnections.begin(), oldConnections.end(), [&](const auto& connectionPair) {
+        const int32_t mixPortConfigId = connectionPair.first;
+        if (auto it = newConnections.find(mixPortConfigId);
+            it == newConnections.end() || it->second != connectionPair.second) {
+            if (auto status = mStreams.setStreamConnectedDevices(mixPortConfigId, {});
+                status.isOk()) {
                 LOG(DEBUG) << "updateStreamsConnectedState: The stream on port config id "
-                           << portConfigId << " has been disconnected";
+                           << mixPortConfigId << " has been disconnected";
             } else {
                 // Disconnection is tricky to roll back, just register a failure.
                 maybeFailure = std::move(status);
@@ -362,23 +384,26 @@
         }
     });
     if (!maybeFailure.isOk()) return maybeFailure;
-    std::for_each(idsToConnect.begin(), idsToConnect.end(), [&](const auto& portConfigId) {
-        if (idsToDisconnect.count(portConfigId) == 0 && mStreams.count(portConfigId) != 0) {
-            const auto connectedDevices = findConnectedDevices(portConfigId);
+    std::set<int32_t> idsToDisconnectOnFailure;
+    std::for_each(newConnections.begin(), newConnections.end(), [&](const auto& connectionPair) {
+        const int32_t mixPortConfigId = connectionPair.first;
+        if (auto it = oldConnections.find(mixPortConfigId);
+            it == oldConnections.end() || it->second != connectionPair.second) {
+            const auto connectedDevices = findConnectedDevices(mixPortConfigId);
             if (connectedDevices.empty()) {
                 // This is important as workers use the vector size to derive the connection status.
                 LOG(FATAL) << "updateStreamsConnectedState: No connected devices found for port "
                               "config id "
-                           << portConfigId;
+                           << mixPortConfigId;
             }
-            if (auto status = mStreams.setStreamConnectedDevices(portConfigId, connectedDevices);
+            if (auto status = mStreams.setStreamConnectedDevices(mixPortConfigId, connectedDevices);
                 status.isOk()) {
                 LOG(DEBUG) << "updateStreamsConnectedState: The stream on port config id "
-                           << portConfigId << " has been connected to: "
+                           << mixPortConfigId << " has been connected to: "
                            << ::android::internal::ToString(connectedDevices);
             } else {
                 maybeFailure = std::move(status);
-                idsToDisconnectOnFailure.insert(portConfigId);
+                idsToDisconnectOnFailure.insert(mixPortConfigId);
             }
         }
     });
@@ -515,7 +540,7 @@
         }
     }
 
-    connectedPort.id = ++getConfig().nextPortId;
+    connectedPort.id = getConfig().nextPortId++;
     auto [connectedPortsIt, _] =
             mConnectedDevicePorts.insert(std::pair(connectedPort.id, std::set<int32_t>()));
     LOG(DEBUG) << __func__ << ": template port " << templateId << " external device connected, "
@@ -865,6 +890,7 @@
         patches.push_back(*_aidl_return);
     } else {
         oldPatch = *existing;
+        *existing = *_aidl_return;
     }
     patchesBackup = mPatches;
     registerPatch(*_aidl_return);
@@ -1277,6 +1303,12 @@
             mmapSources.insert(port.id);
         }
     }
+    if (mmapSources.empty() && mmapSinks.empty()) {
+        AudioMMapPolicyInfo never;
+        never.mmapPolicy = AudioMMapPolicy::NEVER;
+        _aidl_return->push_back(never);
+        return ndk::ScopedAStatus::ok();
+    }
     for (const auto& route : getConfig().routes) {
         if (mmapSinks.count(route.sinkPortId) != 0) {
             // The sink is a mix port, add the sources if they are device ports.
diff --git a/audio/aidl/default/alsa/ModuleAlsa.cpp b/audio/aidl/default/alsa/ModuleAlsa.cpp
index 8e75d56..8512631 100644
--- a/audio/aidl/default/alsa/ModuleAlsa.cpp
+++ b/audio/aidl/default/alsa/ModuleAlsa.cpp
@@ -39,13 +39,14 @@
     if (!deviceProfile.has_value()) {
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
-    auto profile = alsa::readAlsaDeviceInfo(*deviceProfile);
-    if (!profile.has_value()) {
+    auto proxy = alsa::readAlsaDeviceInfo(*deviceProfile);
+    if (proxy.get() == nullptr) {
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
     }
 
-    std::vector<AudioChannelLayout> channels = alsa::getChannelMasksFromProfile(&profile.value());
-    std::vector<int> sampleRates = alsa::getSampleRatesFromProfile(&profile.value());
+    alsa_device_profile* profile = proxy.getProfile();
+    std::vector<AudioChannelLayout> channels = alsa::getChannelMasksFromProfile(profile);
+    std::vector<int> sampleRates = alsa::getSampleRatesFromProfile(profile);
 
     for (size_t i = 0; i < std::min(MAX_PROFILE_FORMATS, AUDIO_PORT_MAX_AUDIO_PROFILES) &&
                        profile->formats[i] != PCM_FORMAT_INVALID;
diff --git a/audio/aidl/default/alsa/StreamAlsa.cpp b/audio/aidl/default/alsa/StreamAlsa.cpp
index 0605d6f..403b94b 100644
--- a/audio/aidl/default/alsa/StreamAlsa.cpp
+++ b/audio/aidl/default/alsa/StreamAlsa.cpp
@@ -83,7 +83,7 @@
             proxy = alsa::openProxyForAttachedDevice(
                     device, const_cast<struct pcm_config*>(&mConfig.value()), mBufferSizeFrames);
         }
-        if (!proxy) {
+        if (proxy.get() == nullptr) {
             return ::android::NO_INIT;
         }
         alsaDeviceProxies.push_back(std::move(proxy));
diff --git a/audio/aidl/default/alsa/Utils.cpp b/audio/aidl/default/alsa/Utils.cpp
index 9dcd024..c08836c 100644
--- a/audio/aidl/default/alsa/Utils.cpp
+++ b/audio/aidl/default/alsa/Utils.cpp
@@ -37,6 +37,23 @@
 
 namespace aidl::android::hardware::audio::core::alsa {
 
+DeviceProxy::DeviceProxy() : mProfile(nullptr), mProxy(nullptr, alsaProxyDeleter) {}
+
+DeviceProxy::DeviceProxy(const DeviceProfile& deviceProfile)
+    : mProfile(new alsa_device_profile), mProxy(new alsa_device_proxy, alsaProxyDeleter) {
+    profile_init(mProfile.get(), deviceProfile.direction);
+    mProfile->card = deviceProfile.card;
+    mProfile->device = deviceProfile.device;
+    memset(mProxy.get(), 0, sizeof(alsa_device_proxy));
+}
+
+void DeviceProxy::alsaProxyDeleter(alsa_device_proxy* proxy) {
+    if (proxy != nullptr) {
+        proxy_close(proxy);
+        delete proxy;
+    }
+}
+
 namespace {
 
 using AudioChannelCountToMaskMap = std::map<unsigned int, AudioChannelLayout>;
@@ -261,39 +278,24 @@
     return sampleRates;
 }
 
-DeviceProxy makeDeviceProxy() {
-    DeviceProxy proxy(new alsa_device_proxy, [](alsa_device_proxy* proxy) {
-        if (proxy != nullptr) {
-            proxy_close(proxy);
-            delete proxy;
-        }
-    });
-    memset(proxy.get(), 0, sizeof(alsa_device_proxy));
-    return proxy;
-}
-
 DeviceProxy openProxyForAttachedDevice(const DeviceProfile& deviceProfile,
                                        struct pcm_config* pcmConfig, size_t bufferFrameCount) {
     if (deviceProfile.isExternal) {
         LOG(FATAL) << __func__ << ": called for an external device, address=" << deviceProfile;
     }
-    alsa_device_profile profile;
-    profile_init(&profile, deviceProfile.direction);
-    profile.card = deviceProfile.card;
-    profile.device = deviceProfile.device;
-    if (!profile_fill_builtin_device_info(&profile, pcmConfig, bufferFrameCount)) {
+    DeviceProxy proxy(deviceProfile);
+    if (!profile_fill_builtin_device_info(proxy.getProfile(), pcmConfig, bufferFrameCount)) {
         LOG(FATAL) << __func__ << ": failed to init for built-in device, address=" << deviceProfile;
     }
-    auto proxy = makeDeviceProxy();
-    if (int err = proxy_prepare_from_default_config(proxy.get(), &profile); err != 0) {
+    if (int err = proxy_prepare_from_default_config(proxy.get(), proxy.getProfile()); err != 0) {
         LOG(FATAL) << __func__ << ": fail to prepare for device address=" << deviceProfile
                    << " error=" << err;
-        return nullptr;
+        return DeviceProxy();
     }
     if (int err = proxy_open(proxy.get()); err != 0) {
         LOG(ERROR) << __func__ << ": failed to open device, address=" << deviceProfile
                    << " error=" << err;
-        return nullptr;
+        return DeviceProxy();
     }
     return proxy;
 }
@@ -303,42 +305,36 @@
     if (!deviceProfile.isExternal) {
         LOG(FATAL) << __func__ << ": called for an attached device, address=" << deviceProfile;
     }
-    auto profile = readAlsaDeviceInfo(deviceProfile);
-    if (!profile.has_value()) {
-        LOG(ERROR) << __func__ << ": unable to read device info, device address=" << deviceProfile;
-        return nullptr;
+    auto proxy = readAlsaDeviceInfo(deviceProfile);
+    if (proxy.get() == nullptr) {
+        return proxy;
     }
-    auto proxy = makeDeviceProxy();
-    if (int err = proxy_prepare(proxy.get(), &profile.value(), pcmConfig, requireExactMatch);
+    if (int err = proxy_prepare(proxy.get(), proxy.getProfile(), pcmConfig, requireExactMatch);
         err != 0) {
         LOG(ERROR) << __func__ << ": fail to prepare for device address=" << deviceProfile
                    << " error=" << err;
-        return nullptr;
+        return DeviceProxy();
     }
     if (int err = proxy_open(proxy.get()); err != 0) {
         LOG(ERROR) << __func__ << ": failed to open device, address=" << deviceProfile
                    << " error=" << err;
-        return nullptr;
+        return DeviceProxy();
     }
     return proxy;
 }
 
-std::optional<alsa_device_profile> readAlsaDeviceInfo(const DeviceProfile& deviceProfile) {
-    alsa_device_profile profile;
-    profile_init(&profile, deviceProfile.direction);
-    profile.card = deviceProfile.card;
-    profile.device = deviceProfile.device;
-    if (!profile_read_device_info(&profile)) {
-        LOG(ERROR) << __func__ << ": failed to read device info, card=" << profile.card
-                   << ", device=" << profile.device;
-        return std::nullopt;
+DeviceProxy readAlsaDeviceInfo(const DeviceProfile& deviceProfile) {
+    DeviceProxy proxy(deviceProfile);
+    if (!profile_read_device_info(proxy.getProfile())) {
+        LOG(ERROR) << __func__ << ": unable to read device info, device address=" << deviceProfile;
+        return DeviceProxy();
     }
-    return profile;
+    return proxy;
 }
 
 void resetTransferredFrames(DeviceProxy& proxy, uint64_t frames) {
-    if (proxy != nullptr) {
-        proxy->transferred = frames;
+    if (proxy.get() != nullptr) {
+        proxy.get()->transferred = frames;
     }
 }
 
diff --git a/audio/aidl/default/alsa/Utils.h b/audio/aidl/default/alsa/Utils.h
index 37414b3..980f685 100644
--- a/audio/aidl/default/alsa/Utils.h
+++ b/audio/aidl/default/alsa/Utils.h
@@ -43,8 +43,21 @@
     bool isExternal;
 };
 std::ostream& operator<<(std::ostream& os, const DeviceProfile& device);
-using DeviceProxyDeleter = std::function<void(alsa_device_proxy*)>;
-using DeviceProxy = std::unique_ptr<alsa_device_proxy, DeviceProxyDeleter>;
+
+class DeviceProxy {
+  public:
+    DeviceProxy();  // Constructs a "null" proxy.
+    explicit DeviceProxy(const DeviceProfile& deviceProfile);
+    alsa_device_profile* getProfile() { return mProfile.get(); }
+    alsa_device_proxy* get() { return mProxy.get(); }
+
+  private:
+    static void alsaProxyDeleter(alsa_device_proxy* proxy);
+    using AlsaProxy = std::unique_ptr<alsa_device_proxy, decltype(alsaProxyDeleter)*>;
+
+    std::unique_ptr<alsa_device_profile> mProfile;
+    AlsaProxy mProxy;
+};
 
 ::aidl::android::media::audio::common::AudioChannelLayout getChannelLayoutMaskFromChannelCount(
         unsigned int channelCount, int isInput);
@@ -60,12 +73,11 @@
         const ::aidl::android::media::audio::common::AudioPort& audioPort);
 std::optional<struct pcm_config> getPcmConfig(const StreamContext& context, bool isInput);
 std::vector<int> getSampleRatesFromProfile(const alsa_device_profile* profile);
-DeviceProxy makeDeviceProxy();
 DeviceProxy openProxyForAttachedDevice(const DeviceProfile& deviceProfile,
                                        struct pcm_config* pcmConfig, size_t bufferFrameCount);
 DeviceProxy openProxyForExternalDevice(const DeviceProfile& deviceProfile,
                                        struct pcm_config* pcmConfig, bool requireExactMatch);
-std::optional<alsa_device_profile> readAlsaDeviceInfo(const DeviceProfile& deviceProfile);
+DeviceProxy readAlsaDeviceInfo(const DeviceProfile& deviceProfile);
 void resetTransferredFrames(DeviceProxy& proxy, uint64_t frames);
 
 ::aidl::android::media::audio::common::AudioFormatDescription
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index cd765d2..04c827b 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -87,6 +87,7 @@
 using aidl::android::media::audio::common::AudioFormatType;
 using aidl::android::media::audio::common::AudioIoFlags;
 using aidl::android::media::audio::common::AudioLatencyMode;
+using aidl::android::media::audio::common::AudioMMapPolicy;
 using aidl::android::media::audio::common::AudioMMapPolicyInfo;
 using aidl::android::media::audio::common::AudioMMapPolicyType;
 using aidl::android::media::audio::common::AudioMode;
@@ -1237,11 +1238,25 @@
                    const AudioPortConfig& portConfig2)
         : mSrcPortConfig(sinkIsCfg1 ? portConfig2 : portConfig1),
           mSinkPortConfig(sinkIsCfg1 ? portConfig1 : portConfig2) {}
+    WithAudioPatch(const WithAudioPatch& patch, const AudioPortConfig& srcPortConfig,
+                   const AudioPortConfig& sinkPortConfig)
+        : mInitialPatch(patch.mPatch),
+          mSrcPortConfig(srcPortConfig),
+          mSinkPortConfig(sinkPortConfig),
+          mModule(patch.mModule),
+          mPatch(patch.mPatch) {}
     WithAudioPatch(const WithAudioPatch&) = delete;
     WithAudioPatch& operator=(const WithAudioPatch&) = delete;
     ~WithAudioPatch() {
         if (mModule != nullptr && mPatch.id != 0) {
-            EXPECT_IS_OK(mModule->resetAudioPatch(mPatch.id)) << "patch id " << getId();
+            if (mInitialPatch.has_value()) {
+                AudioPatch ignored;
+                // This releases our port configs so that they can be reset.
+                EXPECT_IS_OK(mModule->setAudioPatch(*mInitialPatch, &ignored))
+                        << "patch id " << mInitialPatch->id;
+            } else {
+                EXPECT_IS_OK(mModule->resetAudioPatch(mPatch.id)) << "patch id " << getId();
+            }
         }
     }
     void SetUpPortConfigs(IModule* module) {
@@ -1263,6 +1278,16 @@
             EXPECT_GT(latencyMs, 0) << "patch id " << getId();
         }
     }
+    void VerifyAgainstAllPatches(IModule* module) {
+        std::vector<AudioPatch> allPatches;
+        ASSERT_IS_OK(module->getAudioPatches(&allPatches));
+        const auto& patchIt = findById(allPatches, getId());
+        ASSERT_NE(patchIt, allPatches.end()) << "patch id " << getId();
+        if (get() != *patchIt) {
+            FAIL() << "Stored patch: " << get().toString() << " is not the same as returned "
+                   << "by the HAL module: " << patchIt->toString();
+        }
+    }
     int32_t getId() const { return mPatch.id; }
     const AudioPatch& get() const { return mPatch; }
     const AudioPortConfig& getSinkPortConfig() const { return mSinkPortConfig.get(); }
@@ -1272,6 +1297,7 @@
     }
 
   private:
+    std::optional<AudioPatch> mInitialPatch;
     WithAudioPortConfig mSrcPortConfig;
     WithAudioPortConfig mSinkPortConfig;
     IModule* mModule = nullptr;
@@ -2133,7 +2159,13 @@
         std::vector<AudioMMapPolicyInfo> policyInfos;
         EXPECT_IS_OK(module->getMmapPolicyInfos(mmapPolicyType, &policyInfos))
                 << toString(mmapPolicyType);
-        EXPECT_EQ(isMmapSupported, !policyInfos.empty());
+        const bool isMMapSupportedByPolicyInfos =
+                std::find_if(policyInfos.begin(), policyInfos.end(), [](const auto& info) {
+                    return info.mmapPolicy == AudioMMapPolicy::AUTO ||
+                           info.mmapPolicy == AudioMMapPolicy::ALWAYS;
+                }) != policyInfos.end();
+        EXPECT_EQ(isMmapSupported, isMMapSupportedByPolicyInfos)
+                << ::android::internal::ToString(policyInfos);
     }
 }
 
@@ -3630,9 +3662,12 @@
                     patches.push_back(
                             std::make_unique<WithAudioPatch>(srcSink.first, srcSink.second));
                     EXPECT_NO_FATAL_FAILURE(patches[patches.size() - 1]->SetUp(module.get()));
+                    EXPECT_NO_FATAL_FAILURE(
+                            patches[patches.size() - 1]->VerifyAgainstAllPatches(module.get()));
                 } else {
                     WithAudioPatch patch(srcSink.first, srcSink.second);
                     EXPECT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
+                    EXPECT_NO_FATAL_FAILURE(patch.VerifyAgainstAllPatches(module.get()));
                 }
             }
         }
@@ -3653,6 +3688,29 @@
         }
     }
 
+    void UpdatePatchPorts(bool isInput) {
+        auto srcSinkGroups = moduleConfig->getRoutableSrcSinkGroups(isInput);
+        if (srcSinkGroups.empty()) {
+            GTEST_SKIP() << "No routes to any attached " << direction(isInput, false) << " devices";
+        }
+        bool hasAtLeastOnePair = false;
+        for (const auto& srcSinkGroup : srcSinkGroups) {
+            const auto& srcSinks = srcSinkGroup.second;
+            if (srcSinks.size() < 2) continue;
+            hasAtLeastOnePair = true;
+            const auto& pair1 = srcSinks[0];
+            const auto& pair2 = srcSinks[1];
+            WithAudioPatch patch(pair1.first, pair1.second);
+            ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
+            WithAudioPatch update(patch, pair2.first, pair2.second);
+            EXPECT_NO_FATAL_FAILURE(update.SetUp(module.get()));
+            EXPECT_NO_FATAL_FAILURE(update.VerifyAgainstAllPatches(module.get()));
+        }
+        if (!hasAtLeastOnePair) {
+            GTEST_SKIP() << "No routes with multiple sources";
+        }
+    }
+
     void UpdateInvalidPatchId(bool isInput) {
         auto srcSinkGroups = moduleConfig->getRoutableSrcSinkGroups(isInput);
         if (srcSinkGroups.empty()) {
@@ -3692,6 +3750,7 @@
 TEST_PATCH_BOTH_DIRECTIONS(SetPatch);
 TEST_PATCH_BOTH_DIRECTIONS(UpdateInvalidPatchId);
 TEST_PATCH_BOTH_DIRECTIONS(UpdatePatch);
+TEST_PATCH_BOTH_DIRECTIONS(UpdatePatchPorts);
 
 TEST_P(AudioModulePatch, ResetInvalidPatchId) {
     std::set<int32_t> patchIds;
@@ -4167,58 +4226,32 @@
 class WithRemoteSubmix {
   public:
     WithRemoteSubmix() = default;
-    WithRemoteSubmix(AudioDeviceAddress address) : mAddress(address) {}
+    explicit WithRemoteSubmix(AudioDeviceAddress address) : mAddress(address) {}
     WithRemoteSubmix(const WithRemoteSubmix&) = delete;
     WithRemoteSubmix& operator=(const WithRemoteSubmix&) = delete;
-    std::optional<AudioPort> getAudioPort() {
+    static std::optional<AudioPort> getRemoteSubmixAudioPort(
+            ModuleConfig* moduleConfig,
+            const std::optional<AudioDeviceAddress>& address = std::nullopt) {
         AudioDeviceType deviceType = IOTraits<Stream>::is_input ? AudioDeviceType::IN_SUBMIX
                                                                 : AudioDeviceType::OUT_SUBMIX;
-        auto ports = mModuleConfig->getAudioPortsForDeviceTypes(
+        auto ports = moduleConfig->getAudioPortsForDeviceTypes(
                 std::vector<AudioDeviceType>{deviceType},
                 AudioDeviceDescription::CONNECTION_VIRTUAL);
-        if (!ports.empty()) return ports.front();
-        return {};
-    }
-    /* Connect remote submix external device */
-    void SetUpPortConnection() {
-        auto port = getAudioPort();
-        ASSERT_TRUE(port.has_value()) << "Device AudioPort for remote submix not found";
-        if (mAddress.has_value()) {
-            port.value().ext.template get<AudioPortExt::Tag::device>().device.address =
-                    mAddress.value();
+        if (ports.empty()) return {};
+        AudioPort port = ports.front();
+        if (address) {
+            port.ext.template get<AudioPortExt::Tag::device>().device.address = address.value();
         } else {
-            port = GenerateUniqueDeviceAddress(port.value());
+            port = GenerateUniqueDeviceAddress(port);
         }
-        mConnectedPort = std::make_unique<WithDevicePortConnectedState>(port.value());
-        ASSERT_NO_FATAL_FAILURE(mConnectedPort->SetUp(mModule, mModuleConfig));
+        return port;
     }
-    AudioDeviceAddress getAudioDeviceAddress() {
-        if (!mAddress.has_value()) {
-            mAddress = mConnectedPort->get()
-                               .ext.template get<AudioPortExt::Tag::device>()
-                               .device.address;
-        }
-        return mAddress.value();
-    }
-    /* Get mix port config for stream and setup patch for it. */
-    void SetupPatch() {
-        const auto portConfig =
-                mModuleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
-        if (!portConfig.has_value()) {
-            LOG(DEBUG) << __func__ << ": portConfig not found";
-            mSkipTest = true;
-            return;
-        }
-        auto devicePortConfig = mModuleConfig->getSingleConfigForDevicePort(mConnectedPort->get());
-        mPatch = std::make_unique<WithAudioPatch>(IOTraits<Stream>::is_input, portConfig.value(),
-                                                  devicePortConfig);
-        ASSERT_NO_FATAL_FAILURE(mPatch->SetUp(mModule));
-    }
-    void SetUp(IModule* module, ModuleConfig* moduleConfig) {
+    std::optional<AudioDeviceAddress> getAudioDeviceAddress() const { return mAddress; }
+    void SetUp(IModule* module, ModuleConfig* moduleConfig, const AudioPort& connectedPort) {
         mModule = module;
         mModuleConfig = moduleConfig;
-        ASSERT_NO_FATAL_FAILURE(SetUpPortConnection());
-        ASSERT_NO_FATAL_FAILURE(SetupPatch());
+
+        ASSERT_NO_FATAL_FAILURE(SetupPatch(connectedPort));
         if (!mSkipTest) {
             // open stream
             mStream = std::make_unique<WithStream<Stream>>(
@@ -4226,6 +4259,11 @@
             ASSERT_NO_FATAL_FAILURE(
                     mStream->SetUp(mModule, AudioCoreModuleBase::kDefaultBufferSizeFrames));
         }
+        mAddress = connectedPort.ext.template get<AudioPortExt::Tag::device>().device.address;
+    }
+    void SetUp(IModule* module, ModuleConfig* moduleConfig) {
+        ASSERT_NO_FATAL_FAILURE(SetUpPortConnection(module, moduleConfig));
+        SetUp(module, moduleConfig, mConnectedPort->get());
     }
     void sendBurstCommands() {
         const StreamContext* context = mStream->getContext();
@@ -4243,9 +4281,31 @@
         }
         EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
     }
-    bool skipTest() { return mSkipTest; }
+    bool skipTest() const { return mSkipTest; }
 
   private:
+    /* Connect remote submix external device */
+    void SetUpPortConnection(IModule* module, ModuleConfig* moduleConfig) {
+        auto port = getRemoteSubmixAudioPort(moduleConfig, mAddress);
+        ASSERT_TRUE(port.has_value()) << "Device AudioPort for remote submix not found";
+        mConnectedPort = std::make_unique<WithDevicePortConnectedState>(port.value());
+        ASSERT_NO_FATAL_FAILURE(mConnectedPort->SetUp(module, moduleConfig));
+    }
+    /* Get mix port config for stream and setup patch for it. */
+    void SetupPatch(const AudioPort& connectedPort) {
+        const auto portConfig =
+                mModuleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
+        if (!portConfig.has_value()) {
+            LOG(DEBUG) << __func__ << ": portConfig not found";
+            mSkipTest = true;
+            return;
+        }
+        auto devicePortConfig = mModuleConfig->getSingleConfigForDevicePort(connectedPort);
+        mPatch = std::make_unique<WithAudioPatch>(IOTraits<Stream>::is_input, portConfig.value(),
+                                                  devicePortConfig);
+        ASSERT_NO_FATAL_FAILURE(mPatch->SetUp(mModule));
+    }
+
     bool mSkipTest = false;
     IModule* mModule = nullptr;
     ModuleConfig* mModuleConfig = nullptr;
@@ -4283,9 +4343,11 @@
     if (streamOut.skipTest()) {
         GTEST_SKIP() << "No mix port for attached devices";
     }
+    auto address = streamOut.getAudioDeviceAddress();
+    ASSERT_TRUE(address.has_value());
 
     // open input stream
-    WithRemoteSubmix<IStreamIn> streamIn(streamOut.getAudioDeviceAddress());
+    WithRemoteSubmix<IStreamIn> streamIn(address.value());
     ASSERT_NO_FATAL_FAILURE(streamIn.SetUp(module.get(), moduleConfig.get()));
     if (streamIn.skipTest()) {
         GTEST_SKIP() << "No mix port for attached devices";
@@ -4302,9 +4364,11 @@
     if (streamOut.skipTest()) {
         GTEST_SKIP() << "No mix port for attached devices";
     }
+    auto address = streamOut.getAudioDeviceAddress();
+    ASSERT_TRUE(address.has_value());
 
     // open input stream
-    WithRemoteSubmix<IStreamIn> streamIn(streamOut.getAudioDeviceAddress());
+    WithRemoteSubmix<IStreamIn> streamIn(address.value());
     ASSERT_NO_FATAL_FAILURE(streamIn.SetUp(module.get(), moduleConfig.get()));
     if (streamIn.skipTest()) {
         GTEST_SKIP() << "No mix port for attached devices";
@@ -4316,6 +4380,43 @@
     ASSERT_NO_FATAL_FAILURE(streamIn.sendBurstCommands());
 }
 
+TEST_P(AudioModuleRemoteSubmix, OpenInputMultipleTimes) {
+    // open output stream
+    WithRemoteSubmix<IStreamOut> streamOut;
+    ASSERT_NO_FATAL_FAILURE(streamOut.SetUp(module.get(), moduleConfig.get()));
+    if (streamOut.skipTest()) {
+        GTEST_SKIP() << "No mix port for attached devices";
+    }
+    auto address = streamOut.getAudioDeviceAddress();
+    ASSERT_TRUE(address.has_value());
+
+    // connect remote submix input device port
+    auto port = WithRemoteSubmix<IStreamIn>::getRemoteSubmixAudioPort(moduleConfig.get(),
+                                                                      address.value());
+    ASSERT_TRUE(port.has_value()) << "Device AudioPort for remote submix not found";
+    WithDevicePortConnectedState connectedInputPort(port.value());
+    ASSERT_NO_FATAL_FAILURE(connectedInputPort.SetUp(module.get(), moduleConfig.get()));
+
+    // open input streams
+    const int streamInCount = 3;
+    std::vector<std::unique_ptr<WithRemoteSubmix<IStreamIn>>> streamIns(streamInCount);
+    for (int i = 0; i < streamInCount; i++) {
+        streamIns[i] = std::make_unique<WithRemoteSubmix<IStreamIn>>();
+        ASSERT_NO_FATAL_FAILURE(
+                streamIns[i]->SetUp(module.get(), moduleConfig.get(), connectedInputPort.get()));
+        if (streamIns[i]->skipTest()) {
+            GTEST_SKIP() << "No mix port for attached devices";
+        }
+    }
+    // write something to output stream
+    ASSERT_NO_FATAL_FAILURE(streamOut.sendBurstCommands());
+
+    // read from input streams
+    for (int i = 0; i < streamInCount; i++) {
+        ASSERT_NO_FATAL_FAILURE(streamIns[i]->sendBurstCommands());
+    }
+}
+
 INSTANTIATE_TEST_SUITE_P(AudioModuleRemoteSubmixTest, AudioModuleRemoteSubmix,
                          ::testing::ValuesIn(getRemoteSubmixModuleInstance()));
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioModuleRemoteSubmix);
diff --git a/automotive/sv/1.0/default/tests/fuzzer/AutomotiveSvV1_0Fuzzer.cpp b/automotive/sv/1.0/default/tests/fuzzer/AutomotiveSvV1_0Fuzzer.cpp
index 98834f5..4c4cc70 100644
--- a/automotive/sv/1.0/default/tests/fuzzer/AutomotiveSvV1_0Fuzzer.cpp
+++ b/automotive/sv/1.0/default/tests/fuzzer/AutomotiveSvV1_0Fuzzer.cpp
@@ -41,35 +41,32 @@
 
 void SurroundViewFuzzer::invoke2dSessionAPI() {
     sp<ISurroundView2dSession> surroundView2dSession;
+    sp<SurroundViewStream> handler;
+    mSurroundViewService->start2dSession(
+            [&surroundView2dSession](const sp<ISurroundView2dSession>& session, SvResult result) {
+                if (result == SvResult::OK) {
+                    surroundView2dSession = session;
+                }
+            });
+
+    if (surroundView2dSession && !mIs2dStreamStarted) {
+        handler = sp<SurroundViewStream>::make(surroundView2dSession);
+        if (surroundView2dSession->startStream(handler) == SvResult::OK) {
+            mIs2dStreamStarted = true;
+        }
+    }
 
     while (mFuzzedDataProvider.remaining_bytes() > 0) {
         auto surroundView2dFunc = mFuzzedDataProvider.PickValueInArray<
                 const std::function<void()>>({
                 [&]() {
-                    mSurroundViewService->start2dSession(
-                            [&surroundView2dSession](const sp<ISurroundView2dSession>& session,
-                                                     SvResult result) {
-                                if (result == SvResult::OK) {
-                                    surroundView2dSession = session;
-                                }
-                            });
-                },
-                [&]() {
-                    if (surroundView2dSession) {
-                        sp<SurroundViewStream> handler =
-                                sp<SurroundViewStream>::make(surroundView2dSession);
-                        surroundView2dSession->startStream(handler);
-                        mIs2dStreamStarted = true;
-                    }
-                },
-                [&]() {
                     if (surroundView2dSession) {
                         surroundView2dSession->get2dMappingInfo(
                                 []([[maybe_unused]] Sv2dMappingInfo info) {});
                     }
                 },
                 [&]() {
-                    if (surroundView2dSession) {
+                    if (surroundView2dSession && mIs2dStreamStarted) {
                         Sv2dConfig config;
                         config.width = mFuzzedDataProvider.ConsumeIntegralInRange<uint32_t>(
                                 kMinConfigDimension, kMaxConfigDimension);
@@ -149,8 +146,11 @@
                     }
                 },
                 [&]() {
-                    mSurroundViewService->stop2dSession(
+                    SvResult result = mSurroundViewService->stop2dSession(
                             mFuzzedDataProvider.ConsumeBool() ? surroundView2dSession : nullptr);
+                    if (result == SvResult::OK) {
+                        mIs2dStreamStarted = false;
+                    }
                 },
         });
         surroundView2dFunc();
@@ -159,31 +159,40 @@
     if (surroundView2dSession && mIs2dStreamStarted) {
         surroundView2dSession->stopStream();
     }
+
+    if (surroundView2dSession) {
+        mSurroundViewService->stop2dSession(surroundView2dSession);
+    }
 }
 
 void SurroundViewFuzzer::invoke3dSessionAPI() {
     sp<ISurroundView3dSession> surroundView3dSession;
+    sp<SurroundViewStream> handler;
+    mSurroundViewService->start3dSession(
+            [&surroundView3dSession](const sp<ISurroundView3dSession>& session, SvResult result) {
+                if (result == SvResult::OK) {
+                    surroundView3dSession = session;
+                }
+            });
+
+    const size_t numViews = mFuzzedDataProvider.ConsumeIntegralInRange<size_t>(1, kMaxViews);
+    std::vector<View3d> views(numViews);
+    for (size_t i = 0; i < numViews; ++i) {
+        views[i].viewId = mFuzzedDataProvider.ConsumeIntegral<uint32_t>();
+    }
+    surroundView3dSession->setViews(views);
+
+    if (surroundView3dSession) {
+        handler = sp<SurroundViewStream>::make(surroundView3dSession);
+
+        if (surroundView3dSession->startStream(handler) == SvResult::OK) {
+            mIs3dStreamStarted = true;
+        }
+    }
     while (mFuzzedDataProvider.remaining_bytes() > 0) {
         auto surroundView3dFunc = mFuzzedDataProvider.PickValueInArray<
                 const std::function<void()>>({
                 [&]() {
-                    mSurroundViewService->start3dSession(
-                            [&surroundView3dSession](const sp<ISurroundView3dSession>& session,
-                                                     SvResult result) {
-                                if (result == SvResult::OK) {
-                                    surroundView3dSession = session;
-                                }
-                            });
-                },
-                [&]() {
-                    if (surroundView3dSession) {
-                        sp<SurroundViewStream> handler =
-                                sp<SurroundViewStream>::make(surroundView3dSession);
-                        surroundView3dSession->startStream(handler);
-                        mIs3dStreamStarted = true;
-                    }
-                },
-                [&]() {
                     if (surroundView3dSession) {
                         const size_t numViews =
                                 mFuzzedDataProvider.ConsumeIntegralInRange<size_t>(1, kMaxViews);
@@ -195,7 +204,7 @@
                     }
                 },
                 [&]() {
-                    if (surroundView3dSession) {
+                    if (surroundView3dSession && mIs3dStreamStarted) {
                         Sv3dConfig config;
                         config.width = mFuzzedDataProvider.ConsumeIntegralInRange<uint32_t>(
                                 kMinConfigDimension, kMaxConfigDimension);
@@ -306,8 +315,11 @@
                     }
                 },
                 [&]() {
-                    mSurroundViewService->stop3dSession(
+                    SvResult result = mSurroundViewService->stop3dSession(
                             mFuzzedDataProvider.ConsumeBool() ? surroundView3dSession : nullptr);
+                    if (result == SvResult::OK) {
+                        mIs3dStreamStarted = false;
+                    }
                 },
         });
         surroundView3dFunc();
@@ -315,6 +327,10 @@
     if (surroundView3dSession && mIs3dStreamStarted) {
         surroundView3dSession->stopStream();
     }
+
+    if (surroundView3dSession) {
+        mSurroundViewService->stop3dSession(surroundView3dSession);
+    }
 }
 
 void SurroundViewFuzzer::process() {
diff --git a/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.cpp b/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.cpp
index 796c08f..8a085e5 100644
--- a/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.cpp
+++ b/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.cpp
@@ -161,10 +161,13 @@
     hidl_string debugOption = mFuzzedDataProvider->PickValueInArray(
             {"--help", "--list", "--get", "--set", "", "invalid"});
     hidl_handle fd = {};
-    fd.setTo(native_handle_create(/*numFds=*/1, /*numInts=*/0), /*shouldOwn=*/true);
+
+    native_handle_t* rawHandle = native_handle_create(/*numFds=*/1, /*numInts=*/0);
+    fd.setTo(native_handle_clone(rawHandle), /*shouldOwn=*/true);
 
     mManager->debug(fd, {});
     mManager->debug(fd, {debugOption});
+    native_handle_delete(rawHandle);
 }
 
 void VehicleHalManagerFuzzer::invokePropConfigs() {
diff --git a/automotive/vehicle/OWNERS b/automotive/vehicle/OWNERS
index 429ec39..d6969e5 100644
--- a/automotive/vehicle/OWNERS
+++ b/automotive/vehicle/OWNERS
@@ -1,3 +1,2 @@
 ericjeong@google.com
-keunyoung@google.com
 shanyu@google.com
diff --git a/boot/1.1/default/Android.bp b/boot/1.1/default/Android.bp
index e7a8d6e..0b0a5b7 100644
--- a/boot/1.1/default/Android.bp
+++ b/boot/1.1/default/Android.bp
@@ -20,7 +20,6 @@
     srcs: ["BootControl.cpp"],
 
     shared_libs: [
-        "libbase",
         "liblog",
         "libhidlbase",
         "libhardware",
diff --git a/boot/1.1/default/boot_control/Android.bp b/boot/1.1/default/boot_control/Android.bp
index d0dcb59..6aa30c2 100644
--- a/boot/1.1/default/boot_control/Android.bp
+++ b/boot/1.1/default/boot_control/Android.bp
@@ -35,13 +35,14 @@
     ],
 
     shared_libs: [
+        "android.hardware.boot@1.1",
+        "libbase",
         "liblog",
     ],
     static_libs: [
         "libbootloader_message",
         "libfstab",
     ],
-
 }
 
 cc_library_static {
@@ -51,13 +52,7 @@
     recovery_available: true,
     vendor_available: true,
 
-    srcs: [
-        "libboot_control.cpp",
-    ],
-    static_libs: [
-        "android.hardware.boot@1.1",
-        "libbase",
-    ],
+    srcs: ["libboot_control.cpp"],
 }
 
 cc_library_shared {
@@ -72,8 +67,6 @@
         "libboot_control",
     ],
     shared_libs: [
-        "android.hardware.boot@1.1",
-        "libbase",
         "libhardware",
     ],
 }
diff --git a/boot/1.2/default/Android.bp b/boot/1.2/default/Android.bp
index f1e9c34..4e1c35e 100644
--- a/boot/1.2/default/Android.bp
+++ b/boot/1.2/default/Android.bp
@@ -20,7 +20,6 @@
     srcs: ["BootControl.cpp"],
 
     shared_libs: [
-        "libbase",
         "liblog",
         "libhidlbase",
         "libhardware",
diff --git a/boot/aidl/default/Android.bp b/boot/aidl/default/Android.bp
index c1d3c57..dcb40db 100644
--- a/boot/aidl/default/Android.bp
+++ b/boot/aidl/default/Android.bp
@@ -27,77 +27,29 @@
     name: "android.hardware.boot-service_common",
     relative_install_path: "hw",
     defaults: ["libboot_control_defaults"],
-    srcs: [
-        "main.cpp",
-        "BootControl.cpp",
+    vintf_fragments: ["android.hardware.boot-service.default.xml"],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "android.hardware.boot@1.1",
+        "android.hardware.boot-V1-ndk",
     ],
+    static_libs: [
+        "libboot_control",
+    ],
+    srcs: ["main.cpp", "BootControl.cpp"],
 }
 
 cc_binary {
     name: "android.hardware.boot-service.default",
     defaults: ["android.hardware.boot-service_common"],
+    init_rc: ["android.hardware.boot-service.default.rc"],
     vendor: true,
-
-    stl: "c++_static",
-    shared_libs: [
-        "libbinder_ndk",
-        "liblog",
-    ],
-    static_libs: [
-        "android.hardware.boot@1.1",
-        "android.hardware.boot-V1-ndk",
-        "libbase",
-        "libboot_control",
-    ],
-
-    installable: false, // installed in APEX
 }
 
 cc_binary {
     name: "android.hardware.boot-service.default_recovery",
     defaults: ["android.hardware.boot-service_common"],
     init_rc: ["android.hardware.boot-service.default_recovery.rc"],
-    vintf_fragments: ["android.hardware.boot-service.default.xml"],
     recovery: true,
-
-    shared_libs: [
-        "libbase",
-        "libbinder_ndk",
-        "android.hardware.boot@1.1",
-        "android.hardware.boot-V1-ndk",
-    ],
-    static_libs: [
-        "libboot_control",
-    ],
-}
-
-prebuilt_etc {
-    name: "android.hardware.boot-service.default.rc",
-    src: "android.hardware.boot-service.default.rc",
-    installable: false,
-}
-
-prebuilt_etc {
-    name: "android.hardware.boot-service.default.xml",
-    src: "android.hardware.boot-service.default.xml",
-    sub_dir: "vintf",
-    installable: false,
-}
-
-apex {
-    name: "com.android.hardware.boot",
-    vendor: true,
-    manifest: "apex_manifest.json",
-    file_contexts: "apex_file_contexts",
-    key: "com.android.hardware.key",
-    certificate: ":com.android.hardware.certificate",
-    updatable: false,
-
-    binaries: [
-        "android.hardware.boot-service.default",
-    ],
-    prebuilts: [
-        "android.hardware.boot-service.default.rc",
-        "android.hardware.boot-service.default.xml",
-    ],
 }
diff --git a/boot/aidl/default/android.hardware.boot-service.default.rc b/boot/aidl/default/android.hardware.boot-service.default.rc
index 5090e2c..589f803 100644
--- a/boot/aidl/default/android.hardware.boot-service.default.rc
+++ b/boot/aidl/default/android.hardware.boot-service.default.rc
@@ -1,4 +1,4 @@
-service vendor.boot-default /apex/com.android.hardware.boot/bin/hw/android.hardware.boot-service.default
+service vendor.boot-default /vendor/bin/hw/android.hardware.boot-service.default
     class early_hal
     user root
     group root
diff --git a/boot/aidl/default/apex_file_contexts b/boot/aidl/default/apex_file_contexts
deleted file mode 100644
index bf03585..0000000
--- a/boot/aidl/default/apex_file_contexts
+++ /dev/null
@@ -1,3 +0,0 @@
-(/.*)?                                                          u:object_r:vendor_file:s0
-/etc(/.*)?                                                      u:object_r:vendor_configs_file:s0
-/bin/hw/android\.hardware\.boot-service\.default                u:object_r:hal_bootctl_default_exec:s0
diff --git a/boot/aidl/default/apex_manifest.json b/boot/aidl/default/apex_manifest.json
deleted file mode 100644
index 92661c9..0000000
--- a/boot/aidl/default/apex_manifest.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-    "name": "com.android.hardware.boot",
-    "version": 1,
-    "vendorBootstrap": true
-}
\ No newline at end of file
diff --git a/common/aidl/Android.bp b/common/aidl/Android.bp
index 7f6890c..1457b8a 100644
--- a/common/aidl/Android.bp
+++ b/common/aidl/Android.bp
@@ -36,6 +36,9 @@
             ],
             min_sdk_version: "29",
         },
+        rust: {
+            enabled: true,
+        },
     },
     frozen: true,
     versions: [
diff --git a/common/fmq/aidl/Android.bp b/common/fmq/aidl/Android.bp
index 148c63c..ad86aaf 100644
--- a/common/fmq/aidl/Android.bp
+++ b/common/fmq/aidl/Android.bp
@@ -37,6 +37,9 @@
             ],
             min_sdk_version: "29",
         },
+        rust: {
+            enabled: true,
+        },
     },
     frozen: true,
     versions_with_info: [
diff --git a/drm/aidl/vts/Android.bp b/drm/aidl/vts/Android.bp
index 190f60d..5139036 100644
--- a/drm/aidl/vts/Android.bp
+++ b/drm/aidl/vts/Android.bp
@@ -59,13 +59,13 @@
             data: [":libvtswidevine-arm-prebuilts"],
         },
         arm64: {
-            data: [":libvtswidevine-arm64-prebuilts"],
+            data: [":libvtswidevine-arm64-prebuilts", ":libvtswidevine-arm-prebuilts"],
         },
         x86: {
             data: [":libvtswidevine-x86-prebuilts"],
         },
         x86_64: {
-            data: [":libvtswidevine-x86_64-prebuilts"],
+            data: [":libvtswidevine-x86_64-prebuilts", ":libvtswidevine-x86-prebuilts"],
         },
     },
     test_suites: [
diff --git a/health/1.0/default/convert.cpp b/health/1.0/default/convert.cpp
index 31b4679..e12e197 100644
--- a/health/1.0/default/convert.cpp
+++ b/health/1.0/default/convert.cpp
@@ -117,7 +117,7 @@
     info.batteryCycleCount      = p->batteryCycleCount;
     info.batteryFullCharge      = p->batteryFullCharge;
     info.batteryChargeCounter   = p->batteryChargeCounter;
-    info.batteryTechnology      = p->batteryTechnology;
+    info.batteryTechnology      = p->batteryTechnology.c_str();
 }
 
 void convertFromHealthInfo(const HealthInfo& info,
diff --git a/keymaster/4.0/vts/functional/HmacKeySharingTest.cpp b/keymaster/4.0/vts/functional/HmacKeySharingTest.cpp
index f57a668..1bff076 100644
--- a/keymaster/4.0/vts/functional/HmacKeySharingTest.cpp
+++ b/keymaster/4.0/vts/functional/HmacKeySharingTest.cpp
@@ -137,7 +137,7 @@
     auto nonces = copyNonces(params);
     EXPECT_EQ(allKeymasters().size(), nonces.size());
     std::sort(nonces.begin(), nonces.end());
-    std::unique(nonces.begin(), nonces.end());
+    nonces.erase(std::unique(nonces.begin(), nonces.end()), nonces.end());
     EXPECT_EQ(allKeymasters().size(), nonces.size());
 
     auto responses = computeSharedHmac(allKeymasters(), params);
diff --git a/media/bufferpool/aidl/Android.bp b/media/bufferpool/aidl/Android.bp
index b01cdbe..10de755 100644
--- a/media/bufferpool/aidl/Android.bp
+++ b/media/bufferpool/aidl/Android.bp
@@ -46,5 +46,8 @@
             ],
             min_sdk_version: "29",
         },
+        rust: {
+            enabled: true,
+        },
     },
 }
diff --git a/media/c2/aidl/Android.bp b/media/c2/aidl/Android.bp
index 75d74ac..3f2cadb 100644
--- a/media/c2/aidl/Android.bp
+++ b/media/c2/aidl/Android.bp
@@ -11,11 +11,12 @@
 
 aidl_interface {
     name: "android.hardware.media.c2",
+    min_sdk_version: "31",
     vendor_available: true,
     double_loadable: true,
     srcs: ["android/hardware/media/c2/*.aidl"],
-    include_dirs: [
-        "frameworks/base/core/java",
+    headers: [
+        "HardwareBuffer_aidl",
     ],
     imports: [
         "android.hardware.common-V2",
@@ -31,6 +32,11 @@
         },
         ndk: {
             enabled: true,
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.media.swcodec",
+                "test_com.android.media.swcodec",
+            ],
             additional_shared_libraries: [
                 "libnativewindow",
             ],
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl
index da3d5ff..3e460dd 100644
--- a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl
@@ -36,7 +36,7 @@
 interface IGraphicBufferAllocator {
   android.hardware.media.c2.IGraphicBufferAllocator.Allocation allocate(in android.hardware.media.c2.IGraphicBufferAllocator.Description desc);
   boolean deallocate(in long id);
-  android.hardware.media.c2.IGraphicBufferAllocator.WaitableFds getWaitableFds();
+  ParcelFileDescriptor getWaitableFd();
   parcelable Allocation {
     android.hardware.HardwareBuffer buffer;
     ParcelFileDescriptor fence;
@@ -47,8 +47,4 @@
     int format;
     long usage;
   }
-  parcelable WaitableFds {
-    ParcelFileDescriptor allocEvent;
-    ParcelFileDescriptor statusEvent;
-  }
 }
diff --git a/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl b/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl
index 1c97214..49c4ea4 100644
--- a/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl
@@ -75,31 +75,22 @@
     boolean deallocate(in long id);
 
     /**
-     * Fds for waitable object events.
-     *
-     * Fds are created by eventfd() with semaphore mode.
-     * For allocEvent, An integer counter regarding dequeuable buffer count is maintained
-     * by client using read()/write() to the fd. The fd can be checked whether it is
-     * readable via poll(). When in readable status, the specified counter is positive
-     * so allocate/dequeue can happen.
-     *
-     * For statusEvent, the client can notify further allocation is not feasible.
-     * e.g.) life-cycle of the underlying allocator is ended.
-     *
-     * C2Fence object should be implemented based on this Fds. Thus, C2Fence can return
-     * either by allocation being ready or allocation being infeasible by the client status
-     * change.
-     */
-    parcelable WaitableFds {
-        ParcelFileDescriptor allocEvent;
-        ParcelFileDescriptor statusEvent;
-    }
-
-    /**
-     * Gets waiable file descriptors.
+     * Gets a waitable file descriptor.
      *
      * Use this method once and cache it in order not to create unnecessary duplicated fds.
-     * The returned array will have two fds.
+     *
+     * Two file descriptors are created by pipe2(), and the reading end will be returned
+     * and shared by this method. Whenever a dequeuable buffer is ready a byte will be
+     * written to the writing end. Whenever a buffer is allocated(or dequeued) a byte will
+     * be read from the reading end.
+     *
+     * The returned file descriptor(the reading end) can be polled whether the read is ready
+     * via ::poll(). If no more allocate() can be fulfilled(by status change or etc.), the
+     * writing end will be closed. In the case, POLLHUP event can be retrieved via ::poll().
+     *
+     * C2Fence object should be implemented based on this Fd. Thus, C2Fence can return
+     * either by allocation being ready or allocation being infeasible by the client status
+     * change.
      *
      * If many waitable objects based on the same fd are competing, all watiable objects will be
      * notified. After being notified, they should invoke allocate(). At least one of them can
@@ -110,5 +101,5 @@
      * @return an fd array which will be wrapped to C2Fence and will be waited for
      *     until allocating is unblocked.
      */
-    WaitableFds getWaitableFds();
+    ParcelFileDescriptor getWaitableFd();
 }
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 5f8ec0e..3a8a1e8 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -841,7 +841,7 @@
         int vendor_api_level = property_get_int32("ro.vendor.api_level", 0);
         if (SecLevel() == SecurityLevel::STRONGBOX) {
             // This is known to be broken on older vendor implementations.
-            if (vendor_api_level < __ANDROID_API_T__) {
+            if (vendor_api_level <= __ANDROID_API_U__) {
                 compare_output = false;
             } else {
                 additional_information = " (b/194134359) ";
diff --git a/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp b/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
index 51938ba..7599bce 100644
--- a/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
+++ b/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
@@ -164,7 +164,7 @@
     auto nonces = copyNonces(params);
     EXPECT_EQ(sharedSecrets.size(), nonces.size());
     std::sort(nonces.begin(), nonces.end());
-    std::unique(nonces.begin(), nonces.end());
+    nonces.erase(std::unique(nonces.begin(), nonces.end()), nonces.end());
     EXPECT_EQ(sharedSecrets.size(), nonces.size());
 
     auto responses = computeAllSharedSecrets(params);
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp
index bb99ae4..46cba93 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp
@@ -48,6 +48,13 @@
     virtual void SetUp() override {
         wifi_instance_name_ = std::get<0>(GetParam());
         hostapd_instance_name_ = std::get<1>(GetParam());
+
+        // Disable Wi-Fi framework to avoid interference
+        isWifiEnabled_ = isWifiFrameworkEnabled();
+        isScanAlwaysEnabled_ = isWifiScanAlwaysAvailable();
+        toggleWifiFramework(false);
+        toggleWifiScanAlwaysAvailable(false);
+
         stopSupplicantIfNeeded(wifi_instance_name_);
         startHostapdAndWaitForHidlService(wifi_instance_name_,
                                           hostapd_instance_name_);
@@ -58,14 +65,21 @@
     virtual void TearDown() override {
         HIDL_INVOKE_VOID_WITHOUT_ARGUMENTS(hostapd_, terminate);
         stopHostapd(wifi_instance_name_);
+
+        // Restore Wi-Fi framework state
+        toggleWifiFramework(isWifiEnabled_);
+        toggleWifiScanAlwaysAvailable(isScanAlwaysEnabled_);
     }
 
    protected:
-    std::string getPrimaryWlanIfaceName() {
+     bool isWifiEnabled_ = false;
+     bool isScanAlwaysEnabled_ = false;
+
+     std::string getPrimaryWlanIfaceName() {
         std::array<char, PROPERTY_VALUE_MAX> buffer;
         property_get("wifi.interface", buffer.data(), "wlan0");
         return buffer.data();
-    }
+     }
 
     IHostapd::IfaceParams getIfaceParamsWithAcs() {
         IHostapd::IfaceParams iface_params;
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
index 75d6252..3ae9b39 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
@@ -100,3 +100,24 @@
         ::android::hardware::wifi::hostapd::V1_1::IHostapd::castFrom(hostapd);
     return hostapd_1_1.get() != nullptr;
 }
+
+void toggleWifiFramework(bool enable) {
+    std::string cmd = "/system/bin/cmd wifi set-wifi-enabled ";
+    cmd += enable ? "enabled" : "disabled";
+    testing::checkSubstringInCommandOutput(cmd.c_str(), "X");
+}
+
+void toggleWifiScanAlwaysAvailable(bool enable) {
+    std::string cmd = "/system/bin/cmd wifi set-scan-always-available ";
+    cmd += enable ? "enabled" : "disabled";
+    testing::checkSubstringInCommandOutput(cmd.c_str(), "X");
+}
+
+bool isWifiFrameworkEnabled() {
+    return testing::checkSubstringInCommandOutput("/system/bin/cmd wifi status", "Wifi is enabled");
+}
+
+bool isWifiScanAlwaysAvailable() {
+    return testing::checkSubstringInCommandOutput("/system/bin/cmd wifi status",
+                                                  "Wifi scanning is always available");
+}
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h
index 5cb4f01..ea7c112 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h
@@ -17,14 +17,17 @@
 #ifndef HOSTAPD_HIDL_TEST_UTILS_H
 #define HOSTAPD_HIDL_TEST_UTILS_H
 
+#include <VtsCoreUtil.h>
 #include <android/hardware/wifi/hostapd/1.0/IHostapd.h>
 #include <android/hardware/wifi/hostapd/1.1/IHostapd.h>
 
 // Used to stop the android wifi framework before every test.
-void stopWifiFramework(const std::string& instance_name);
-void startWifiFramework(const std::string& instance_name);
 void stopSupplicantIfNeeded(const std::string& instance_name);
 void stopHostapd(const std::string& instance_name);
+void toggleWifiFramework(bool enable);
+void toggleWifiScanAlwaysAvailable(bool enable);
+bool isWifiFrameworkEnabled();
+bool isWifiScanAlwaysAvailable();
 // Used to configure the chip, driver and start wpa_hostapd before every
 // test.
 void startHostapdAndWaitForHidlService(