Anonymize bt addresses in listAudioPorts

Fix a security bypass where listAudioPorts would provide BT MAC
addresses without the required permission.

If a client doesn't have BLUETOOTH_CONNECT, partially redact the
address. To avoid performance issues, this change:
 - Caches uids which hold the permission, invalidating them on the
   package manager cache invalidation sysprop
 - Ensures we only call the check outside of any locks in audioserver.

Soaking for backport on main, a better solution to follow.

Test: Manual repro using the POC app
Bug: 285588444
Flag: EXEMPT security
Change-Id: Ide27226237236380814e6f19a74d1ce1e72828fd
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index 01b6e42..890a1c7 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -1055,6 +1055,14 @@
     return OK;
 }
 
+namespace {
+    // Use '01' for LSB bits 0 and 1 as Bluetooth MAC addresses are never multicast
+    // and universaly administered
+    constexpr std::array<uint8_t, 4> BTANON_PREFIX {0xFD, 0xFF, 0xFF, 0xFF};
+    // Keep sync with ServiceUtilities.cpp mustAnonymizeBluetoothAddress
+    constexpr const char * BTANON_PREFIX_STR = "XX:XX:XX:XX:";
+}
+
 ::android::status_t aidl2legacy_AudioDevice_audio_device(
         const AudioDevice& aidl,
         audio_devices_t* legacyType, std::string* legacyAddress) {
@@ -1069,8 +1077,16 @@
         case Tag::mac: {
             const std::vector<uint8_t>& mac = aidl.address.get<AudioDeviceAddress::mac>();
             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]);
+            if (std::equal(BTANON_PREFIX.begin(), BTANON_PREFIX.end(), mac.begin())) {
+                // special case for anonymized mac address:
+                // change anonymized bytes back from FD:FF:FF:FF: to XX:XX:XX:XX:
+                snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN,
+                        "%s%02X:%02X", BTANON_PREFIX_STR, mac[4], mac[5]);
+            } else {
+                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]);
+            }
         } break;
         case Tag::ipv4: {
             const std::vector<uint8_t>& ipv4 = aidl.address.get<AudioDeviceAddress::ipv4>();
@@ -1132,8 +1148,20 @@
         switch (suggestDeviceAddressTag(aidl.type)) {
             case Tag::mac: {
                 std::vector<uint8_t> mac(6);
-                int status = sscanf(legacyAddress.c_str(), "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX",
-                        &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
+                int status;
+                // special case for anonymized mac address:
+                // change anonymized bytes so that they can be scanned as HEX bytes
+                if (legacyAddress.starts_with(BTANON_PREFIX_STR)) {
+                    std::copy(BTANON_PREFIX.begin(), BTANON_PREFIX.end(), mac.begin());
+                    LOG_ALWAYS_FATAL_IF(legacyAddress.length() <= strlen(BTANON_PREFIX_STR));
+                    status = sscanf(legacyAddress.c_str() + strlen(BTANON_PREFIX_STR),
+                                        "%hhX:%hhX",
+                                        &mac[4], &mac[5]);
+                    status += 4;
+                } else {
+                    status = sscanf(legacyAddress.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());
                     return unexpected(BAD_VALUE);