Merge "media.c2: link libnativewindow to libcodec2_aidl" into main
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index e0110cf..362f373 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -1024,11 +1024,12 @@
// There is not AIDL API defined for `prepareToDisconnectExternalDevice`.
// Call `setConnectedState` instead.
// TODO(b/279824103): call prepareToDisconnectExternalDevice when it is added.
- const status_t status = setConnectedState(port, false /*connected*/);
- if (status == NO_ERROR) {
+ if (const status_t status = setConnectedState(port, false /*connected*/); status == NO_ERROR) {
mDeviceDisconnectionNotified.insert(port->id);
}
- return status;
+ // Return that there was no error as otherwise the disconnection procedure will not be
+ // considered complete for upper layers, and 'setConnectedState' will not be called again.
+ return NO_ERROR;
}
status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
@@ -1068,6 +1069,7 @@
ALOGD("%s: device port for device %s found in the module %s",
__func__, matchDevice.toString().c_str(), mInstance.c_str());
}
+ resetUnusedPatchesAndPortConfigs();
// Use the ID of the "template" port, use all the information from the provided port.
aidlPort.id = portsIt->first;
AudioPort connectedPort;
@@ -1089,12 +1091,19 @@
ALOGD("%s: device port for device %s found in the module %s",
__func__, matchDevice.toString().c_str(), mInstance.c_str());
}
- // Any streams opened on the external device must be closed by this time,
- // thus we can clean up patches and port configs that were created for them.
resetUnusedPatchesAndPortConfigs();
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
- portsIt->second.id)));
- mPorts.erase(portsIt);
+ // Streams are closed by AudioFlinger independently from device disconnections.
+ // It is possible that the stream has not been closed yet.
+ const int32_t portId = portsIt->second.id;
+ if (!isPortHeldByAStream(portId)) {
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mModule->disconnectExternalDevice(portId)));
+ mPorts.erase(portsIt);
+ } else {
+ ALOGD("%s: since device port ID %d is used by a stream, "
+ "external device disconnection postponed", __func__, portId);
+ mConnectedPortIdsHeldByStreams.insert(portId);
+ }
}
return updateRoutes();
}
@@ -1102,6 +1111,7 @@
status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
TIME_CHECK();
if (!mModule) return NO_INIT;
+ resetUnusedPatchesAndPortConfigs();
ModuleDebug debug{ .simulateDeviceConnections = enabled };
status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
// This is important to log as it affects HAL behavior.
@@ -1670,6 +1680,28 @@
p.ext.template get<Tag::mix>().handle == ioHandle; });
}
+bool DeviceHalAidl::isPortHeldByAStream(int32_t portId) {
+ // It is assumed that mStreams has already been cleaned up.
+ for (const auto& streamPair : mStreams) {
+ int32_t patchId = streamPair.second;
+ auto patchIt = mPatches.find(patchId);
+ if (patchIt == mPatches.end()) continue;
+ for (int32_t id : patchIt->second.sourcePortConfigIds) {
+ auto portConfigIt = mPortConfigs.find(id);
+ if (portConfigIt != mPortConfigs.end() && portConfigIt->second.portId == portId) {
+ return true;
+ }
+ }
+ for (int32_t id : patchIt->second.sinkPortConfigIds) {
+ auto portConfigIt = mPortConfigs.find(id);
+ if (portConfigIt != mPortConfigs.end() && portConfigIt->second.portId == portId) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
void DeviceHalAidl::resetPatch(int32_t patchId) {
if (auto it = mPatches.find(patchId); it != mPatches.end()) {
mPatches.erase(it);
@@ -1719,10 +1751,10 @@
// The assumption is that port configs are used to create patches
// (or to open streams, but that involves creation of patches, too). Thus,
// orphaned port configs can and should be reset.
- std::set<int32_t> portConfigIds;
+ std::map<int32_t, int32_t /*portID*/> portConfigIds;
std::transform(mPortConfigs.begin(), mPortConfigs.end(),
std::inserter(portConfigIds, portConfigIds.end()),
- [](const auto& pcPair) { return pcPair.first; });
+ [](const auto& pcPair) { return std::make_pair(pcPair.first, pcPair.second.portId); });
for (const auto& p : mPatches) {
for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
@@ -1730,7 +1762,27 @@
for (int32_t id : mInitialPortConfigIds) {
portConfigIds.erase(id);
}
- for (int32_t id : portConfigIds) resetPortConfig(id);
+ std::set<int32_t> retryDeviceDisconnection;
+ for (const auto& portConfigAndIdPair : portConfigIds) {
+ resetPortConfig(portConfigAndIdPair.first);
+ if (mConnectedPortIdsHeldByStreams.count(portConfigAndIdPair.second) != 0) {
+ retryDeviceDisconnection.insert(portConfigAndIdPair.second);
+ }
+ }
+ for (int32_t portId : retryDeviceDisconnection) {
+ if (!isPortHeldByAStream(portId)) {
+ TIME_CHECK();
+ if (auto status = mModule->disconnectExternalDevice(portId); status.isOk()) {
+ mPorts.erase(portId);
+ mConnectedPortIdsHeldByStreams.erase(portId);
+ ALOGD("%s: executed postponed external device disconnection for port ID %d",
+ __func__, portId);
+ }
+ }
+ }
+ if (!retryDeviceDisconnection.empty()) {
+ updateRoutes();
+ }
}
status_t DeviceHalAidl::updateRoutes() {
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index 2e393c7..329adba 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -257,6 +257,7 @@
const ::aidl::android::media::audio::common::AudioConfig& config,
const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
int32_t ioHandle);
+ bool isPortHeldByAStream(int32_t portId);
status_t prepareToOpenStream(
int32_t aidlHandle,
const ::aidl::android::media::audio::common::AudioDevice& aidlDevice,
@@ -312,6 +313,7 @@
std::mutex mLock;
std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
std::set<audio_port_handle_t> mDeviceDisconnectionNotified;
+ std::set<int32_t> mConnectedPortIdsHeldByStreams;
};
} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index e16fcf0..aecbba7 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -182,8 +182,9 @@
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getState(&state)));
// in case of buffer/ioHandle re-configure for an opened effect, close it and re-open
if (state != State::INIT && mCommon != common) {
- ALOGI("%s at state %s, closing effect", __func__,
- android::internal::ToString(state).c_str());
+ ALOGI("%s at state %s, common parameter change from %s to %s, closing effect", __func__,
+ android::internal::ToString(state).c_str(), mCommon.toString().c_str(),
+ common.toString().c_str());
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->close()));
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getState(&state)));
mStatusQ.reset();
@@ -476,8 +477,9 @@
efGroup);
status = (status == OK) ? BAD_VALUE : status;
}
- } else if (isBypassing()) {
- // for effect with bypass (no processing) flag, it's okay to not have statusQ
+ } else if (isBypassingOrOffload()) {
+ // for effect with bypass (no processing) or offloadIndication flag, it's okay to not have
+ // statusQ
return OK;
}
@@ -485,12 +487,22 @@
return status;
}
+bool EffectConversionHelperAidl::isBypassingOrOffload() const {
+ return isBypassing() || isOffload();
+}
+
bool EffectConversionHelperAidl::isBypassing() const {
return mEffect &&
(mDesc.common.flags.bypass ||
(mIsProxyEffect && std::static_pointer_cast<EffectProxy>(mEffect)->isBypassing()));
}
+bool EffectConversionHelperAidl::isOffload() const {
+ return mEffect &&
+ (mDesc.common.flags.offloadIndication ||
+ (mIsProxyEffect && std::static_pointer_cast<EffectProxy>(mEffect)->isOffload()));
+}
+
Descriptor EffectConversionHelperAidl::getDescriptor() const {
if (!mIsProxyEffect) {
return mDesc;
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 17ff944..b2ef155 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -41,7 +41,10 @@
std::shared_ptr<DataMQ> getInputMQ() { return mInputQ; }
std::shared_ptr<DataMQ> getOutputMQ() { return mOutputQ; }
std::shared_ptr<android::hardware::EventFlag> getEventFlagGroup() { return mEfGroup; }
+
bool isBypassing() const;
+ bool isOffload() const;
+ bool isBypassingOrOffload() const;
::aidl::android::hardware::audio::effect::Descriptor getDescriptor() const;
diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
index 7b5e195..4d7db4c 100644
--- a/media/libaudiohal/impl/EffectProxy.cpp
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -278,6 +278,10 @@
return mSubEffects[mActiveSubIdx].descriptor.common.flags.bypass;
}
+bool EffectProxy::isOffload() const {
+ return mSubEffects[mActiveSubIdx].descriptor.common.flags.offloadIndication;
+}
+
binder_status_t EffectProxy::dump(int fd, const char** args, uint32_t numArgs) {
const std::string dumpString = toString();
write(fd, dumpString.c_str(), dumpString.size());
diff --git a/media/libaudiohal/impl/EffectProxy.h b/media/libaudiohal/impl/EffectProxy.h
index 18e1567..e14eb8a 100644
--- a/media/libaudiohal/impl/EffectProxy.h
+++ b/media/libaudiohal/impl/EffectProxy.h
@@ -98,6 +98,7 @@
}
bool isBypassing() const;
+ bool isOffload() const;
// call dump for all sub-effects
binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 495badf..4198b71 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2937,7 +2937,6 @@
mRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_NONE),
mComposerOutput(false),
mCameraMute(ANDROID_SENSOR_TEST_PATTERN_MODE_OFF),
- mCameraMuteChanged(false),
mRepeatingLastFrameNumber(
hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES),
mPrepareVideoStream(false),
@@ -4110,7 +4109,6 @@
Mutex::Autolock l(mTriggerMutex);
if (muteMode != mCameraMute) {
mCameraMute = muteMode;
- mCameraMuteChanged = true;
}
return OK;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index e572718..d7cfa94 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -1085,7 +1085,6 @@
camera_metadata_enum_android_scaler_rotate_and_crop_t mRotateAndCropOverride;
bool mComposerOutput;
int32_t mCameraMute; // 0 = no mute, otherwise the TEST_PATTERN_MODE to use
- bool mCameraMuteChanged;
int64_t mRepeatingLastFrameNumber;