Android 蓝牙hfp初始化、rfcomm连接、slc连接、sco连接源代码分析大全,非常详细的从btif-bta-btm - 点击下载
上文我们分析到:当HFP SLC服务水平连接完成后,发出广播:
BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED
那么谁来接收这个广播的呢?
一、设置当前device为active state/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/ActiveDeviceManager.java
BluetoothPhonePolicy: processProfileStateChanged, device=D8:AF:F1:92:D0:54, profile=1, 1 -> 2 然后开始连接其他profile
BluetoothActiveDeviceManager: handleMessage(MESSAGE_HFP_ACTION_CONNECTION_STATE_CHANGED): device D8:AF:F1:92:D0:54 connected
接收到广播,并发送给target
case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED: 150 mHandler.obtainMessage(MESSAGE_HFP_ACTION_CONNECTION_STATE_CHANGED, 151 intent).sendToTarget(); 152 break;
/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/ActiveDeviceManager.java
继续再对应的handle中处理此条消息
BluetoothActiveDeviceManager: setHfpActiveDevice(D8:AF:F1:92:D0:54)
public void handleMessage(Message msg) {
175 switch (msg.what) {
case MESSAGE_HFP_ACTION_CONNECTION_STATE_CHANGED: {
249 Intent intent = (Intent) msg.obj;
。。。。。
if (nextState == BluetoothProfile.STATE_CONNECTED) {
259 // Device connected
260 if (DBG) {
261 Log.d(TAG,
262 "handleMessage(MESSAGE_HFP_ACTION_CONNECTION_STATE_CHANGED): "
263 + "device " + device + " connected");
264 }
265 if (mHfpConnectedDevices.contains(device)) {
266 break; // The device is already connected
267 }
268 mHfpConnectedDevices.add(device);
269 if (mHearingAidActiveDevice == null) {
270 // New connected device: select it as active
271 setHfpActiveDevice(device);//此时需要将此设备设置为active状态。
272 break;
273 }
274 break;
275 }
private void setHfpActiveDevice(BluetoothDevice device) {
438 if (DBG) {
439 Log.d(TAG, "setHfpActiveDevice(" + device + ")");
440 }
441 final HeadsetService headsetService = mFactory.getHeadsetService();
442 if (headsetService == null) {
443 return;
444 }
445 if (!headsetService.setActiveDevice(device)) {//调用headset服务中的setactivedevice函数
446 return;
447 }
448 mHfpActiveDevice = device;
449 }
我们看将此设备设置为active流程:
/packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetService.java
public boolean setActiveDevice(BluetoothDevice device, AttributionSource source) {
716 Attributable.setAttributionSource(device, source);
717 HeadsetService service = getService(source);
718 if (service == null) {
719 return false;
720 }
721 return service.setActiveDevice(device);
722 }
* Set the active device.
public boolean setActiveDevice(BluetoothDevice device) {
1168 Log.i(TAG, "setActiveDevice: device=" + device + ", " + Utils.getUidPidString());
1169 synchronized (mStateMachines) {
1170 if (device == null) {
......
if (!mNativeInterface.setActiveDevice(device)) {//这里会走到协议栈去设置为active。
1203 Log.e(TAG, "setActiveDevice: Cannot set " + device + " as active in native layer");
1204 return false;
1205 }
BluetoothDevice previousActiveDevice = mActiveDevice;
1207 mActiveDevice = device; //获取到改设备
1208 if (getAudioState(previousActiveDevice) != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
1209 if (!disconnectAudio(previousActiveDevice)) {
1210 Log.e(TAG, "setActiveDevice: fail to disconnectAudio from "
1211 + previousActiveDevice);
1212 mActiveDevice = previousActiveDevice;
1213 mNativeInterface.setActiveDevice(previousActiveDevice);
1214 return false;
1215 }
1216 。。。。。。。。。。
1225 } else {
1226 broadcastActiveDevice(mActiveDevice);//如果之前的active设备已经断开,发送广播,设备为active状态
1227 }
1228 }
1229 return true;
上面这个函数会走到协议栈中去,进行设置为active。在协议栈中其实是用一个全局变量来存放当前active设备,我们暂且不追踪了。
在上一个函数中继续发送广播:
//发送广播:BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED
private void broadcastActiveDevice(BluetoothDevice device) {
1806 logD("broadcastActiveDevice: " + device);
1807 BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_ACTIVE_DEVICE_CHANGED,
1808 BluetoothProfile.HEADSET, mAdapterService.obfuscateAddress(device),
1809 mAdapterService.getMetricId(device));
1810 Intent intent = new Intent(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED);
1811 intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
1812 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1813 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
1814 sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_CONNECT,
1815 Utils.getTempAllowlistBroadcastOptions());
1816 }
谁来接收广播呢?
/frameworks/base/services/core/java/com/android/server/audio/AudioService.java
* Receiver for misc intent broadcasts the Phone app cares about.
7792 */
7793 private class AudioServiceBroadcastReceiver extends BroadcastReceiver {
7794 @Override
7795 public void onReceive(Context context, Intent intent) {
7796 final String action = intent.getAction();
7797 int outDevice;
7798 int inDevice;
7799 int state;
。。。。。。
} else if (action.equals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)
7832 || action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
7833 mDeviceBroker.receiveBtEvent(intent);//走到这个函数中处理
frameworks/base/services/core/java/com/android/server/audio/AudioDeviceBroker.java
接收到active广播:
* Handle BluetoothHeadset intents where the action is one of
207 * {@link BluetoothHeadset#ACTION_ACTIVE_DEVICE_CHANGED} or
208 * {@link BluetoothHeadset#ACTION_AUDIO_STATE_CHANGED}.
209 * @param intent
210 */
211 void receiveBtEvent(@NonNull Intent intent) {
212 synchronized (mSetModeLock) {
213 synchronized (mDeviceStateLock) {
214 mBtHelper.receiveBtEvent(intent);
215 }
216 }
217 }
/frameworks/base/services/core/java/com/android/server/audio/BtHelper.java
类来封装使用蓝牙服务的所有通信。
synchronized void receiveBtEvent(Intent intent) {
296 final String action = intent.getAction();
297
298 Log.i(TAG, "receiveBtEvent action: " + action + " mScoAudioState: " + mScoAudioState);
299 if (action.equals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)) {
300 BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
301 setBtScoActiveDevice(btDevice);//将此设备设为active状态。
private void setBtScoActiveDevice(BluetoothDevice btDevice) {
606 Log.i(TAG, "setBtScoActiveDevice: " + getAnonymizedAddress(mBluetoothHeadsetDevice)
607 + " -> " + getAnonymizedAddress(btDevice));
608 final BluetoothDevice previousActiveDevice = mBluetoothHeadsetDevice;
609 if (Objects.equals(btDevice, previousActiveDevice)) {
610 return;
611 }
//首先移除之前的active设备
612 if (!handleBtScoActiveDeviceChange(previousActiveDevice, false)) {
613 Log.w(TAG, "setBtScoActiveDevice() failed to remove previous device "
614 + getAnonymizedAddress(previousActiveDevice));
615 }//添加新的active设备
616 if (!handleBtScoActiveDeviceChange(btDevice, true)) {
617 Log.e(TAG, "setBtScoActiveDevice() failed to add new device "
618 + getAnonymizedAddress(btDevice));
619 // set mBluetoothHeadsetDevice to null when failing to add new device
620 btDevice = null;
621 }
622 mBluetoothHeadsetDevice = btDevice;
623 if (mBluetoothHeadsetDevice == null) {
624 resetBluetoothSco();
625 }
626 }
private boolean handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive) {
570 if (btDevice == null) {
571 return true;
572 }
573 int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
574 AudioDeviceAttributes audioDevice = btHeadsetDeviceToAudioDevice(btDevice);//添加设备属性
575 String btDeviceName = getName(btDevice);
576 boolean result = false;
577 if (isActive) {
578 result |= mDeviceBroker.handleDeviceConnection(isActive, audioDevice.getInternalType(),
579 audioDevice.getAddress(), btDeviceName);
580 } else {
581 int[] outDeviceTypes = {
582 AudioSystem.DEVICE_OUT_BLUETOOTH_SCO,
583 AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
584 AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT
585 };
586 for (int outDeviceType : outDeviceTypes) {
587 result |= mDeviceBroker.handleDeviceConnection(
588 isActive, outDeviceType, audioDevice.getAddress(), btDeviceName);
589 }
590 }
591 // handleDeviceConnection() && result to make sure the method get executed
592 result = mDeviceBroker.handleDeviceConnection(
593 isActive, inDevice, audioDevice.getAddress(), btDeviceName) && result;
594 return result;
595 }
596
执行mDeviceBroker.handleDeviceConnection()函数
/frameworks/base/services/core/java/com/android/server/audio/AudioDeviceBroker.java
boolean handleDeviceConnection(boolean connect, int device, String address,
987 String deviceName) {
988 synchronized (mDeviceStateLock) {
989 return mDeviceInventory.handleDeviceConnection(connect, device, address, deviceName);
990 }
991 }
/frameworks/base/services/core/java/com/android/server/audio/AudioDeviceInventory.java
•使用AudioSystem实现通信,以(断开)连接本机层中的设备。
开始连接到设备
boolean handleDeviceConnection(boolean connect, int device, String address,
734 String deviceName) {
735 if (AudioService.DEBUG_DEVICES) {
736 Slog.i(TAG, "handleDeviceConnection(" + connect + " dev:"
737 + Integer.toHexString(device) + " address:" + address
738 + " name:" + deviceName + ")");
739 }
740 MediaMetrics.Item mmi = new MediaMetrics.Item(mMetricsId + "handleDeviceConnection")
741 .set(MediaMetrics.Property.ADDRESS, address)
742 .set(MediaMetrics.Property.DEVICE, AudioSystem.getDeviceName(device))
743 .set(MediaMetrics.Property.MODE, connect
744 ? MediaMetrics.Value.CONNECT : MediaMetrics.Value.DISCONNECT)
745 .set(MediaMetrics.Property.NAME, deviceName);
746 synchronized (mDevicesLock) {
747 final String deviceKey = DeviceInfo.makeDeviceListKey(device, address);
748 if (AudioService.DEBUG_DEVICES) {
749 Slog.i(TAG, "deviceKey:" + deviceKey);
750 }
751 DeviceInfo di = mConnectedDevices.get(deviceKey);
752 boolean isConnected = di != null;
753 if (AudioService.DEBUG_DEVICES) {
754 Slog.i(TAG, "deviceInfo:" + di + " is(already)Connected:" + isConnected);
755 }
756 if (connect && !isConnected) {
//开始设置设备连接状态:
757 final int res = mAudioSystem.setDeviceConnectionState(device,
758 AudioSystem.DEVICE_STATE_AVAILABLE, address, deviceName,
759 AudioSystem.AUDIO_FORMAT_DEFAULT);
760 if (res != AudioSystem.AUDIO_STATUS_OK) {
761 final String reason = "not connecting device 0x" + Integer.toHexString(device)
762 + " due to command error " + res;
763 Slog.e(TAG, reason);
764 mmi.set(MediaMetrics.Property.EARLY_RETURN, reason)
765 .set(MediaMetrics.Property.STATE, MediaMetrics.Value.DISCONNECTED)
766 .record();
767 return false;
768 }
/frameworks/base/services/core/java/com/android/server/audio/AudioSystemAdapter.java
public int setDeviceConnectionState(int device, int state, String deviceAddress,
247 String deviceName, int codecFormat) {
248 invalidateRoutingCache();
249 return AudioSystem.setDeviceConnectionState(device, state, deviceAddress, deviceName,
250 codecFormat);
251 }
/frameworks/av/media/libaudioclient/AudioSystem.cpp
status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,
831 audio_policy_dev_state_t state,
832 const char* device_address,
833 const char* device_name,
834 audio_format_t encodedFormat) {
835 const sp& aps = AudioSystem::get_audio_policy_service();//为AudioPolicy service建立binder通信接口
836 const char* address = "";
837 const char* name = "";
838
839 if (aps == 0) return PERMISSION_DENIED;
840
841 if (device_address != NULL) {
842 address = device_address;
843 }
844 if (device_name != NULL) {
845 name = device_name;
846 }
847
848 media::AudioDevice deviceAidl;
849 deviceAidl.type = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_devices_t_int32_t(device));
850 deviceAidl.address = address;
851
852 return statusTFromBinderStatus(
853 aps->setDeviceConnectionState( //调用此接口
854 deviceAidl,
855 VALUE_OR_RETURN_STATUS(
856 legacy2aidl_audio_policy_dev_state_t_AudioPolicyDeviceState(state)),
857 name,
858 VALUE_OR_RETURN_STATUS(legacy2aidl_audio_format_t_AudioFormat(encodedFormat))));
859 }
/frameworks/av/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
Status AudioPolicyService::setDeviceConnectionState(
99 const media::AudioDevice& deviceAidl,
100 media::AudioPolicyDeviceState stateAidl,
101 const std::string& deviceNameAidl,
.....
ALOGV("setDeviceConnectionState()");
122 Mutex::Autolock _l(mLock);
123 AutoCallerClear acc;
124 return binderStatusFromStatusT(
125 mAudioPolicyManager->setDeviceConnectionState(device, state,
126 deviceAidl.address.c_str(),
127 deviceNameAidl.c_str(),
128 encodedFormat));
129 }
/frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
101 audio_policy_dev_state_t state,
102 const char *device_address,
103 const char *device_name,
104 audio_format_t encodedFormat)
105 {
106 status_t status = setDeviceConnectionStateInt(device, state, device_address,
107 device_name, encodedFormat);
108 nextAudioPortGeneration();
109 return status;
110 }
status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t deviceType,
123 audio_policy_dev_state_t state,
124 const char *device_address,
125 const char *device_name,
126 audio_format_t encodedFormat)
127 {
128 ALOGV("setDeviceConnectionStateInt() device: 0x%X, state %d, address %s name %s format 0x%X",
129 deviceType, state, device_address, device_name, encodedFormat);
130
131 // connect/disconnect only 1 device at a time如果不是输入或者输出设备,则返回错误
132 if (!audio_is_output_device(deviceType) && !audio_is_input_device(deviceType)) return BAD_VALUE;
133 //mHwModules 包含了所有模块的设备描述符
134 sp device =
135 mHwModules.getDeviceDescriptor(deviceType, device_address, device_name, encodedFormat,
136 state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
137 return device ? setDeviceConnectionStateInt(device, state) : INVALID_OPERATION;
138 }
139
先去获取硬件模块走mHwModules.getDeviceDescriptor()这个函数:
返回一个与设备类型和设备地址相关联的设备描述符(如果matchAddress为true)。
是从hw_mode中去获取驱动支持的设备,获取到对应的硬件模块:
spHwModuleCollection::getDeviceDescriptor(const audio_devices_t deviceType, 332 const char *address, 333 const char *name, 334 const audio_format_t encodedFormat, 335 bool allowToCreate, 336 bool matchAddress) const 337 { 338 String8 devAddress = (address == nullptr || !matchAddress) ? String8("") : String8(address); 339 // handle legacy remote submix case where the address was not always specified 340 if (audio_is_remote_submix_device(deviceType) && (devAddress.length() == 0)) { 341 devAddress = String8("0"); 342 } ..... if (!allowToCreate) { 377 ALOGV("%s: could not find HW module for device %s %04x address %s", __FUNCTION__, 378 name, deviceType, address); 379 return nullptr; 380 } 381 return createDevice(deviceType, address, name, encodedFormat);
APM::HwModule: createDevice: adding dynamic device type:0x10,@:D8:AF:F1:92:D0:54 to module primary
spHwModuleCollection::createDevice(const audio_devices_t type, 385 const char *address, 386 const char *name, 387 const audio_format_t encodedFormat) const 388 { 389 std::string tagName = {}; 390 sp hwModule = getModuleForDeviceType(type, encodedFormat, &tagName); 391 if (hwModule == 0) { 392 ALOGE("%s: could not find HW module for device %04x address %s", __FUNCTION__, type, 393 address); 394 return nullptr; 395 } 396 397 sp device = new DeviceDescriptor(type, tagName, address); 398 device->setName(name); 399 device->setEncodedFormat(encodedFormat); 400 device->setDynamic(); 401 // Add the device to the list of dynamic devices 402 hwModule->addDynamicDevice(device); 403 // Reciprocally attach the device to the module 404 device->attach(hwModule); 405 ALOGD("%s: adding dynamic device %s to module %s", __FUNCTION__, 406 device->toString().c_str(), hwModule->getName()); 407 ....... 10 for (const auto &profile : profiles) {//根据profile,获取到hwmodule 411 // Add the device as supported to all profile supporting "weakly" or not the device 412 // according to its type 413 if (profile->supportsDevice(device, false )) { 414 415 // @todo quid of audio profile? import the profile from device of the same type? 416 const auto &isoTypeDeviceForProfile = 417 profile->getSupportedDevices().getDevice(type, String8(), AUDIO_FORMAT_DEFAULT); 418 device->importAudioPortAndPickAudioProfile(isoTypeDeviceForProfile, true ); 419 420 ALOGV("%s: adding device %s to profile %s", __FUNCTION__, 421 device->toString().c_str(), profile->getTagName().c_str()); 422 profile->addSupportedDevice(device); 423 } 424 } 425 return device;
继续看这个函数:setDeviceConnectionStateInt
status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp&device, 141 audio_policy_dev_state_t state) 142 { 143 // handle output devices如果不是输入或者输出设备,返回错误 144 if (audio_is_output_device(device->type())) { 145 SortedVector outputs; 146 147 ssize_t index = mAvailableOutputDevices.indexOf(device); 148 149 // save a copy of the opened output descriptors before any output is opened or closed 150 // by checkOutputsForDevice(). This will be needed by checkOutputForAllStrategies() 151 mPreviousOutputs = mOutputs; 152 switch (state) 153 { 154 // handle output device connection 155 case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: { 156 if (index >= 0) {//说明已经连接,而且已经处理过了 157 ALOGW("%s() device already connected: %s", __func__, device->toString().c_str()); 158 return INVALID_OPERATION; 159 } 160 ALOGV("%s() connecting device %s format %x", 161 __func__, device->toString().c_str(), device->getEncodedFormat()); 162 163 // register new device as available添加到mAvailableOutputDevices中 164 if (mAvailableOutputDevices.add(device) < 0) { 165 return NO_MEMORY; 166 } 167 //在检查输出之前,广播连接事件以允许HAL在新连接的设备上检索动态参数(而不是打开输出…) 168 // Before checking outputs, broadcast connect event to allow HAL to retrieve dynamic 169 // parameters on newly connected devices (instead of opening the outputs...) 170 broadcastDeviceConnectionState(device, state); 171 172 if (checkOutputsForDevice(device, state, outputs) != NO_ERROR) { 173 mAvailableOutputDevices.remove(device); 174 175 mHwModules.cleanUpForDevice(device); 176 177 broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE); 178 return INVALID_OPERATION; 179 } 180 181 // Populate encapsulation information when a output device is connected. 182 device->setEncapsulationInfoFromHal(mpClientInterface); 183 184 // outputs should never be empty here 185 ALOG_ASSERT(outputs.size() != 0, "setDeviceConnectionState():" 186 "checkOutputsForDevice() returned no outputs but status OK"); 187 ALOGV("%s() checkOutputsForDevice() returned %zu outputs", __func__, outputs.size()); 188 189 } break; 。。。。。。 mpClientInterface->onAudioPortListUpdate(); 这里会更新audio列表 /frameworks/base/media/java/android/media/AudioManager.java onAudioPortListUpdate--》broadcastDeviceListChange_sync--》NativeEventHandlerDelegate(MSG_DEVICES_DEVICES_ADDED) /packages/apps/Bluetooth/src/com/android/bluetooth/btservice/ActiveDeviceManager.java onAudioDevicesAdded //BluetoothActiveDeviceManager: 【】Audio device added: RP-HD605N type: 7
在调用checkingoutput之前广播调用setparameters去通知通知所有的hardware module,有新的设备正在处理中,不同的hardware module会有不同的操作。比如primary module回去判断是否需要做bootcomplete.
void AudioPolicyManager::broadcastDeviceConnectionState(const sp&device, 113 audio_policy_dev_state_t state) 114 { 115 AudioParameter param(String8(device->address().c_str())); 116 const String8 key(state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE ? 117 AudioParameter::keyDeviceConnect : AudioParameter::keyDeviceDisconnect); 118 param.addInt(key, device->type()); 119 mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString()); 120 }
/frameworks/av/services/audiopolicy/service/AudioPolicyClientImpl.cpp
mpClientInterface指向的是AudioPolicyClientImpl.cpp,但最终会调用到AudioFlinger.cpp文件中。
175 void AudioPolicyService::AudioPolicyClient::setParameters(audio_io_handle_t io_handle,
176 const String8& keyValuePairs,
177 int delay_ms)
178 {
179 mAudioPolicyService->setParameters(io_handle, keyValuePairs.string(), delay_ms);
180 }
/frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp
void AudioPolicyService::setParameters(audio_io_handle_t ioHandle,
2301 const char *keyValuePairs,
2302 int delayMs)
2303 {
2304 mAudioCommandThread->parametersCommand(ioHandle, keyValuePairs,
2305 delayMs);
2306 }
frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp
status_t AudioPolicyService::AudioCommandThread::parametersCommand(audio_io_handle_t ioHandle,
1871 const char *keyValuePairs,
1872 int delayMs)
1873 {
1874 sp command = new AudioCommand();
1875 command->mCommand = SET_PARAMETERS;
1876 sp data = new ParametersData();
1877 data->mIO = ioHandle;
1878 data->mKeyValuePairs = String8(keyValuePairs);
1879 command->mParam = data;
1880 command->mWaitStatus = true;
1881 ALOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d",
1882 keyValuePairs, ioHandle, delayMs);
1883 return sendCommand(command, delayMs);
1884 }
AudioPolicyService: AudioCommandThread() adding set parameter string D8:AF:F1:92:D0:54=;connect=16, io 0 ,delay 0【】
AudioCommandThread线程里面处理(SET_PARAMETERS)
AudioPolicyService::AudioCommandThread::threadLoop()
case SET_PARAMETERS
AudioSystem::setParameters()
af->setParameters()【AudioFlinger】
AudioFlinger处理(setParameters)
设置参数到此为止,剩下的属于audio模块了,暂不深究了。
接下来继续分析checkOutputsForDevice这个函数,非常重要的函数:
setOutputDevices()设置输出设备
/frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
之后就是打开了设备等等一系列操作,奈何本博主是个蓝牙开发,之后有时间再研究下河audio有关的这个函数吧。



