安卓音频输出设备切换时framwork代码流程

您所在的位置:网站首页 安卓调用api切换音频输出设备是什么 安卓音频输出设备切换时framwork代码流程

安卓音频输出设备切换时framwork代码流程

2024-07-17 14:39| 来源: 网络整理| 查看: 265

          安卓系统维护着很多种的streamType并且根据音频策略尽量做到了互不影响。这其中的复杂繁复程度绝不是我们使用手机播放个音乐那么简单。比如我们接上蓝牙耳机播放网易云音乐,此时此刻来了电话会怎样?底层代码流程会怎么处理?这些都是我们需要了解并熟知于心的。笔者也是刚接触不久,作此文仅当备忘与加强记忆。

           比如我们正在播放音乐,玩家接入了蓝牙耳机会怎么处理呢?

           首先桌面Luncher会相应设备接入信号,并且响应设备切换逻辑,调用AudioSystem的setDeviceConnectionState()函数:

public static native int setDeviceConnectionState(int device, int state, String device_address, String device_name);

            直接就捅到了JNI层,所以我们要在JNI曾的AudioSystem类中寻找这个函数的实现:

status_t AudioSystem::setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address, const char *device_name) { const sp& aps = AudioSystem::get_audio_policy_service(); const char *address = ""; const char *name = ""; if (aps == 0) return PERMISSION_DENIED; if (device_address != NULL) { address = device_address; } if (device_name != NULL) { name = device_name; } return aps->setDeviceConnectionState(device, state, address, name); }

          逻辑检查并获取AudioPolicyService的服务,并调用其setDeviceConnectionState()函数:

//xref: /frameworks/av/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address, const char *device_name) { if (mAudioPolicyManager == NULL) { return NO_INIT; } if (!settingsAllowed()) { return PERMISSION_DENIED; } if (state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE && state != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) { return BAD_VALUE; } ALOGV("setDeviceConnectionState()"); Mutex::Autolock _l(mLock); return mAudioPolicyManager->setDeviceConnectionState(device, state, device_address, device_name); }

      还是检查和调用,直接看AudioPolicyManager:

status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address, const char *device_name) { return setDeviceConnectionStateInt(device, state, device_address, device_name); } status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address, const char *device_name) { ALOGD("setDeviceConnectionStateInt() device: 0x%X, state %d, address %s name %s", - device, state, device_address, device_name); // connect/disconnect only 1 device at a time if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE; sp devDesc = mHwModules.getDeviceDescriptor(device, device_address, device_name); // handle output devices if (audio_is_output_device(device)) { SortedVector outputs; ssize_t index = mAvailableOutputDevices.indexOf(devDesc); // save a copy of the opened output descriptors before any output is opened or closed // by checkOutputsForDevice(). This will be needed by checkOutputForAllStrategies() mPreviousOutputs = mOutputs; switch (state) { // handle output device connection case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: { if (index >= 0) { ALOGW("setDeviceConnectionState() device already connected: %x", device); return INVALID_OPERATION; } ALOGV("setDeviceConnectionState() connecting device %x", device); // register new device as available index = mAvailableOutputDevices.add(devDesc); if (index >= 0) { sp module = mHwModules.getModuleForDevice(device); if (module == 0) { ALOGD("setDeviceConnectionState() could not find HW module for device %08x", device); mAvailableOutputDevices.remove(devDesc); return INVALID_OPERATION; } mAvailableOutputDevices[index]->attach(module); } else { return NO_MEMORY; } // Before checking outputs, broadcast connect event to allow HAL to retrieve dynamic // parameters on newly connected devices (instead of opening the outputs...) broadcastDeviceConnectionState(device, state, devDesc->mAddress); if (checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress) != NO_ERROR) { mAvailableOutputDevices.remove(devDesc); broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, devDesc->mAddress); return INVALID_OPERATION; } // Propagate device availability to Engine mEngine->setDeviceConnectionState(devDesc, state); // outputs should never be empty here ALOG_ASSERT(outputs.size() != 0, "setDeviceConnectionState():" "checkOutputsForDevice() returned no outputs but status OK"); ALOGV("setDeviceConnectionState() checkOutputsForDevice() returned %zu outputs", outputs.size()); } break; // handle output device disconnection case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: { if (index < 0) { ALOGW("setDeviceConnectionState() device not connected: %x", device); return INVALID_OPERATION; } ALOGV("setDeviceConnectionState() disconnecting output device %x", device); // Send Disconnect to HALs broadcastDeviceConnectionState(device, state, devDesc->mAddress); // remove device from available output devices mAvailableOutputDevices.remove(devDesc); checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress); // Propagate device availability to Engine mEngine->setDeviceConnectionState(devDesc, state); } break; default: ALOGE("setDeviceConnectionState() invalid state: %x", state); return BAD_VALUE; } // checkA2dpSuspend must run before checkOutputForAllStrategies so that A2DP // output is suspended before any tracks are moved to it checkA2dpSuspend(); checkOutputForAllStrategies(); // outputs must be closed after checkOutputForAllStrategies() is executed if (!outputs.isEmpty()) { for (size_t i = 0; i < outputs.size(); i++) { sp desc = mOutputs.valueFor(outputs[i]); // close unused outputs after device disconnection or direct outputs that have been // opened by checkOutputsForDevice() to query dynamic parameters if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) || (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) && (desc->mDirectOpenCount == 0))) { closeOutput(outputs[i]); } } // check again after closing A2DP output to reset mA2dpSuspended if needed checkA2dpSuspend(); } updateDevicesAndOutputs(); if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) { audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/); updateCallRouting(newDevice); } for (size_t i = 0; i < mOutputs.size(); i++) { sp desc = mOutputs.valueAt(i); if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (desc != mPrimaryOutput)) { audio_devices_t newDevice = getNewOutputDevice(desc, true /*fromCache*/); // do not force device change on duplicated output because if device is 0, it will // also force a device 0 for the two outputs it is duplicated to which may override // a valid device selection on those outputs. bool force = !desc->isDuplicated() && (!device_distinguishes_on_address(device) // always force when disconnecting (a non-duplicated device) || (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)); setOutputDevice(desc, newDevice, force, 0); } } if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) { cleanUpForDevice(devDesc); } mpClientInterface->onAudioPortListUpdate(); return NO_ERROR; } // end if is output device

        不得不说谷歌的代码注释写的真的好



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3