1. AudioTrack::play()
Frameworks/base/media/java/android/media/AudioTrack.java
public void play()
throws IllegalStateException {
if (mState != STATE_INITIALIZED) {
throw new IllegalStateException("play() called on uninitializedAudioTrack.");
}
synchronized(mPlayStateLock) {
native_start();
mPlayState = PLAYSTATE_PLAYING;
}
}
2. android_media_AudioTrack_start()
frameworks/base/core/jni/android_media_AudioTrack.cpp
static void
android_media_AudioTrack_start(JNIEnv*env, jobject thiz)
{
sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
//这儿lpTrack是保存在javaenv中本地AudioTrack对象
//这个对象的mAudioTrack成员变量指向一个BpAudioTrack(BpBinder)对象
if (lpTrack == NULL) {
jniThrowException(env,"java/lang/IllegalStateException",
"Unable to retrieve AudioTrackpointer for start()");
return;
}
lpTrack->start();
}
3. AudioTrack::start()
Frameworks/av/media/libmedia/AudioTrack.cpp
voidAudioTrack::start()
{
sp<AudioTrackThread> t =mAudioTrackThread;
ALOGV("start %p", this);
AutoMutex lock(mLock);
// acquire a strong reference on theIMemory and IAudioTrack so that they cannot be destroyed
// while we are accessing the cblk
sp<IAudioTrack> audioTrack = mAudioTrack;
// get BpAudioTrack(BpBinder)对象指针
sp<IMemory> iMem = mCblkMemory;
audio_track_cblk_t* cblk = mCblk;
if (!mActive) {
mFlushed = false;
mActive = true;
mNewPosition = cblk->server +mUpdatePeriod;
cblk->lock.lock();
cblk->bufferTimeoutMs =MAX_STARTUP_TIMEOUT_MS;
cblk->waitTimeMs = 0;
android_atomic_and(~CBLK_DISABLED,&cblk->flags);
if (t != 0) {
t->resume();
} else {
mPreviousPriority =getpriority(PRIO_PROCESS, 0);
get_sched_policy(0,&mPreviousSchedulingGroup);
androidSetThreadPriority(0,ANDROID_PRIORITY_AUDIO);
}
ALOGV("start %p before lock cblk%p", this, cblk);
status_t status = NO_ERROR;
if (!(cblk->flags &CBLK_INVALID)) {
cblk->lock.unlock();
ALOGV("mAudioTrack->start()");
status =mAudioTrack->start();
// mAudioTrack指向BpAudioTrack(BpBinder)对象
//因此这儿实际调用的是BpAudioTrack::start()
cblk->lock.lock();
if (status == DEAD_OBJECT) {
android_atomic_or(CBLK_INVALID,&cblk->flags);
}
}
if (cblk->flags & CBLK_INVALID){
audio_track_cblk_t* temp = cblk;
status = restoreTrack_l(temp, true/*fromStart*/);
cblk = temp;
}
cblk->lock.unlock();
if (status != NO_ERROR) {
ALOGV("start() failed");
mActive = false;
if (t != 0) {
t->pause();
} else {
setpriority(PRIO_PROCESS, 0,mPreviousPriority);
set_sched_policy(0,mPreviousSchedulingGroup);
}
}
}
}
4. BpAudioTrack::start()
Frameworks/av/media/libmedia/IAudioTrack.cpp
virtual status_t start()
{
Parcel data, reply;
data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
status_t status= remote()->transact(START, data, &reply);
// remote返回 BpAudioTrack::mRemote成员变量
//这个变量指向一个BpBinder对象
//因此这儿实际调用的BpBinder::transact()
if (status == NO_ERROR) {
status = reply.readInt32();
} else {
ALOGW("start() error:%s", strerror(-status));
}
return status;
}
5. BpBinder::transact()
Frameworks/native/libs/binder/BpBinder.cpp
status_tBpBinder::transact(
uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will nevercome back to life.
if (mAlive) {
status_t status= IPCThreadState::self()->transact(
mHandle,code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
6. IPCThreadState::transact()
……………………………………….
IPCThreadState::waitForResponse() -> executeCommand()
……………………………………….
7. BBinder::transact()
--〉status_t AudioFlinger::TrackHandle::onTransact(
uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{
return BnAudioTrack::onTransact(code, data, reply, flags);
}
8. BnAudioTrack::onTransact()
Frameworks/av/media/libmedia/IAudioTrack.cpp
status_tBnAudioTrack::onTransact(
uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{
switch (code) {
case GET_CBLK: {
CHECK_INTERFACE(IAudioTrack, data,reply);
reply->writeStrongBinder(getCblk()->asBinder());
return NO_ERROR;
} break;
case START: {
CHECK_INTERFACE(IAudioTrack, data, reply);
reply->writeInt32(start());
return NO_ERROR;
} break;
case STOP: {
CHECK_INTERFACE(IAudioTrack, data,reply);
stop();
return NO_ERROR;
} break;
case FLUSH: {
CHECK_INTERFACE(IAudioTrack, data,reply);
flush();
return NO_ERROR;
} break;
case PAUSE: {
CHECK_INTERFACE(IAudioTrack, data, reply);
pause();
return NO_ERROR;
}
case ATTACH_AUX_EFFECT: {
CHECK_INTERFACE(IAudioTrack, data,reply);
reply->writeInt32(attachAuxEffect(data.readInt32()));
return NO_ERROR;
} break;
case ALLOCATE_TIMED_BUFFER: {
CHECK_INTERFACE(IAudioTrack, data,reply);
sp<IMemory> buffer;
status_t status =allocateTimedBuffer(data.readInt32(), &buffer);
reply->writeInt32(status);
if (status == NO_ERROR) {
reply->writeStrongBinder(buffer->asBinder());
}
return NO_ERROR;
} break;
case QUEUE_TIMED_BUFFER: {
CHECK_INTERFACE(IAudioTrack, data,reply);
sp<IMemory> buffer =interface_cast<IMemory>(
data.readStrongBinder());
uint64_t pts = data.readInt64();
reply->writeInt32(queueTimedBuffer(buffer, pts));
return NO_ERROR;
} break;
case SET_MEDIA_TIME_TRANSFORM: {
CHECK_INTERFACE(IAudioTrack, data,reply);
LinearTransform xform;
xform.a_zero = data.readInt64();
xform.b_zero = data.readInt64();
xform.a_to_b_numer = data.readInt32();
xform.a_to_b_denom =data.readInt32();
int target = data.readInt32();
reply->writeInt32(setMediaTimeTransform(xform, target));
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code,data, reply, flags);
}
}
9. AudioFlinger::TrackHandle::start()
Frameworks/av/services/audioflinger/AudioFlinger.cpp
status_t AudioFlinger::TrackHandle::start() {
return mTrack->start();
}
10. AudioFlinger::PlaybackThread::Track::start()
Frameworks/av/services/audioflinger/Tracks.cpp
status_tAudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event,
int triggerSession)
{
status_t status = NO_ERROR;
ALOGV("start(%d), calling pid %dsession %d",
mName,IPCThreadState::self()->getCallingPid(), mSessionId);
sp<ThreadBase> thread =mThread.promote();
if (thread != 0) {
Mutex::Autolock _l(thread->mLock);
track_state state = mState;
// here the track could be either new,or restarted
// in both cases "unstop" thetrack
if (state == PAUSED) {
mState = TrackBase::RESUMING;
ALOGV("PAUSED => RESUMING(%d) on thread %p", mName, this);
} else {
mState = TrackBase::ACTIVE;
ALOGV("? => ACTIVE (%d) onthread %p", mName, this);
}
if (!isOutputTrack() && state!= ACTIVE && state != RESUMING) {
thread->mLock.unlock();
status =AudioSystem::startOutput(thread->id(), mStreamType, mSessionId);
thread->mLock.lock();
#ifdefADD_BATTERY_DATA
// to track the speaker usage
if (status == NO_ERROR) {
addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart);
}
#endif
}
if (status == NO_ERROR) {
PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
playbackThread->addTrack_l(this);
} else {
mState = state;
triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
}
} else {
status = BAD_VALUE;
}
return status;
}
11. AudioFlinger::PlaybackThread::addTrack_l()
Frameworks/av/services/audioflinger/Threads.cpp
status_tAudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
{
status_t status = ALREADY_EXISTS;
// set retry count for buffer fill
track->mRetryCount =kMaxTrackStartupRetries;
if (mActiveTracks.indexOf(track) < 0) {
// the track is newly added, make sureit fills up all its
// buffers before playing. This is toensure the client will
// effectively get the latency itrequested.
track->mFillingUpStatus =Track::FS_FILLING;
track->mResetDone = false;
track->mPresentationCompleteFrames =0;
mActiveTracks.add(track);
sp<EffectChain> chain =getEffectChain_l(track->sessionId());
if (chain != 0) {
ALOGV("addTrack_l() startingtrack on chain %p for session %d", chain.get(),
track->sessionId());
chain->incActiveTrackCnt();
}
status = NO_ERROR;
}
ALOGV("mWaitWorkCV.broadcast");
mWaitWorkCV.broadcast();
return status;
}