Loading media/audio/aconfig/audio_flags.aconfig +9 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,15 @@ Enable configurable pre-scale absolute volume." bug: "302553525" } flag { name: "bluetooth_mac_address_anonymization" namespace: "media_audio" description: "\ Enable Bluetooth MAC address anonymization when reporting \ audio device descriptors to non privileged apps." bug: "285588444" } flag { name: "mutex_priority_inheritance" namespace: "media_audio" Loading media/audioaidlconversion/AidlConversionCppNdk.cpp +18 −2 Original line number Diff line number Diff line Loading @@ -1069,6 +1069,13 @@ AudioDeviceAddress::Tag suggestDeviceAddressTag(const AudioDeviceDescription& de if (mac.size() != 6) return BAD_VALUE; snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); // special case for anonymized mac address: // change anonymized bytes back from FD:FF:FF:FF to XX:XX:XX:XX std::string address(addressBuffer); if (address.compare(0, strlen("FD:FF:FF:FF"), "FD:FF:FF:FF") == 0) { address.replace(0, strlen("FD:FF:FF:FF"), "XX:XX:XX:XX"); } strcpy(addressBuffer, address.c_str()); } break; case Tag::ipv4: { const std::vector<uint8_t>& ipv4 = aidl.address.get<AudioDeviceAddress::ipv4>(); Loading Loading @@ -1125,11 +1132,20 @@ legacy2aidl_audio_device_AudioDevice( if (!legacyAddress.empty()) { switch (suggestDeviceAddressTag(aidl.type)) { case Tag::mac: { // special case for anonymized mac address: // change anonymized bytes so that they can be scanned as HEX bytes // Use '01' for LSB bits 0 and 1 as Bluetooth MAC addresses are never multicast // and universaly administered std::string address = legacyAddress; if (address.compare(0, strlen("XX:XX:XX:XX"), "XX:XX:XX:XX") == 0) { address.replace(0, strlen("XX:XX:XX:XX"), "FD:FF:FF:FF"); } std::vector<uint8_t> mac(6); int status = sscanf(legacyAddress.c_str(), "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX", int status = sscanf(address.c_str(), "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); if (status != mac.size()) { ALOGE("%s: malformed MAC address: \"%s\"", __func__, legacyAddress.c_str()); ALOGE("%s: malformed MAC address: \"%s\"", __func__, address.c_str()); return unexpected(BAD_VALUE); } aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::mac>(std::move(mac)); Loading media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp +20 −0 Original line number Diff line number Diff line Loading @@ -481,8 +481,28 @@ INSTANTIATE_TEST_SUITE_P( AudioDeviceAddress::make<AudioDeviceAddress::Tag::alsa>( std::vector<int32_t>{1, 2})))); TEST(AnonymizedBluetoothAddressRoundTripTest, Legacy2Aidl2Legacy) { const std::vector<uint8_t> sAnonymizedAidlAddress = std::vector<uint8_t>{0xFD, 0xFF, 0xFF, 0xFF, 0xAB, 0xCD}; const std::string sAnonymizedLegacyAddress = std::string("XX:XX:XX:XX:AB:CD"); auto device = legacy2aidl_audio_device_AudioDevice(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, sAnonymizedLegacyAddress); ASSERT_TRUE(device.ok()); ASSERT_EQ(AudioDeviceAddress::Tag::mac, device.value().address.getTag()); ASSERT_EQ(sAnonymizedAidlAddress, device.value().address.get<AudioDeviceAddress::mac>()); audio_devices_t legacyType; std::string legacyAddress; status_t status = aidl2legacy_AudioDevice_audio_device(device.value(), &legacyType, &legacyAddress); ASSERT_EQ(OK, status); EXPECT_EQ(legacyType, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP); EXPECT_EQ(sAnonymizedLegacyAddress, legacyAddress); } class AudioFormatDescriptionRoundTripTest : public testing::TestWithParam<AudioFormatDescription> { }; TEST_P(AudioFormatDescriptionRoundTripTest, Aidl2Legacy2Aidl) { const auto initial = GetParam(); auto conv = aidl2legacy_AudioFormatDescription_audio_format_t(initial); Loading media/utils/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ cc_library { "liblog", "libpermission", "libutils", "aconfig_audio_flags_c_lib", "android.hardware.graphics.bufferqueue@1.0", "android.hidl.token@1.0-utils", "packagemanager_aidl-cpp", Loading media/utils/ServiceUtilities.cpp +48 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <media/AidlConversionUtil.h> #include <android/content/AttributionSourceState.h> #include <com_android_media_audio_flags.h> #include <iterator> #include <algorithm> #include <pwd.h> Loading @@ -46,6 +47,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<String16> opPackageName, uid_t uid) { Loading Loading @@ -374,6 +376,52 @@ status_t checkIMemory(const sp<IMemory>& 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) { if (!com::android::media::audio::flags::bluetooth_mac_address_anonymization()) { return false; } uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)); if (isAudioServerOrSystemServerUid(uid)) { return false; } const std::optional<AttributionSourceState> 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<content::pm::IPackageManagerNative> MediaPackageManager::retrievePackageManager() { const sp<IServiceManager> sm = defaultServiceManager(); if (sm == nullptr) { Loading Loading
media/audio/aconfig/audio_flags.aconfig +9 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,15 @@ Enable configurable pre-scale absolute volume." bug: "302553525" } flag { name: "bluetooth_mac_address_anonymization" namespace: "media_audio" description: "\ Enable Bluetooth MAC address anonymization when reporting \ audio device descriptors to non privileged apps." bug: "285588444" } flag { name: "mutex_priority_inheritance" namespace: "media_audio" Loading
media/audioaidlconversion/AidlConversionCppNdk.cpp +18 −2 Original line number Diff line number Diff line Loading @@ -1069,6 +1069,13 @@ AudioDeviceAddress::Tag suggestDeviceAddressTag(const AudioDeviceDescription& de if (mac.size() != 6) return BAD_VALUE; snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); // special case for anonymized mac address: // change anonymized bytes back from FD:FF:FF:FF to XX:XX:XX:XX std::string address(addressBuffer); if (address.compare(0, strlen("FD:FF:FF:FF"), "FD:FF:FF:FF") == 0) { address.replace(0, strlen("FD:FF:FF:FF"), "XX:XX:XX:XX"); } strcpy(addressBuffer, address.c_str()); } break; case Tag::ipv4: { const std::vector<uint8_t>& ipv4 = aidl.address.get<AudioDeviceAddress::ipv4>(); Loading Loading @@ -1125,11 +1132,20 @@ legacy2aidl_audio_device_AudioDevice( if (!legacyAddress.empty()) { switch (suggestDeviceAddressTag(aidl.type)) { case Tag::mac: { // special case for anonymized mac address: // change anonymized bytes so that they can be scanned as HEX bytes // Use '01' for LSB bits 0 and 1 as Bluetooth MAC addresses are never multicast // and universaly administered std::string address = legacyAddress; if (address.compare(0, strlen("XX:XX:XX:XX"), "XX:XX:XX:XX") == 0) { address.replace(0, strlen("XX:XX:XX:XX"), "FD:FF:FF:FF"); } std::vector<uint8_t> mac(6); int status = sscanf(legacyAddress.c_str(), "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX", int status = sscanf(address.c_str(), "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); if (status != mac.size()) { ALOGE("%s: malformed MAC address: \"%s\"", __func__, legacyAddress.c_str()); ALOGE("%s: malformed MAC address: \"%s\"", __func__, address.c_str()); return unexpected(BAD_VALUE); } aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::mac>(std::move(mac)); Loading
media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp +20 −0 Original line number Diff line number Diff line Loading @@ -481,8 +481,28 @@ INSTANTIATE_TEST_SUITE_P( AudioDeviceAddress::make<AudioDeviceAddress::Tag::alsa>( std::vector<int32_t>{1, 2})))); TEST(AnonymizedBluetoothAddressRoundTripTest, Legacy2Aidl2Legacy) { const std::vector<uint8_t> sAnonymizedAidlAddress = std::vector<uint8_t>{0xFD, 0xFF, 0xFF, 0xFF, 0xAB, 0xCD}; const std::string sAnonymizedLegacyAddress = std::string("XX:XX:XX:XX:AB:CD"); auto device = legacy2aidl_audio_device_AudioDevice(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, sAnonymizedLegacyAddress); ASSERT_TRUE(device.ok()); ASSERT_EQ(AudioDeviceAddress::Tag::mac, device.value().address.getTag()); ASSERT_EQ(sAnonymizedAidlAddress, device.value().address.get<AudioDeviceAddress::mac>()); audio_devices_t legacyType; std::string legacyAddress; status_t status = aidl2legacy_AudioDevice_audio_device(device.value(), &legacyType, &legacyAddress); ASSERT_EQ(OK, status); EXPECT_EQ(legacyType, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP); EXPECT_EQ(sAnonymizedLegacyAddress, legacyAddress); } class AudioFormatDescriptionRoundTripTest : public testing::TestWithParam<AudioFormatDescription> { }; TEST_P(AudioFormatDescriptionRoundTripTest, Aidl2Legacy2Aidl) { const auto initial = GetParam(); auto conv = aidl2legacy_AudioFormatDescription_audio_format_t(initial); Loading
media/utils/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ cc_library { "liblog", "libpermission", "libutils", "aconfig_audio_flags_c_lib", "android.hardware.graphics.bufferqueue@1.0", "android.hidl.token@1.0-utils", "packagemanager_aidl-cpp", Loading
media/utils/ServiceUtilities.cpp +48 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <media/AidlConversionUtil.h> #include <android/content/AttributionSourceState.h> #include <com_android_media_audio_flags.h> #include <iterator> #include <algorithm> #include <pwd.h> Loading @@ -46,6 +47,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<String16> opPackageName, uid_t uid) { Loading Loading @@ -374,6 +376,52 @@ status_t checkIMemory(const sp<IMemory>& 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) { if (!com::android::media::audio::flags::bluetooth_mac_address_anonymization()) { return false; } uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)); if (isAudioServerOrSystemServerUid(uid)) { return false; } const std::optional<AttributionSourceState> 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<content::pm::IPackageManagerNative> MediaPackageManager::retrievePackageManager() { const sp<IServiceManager> sm = defaultServiceManager(); if (sm == nullptr) { Loading