上一章节中静态分析了相机拍照音流程,本章节中在 CameraService 中添加堆栈信息,动态分析拍照音的流程。
堆栈信息参考: Android 使用 addr2line 查看堆栈信息
文件列表:
- frameworks\av\services\camera\libcameraservice\api1\client2\CaptureSequencer.cpp
- frameworks\av\services\camera\libcameraservice\CameraService.cpp
堆栈信息如下图所示:
拍照音堆栈定位源码:
Camera Capturesequencer 的线程调用流程:
// 拍照音程序动态流程
bool CaptureSequencer::threadLoop()
currentState = (this->*kStateManagers[currentState])(client);
CaptureSequencer::CaptureState CaptureSequencer::manageStandardCaptureWait(sp<Camera2Client> &client) // 函数原型
shutterNotifyLocked(l.mParameters, client, mMsgType);
void CaptureSequencer::shutterNotifyLocked(const Parameters ¶ms, const sp<Camera2Client>& client, int msgType) // 函数原型
client->getCameraService()->playSound(CameraService::SOUND_SHUTTER)
void CameraService::playSound(sound_kind kind) // 函数原型
源码如下所示
threadLoop
// frameworks\av\services\camera\libcameraservice\api1\client2\CaptureSequencer.cpp
bool CaptureSequencer::threadLoop() {
sp<Camera2Client> client = mClient.promote();
if (client == 0) return false;
CaptureState currentState;
{
Mutex::Autolock l(mStateMutex);
currentState = mCaptureState;
}
currentState = (this->*kStateManagers[currentState])(client);
Mutex::Autolock l(mStateMutex);
if (currentState != mCaptureState) {
if (mCaptureState != IDLE) {
ATRACE_ASYNC_END(kStateNames[mCaptureState], mStateTransitionCount);
}
mCaptureState = currentState;
mStateTransitionCount++;
if (mCaptureState != IDLE) {
ATRACE_ASYNC_BEGIN(kStateNames[mCaptureState], mStateTransitionCount);
}
ALOGV("Camera %d: New capture state %s",
client->getCameraId(), kStateNames[mCaptureState]);
mStateChanged.signal();
}
if (mCaptureState == ERROR) {
ALOGE("Camera %d: Stopping capture sequencer due to error",
client->getCameraId());
return false;
}
return true;
}
manageStandardCaptureWait
// frameworks\av\services\camera\libcameraservice\api1\client2\CaptureSequencer.cpp
CaptureSequencer::CaptureState CaptureSequencer::manageStandardCaptureWait(
sp<Camera2Client> &client) {
status_t res;
ATRACE_CALL();
Mutex::Autolock l(mInputMutex);
// Wait for shutter callback
while (!mHalNotifiedShutter) {
if (mTimeoutCount <= 0) {
break;
}
res = mShutterNotifySignal.waitRelative(mInputMutex, kWaitDuration);
if (res == TIMED_OUT) {
mTimeoutCount--;
return STANDARD_CAPTURE_WAIT;
}
}
if (mHalNotifiedShutter) {
if (!mShutterNotified) {
SharedParameters::Lock l(client->getParameters());
/* warning: this also locks a SharedCameraCallbacks */
shutterNotifyLocked(l.mParameters, client, mMsgType);
mShutterNotified = true;
}
} else if (mTimeoutCount <= 0) {
ALOGW("Timed out waiting for shutter notification");
return DONE;
}
// Wait for new metadata result (mNewFrame)
while (!mNewFrameReceived) {
res = mNewFrameSignal.waitRelative(mInputMutex, kWaitDuration);
if (res == TIMED_OUT) {
mTimeoutCount--;
break;
}
}
// Wait until jpeg was captured by JpegProcessor
while (mNewFrameReceived && !mNewCaptureReceived) {
res = mNewCaptureSignal.waitRelative(mInputMutex, kWaitDuration);
if (res == TIMED_OUT) {
mTimeoutCount--;
break;
}
}
if (mNewCaptureReceived) {
if (mNewCaptureErrorCnt > kMaxRetryCount) {
ALOGW("Exceeding multiple retry limit of %d due to buffer drop", kMaxRetryCount);
return DONE;
} else if (mNewCaptureErrorCnt > 0) {
ALOGW("Capture error happened, retry %d...", mNewCaptureErrorCnt);
mNewCaptureReceived = false;
return STANDARD_CAPTURE;
}
}
if (mTimeoutCount <= 0) {
ALOGW("Timed out waiting for capture to complete");
return DONE;
}
if (mNewFrameReceived && mNewCaptureReceived) {
if (mNewFrameId != mCaptureId) {
ALOGW("Mismatched capture frame IDs: Expected %d, got %d",
mCaptureId, mNewFrameId);
}
camera_metadata_entry_t entry;
entry = mNewFrame.find(ANDROID_SENSOR_TIMESTAMP);
if (entry.count == 0) {
ALOGE("No timestamp field in capture frame!");
} else if (entry.count == 1) {
if (entry.data.i64[0] != mCaptureTimestamp) {
ALOGW("Mismatched capture timestamps: Metadata frame %" PRId64 ","
" captured buffer %" PRId64,
entry.data.i64[0],
mCaptureTimestamp);
}
} else {
ALOGE("Timestamp metadata is malformed!");
}
client->removeFrameListener(mCaptureId, mCaptureId + 1, this);
mNewFrameReceived = false;
mNewCaptureReceived = false;
return DONE;
}
return STANDARD_CAPTURE_WAIT;
}
shutterNotifyLocked
// frameworks\av\services\camera\libcameraservice\api1\client2\CaptureSequencer.cpp
/*static*/ void CaptureSequencer::shutterNotifyLocked(const Parameters ¶ms,
const sp<Camera2Client>& client, int msgType) {
ATRACE_CALL();
if (params.state == Parameters::STILL_CAPTURE
&& params.playShutterSound
&& (msgType & CAMERA_MSG_SHUTTER)) {
// 通过 CameraClient 获取 CameraService 的方法 playSound 播放拍照音
client->getCameraService()->playSound(CameraService::SOUND_SHUTTER);
}
{
Camera2Client::SharedCameraCallbacks::Lock
l(client->mSharedCameraCallbacks);
ALOGV("%s: Notifying of shutter close to client", __FUNCTION__);
if (l.mRemoteCallback != 0) {
// ShutterCallback
l.mRemoteCallback->notifyCallback(CAMERA_MSG_SHUTTER,
/*ext1*/0, /*ext2*/0);
// RawCallback with null buffer
l.mRemoteCallback->notifyCallback(CAMERA_MSG_RAW_IMAGE_NOTIFY,
/*ext1*/0, /*ext2*/0);
} else {
ALOGV("%s: No client!", __FUNCTION__);
}
}
}
playSound
// frameworks\av\services\camera\libcameraservice\CameraService.cpp
void CameraService::playSound(sound_kind kind) {
ATRACE_CALL();
ALOGD("AAAAA bbbplaySound");
android::CallStack Stack("fengchya");
// return;
LOG1("playSound(%d)", kind);
Mutex::Autolock lock(mSoundLock);
//!++
waitloadSoundDone();
//!--
sp<MediaPlayer> player = mSoundPlayer[kind];
if (player != 0) {
player->seekTo(0);
player->start();
}
}