1.AudioPolicyService::SetAudioScene中,会调用FetchDevice去更改输出设备与输入设备,再调用SetAudioScene去修改音频场景,最后如果是通话则去修改音量为通话场景的音量。

int32_t AudioPolicyService::SetAudioScene(AudioScene audioScene)
{
    ...
    // fetch input&output device
    FetchDevice(true); // output
    FetchDevice(false); // input

    ...
    if (haveArmUsbDevice) {
        result = gsp->SetAudioScene(audioScene, activeOutputDevices, DEVICE_TYPE_USB_ARM_HEADSET,
            a2dpOffloadFlag_);
    } else {
        result = gsp->SetAudioScene(audioScene, activeOutputDevices, GetCurrentInputDeviceType(),
            a2dpOffloadFlag_);
    }
    IPCSkeleton::SetCallingIdentity(identity);
    CHECK_AND_RETURN_RET_LOG(result == SUCCESS, ERR_OPERATION_FAILED, "failed [%{public}d]", result);

    if (audioScene_ == AUDIO_SCENE_PHONE_CALL) {
        SetVoiceCallVolume(GetSystemVolumeLevel(STREAM_VOICE_CALL));
    }

    return SUCCESS;
}

2.AudioPolicyService::FetchDevice根据传入的参数判断是更改输入设备还是输出设备,isOutputDevice为true则为输出设备

void AudioPolicyService::FetchDevice(bool isOutputDevice, const AudioStreamDeviceChangeReasonExt reason)
{
    Trace trace("AudioPolicyService::FetchDevice reason:" + std::to_string(static_cast<int>(reason)));
    AUDIO_DEBUG_LOG("FetchDevice start");

    if (isOutputDevice) {
        vector<unique_ptr<AudioRendererChangeInfo>> rendererChangeInfos;
        streamCollector_.GetCurrentRendererChangeInfos(rendererChangeInfos);
        FetchOutputDevice(rendererChangeInfos, reason);
    } else {
        vector<unique_ptr<AudioCapturerChangeInfo>> capturerChangeInfos;
        streamCollector_.GetCurrentCapturerChangeInfos(capturerChangeInfos);
        FetchInputDevice(capturerChangeInfos, reason);
    }
}

3.更改输入设备

void AudioPolicyService::FetchInputDevice(vector<unique_ptr<AudioCapturerChangeInfo>> &capturerChangeInfos,
    const AudioStreamDeviceChangeReasonExt reason)
{
    Trace trace("AudioPolicyService::FetchInputDevice");
    AUDIO_INFO_LOG("Start for %{public}zu stream, connected %{public}s",
        capturerChangeInfos.size(), audioDeviceManager_.GetConnDevicesStr().c_str());
    bool needUpdateActiveDevice = true;
    bool isUpdateActiveDevice = false;
    int32_t runningStreamCount = 0;
    // 遍历捕获流信息并处理
    for (auto &capturerChangeInfo : capturerChangeInfos) {
        SourceType sourceType = capturerChangeInfo->capturerInfo.sourceType;
        // 判断是否需要跳过捕获流
        if ((sourceType == SOURCE_TYPE_VIRTUAL_CAPTURE && audioScene_ != AUDIO_SCENE_PHONE_CALL) ||
            (sourceType != SOURCE_TYPE_VIRTUAL_CAPTURE && capturerChangeInfo->capturerState != CAPTURER_RUNNING)) {
            AUDIO_INFO_LOG("stream %{public}d not running, no need fetch device", capturerChangeInfo->sessionId);
            continue;
        }
        runningStreamCount++;
        // 获取输入设备描述符
        unique_ptr<AudioDeviceDescriptor> desc = audioRouterCenter_.FetchInputDevice(sourceType,
            capturerChangeInfo->clientUID);
        DeviceInfo inputDeviceInfo = capturerChangeInfo->inputDeviceInfo;
        // 设备变更处理
        if (HandleDeviceChangeForFetchInputDevice(desc, capturerChangeInfo) == ERR_NEED_NOT_SWITCH_DEVICE) {
            continue;
        }
        // 蓝牙设备处理
        if (desc->deviceType_ == DEVICE_TYPE_BLUETOOTH_SCO) {
            BluetoothScoFetch(desc, capturerChangeInfos, sourceType);
        }
        // 更新当前活跃输入设备
        if (needUpdateActiveDevice) {
            AudioDeviceDescriptor tempDesc = GetCurrentInputDevice();
            if (!IsSameDevice(desc, tempDesc)) {
                WriteInputRouteChangeEvent(desc, reason);
                SetCurrenInputDevice(*desc);    // 修改当前设备参数
                AUDIO_DEBUG_LOG("currentActiveInputDevice update %{public}d", GetCurrentInputDeviceType());
                isUpdateActiveDevice = true;
            }
            needUpdateActiveDevice = false;
        }
        if (NotifyRecreateCapturerStream(isUpdateActiveDevice, capturerChangeInfo, reason)) {continue;}
        // 切换设备
        MoveToNewInputDevice(capturerChangeInfo, desc);
        // 更新音频捕获器的麦克风描述符
        AddAudioCapturerMicrophoneDescriptor(capturerChangeInfo->sessionId, desc->deviceType_);
    }
    // 如果设备已更新,则更新系统中首选的输入设备
    if (isUpdateActiveDevice) {
        OnPreferredInputDeviceUpdated(GetCurrentInputDeviceType(), ""); // networkId is not used.
    }
    if (runningStreamCount == 0) {
        FetchInputDeviceWhenNoRunningStream();
    }
}
Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐