Introduction
Audiopolicyservice is one of the two major services of the android audio system, and the other is audioflinger. Both of these services are loaded with mediasever when the system is started. The loaded code is located: frameworks/base/Media/mediaserver/main_mediaserver.cpp. Audioflinger is mainly responsible for managing audio data processing and work related to the hardware abstraction layer. This topic describes audiopolicyservice.
Audiopolicyservice mainly completes the following tasks:
- The Java application layer uses JNI to access the services provided by audiopolicyservice through the iaudiopolicyservice interface.
- Connection status of input and output devices
- System Strategy Switching
- Volume/audio parameter settings
Composition of audiopolicyservice
The following figure describes the static structure of audiopolicyservice:
Further description:
1. audiopolicyservice inherits the iaudiopolicyservice interface, so that audiopolicyservice can provide external services based on the android Binder Mechanism;
2. audiopolicyservice also inherits the audiopolicyclientinterface class, which has a member pointer to the audiopolicyinterface class mppolicymanager, which actually points to the audiopolicymanager;
3. the audiopolicymanager class inherits the audiopolicyinterface class to provide services to audiopolicyservice. In turn, there is also an audiopolicyclientinterface pointer, Which is initialized in the constructor and points to audiopolicyservice. In fact, audiopolicyservice accesses audiopolicymanager through the member pointer mppolicymanager, while audiopolicymanager accesses audiopolicyservice through audiopolicyclientinterface (mpclientinterface;
4. audiopolicyservice has an Internal Thread class audiocommandthread. As the name suggests, all commands (volume control, input, output switching, etc.) will be queued for execution in this thread;
Audiopolicymanager
A large part of audiopolicyservice management work is completed in audiopolicymanager. Includes volume management, audio strategy management, and input/output device management.
Input/output device management
The audio system defines an enumeration for audio devices: audiosystem: audio_devices, for example: device_out_speaker, device_out_wired_headphone, device_out_rjth_a2dp, device_in_builtin_mic, device_in_voice_call, each enumerated value corresponds to a single bit of a 32-bit integer, so these values can be bitwise OR operated. For example, if I want to enable both the Speaker and the headset at the same time, we can do this:
Newdevice = device_out_speaker | device_out_wired_headphone; <br/> setoutputdevice (mhardwareoutput, newdevice );
Audiopolicymanager has two member variables: mavailableoutputdevices and mavailableinputdevices. They record the currently available input and output devices. When the system detects that the headset or Bluetooth is connected, it calls the audiopolicymanager member function:
Status_t audiopolicymanager: setdeviceconnectionstate (audiosystem: audio_devices device, <br/> audiosystem: device_connection_state state, <br/> const char * device_address)
This function sets mavailableoutputdevices or mavailableinputdevices based on the input device value and State (device_state_available/device_state_unavailable), and then selects the corresponding input or output device.
Other related functions:
- Setforceuse () is used to forcibly use a certain device in a certain scenario. For example, setforceuse (for_media, force_speaker) enables the speaker when playing music.
- Startoutput ()/stopoutput ()
- Startinput ()/stopinput ()
Volume Management
Audiopolicymanager provides several volume-related functions:
- Initstreamvolume (audiosystem: stream_type stream, int indexmin, int indexmax)
- Setstreamvolumeindex (audiosystem: stream_type stream, int index)
- Getstreamvolumeindex (audiosystem: stream_type Stream)
Audioservice. Java defines the maximum volume level of each audio stream:
/** @ Hide maximum volume index values for audio streams */<br/> private int [] max_stream_volume = new int [] {<br/> 5, // stream_voice_call <br/> 7, // stream_system <br/> 7, // stream_ring <br/> 15, // stream_music <br/> 7, // stream_alarm <br/> 7, // stream_notification <br/> 15, // stream_effecth_sco <br/> 7, // stream_system_enforced <br/> 15, // stream_dtmf <br/> 15 // stream_tts <br/> };
It can be seen that phone ringtones can have 7 levels of volume, while music can have 15 levels of volume. Java code uses JNI to call audiopolicymanager's initstreamvolume (), pass the content of this array into audiopolicymanager, so that audiopolicymanager remembers the volume level of each audio stream. The application can call setstreamvolumeindex to set the volume level of each audio stream. setstreamvolumeindex converts the volume level of this integer to the logarithm level suitable for human ears, and then uses audiocommandthread of audiopolicyservice, the settings will be applied to the corresponding track of audioflinger.
Audio Policy Management
First, I want to figure out the relationship among stream_type, device, and strategy:
- Audiosystem: Specifies the stream_type audio stream type. There are 10 types in total.
- Audiosystem: audio_devices audio input/output device. Each bit represents a device. See the preceding description.
- Audiopolicymanager: routing_strategy audio routing policy. Four policies are available.
Getstrategy (stream_type) returns the corresponding Routing Strategy Value Based on stream type. getdeviceforstrategy () returns available devices based on routing strategy. Android classifies 10 stream types into four routing policies, and then determines the specific output device based on the routing policy.
Member variable moutputs
Keyedvector <audio_io_handle_t, audiooutputdescriptor *> moutputs; // list of output Descriptors
This is the key-Value Pair vector (array) used by audiopolocymanager to manage output. Generally, audiopolocymanager opens three output handles (audio_io_handle_t). For more information about audio_io_handle_t, see another blog: compile. The three handles are:
- Mhardwareoutput // hardware output Handler
- Ma2dpoutput // a2dp output Handler
- Mduplicatedoutput // duplicated output handler: outputs to hardware and a2dp
You can use startoutput () to put a stream type into the corresponding output.
Popcount ()
This function is mainly used to calculate the number of non-zero bits in the device variable (the number of 32-digit type 1). For example, if this function returns 2, two devices need to process the variable at the same time. The reason for special introduction is that the implementation of this function is very interesting:
Uint32_t audiosystem: popcount (uint32_t U) <br/>{< br/> U = (U & 0x55555555) + (u> 1) & 0x55555555); <br/> U = (U & 0x33333333) + (u> 2) & 0x33333333 )); <br/> U = (U & 0x0f0f0f) + (u> 4) & 0x0f0f0f); <br/> U = (U & 0x00ff00ff) + (u> 8) & 0x00ff00ff); <br/> U = (U & 0x0000ffff) + (u> 16); <br/> return U; <br/>}
Do you understand this?
Audiocommandthread
This is a thread in audiopolicyservice and is mainly used to process commands related to audio settings. Including:
- Start_tone
- Stop_tone
- Set_volume
- SET_PARAMETERS
- Set_voice_volume
The parameters of each command are packaged accordingly:
- Class tonedata
- Class volumedata
- Class parametersdata
- Class voicevolumedata
Start_tone/stop_tone: Special tones commonly used in the playing phone system, such as tone_dtmf_0 and tone_sup_busy.
Set_volume: audioflinger is called to set the volume.
Set_voice_volume: audioflinger is called to set the telephone volume.
SET_PARAMETERS: set parameters using a string in the form of keyvaluepairs. The format of keyvaluepairs can be as follows:
- & Quot; sampling_rate = 44100 & quot"
- "Channels = 2"
- "Sampling_rate = 44100; channels = 2" // combination form
These keyvaluepairs can be passed in through the audiopolicyservice member function setparameters.