frameworks\base\services\AudioFlinger.cpp
status_t AudioFlinger::PlaybackThread::Track::start() { status_t status = NO_ERROR; LOGV("start(%d), calling thread %d session %d", mName, IPCThreadState::self()->getCallingPid(), mSessionId); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { Mutex::Autolock _l(thread->mLock); int state = mState; // here the track could be either new, or restarted // in both cases "unstop" the track if (mState == PAUSED) { mState = TrackBase::RESUMING; LOGV("PAUSED => RESUMING (%d) on thread %p", mName, this); } else { mState = TrackBase::ACTIVE; LOGV("? => ACTIVE (%d) on thread %p", mName, this); } if (!isOutputTrack() && state != ACTIVE && state != RESUMING) { thread->mLock.unlock(); status = AudioSystem::startOutput(thread->id(), (AudioSystem::stream_type)mStreamType, mSessionId); thread->mLock.lock(); } if (status == NO_ERROR) { PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); playbackThread->addTrack_l(this); } else { mState = state; } } else { status = BAD_VALUE; } return status; }
status_t AudioSystem::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream, int session) { const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return PERMISSION_DENIED; return aps->startOutput(output, stream, session); } status_t AudioPolicyService::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream, int session) { if (mpPolicyManager == NULL) { return NO_INIT; } LOGV("startOutput() tid %d", gettid()); Mutex::Autolock _l(mLock); return mpPolicyManager->startOutput(output, stream, session);
}
// 主要的处理是从这儿开始的 status_t AudioPolicyManagerBase::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream, int session) { LOGV("startOutput() output %d, stream %d, session %d", output, stream, session); ssize_t index = mOutputs.indexOfKey(output); if (index < 0) { LOGW("startOutput() unknow output %d", output); return BAD_VALUE; } AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index); // 函数 getStrategy 就是根据 stream type 返回特定的 strategy routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
需要知道每种策略分别是用来做什么的。
所以首先要知道策略对应的 stream type
AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy( AudioSystem::stream_type stream) { // stream to strategy mapping switch (stream) { case AudioSystem::VOICE_CALL: // 电话来了 case AudioSystem::BLUETOOTH_SCO: // 蓝牙耳机接通了 return STRATEGY_PHONE; case AudioSystem::RING: // 铃声响了 case AudioSystem::NOTIFICATION: // 通知,例如界面中最上面一栏中有消息了 case AudioSystem::ALARM: // 警告,电池没电时的警告? case AudioSystem::ENFORCED_AUDIBLE: return STRATEGY_SONIFICATION; case AudioSystem::DTMF: // 可参考链接:http://baike.baidu.com/view/171916.htm return STRATEGY_DTMF; default: LOGE("unknown stream type"); case AudioSystem::SYSTEM: // 系统声音采用 media strategy, 例如,如果正在播放音乐的时候按键, // mute 掉音乐,并切换 output 的话,将导致 很差的用户体验。 // 其中可以得到以下信息: // 1、按键声音属于 system stream type 。 // 2、策略的改变将会导致 output 的切换 // 3、优先级高的策略 start 时会 mute 掉优先级低的策略 // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs // while key clicks are played produces a poor result case AudioSystem::TTS: // TTS 就是 Text To Speech case AudioSystem::MUSIC: return STRATEGY_MEDIA; } }
// incremenent usage count for this stream on the requested output: // NOTE that the usage count is the same for duplicated output and hardware output which is // necassary for a correct control of hardware output routing by startOutput() and stopOutput() // 增加请求的 output 上该 stream 的使用计数 // 注意: duplicated output 和 hardware output 中的使用计数是相同的。 // 因为这对通过 startOutput() 函数和 stopOutput() 函数正确地控制 hardware output routing 是必要的。 outputDesc->changeRefCount(stream, 1); void AudioPolicyManagerBase::AudioOutputDescriptor::changeRefCount(AudioSystem::stream_type stream, int delta) { // forward usage count change to attached outputs // 如果是 duplicated 的,需要改变它所包含的两个 output 中的使用计数。 if (isDuplicated()) { mOutput1->changeRefCount(stream, delta); mOutput2->changeRefCount(stream, delta); } if ((delta + (int)mRefCount[stream]) < 0) { LOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", delta, stream, mRefCount[stream]); mRefCount[stream] = 0; return; } mRefCount[stream] += delta; LOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]); }
setOutputDevice(output, getNewDevice(output)); uint32_t AudioPolicyManagerBase::getNewDevice(audio_io_handle_t output, bool fromCache) { uint32_t device = 0; AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output); // check the following by order of priority to request a routing change if necessary: // 1: we are in call or the strategy phone is active on the hardware output: // use device for strategy phone // 2: the strategy sonification is active on the hardware output: // use device for strategy sonification // 3: the strategy media is active on the hardware output: // use device for strategy media // 4: the strategy DTMF is active on the hardware output: // use device for strategy DTMF // 根据以下的优先级顺序,来检查必要的路线改变 // 1、如果来电话了,或者 hardware output 中的 strategy phone 是活动的, // 则使用 phone strategy 。 //