diff --git a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp index 807841e4c6dbd32f84ad5a0d1a7b40c1b593d5b7..4f21990ef01af911f4d0b7c51d8097685b90edb6 100644 --- a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp +++ b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp @@ -581,8 +581,8 @@ status_t ConvertRGBToPlanarYUV( uint8_t maxLvlChroma = colorRange == C2Color::RANGE_FULL ? 255 : 240; #define CLIP3(min,v,max) (((v) < (min)) ? (min) : (((max) > (v)) ? (v) : (max))) - for (size_t y = 0; y < src.height(); ++y) { - for (size_t x = 0; x < src.width(); ++x) { + for (size_t y = 0; y < src.crop().height; ++y) { + for (size_t x = 0; x < src.crop().width; ++x) { uint8_t r = *pRed; uint8_t g = *pGreen; uint8_t b = *pBlue; diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp index 997f62a19a4a1f29e6974957f59a66ebd4ea603c..307802b5256e45435d6db9bcb62e9fcf6bef0120 100644 --- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp +++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp @@ -274,6 +274,7 @@ INSTANTIATE_TEST_SUITE_P(AudioDeviceDescriptionRoundTrip, class AudioFormatDescriptionRoundTripTest : public testing::TestWithParam {}; + TEST_P(AudioFormatDescriptionRoundTripTest, Aidl2Legacy2Aidl) { const auto initial = GetParam(); auto conv = aidl2legacy_AudioFormatDescription_audio_format_t(initial); diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp index 4df79efea5db5e1abb79bd7716e139058c4bf154..0db588d9ff14ebbaf3fcaeb799e2c8db6be1f3ff 100644 --- a/media/libstagefright/colorconversion/ColorConverter.cpp +++ b/media/libstagefright/colorconversion/ColorConverter.cpp @@ -962,7 +962,8 @@ status_t ColorConverter::convertYUV420Planar16ToY410( uint32_t u01, v01, y01, y23, y45, y67, uv0, uv1; size_t x = 0; - for (; x < src.cropWidth() - 3; x += 4) { + // x % 4 is always 0 so x + 3 will never overflow. + for (; x + 3 < src.cropWidth(); x += 4) { u01 = *((uint32_t*)ptr_u); ptr_u += 2; v01 = *((uint32_t*)ptr_v); ptr_v += 2; diff --git a/media/libstagefright/foundation/MetaDataBase.cpp b/media/libstagefright/foundation/MetaDataBase.cpp index 33707482c9bc7937a604bf6e0eac0514f30d3737..46a600a9d9d99109a6ef92938817a1ab38b52ddf 100644 --- a/media/libstagefright/foundation/MetaDataBase.cpp +++ b/media/libstagefright/foundation/MetaDataBase.cpp @@ -23,6 +23,8 @@ #include #include +#include + #include #include #include @@ -78,6 +80,7 @@ struct MetaDataBase::Rect { struct MetaDataBase::MetaDataInternal { + std::mutex mLock; KeyedVector mItems; }; @@ -102,10 +105,12 @@ MetaDataBase::~MetaDataBase() { } void MetaDataBase::clear() { + std::lock_guard guard(mInternalData->mLock); mInternalData->mItems.clear(); } bool MetaDataBase::remove(uint32_t key) { + std::lock_guard guard(mInternalData->mLock); ssize_t i = mInternalData->mItems.indexOfKey(key); if (i < 0) { @@ -252,6 +257,7 @@ bool MetaDataBase::setData( uint32_t key, uint32_t type, const void *data, size_t size) { bool overwrote_existing = true; + std::lock_guard guard(mInternalData->mLock); ssize_t i = mInternalData->mItems.indexOfKey(key); if (i < 0) { typed_data item; @@ -269,6 +275,7 @@ bool MetaDataBase::setData( bool MetaDataBase::findData(uint32_t key, uint32_t *type, const void **data, size_t *size) const { + std::lock_guard guard(mInternalData->mLock); ssize_t i = mInternalData->mItems.indexOfKey(key); if (i < 0) { @@ -283,6 +290,7 @@ bool MetaDataBase::findData(uint32_t key, uint32_t *type, } bool MetaDataBase::hasData(uint32_t key) const { + std::lock_guard guard(mInternalData->mLock); ssize_t i = mInternalData->mItems.indexOfKey(key); if (i < 0) { @@ -429,6 +437,7 @@ static void MakeFourCCString(uint32_t x, char *s) { String8 MetaDataBase::toString() const { String8 s; + std::lock_guard guard(mInternalData->mLock); for (int i = mInternalData->mItems.size(); --i >= 0;) { int32_t key = mInternalData->mItems.keyAt(i); char cc[5]; @@ -443,6 +452,7 @@ String8 MetaDataBase::toString() const { } void MetaDataBase::dumpToLog() const { + std::lock_guard guard(mInternalData->mLock); for (int i = mInternalData->mItems.size(); --i >= 0;) { int32_t key = mInternalData->mItems.keyAt(i); char cc[5]; @@ -455,6 +465,7 @@ void MetaDataBase::dumpToLog() const { #if defined(__ANDROID__) && !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__) status_t MetaDataBase::writeToParcel(Parcel &parcel) { status_t ret; + std::lock_guard guard(mInternalData->mLock); size_t numItems = mInternalData->mItems.size(); ret = parcel.writeUint32(uint32_t(numItems)); if (ret) { diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp index 41f2d67bb7bb567ca4e409c3a6ab5c61518405ec..bc8341078d2755adcad81af557e50f98aebf056b 100644 --- a/media/libstagefright/rtsp/ARTPWriter.cpp +++ b/media/libstagefright/rtsp/ARTPWriter.cpp @@ -105,6 +105,7 @@ ARTPWriter::ARTPWriter(int fd) mRTCPAddr = mRTPAddr; mRTCPAddr.sin_port = htons(ntohs(mRTPAddr.sin_port) | 1); + mVPSBuf = NULL; mSPSBuf = NULL; mPPSBuf = NULL; diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp index 2ffd7759e099f9a366eb9efea673784b85ed61a9..ef8c9aa789b81442492cd64e3af725e44c53b26a 100644 --- a/media/mtp/MtpFfsHandle.cpp +++ b/media/mtp/MtpFfsHandle.cpp @@ -297,6 +297,10 @@ int MtpFfsHandle::start(bool ptp) { } void MtpFfsHandle::close() { + auto timeout = std::chrono::seconds(2); + std::unique_lock lk(m); + cv.wait_for(lk, timeout ,[this]{return child_threads==0;}); + io_destroy(mCtx); closeEndpoints(); closeConfig(); @@ -669,6 +673,11 @@ int MtpFfsHandle::sendEvent(mtp_event me) { char *temp = new char[me.length]; memcpy(temp, me.data, me.length); me.data = temp; + + std::unique_lock lk(m); + child_threads++; + lk.unlock(); + std::thread t([this, me]() { return this->doSendEvent(me); }); t.detach(); return 0; @@ -680,6 +689,11 @@ void MtpFfsHandle::doSendEvent(mtp_event me) { if (static_cast(ret) != length) PLOG(ERROR) << "Mtp error sending event thread!"; delete[] reinterpret_cast(me.data); + + std::unique_lock lk(m); + child_threads--; + lk.unlock(); + cv.notify_one(); } } // namespace android diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h index e552e03bec2e9db63fd140c948f9a167a38fe07d..51cdef0953c8c799ffffb409c93957268b785b30 100644 --- a/media/mtp/MtpFfsHandle.h +++ b/media/mtp/MtpFfsHandle.h @@ -60,6 +60,10 @@ protected: bool mCanceled; bool mBatchCancel; + std::mutex m; + std::condition_variable cv; + std::atomic child_threads{0}; + android::base::unique_fd mControl; // "in" from the host's perspective => sink for mtp server android::base::unique_fd mBulkIn; diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp index f069a83b5f55412e56f49ffc1a9a7121bd3f13eb..634aa46dd9af57cc4341abd1353f38d7b73c029b 100644 --- a/media/mtp/MtpPacket.cpp +++ b/media/mtp/MtpPacket.cpp @@ -92,24 +92,46 @@ void MtpPacket::copyFrom(const MtpPacket& src) { } uint16_t MtpPacket::getUInt16(int offset) const { - return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + if ((unsigned long)(offset+2) <= mBufferSize) { + return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } uint32_t MtpPacket::getUInt32(int offset) const { - return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | - ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + if ((unsigned long)(offset+4) <= mBufferSize) { + return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | + ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } void MtpPacket::putUInt16(int offset, uint16_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + if ((unsigned long)(offset+2) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } void MtpPacket::putUInt32(int offset, uint32_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + if ((unsigned long)(offset+4) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } uint16_t MtpPacket::getContainerCode() const { @@ -146,8 +168,10 @@ void MtpPacket::setParameter(int index, uint32_t value) { return; } int offset = MTP_CONTAINER_PARAMETER_OFFSET + (index - 1) * sizeof(uint32_t); - if (mPacketSize < offset + sizeof(uint32_t)) + if (mPacketSize < offset + sizeof(uint32_t)) { mPacketSize = offset + sizeof(uint32_t); + allocate(mPacketSize); + } putUInt32(offset, value); } diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp index 83b84e392c117cb8716d1d5d99864140812c54a5..4ee45c795e8fa43e3c90a75e7da69869a3829690 100644 --- a/media/utils/ServiceUtilities.cpp +++ b/media/utils/ServiceUtilities.cpp @@ -46,6 +46,7 @@ static const String16 sAndroidPermissionRecordAudio("android.permission.RECORD_A static const String16 sModifyPhoneState("android.permission.MODIFY_PHONE_STATE"); static const String16 sModifyAudioRouting("android.permission.MODIFY_AUDIO_ROUTING"); static const String16 sCallAudioInterception("android.permission.CALL_AUDIO_INTERCEPTION"); +static const String16 sAndroidPermissionBluetoothConnect("android.permission.BLUETOOTH_CONNECT"); static String16 resolveCallingPackage(PermissionController& permissionController, const std::optional opPackageName, uid_t uid) { @@ -374,6 +375,48 @@ status_t checkIMemory(const sp& iMemory) return NO_ERROR; } +/** + * Determines if the MAC address in Bluetooth device descriptors returned by APIs of + * a native audio service (audio flinger, audio policy) must be anonymized. + * MAC addresses returned to system server or apps with BLUETOOTH_CONNECT permission + * are not anonymized. + * + * @param attributionSource The attribution source of the calling app. + * @param caller string identifying the caller for logging. + * @return true if the MAC addresses must be anonymized, false otherwise. + */ +bool mustAnonymizeBluetoothAddress( + const AttributionSourceState& attributionSource, const String16& caller) { + uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)); + if (isAudioServerOrSystemServerUid(uid)) { + return false; + } + const std::optional resolvedAttributionSource = + resolveAttributionSource(attributionSource); + if (!resolvedAttributionSource.has_value()) { + return true; + } + permission::PermissionChecker permissionChecker; + return permissionChecker.checkPermissionForPreflightFromDatasource( + sAndroidPermissionBluetoothConnect, resolvedAttributionSource.value(), caller, + AppOpsManager::OP_BLUETOOTH_CONNECT) + != permission::PermissionChecker::PERMISSION_GRANTED; +} + +/** + * Modifies the passed MAC address string in place for consumption by unprivileged clients. + * the string is assumed to have a valid MAC address format. + * the anonymzation must be kept in sync with toAnonymizedAddress() in BluetoothUtils.java + * + * @param address input/output the char string contining the MAC address to anonymize. + */ +void anonymizeBluetoothAddress(char *address) { + if (address == nullptr || strlen(address) != strlen("AA:BB:CC:DD:EE:FF")) { + return; + } + memcpy(address, "XX:XX:XX:XX", strlen("XX:XX:XX:XX")); +} + sp MediaPackageManager::retrievePackageManager() { const sp sm = defaultServiceManager(); if (sm == nullptr) { diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h index de20d559efadc5ffde9902a8badeebf6f80fa00f..46a70ddad5f58395365ecaa8104c59bcc4d097ca 100644 --- a/media/utils/include/mediautils/ServiceUtilities.h +++ b/media/utils/include/mediautils/ServiceUtilities.h @@ -108,6 +108,10 @@ bool modifyPhoneStateAllowed(const AttributionSourceState& attributionSource); bool bypassInterruptionPolicyAllowed(const AttributionSourceState& attributionSource); bool callAudioInterceptionAllowed(const AttributionSourceState& attributionSource); void purgePermissionCache(); +bool mustAnonymizeBluetoothAddress( + const AttributionSourceState& attributionSource, const String16& caller); +void anonymizeBluetoothAddress(char *address); + int32_t getOpForSource(audio_source_t source); AttributionSourceState getCallingAttributionSource(); diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 73ee69122663d4538ec8432cbd5ca6e12b49e8f2..458828c2c570dfdcc7695aceb97bcba55f48c9d5 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -9675,6 +9675,9 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE; audio_io_handle_t io = mId; + AttributionSourceState adjAttributionSource = AudioFlinger::checkAttributionSourcePackage( + client.attributionSource); + if (isOutput()) { audio_config_t config = AUDIO_CONFIG_INITIALIZER; config.sample_rate = mSampleRate; @@ -9689,7 +9692,7 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, ret = AudioSystem::getOutputForAttr(&mAttr, &io, mSessionId, &stream, - client.attributionSource, + adjAttributionSource, &config, flags, &deviceId, @@ -9707,7 +9710,7 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, ret = AudioSystem::getInputForAttr(&mAttr, &io, RECORD_RIID_INVALID, mSessionId, - client.attributionSource, + adjAttributionSource, &config, AUDIO_INPUT_FLAG_MMAP_NOIRQ, &deviceId, diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp index 5f323230faf1d0469c6f3279662583862bb94f81..f1cb12e66e1cf0f968bbf095c02599e87a417ea4 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp @@ -1506,6 +1506,19 @@ Status AudioPolicyService::isDirectOutputSupported( return Status::ok(); } +template +void anonymizePortBluetoothAddress(Port *port) { + if (port->type != AUDIO_PORT_TYPE_DEVICE) { + return; + } + if (!(audio_is_a2dp_device(port->ext.device.type) + || audio_is_ble_device(port->ext.device.type) + || audio_is_bluetooth_sco_device(port->ext.device.type) + || audio_is_hearing_aid_out_device(port->ext.device.type))) { + return; + } + anonymizeBluetoothAddress(port->ext.device.address); +} Status AudioPolicyService::listAudioPorts(media::AudioPortRole roleAidl, media::AudioPortType typeAidl, Int* count, @@ -1528,10 +1541,20 @@ Status AudioPolicyService::listAudioPorts(media::AudioPortRole roleAidl, if (mAudioPolicyManager == NULL) { return binderStatusFromStatusT(NO_INIT); } + + const AttributionSourceState attributionSource = getCallingAttributionSource(); + AutoCallerClear acc; RETURN_IF_BINDER_ERROR(binderStatusFromStatusT( mAudioPolicyManager->listAudioPorts(role, type, &num_ports, ports.get(), &generation))); numPortsReq = std::min(numPortsReq, num_ports); + + if (mustAnonymizeBluetoothAddress(attributionSource, String16(__func__))) { + for (size_t i = 0; i < numPortsReq; ++i) { + anonymizePortBluetoothAddress(&ports[i]); + } + } + RETURN_IF_BINDER_ERROR(binderStatusFromStatusT( convertRange(ports.get(), ports.get() + numPortsReq, std::back_inserter(*portsAidl), legacy2aidl_audio_port_v7_AudioPort))); @@ -1547,8 +1570,16 @@ Status AudioPolicyService::getAudioPort(int portId, if (mAudioPolicyManager == NULL) { return binderStatusFromStatusT(NO_INIT); } + + const AttributionSourceState attributionSource = getCallingAttributionSource(); + AutoCallerClear acc; RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(mAudioPolicyManager->getAudioPort(&port))); + + if (mustAnonymizeBluetoothAddress(attributionSource, String16(__func__))) { + anonymizePortBluetoothAddress(&port); + } + *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_port_v7_AudioPort(port)); return Status::ok(); } @@ -1609,10 +1640,25 @@ Status AudioPolicyService::listAudioPatches(Int* count, if (mAudioPolicyManager == NULL) { return binderStatusFromStatusT(NO_INIT); } + + const AttributionSourceState attributionSource = getCallingAttributionSource(); + AutoCallerClear acc; RETURN_IF_BINDER_ERROR(binderStatusFromStatusT( mAudioPolicyManager->listAudioPatches(&num_patches, patches.get(), &generation))); numPatchesReq = std::min(numPatchesReq, num_patches); + + if (mustAnonymizeBluetoothAddress(attributionSource, String16(__func__))) { + for (size_t i = 0; i < numPatchesReq; ++i) { + for (size_t j = 0; j < patches[i].num_sources; ++j) { + anonymizePortBluetoothAddress(&patches[i].sources[j]); + } + for (size_t j = 0; j < patches[i].num_sinks; ++j) { + anonymizePortBluetoothAddress(&patches[i].sinks[j]); + } + } + } + RETURN_IF_BINDER_ERROR(binderStatusFromStatusT( convertRange(patches.get(), patches.get() + numPatchesReq, std::back_inserter(*patchesAidl), legacy2aidl_audio_patch_AudioPatch))); diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp index 21fa82e0d2f6f9ffb99a238b4877bada749b79bb..459ed5802ccea895a16fa8841addc3561f8fa27d 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -192,6 +193,27 @@ static void destroyAudioPolicyManager(AudioPolicyInterface *interface) { delete interface; } + +namespace { +int getTargetSdkForPackageName(std::string_view packageName) { + const auto binder = defaultServiceManager()->checkService(String16{"package_native"}); + int targetSdk = -1; + if (binder != nullptr) { + const auto pm = interface_cast(binder); + if (pm != nullptr) { + const auto status = pm->getTargetSdkVersionForPackage( + String16{packageName.data(), packageName.size()}, &targetSdk); + return status.isOk() ? targetSdk : -1; + } + } + return targetSdk; +} + +bool doesPackageTargetAtLeastU(std::string_view packageName) { + constexpr int ANDROID_API_U = 34; + return getTargetSdkForPackageName(packageName) >= ANDROID_API_U; +} +} // anonymous // ---------------------------------------------------------------------------- AudioPolicyService::AudioPolicyService() @@ -1885,10 +1907,14 @@ void AudioPolicyService::OpRecordAudioMonitor::onFirstRef() checkOp(); mOpCallback = new RecordAudioOpCallback(this); ALOGV("start watching op %d for %s", mAppOp, mAttributionSource.toString().c_str()); + int flags = doesPackageTargetAtLeastU( + mAttributionSource.packageName.value_or("")) ? + AppOpsManager::WATCH_FOREGROUND_CHANGES : 0; // TODO: We need to always watch AppOpsManager::OP_RECORD_AUDIO too // since it controls the mic permission for legacy apps. mAppOpsManager.startWatchingMode(mAppOp, VALUE_OR_FATAL(aidl2legacy_string_view_String16( mAttributionSource.packageName.value_or(""))), + flags, mOpCallback); }