Audiotrack's Start method is used to achieve Android audio output, what exactly did start do? Recalling the last section of the previous section createtrack_l, a track handle was returned through binder and saved
status_t audiotrack::createtrack_l (...) { sp<iaudiotrack> track = Audioflinger->createtrack (...); Maudiotrack = track;}
Start is primarily called the Start method of the track to achieve the audio output function
-------------------------------------------------------------------------status_t Audiotrack::start () { Automutex Lock (MLock); If the audiotrack is already in the start state, return directly if (mstate = = state_active) {return invalid_operation; } Minunderrun = true; Save last state previousstate = mstate; Sets the current state if (previousstate = = state_paused_stopping) {mstate = state_stopping; } else {mstate = state_active; }//If the previous state is a stop state, indicating the need to reset position to 0, play from the beginning if (previousstate = = State_stopped | | previousstate = = state_flushed) { Reset current position as seen by client to 0 Mproxy->setepoch (Mproxy->getepoch ()-Mproxy->getposi tion ()); Force refresh of remaining frames by Processaudiobuffer () as last//write before stop could is partial. Mrefreshremaining = true; }//Current position mnewposition = mproxy->getposition () + mupdateperiod; Gets share buffer's flag, atomic operation int32_t flags = Android_atomic_and (~CBLK_disabled, &mcblk->mflags); If there is a callback thread, generally if we call Audiotrack on the apk side independently, the callback thread will not be set, but the Audioplayer system player will set the callback thread//To set the priority, otherwise audio may not get the time slice, and the stutter//if it is Audioplayer, will have its own defined priority, audiotrack after the newly created thread will inherit its priority//if it is the APK call, the priority is generally fixed, then we need to set a android_priority_ here Audio priority to ensure the smooth output of audio sp<audiotrackthread> t = maudiotrackthread; if (t! = 0) {if (previousstate = = state_stopping) {//interrupt mproxy->interrupt (); } else {//resume playing t->resume (); }} else {//Save current thread priority, set back when stop later mpreviouspriority = getpriority (prio_process, 0); Get_sched_policy (0, &mpreviousschedulinggroup); Set thread priority to Android_priority_audio androidsetthreadpriority (0, Android_priority_audio); } status_t status = No_error; if (! ( Flags & Cblk_invalid) {//If share buffer is available, call track's Start method status = Maudiotrack->start (); if (status = = Dead_object) {Flags|= Cblk_invalid; }} if (Flags & cblk_invalid) {status = restoretrack_l ("Start"); } if (Status! = No_error) {//start error after processing Aloge ("Start () status%d", status); Mstate = previousstate; if (t! = 0) {if (previousstate! = state_stopping) {t->pause (); }} else {setpriority (prio_process, 0, mpreviouspriority); Set_sched_policy (0, Mpreviousschedulinggroup); }} return status;}
Since Maudiotrack is a proxy object for binder, start invokes the Start method to the Bbinder object, which is
status_t Audioflinger::trackhandle::start () { return Mtrack->start ();}
Since we are doing audio output under Playbackthread, we will call further to Playbackthread::track:: Start method, the most important of which is the following two steps:
status_t Audioflinger::P laybackthread::track::start ( playbackthread *playbackthread = (PlaybackThread *) Thread.get (); Status = playbackthread->addtrack_l (this);}
Remember when we created a mixerthread at the time of the GetOutput, and in createtrack_l, the thread was added to the mplaybackthreads for management, and now we're going to take it out, It's called the addtrack_l method.
audio_io_handle_t audioflinger::openoutput (audio_module_handle_t module,...) {thread = new Mixerthread (this, output, ID, *pdevices); return ID;} Audioflinger::P laybackthread *audioflinger::checkplaybackthread_l (audio_io_handle_t output) const{return Mplaybackthreads.valuefor (output). get ();}
Within the addtrack_l method, there are three main steps:
- If the track (share buffer) is a new track, you need to call Startoutput to initialize
- Add the track to Mactivetracks
- Send a broadcast to notify Mixerthread to start working
Addtrack_l () must is called with Threadbase::mlock heldstatus_t Audioflinger::P laybackthread::addtrack_l (const SP <Track>& track) { if (Mactivetracks.indexof (track) < 0) { status = Audiosystem::startoutput (MId, Track->streamtype (), Track->sessionid ()); } Mactivetracks.add (track); Broadcast_l ();}
1. Track initialization
In analyzing getoutput, we already know the call flow of the Audio interface, that is, audiosystem->audiopolicyservice->audio_policy_hal-> Audiopolicymanagerbase, now let's take a look at Audiopolicymanagerbase:: What did Startoutput do
status_t audiopolicymanagerbase::startoutput (audio_io_handle_t output, audiosystem::stream_type stream, int session) { Checkandsetvolume (stream, mstreams[stream].getvolumeindex (newdevice), output, Newdevice);}
Checkandsetvolume actually just set the stream volume.
2. Track Join Maudiotrack
Maudiotrack is the track set that is contained in the current Mixerthread, which is followed by mixing these track sets
3. broadcast_l
void Audioflinger::P laybackthread::broadcast_l () { //Thread could is blocked waiting for async //So signal it to Handle state changes immediately //If Threadloop is currently unlocked a signal of MWAITWORKCV of would //be lost so We also flag to prevent it blocking on MWAITWORKCV msignalpending = true; Mwaitworkcv.broadcast ();}
We have mixerthread, because mixerthread inherit and Playbackthread, so run is playbackthread::threadloop, within Threadloop, If the mactivetrack is empty, indicating that no audio data is waiting for the output, then Threadloop will go to sleep and wait for the wake-up, broadcast is doing this wake-up work
BOOL Audioflinger::P Laybackthread::threadloop () { if (!mactivetracks.size () && systemTime () > Standbytime) | | Issuspended ()) mwaitworkcv.wait (MLock); } ...}
The following is the overall process of start
[Android] Audiotrack::start