In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-21 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
How to analyze AudioPolicyService in Android? in view of this problem, this article introduces the corresponding analysis and solution in detail, hoping to help more partners who want to solve this problem to find a more simple and feasible method.
One purpose
What is AudioPolicyService (APS)? Why does it exist? How is the lower Audio HAL layer integrated into Android? What's more, ask a real question: after the headphones are plugged in, how does the sound change from the initial external playback to the output from the headphones? When adjusting the volume, do you adjust the Music or the incoming volume? We didn't talk about any of these things in the AF process. But these are very important. From my personal understanding, Policy is more complex and difficult to understand than the process.
Of course, to follow our traditional analytical habits, we have to have a starting point, otherwise we don't know where to start.
The entry point here will be:
What exactly did the AF and APS systems do when they first got up?
The processing of AF and APS after the headphone insertion event is detected.
Everyone followed me step by step, and soon found that, ah, APS is not that difficult.
In addition, the format of this code analysis will refer to the appearance of "Linux Kernel scenario Analysis", and the parsing of function calls will adopt a depth-first approach, that is, explain the called function first, and then come out to continue.
I have given up analyzing APS several times, the key reason is that I didn't find an entry point, only knowing that the code was seen from beginning to end!
The birth of AF and APS
Too much has been said about this thing. In framework/base/media/MediaServer/Main_MediaServer.
Let's see.
Int main (int argc, char** argv) {sp proc (ProcessState::self ()); sp sm = defaultServiceManager (); / / create AF AudioFlinger::instantiate () first; / / then create APS AudioPolicyService::instantiate (); ProcessState::self ()-> startThreadPool (); IPCThreadState::self ()-> joinThreadPool ();} 2.1 new AudioFlinger
As mentioned earlier, an object is instantiated internally in instantiate, which looks directly at the constructor of AF.
AudioFlinger::AudioFlinger (): BnAudioFlinger (), / / Base class constructor mAudioHardware (0), mMasterVolume (1.0f), mMasterMute (false), mNextThreadId (0) {
Note mAudioHardware and mNextThreadId
MHardwareStatus = AUDIO_HW_IDLE
/ / create a HAL representative of audio
MAudioHardware = AudioHardwareInterface::create ()
MHardwareStatus = AUDIO_HW_INIT
/ / will you not be able to use APS as follows? APS hasn't been created yet!
If (mAudioHardware- > initCheck () = = NO_ERROR) {setMode (AudioSystem::MODE_NORMAL); setMasterVolume (1.0f); setMasterMute (false);}
It feels like the constructor of AF is to create a HAL representative of the most important AudioHardWare.
The rest seems to have nothing to do with strategy.
However: AF creates a HAL object for AudioHardware. Note that this is the only AudioHardware for the whole system. In other words, whether it is line-controlled headset, Bluetooth headset, Mike, external, and so on, it will eventually be managed by this HAL.
Watch APS again.
2.2 new AudioPolicyServiceAudioPolicyService::AudioPolicyService (): BnAudioPolicyService (), mpPolicyManager (NULL) {/ / mpPolicyManager? Policy Manager? May be very important char value [property _ VALUE_MAX]; / / TonePlayback? Who plays the ringtone? Why did you put it here? Let's take a look at mTonePlaybackThread = new AudioCommandThread (String8 ("")); / / AudioCommand? Audio commands? When I see Command, I think of the Command pattern in the design pattern / / this pattern is widely used in Android, especially in MediaPlayerService. MAudioCommandThread = new AudioCommandThread (String8 ("ApmCommandThread")); # if (defined GENERIC_AUDIO) | | (defined AUDIO_POLICY_TEST) / / pay attention to the constructor of AudioPolicyManagerBase, passing this in. MpPolicyManager = new AudioPolicyManagerBase (this); / / Let's assume we use Generic's Audio device. # else... # endif
/ / determine whether the camera is forced to use sound according to the system properties. This. Why did you put it here?
/ / it seems that when the phone comes out with a camera, it must make a sound when it is forced to press the shutter in order to prevent secretly taking pictures.
/ / is that the purpose?
Property_get ("ro.camera.sound.forced", value, "0"); mpPolicyManager- > setSystemProperty ("ro.camera.sound.forced", value);}
So easygoing, really? We should not let go of any doubt! With so many questions, which one should we look at first? AudioPolicy is analyzed here, and an AudioPolicyManagerBase is created in the constructor, and different vendors can also implement their own AudioPolicyManager, which seems to play a vital role in the audio strategy.
I have to say that these names in Android code are discreet and accurate in key places.
In addition, the constructor of AudioPolicyManagerBase passes APS in, so it looks like there will be some callbacks on APS. It's really roundabout.
2.3 AudioPolicyManagerBase
The code location is in framework/base/libs/audioflinger/AudioPolicyManagerBase.cpp
AudioPolicyManagerBase::AudioPolicyManagerBase (AudioPolicyClientInterface * clientInterface): mPhoneState (AudioSystem::MODE_NORMAL),-> the status of the phone here? MRingerMode (0), mMusicStopTime (0), mLimitRingtoneVolume (false) {[--> mPhoneState (AudioSystem::MODE_NORMAL)]
AudioSystem is actually a good place to peek into how Android manages your audio system. Location in
In framework/base/include/media/AudioSystem.h, a large number of enumerations and the like are defined to express Google's view of the audio system. All we can do is to open it up.
Here is the definition of audio_mode. Here is one thing to pay attention to:
These definitions are similar to the JAVA layer definitions in SDK. In fact, it should be said that there is a definition of the C++ layer first, and then reflected in the JAVA layer. However, the definition of C++ layer is generally unexplained, which is found in SDK. So we have to face a painful reality: we often need to refer to SDK's instructions to figure out what it is.
For the AudioSystem section of C++, SDK's description is in AudioManager.
Enum audio_mode {/ / explain with reference to SDK instructions, the following no longer states that MODE_INVALID =-2, / / invalid mode MODE_CURRENT =-1 mode / current mode, and switching (routing) of audio equipment related to MODE_NORMAL = 0 mode / normal mode, no phone and ring tone MODE_RINGTONE,// received an incoming call signal At this point, there will be a ring tone MODE_IN_CALL,// phone mode, which means that a call has been established. NUM_MODES / / Android uses this technique a lot to indicate that the enumeration is over. }
All right, go on:
... MPhoneState (AudioSystem::MODE_NORMAL),-> is there a phone status here? MRingerMode (0), mMusicStopTime (0), mLimitRingtoneVolume (false) {mpClientInterface = clientInterface;//BT, save the APS object. / / forceUse? What is this? For (int I = 0; I
< AudioSystem::NUM_FORCE_USE; i++) { mForceUse[i] = AudioSystem::FORCE_NONE; } [---->AudioSystem::FORCE_NONE and AudioSystem::NUM_FORCE_USE]
Notice that there are two enumerations here, which is shameless. Let's take a look at this FORCE_NONE.
Enum forced_config {mandatory _ configuration. The name seems to force the use of devices, such as external player and headphones. Bluetooth and other FORCE_NONE, FORCE_SPEAKER, FORCE_HEADPHONES, FORCE_BT_SCO, FORCE_BT_A2DP, FORCE_WIRED_ACCESSORY, FORCE_BT_CAR_DOCK, FORCE_BT_DESK_DOCK, NUM_FORCE_CONFIG, FORCE_DEFAULT = FORCE_NONE / / this, too boring. }
And take a look at AudioSystem::NUM_FORCE_USE this.
Enum force_use {FOR_COMMUNICATION,// this is for_xxx, not force_xxx. FOR_MEDIA, FOR_RECORD, FOR_DOCK, NUM_FORCE_USE}
No, I don't understand either of them. What for? Can you guess anything? I can't either. Because we didn't find the right scene! All right, let's go to SDK. Mm-hmm.
I see the function AudioManager, setSpeakerphoneOn (boolean on). Okay, I.
Call like this
SetSpeakerphoneOn (true), look at the implementation.
I didn't waste any more time this time. I used a new tool, coolfind, to search the framework directory, find the * .java file, and match the string setSpeakerphone. Finally, I am.
I found it in framework/base/media/java/android/media/AudioService.java. Public void setSpeakerphoneOn (boolean on) {if (! checkAudioSettingsPermission ("setSpeakerphoneOn ()")) {return;} if (on) {
/ / seeing here, do you understand nine times out of ten? The following call is:
/ / force calls to use speaker! That's what it means!
AudioSystem.setForceUse (AudioSystem.FOR_COMMUNICATION, ioSystem.FORCE_SPEAKER); mForcedUseForComm = AudioSystem.FORCE_SPEAKER;} else {AudioSystem.setForceUse (AudioSystem.FOR_COMMUNICATION, ioSystem.FORCE_NONE); mForcedUseForComm = AudioSystem.FORCE_NONE;}}
All right, to get to the point, now that the Android source code has been released to us, is there any reason why we should not search more? Online google is also a search, search source code is also the same. But we have to have a purpose: to find a suitable use scenario.
Force_use and force_config don't need me to explain, do they?
[- > AudioPolicyManagerBase::AudioPolicyManagerBase].
/ / the meaning below is to set all the devices used in several for_use situations to NONE.
/ / for example, when setting up a FOR_MEDIA scenario, the device used is FORCE_NONE
For (int I = 0; I
< AudioSystem::NUM_FORCE_USE; i++) { mForceUse[i] = AudioSystem::FORCE_NONE; } // 目前可以的输出设备,耳机和外放 mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE | AudioSystem::DEVICE_OUT_SPEAKER; //目前可用的输入设备,内置MIC mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC; 又得来看看AudioSystem是怎么定义输入输出设备的了。 [--->MAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE] enum audio_devices {/ / output devices DEVICE_OUT_EARPIECE = 0x1, DEVICE_OUT_SPEAKER = 0x2, DEVICE_OUT_WIRED_HEADSET = 0x4, DEVICE_OUT_WIRED_HEADPHONE = 0x8, DEVICE_OUT_BLUETOOTH_SCO = 0x10, DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20, DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40 DEVICE_OUT_BLUETOOTH_A2DP = 0x80, DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100, DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200, DEVICE_OUT_AUX_DIGITAL = 0x400, DEVICE_OUT_DEFAULT = 0x8000 DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE | DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADSET | DEVICE_OUT_WIRED_HEADPHONE | DEVICE_OUT_BLUETOOTH_SCO | DEVICE_OUT_BLUETOOTH_SCO_HEADSET | DEVICE_OUT_BLUETOOTH_SCO_CARKIT | DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER | DEVICE_OUT_AUX_DIGITAL | DEVICE_OUT_DEFAULT) DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER), / / input devices DEVICE_IN_COMMUNICATION = 0x10000, DEVICE_IN_AMBIENT = 0x20000, DEVICE_IN_BUILTIN_MIC = 0x40000, DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x80000, DEVICE_IN_WIRED_HEADSET = 0x100000 DEVICE_IN_AUX_DIGITAL = 0x200000, DEVICE_IN_VOICE_CALL = 0x400000, DEVICE_IN_BACK_MIC = 0x800000, DEVICE_IN_DEFAULT = 0x80000000 DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION | DEVICE_IN_AMBIENT | DEVICE_IN_BUILTIN_MIC | DEVICE_IN_BLUETOOTH_SCO_HEADSET | DEVICE_IN_WIRED_HEADSET | DEVICE_IN_AUX_DIGITAL | DEVICE_IN_VOICE_CALL | DEVICE_IN_BACK_MIC | DEVICE_IN_DEFAULT)}
I marked some things that are easier to be dazzled in red. There are so many things, but there is nothing we don't understand.
All right, keep going.
[- > AudioPolicyManagerBase::AudioPolicyManagerBase]
/ / currently available output devices, with both headphones and external devices, the configuration is very strong.
/ / Note here is the OR operator, and finally mAvailableOutputDevices = 0X3
MAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE |
AudioSystem::DEVICE_OUT_SPEAKER
/ / currently available input devices. The built-in MIC,mAvailableInputDevices is 0x4000, but we don't care about input.
MAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC
There were very few things below, and we did it in one fell swoop.
/ / create an AudioOutputDescriptor and set its device to peripheral 0x2
AudioOutputDescriptor * outputDesc = new AudioOutputDescriptor (); outputDesc- > mDevice = (uint32_t) AudioSystem::DEVICE_OUT_SPEAKER
/ / call APS's openOutput to get a mHardwareOutput thing. This is an int type.
/ / but it may not be a pointer or a pointer.
/ / and the following parameters are all pointer types (except flags), isn't it? Will anyone change value?
MHardwareOutput = mpClientInterface- > openOutput (& outputDesc- > mDevice, & outputDesc- > mSamplingRate, & outputDesc- > mFormat, & outputDesc- > mChannels, & outputDesc- > mLatency, outputDesc- > mFlags)
/ / this. It is estimated that the int and pointers are added to a map, which is easy to manage.
AddOutput (mHardwareOutput, outputDesc)
/ / I don't know what to do. I'll see it later.
SetOutputDevice (mHardwareOutput, (uint32_t) AudioSystem::DEVICE_OUT_SPEAKER, true)
/ / I don't know what to do. I'll see it later.
UpdateDeviceForStrategy ()
Well, there are a series of functions waiting for us to call. Let's watch it one by one.
By the way, this is the core of AudioManagerBase.
[- > AudioOutputDescriptor * outputDesc = new AudioOutputDescriptor ()]
What is an AudioOutputDescriptor? I'm not a god. I have to read the notes, too.
/ / descriptor for audio outputs. Used to maintain current configuration of each opened audio output
/ / and keep track of the usage of this output by each audio stream type.
Do you understand? It probably means that it is such a thing:
L describes the audio output and can be used to save some configuration information.
L tracks how the audio stream type uses this output.
Don't you get it? You'll understand when it comes to the scene.
Its constructor does the following:
AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor (): mId (0), mSamplingRate (0), mFormat (0), mChannels (0), mLatency (0), mFlags ((AudioSystem::output_flags) 0), mDevice (0), mOutput1 (0), mOutput2 (0) {}
/ / good, everything is set to zero. I don't need to explain all these things, do I? The naming rules can also be seen.
OK,go on.
[- > mHardwareOutput = mpClientInterface- > openOutput ()]:
The openOutput of APS is called here. Take a look at this:
[--> AudioPolicyService::openOutput] audio_io_handle_t AudioPolicyService::openOutput (uint32_t * pDevices, uint32_t * pSamplingRate, uint32_t * pFormat, uint32_t * pChannels, uint32_t * pLatencyMs AudioSystem::output_flags flags) {sp af = AudioSystem::get_audio_flinger () / / Niang Hipi, get AF to return af- > openOutput (pDevices, pSamplingRate, (uint32_t *) pFormat, pChannels, pLatencyMs, flags) } [- > AudioFlinger::openOutput] int AudioFlinger::openOutput (uint32_t * pDevices, uint32_t * pSamplingRate, uint32_t * pFormat, uint32_t * pChannels, uint32_t * pLatencyMs Uint32_t flags) {/ / Let's think about the value passed in / / * pDevices=0x2, which means outward / / everything else is 0. Hey, hey, it's worth it, so don't you know how to go next? Status_t status; PlaybackThread * thread = NULL; mHardwareStatus = AUDIO_HW_OUTPUT_OPEN; uint32_t samplingRate = pSamplingRate? * pSamplingRate: 0; uint32_t format = pFormat? * pFormat: 0; uint32_t channels = pChannels? * pChannels: 0; uint32_t latency = pLatencyMs? * pLatencyMs: 0; Mutex::Autolock _ l (mLock); / / HAL object gets an AudioStreamOut, will the value passed in change? AudioStreamOut * output = mAudioHardware- > openOutputStream (* pDevices, (int *) & format, & channels, & samplingRate & status) MHardwareStatus = AUDIO_HW_IDLE; if (output! = 0) {
/ / which branch to take? Let me tell you the answer.
/ / the mAudioHardware- > openOutputStream just now does change the value corresponding to the pointer.
/ / of course, as we said, AF uses GENERIC's Audio hardware. If you are interested, you can take a look at its implementation.
/ / I'll post its contents later. Anyway, here.
/ / the values become: format is PCM_16_BIT,channels, PCM_16_BIT,channels is 2, sampling rate is 44100
/ / in that case, we can only go to the else branch.
If ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) | | (format! = AudioSystem::PCM_16_BIT) | | (channels! = AudioSystem::CHANNEL_OUT_STEREO) {thread = new DirectOutputThread (this, output, + + mNextThreadId);} else {
/ / do you still remember the students who analyzed in the first two sections, do you understand when you see here? Well, it turns out
/ / open an Output, a mixing thread is created in AF. That's a good design.
/ / imagine that the output of all programs that are set to be external is this outgoing stream mixing thread to work
/ / the output of all programs set to headphones is completed by this headset stream mixing thread.
/ / Why is there a special emphasis on stream? I don't see it.
/ / We are calling mAudioHardware- > openOutputStream. Returned
/ / it's an AudioStreamOut, but not a device. Android leaves all these things to the HAL layer to implement.
/ / you don't have to manage the headphones, peripherals, Bluetooth real devices and other things on the system on your own, it just uses AudioStreamOut to express what it wants. For example, Generic's Audio Hal supports only one OutputStream. -> only my opinion
Thread = new MixerThread (this, output, + + mNextThreadId)
}
/ / all right, there's another thread.
MPlaybackThreads.add (mNextThreadId, thread); if (pSamplingRate) * pSamplingRate = samplingRate; if (pFormat) * pFormat = format; if (pChannels) * pChannels = channels; if (pLatencyMs) * pLatencyMs = thread- > latency ()
/ / what is returned from here is the index of the mixing thread.
Return mNextThreadId
Return 0 handle / returns zero if the thread is not created successfully.
}
Okay, let's go back to AudioManagerBase.
[--> AudioPolicyManagerBase::AudioPolicyManagerBase] mHardwareOutput = mpClientInterface- > openOutput (& outputDesc- > mDevice, & outputDesc- > mSamplingRate, & outputDesc- > mFormat, & outputDesc- > mChannels, & outputDesc- > mLatency OutputDesc- > mFlags)
/ / A thread index is actually returned above. I'm a little confused, is APS just one thing that is actually a thread index? Although it uses this index as the logo of hardware.
/ / this. It is estimated that the int and pointers are added to a map, which is easy to manage. I won't look.
AddOutput (mHardwareOutput, outputDesc)
/ / I don't know what to do. I'll see it later.
SetOutputDevice (mHardwareOutput, (uint32_t) AudioSystem::DEVICE_OUT_SPEAKER, true); [- > setOutputDevice (mHardwareOutput,...)]
This function is very important! In addition, pass on some skills. Instead of backing back in source insight, just go to the window menu, which lists the recently opened files, and find our AudioManagerBase.cpp, right?
Void AudioPolicyManagerBase::setOutputDevice (audio_io_handle_t output, uint32_t device, bool force, int delayMs)
{
/ / pay attention to our parameters:
/ / output = 1
/ / device is AudioSystem::DEVICE_OUT_SPEAKER
/ / force is true,delayMs with a default value of 0
/ / map, right? It has been added through addOutput just now.
AudioOutputDescriptor * outputDesc = mOutputs.valueFor (output); if (outputDesc- > isDuplicated ()) {setOutputDevice (outputDesc- > mOutput1- > mId, device, force, delayMs); setOutputDevice (outputDesc- > mOutput2- > mId, device, force, delayMs); return;}
/ / do you remember the device set before addOutput? By the way, it is 0X3, which is put out | headphones
Uint32_t prevDevice = (uint32_t) outputDesc- > device (); now the peripheral is set, if ((device= = 0 | device= = prevDevice) & &! force) {return;} / / Oh, set the outputDesc to external outputDesc- > mDevice = device; popCount to 2, because device=0x2=0010
/ / in addition, I am particularly interested in the following output== mHardwareOutput. Remember the question we just asked?
/ / mHardwareOutput is actually a thread index returned by AF, so how does AMB base on such a thing?
/ / manage all threads? Sure enough, here we compare whether output is equal to the thread index originally created
/ / this shows that. Although there is only one mHardwareOutput, it can actually operate other output!
If (output = = mHardwareOutput & & AudioSystem::popCount (device) = = 2) {setStrategyMute (STRATEGY_MEDIA, true, output); usleep (outputDesc- > mLatency*2*1000);}
/ / dizzy, there is another AudioParameter, but the meaning is very clear
/ / it is said that we want to set the route, and the new output device is external.
/ / Let's switch from external player to headset later, and then we'll look at this problem.
AudioParameter param = AudioParameter (); param.addInt (String8 (AudioParameter::keyRouting), (int) device); mpClientInterface- > setParameters (mHardwareOutput, param.toString (), delayMs); / / update stream volumes according to new device applyStreamVolumes (output, device, delayMs)
/ / if changing from a combined headset + speaker route, unmute media streams
If (output = = mHardwareOutput & & AudioSystem::popCount (prevDevice) = = 2) {
/ / here, set the volume of the media to 0. We'll talk later.
SetStrategyMute (STRATEGY_MEDIA, false, output, delayMs)
}
}
All right, here we go.
SetOutputDevice (mHardwareOutput, (uint32_t) AudioSystem::DEVICE_OUT_SPEAKER, true)
This survey updated the output routing device corresponding to mHardwareOutput, and sent a command to APS, saying that you would update the output routing device corresponding to the mixing thread.
[- > AudioPolicyManagerBase::AudioPolicyManagerBase] AddOutput (mHardwareOutput, outputDesc); setOutputDevice (mHardwareOutput, (uint32_t) AudioSystem::DEVICE_OUT_SPEAKER, true)
/ / there is only one function left.
UpdateDeviceForStrategy (); [- > updateDeviceForStrategy ()] void AudioPolicyManagerBase::updateDeviceForStrategy () {for (int I = 0; I
< NUM_STRATEGIES; i++) { mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false); } } 晕,又出来一个枚举。我们看看 [---->For (int I = 0; I
< NUM_STRATEGIES; i++)] NUM_STRATEGIES在hardware/libhardware_legacy/include/hardware_legacy/ AudioPolicyManagerBase.h中定义。 enum routing_strategy { //好像很好理解 STRATEGY_MEDIA, STRATEGY_PHONE,//通话音吗? STRATEGY_SONIFICATION,//除了其他三个外的,可以是铃声,提醒声等。 STRATEGY_DTMF,//好像是拨号音 NUM_STRATEGIES }; 这个,反正我在SDK上没找到对应说明,我们待到以后看看会不会柳暗花明呢? [----->GetDeviceForStrategy ((routing_strategy) I, false)]
Looking at this function name means to find its corresponding device for various policies.
Uint32_t AudioPolicyManagerBase::getDeviceForStrategy (routing_strategy strategy, bool fromCache)
{
/ / fromCache is false
/ / looking at it, this function seems to involve a lot of strategic issues.
/ / Let's give a general explanation, but as to why the system does this, ask Google.
Uint32_t device = 0; switch (strategy) {case STRATEGY_DTMF: if (mPhoneState! = AudioSystem::MODE_IN_CALL) {/ / if you press the button again during the phone call, then go to the same device with MEDIA device = getDeviceForStrategy (STRATEGY_MEDIA, false); break;}
/ / Note that there is no break here, so under other mode, DTMF and PHONE use a strategy.
Case STRATEGY_PHONE:
/ / it is also necessary to determine whether the user is forced to use the output device.
Switch (mForceUse [AudioSystem:: FOR_COMMUNICATION]) {case AudioSystem::FORCE_BT_SCO: if (mPhoneState! = AudioSystem::MODE_IN_CALL | | strategy! = STRATEGY_DTMF) {device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT; if (device) break } device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET; if (device) break; device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO; if (device) break / / if SCO device is requested but no SCO device is available, fall back to default / / case / / FALL THROUGH / / do we remember to force it there? By the way, it's all FORCE_NONE / / and mAvailableOutputDevices is 0X3 (external player | headset) default: / / FORCE_NONE device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE; if (device) break; device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET; if (device) break; / / look, the following sentence will be true. What do you mean? If there are headphones, then the output device is headphones / / too correct. Is that what the actual mobile phone looks like? Device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE; break; / / revalidate what we just said, if the use of case AudioSystem::FORCE_SPEAKER is mandatory, case AudioSystem::FORCE_SPEAKER: if (mPhoneState! = AudioSystem::MODE_IN_CALL | | strategy! = STRATEGY_DTMF) {device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT If (device) break;} / / sure enough, the use of externalization is enforced. Device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; break;} break; case STRATEGY_SONIFICATION:// analysis method is the same as above, I will not say. If (mPhoneState = = AudioSystem::MODE_IN_CALL) {device = getDeviceForStrategy (STRATEGY_PHONE, false); break;} device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; / / also does not have break, indicating that SONIFICATION is affected by MEDIA policy. Case STRATEGY_MEDIA: {uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL; if (device2 = = 0) {device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;} if (device2 = = 0) {device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET } / / Unfortunately, we don't have if (device2 = = 0) {device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;} / / assuming we haven't come down from SONIFICATION, then device will eventually = DEVICE_OUT_SPEAKER. / / suppose we come down from SONIFICATION, then device is still equal to DEVICE_OUT_SPEAKER / / strange, why would you put it out if you have headphones? Can you tell the difference between ordinary headphones and wire-controlled headphones? Device | = device2;} break; default: break;} return device;}
All right, go back to
[- > AudioPolicyManagerBase::updateDeviceForStrategy ()] void AudioPolicyManagerBase::updateDeviceForStrategy () {for (int I = 0; I
< NUM_STRATEGIES; i++) { mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false); } } 这个函数完了,表明各种策略下使用的对应设备也准备好了。 真爽,一路回去,APS的构造就完了。 留个纪念: AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface) { .... updateDeviceForStrategy(); } AudioPolicyService::AudioPolicyService() : BnAudioPolicyService() , mpPolicyManager(NULL) { #if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST) mpPolicyManager = new AudioPolicyManagerBase(this); LOGV("build for GENERIC_AUDIO - using generic audio policy"); ... #endif property_get("ro.camera.sound.forced", value, "0"); mpPolicyManager->SetSystemProperty ("ro.camera.sound.forced", value);
To sum up, the AF,APS is all created. Did you get anything? Let's talk about it in order.
L AF created something that represents a HAL object
L APS creates two AudioCommandThread, one for processing commands and one for playing tone. We haven't seen it yet.
L APS will also create AudioManagerBase as the default audio management of the system.
L AMB centrally manages the above policies and creates a mixing thread in AF's openOutput. At the same time, AMB will update some policy arrangements.
In addition, the AMB we analyzed is Generic, but different vendors can implement their own strategies. For example, I can set that as long as there are headphones, all types of sounds come out of the headphones.
This is the answer to the question on how to analyze AudioPolicyService in Android. I hope the above content can be of some help to you. If you still have a lot of doubts to solve, you can follow the industry information channel to learn more about it.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.