Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f9b77f9a authored by Eric Laurent's avatar Eric Laurent Committed by Android (Google) Code Review
Browse files

Merge "Audio policy: anonymize Bluetooth MAC addresses" into udc-dev

parents 2b75777e 8f9a40ad
Loading
Loading
Loading
Loading
+18 −2
Original line number Original line Diff line number Diff line
@@ -1052,6 +1052,13 @@ AudioDeviceAddress::Tag suggestDeviceAddressTag(const AudioDeviceDescription& de
            if (mac.size() != 6) return BAD_VALUE;
            if (mac.size() != 6) return BAD_VALUE;
            snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%02X:%02X:%02X:%02X:%02X:%02X",
            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]);
                    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;
        } break;
        case Tag::ipv4: {
        case Tag::ipv4: {
            const std::vector<uint8_t>& ipv4 = aidl.address.get<AudioDeviceAddress::ipv4>();
            const std::vector<uint8_t>& ipv4 = aidl.address.get<AudioDeviceAddress::ipv4>();
@@ -1108,11 +1115,20 @@ legacy2aidl_audio_device_AudioDevice(
    if (!legacyAddress.empty()) {
    if (!legacyAddress.empty()) {
        switch (suggestDeviceAddressTag(aidl.type)) {
        switch (suggestDeviceAddressTag(aidl.type)) {
            case Tag::mac: {
            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);
                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]);
                        &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
                if (status != mac.size()) {
                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);
                    return unexpected(BAD_VALUE);
                }
                }
                aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::mac>(std::move(mac));
                aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::mac>(std::move(mac));
+20 −0
Original line number Original line Diff line number Diff line
@@ -475,8 +475,28 @@ INSTANTIATE_TEST_SUITE_P(
                                 AudioDeviceAddress::make<AudioDeviceAddress::Tag::alsa>(
                                 AudioDeviceAddress::make<AudioDeviceAddress::Tag::alsa>(
                                         std::vector<int32_t>{1, 2}))));
                                         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> {
class AudioFormatDescriptionRoundTripTest : public testing::TestWithParam<AudioFormatDescription> {
};
};

TEST_P(AudioFormatDescriptionRoundTripTest, Aidl2Legacy2Aidl) {
TEST_P(AudioFormatDescriptionRoundTripTest, Aidl2Legacy2Aidl) {
    const auto initial = GetParam();
    const auto initial = GetParam();
    auto conv = aidl2legacy_AudioFormatDescription_audio_format_t(initial);
    auto conv = aidl2legacy_AudioFormatDescription_audio_format_t(initial);
+43 −0
Original line number Original line Diff line number Diff line
@@ -46,6 +46,7 @@ static const String16 sAndroidPermissionRecordAudio("android.permission.RECORD_A
static const String16 sModifyPhoneState("android.permission.MODIFY_PHONE_STATE");
static const String16 sModifyPhoneState("android.permission.MODIFY_PHONE_STATE");
static const String16 sModifyAudioRouting("android.permission.MODIFY_AUDIO_ROUTING");
static const String16 sModifyAudioRouting("android.permission.MODIFY_AUDIO_ROUTING");
static const String16 sCallAudioInterception("android.permission.CALL_AUDIO_INTERCEPTION");
static const String16 sCallAudioInterception("android.permission.CALL_AUDIO_INTERCEPTION");
static const String16 sAndroidPermissionBluetoothConnect("android.permission.BLUETOOTH_CONNECT");


static String16 resolveCallingPackage(PermissionController& permissionController,
static String16 resolveCallingPackage(PermissionController& permissionController,
        const std::optional<String16> opPackageName, uid_t uid) {
        const std::optional<String16> opPackageName, uid_t uid) {
@@ -374,6 +375,48 @@ status_t checkIMemory(const sp<IMemory>& iMemory)
    return NO_ERROR;
    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<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() {
sp<content::pm::IPackageManagerNative> MediaPackageManager::retrievePackageManager() {
    const sp<IServiceManager> sm = defaultServiceManager();
    const sp<IServiceManager> sm = defaultServiceManager();
    if (sm == nullptr) {
    if (sm == nullptr) {
+4 −0
Original line number Original line Diff line number Diff line
@@ -108,6 +108,10 @@ bool modifyPhoneStateAllowed(const AttributionSourceState& attributionSource);
bool bypassInterruptionPolicyAllowed(const AttributionSourceState& attributionSource);
bool bypassInterruptionPolicyAllowed(const AttributionSourceState& attributionSource);
bool callAudioInterceptionAllowed(const AttributionSourceState& attributionSource);
bool callAudioInterceptionAllowed(const AttributionSourceState& attributionSource);
void purgePermissionCache();
void purgePermissionCache();
bool mustAnonymizeBluetoothAddress(
        const AttributionSourceState& attributionSource, const String16& caller);
void anonymizeBluetoothAddress(char *address);

int32_t getOpForSource(audio_source_t source);
int32_t getOpForSource(audio_source_t source);


AttributionSourceState getCallingAttributionSource();
AttributionSourceState getCallingAttributionSource();
+46 −0
Original line number Original line Diff line number Diff line
@@ -1528,6 +1528,19 @@ Status AudioPolicyService::isDirectOutputSupported(
    return Status::ok();
    return Status::ok();
}
}


template <typename Port>
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,
Status AudioPolicyService::listAudioPorts(media::AudioPortRole roleAidl,
                                          media::AudioPortType typeAidl, Int* count,
                                          media::AudioPortType typeAidl, Int* count,
@@ -1550,10 +1563,20 @@ Status AudioPolicyService::listAudioPorts(media::AudioPortRole roleAidl,
    if (mAudioPolicyManager == NULL) {
    if (mAudioPolicyManager == NULL) {
        return binderStatusFromStatusT(NO_INIT);
        return binderStatusFromStatusT(NO_INIT);
    }
    }

    const AttributionSourceState attributionSource = getCallingAttributionSource();

    AutoCallerClear acc;
    AutoCallerClear acc;
    RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
    RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
            mAudioPolicyManager->listAudioPorts(role, type, &num_ports, ports.get(), &generation)));
            mAudioPolicyManager->listAudioPorts(role, type, &num_ports, ports.get(), &generation)));
    numPortsReq = std::min(numPortsReq, num_ports);
    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(
    RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
            convertRange(ports.get(), ports.get() + numPortsReq, std::back_inserter(*portsAidl),
            convertRange(ports.get(), ports.get() + numPortsReq, std::back_inserter(*portsAidl),
                         legacy2aidl_audio_port_v7_AudioPortFw)));
                         legacy2aidl_audio_port_v7_AudioPortFw)));
@@ -1580,8 +1603,16 @@ Status AudioPolicyService::getAudioPort(int portId,
    if (mAudioPolicyManager == NULL) {
    if (mAudioPolicyManager == NULL) {
        return binderStatusFromStatusT(NO_INIT);
        return binderStatusFromStatusT(NO_INIT);
    }
    }

    const AttributionSourceState attributionSource = getCallingAttributionSource();

    AutoCallerClear acc;
    AutoCallerClear acc;
    RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(mAudioPolicyManager->getAudioPort(&port)));
    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_AudioPortFw(port));
    *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_port_v7_AudioPortFw(port));
    return Status::ok();
    return Status::ok();
}
}
@@ -1643,10 +1674,25 @@ Status AudioPolicyService::listAudioPatches(Int* count,
    if (mAudioPolicyManager == NULL) {
    if (mAudioPolicyManager == NULL) {
        return binderStatusFromStatusT(NO_INIT);
        return binderStatusFromStatusT(NO_INIT);
    }
    }

    const AttributionSourceState attributionSource = getCallingAttributionSource();

    AutoCallerClear acc;
    AutoCallerClear acc;
    RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
    RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
            mAudioPolicyManager->listAudioPatches(&num_patches, patches.get(), &generation)));
            mAudioPolicyManager->listAudioPatches(&num_patches, patches.get(), &generation)));
    numPatchesReq = std::min(numPatchesReq, num_patches);
    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(
    RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
            convertRange(patches.get(), patches.get() + numPatchesReq,
            convertRange(patches.get(), patches.get() + numPatchesReq,
                         std::back_inserter(*patchesAidl), legacy2aidl_audio_patch_AudioPatchFw)));
                         std::back_inserter(*patchesAidl), legacy2aidl_audio_patch_AudioPatchFw)));