Android P 相机拍照音程序流程 一

10 篇文章 2 订阅

Android P 相机拍照音程序流程 一

Android P 相机拍照音程序流程 二

本章节中静态分析了推测相机拍照音流程,下一章节中在 CameraService 中添加堆栈信息,动态分析拍照音的流程。

文件列表:

  • frameworks\base\core\java\android\hardware\Camera.java
  • frameworks\base\core\jni\android_hardware_Camera.cpp
  • frameworks\av\camera\Camera.cpp
  • frameworks\av\services\camera\libcameraservice\api1\CameraClient.cpp
  • frameworks\av\services\camera\libcameraservice\CameraService.cpp

 

APK 中调用 

// frameworks\base\core\java\android\hardware\Camera.java
public final boolean disableShutterSound() 
{
    return _enableShutterSound(/*enabled*/false);
}

// native 相机拍照音方法
private native final boolean _enableShutterSound(boolean enabled);

进入本地方法 android_hardware_Camera.cpp 中的拍照音函数:

// frameworks\base\core\jni\android_hardware_Camera.cpp
static jboolean android_hardware_Camera_enableShutterSound(JNIEnv *env, jobject thiz,
        jboolean enabled)
{
    ALOGV("enableShutterSound");
    sp<Camera> camera = get_native_camera(env, thiz, NULL);  // 获取本地相机实例,从类名上定位到 Camera.cpp
    if (camera == 0) return JNI_FALSE;

    int32_t value = (enabled == JNI_TRUE) ? 1 : 0;
    status_t rc = camera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, value, 0); // 发送拍照音命令
    if (rc == NO_ERROR) {
        return JNI_TRUE;
    } else if (rc == PERMISSION_DENIED) {
        return JNI_FALSE;
    } else {
        jniThrowRuntimeException(env, "enable shutter sound failed");
        return JNI_FALSE;
    }
}

 

JNI 的拍照音代码中调用 

status_t rc = camera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, value, 0);

定位到 Camera 类

// frameworks\av\camera\Camera.cpp
// send command to camera driver
status_t Camera::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
{
    ALOGV("sendCommand");
    sp <::android::hardware::ICamera> c = mCamera;  // 接口类
    if (c == 0) return NO_INIT;
    return c->sendCommand(cmd, arg1, arg2);  
}

::android::hardware::ICamera 是接口类,该类定义了一系列 camera 虚函数

  • disconnect/connect   打开关闭相机
  • startPreview/stopPreview 启动关闭预览
  • startRecording/stopRecording  启动关闭录像
  • onTransact  binder 通讯

 

framework camera

结合分析 camera API 1 的经验

Android Camera 二 JNI JAVA和C/CPP图像数据传输流程分析

可以推测出 ICamera 是相机客户端 CameraClient

// frameworks\av\services\camera\libcameraservice\api1\CameraClient.cpp
status_t CameraClient::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
    LOG1("sendCommand (pid %d)", getCallingPid());
    int orientation;
    Mutex::Autolock lock(mLock);
    status_t result = checkPidAndHardware();
    if (result != NO_ERROR) return result;

    if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
        //!++
        LOG1("CAMERA_CMD_SET_DISPLAY_ORIENTATION - tid(%d), (degrees, mirror)=(%d, %d)", ::gettid(), arg1, mCameraFacing); //Add debug log
        //!--
        // Mirror the preview if the camera is front-facing.
        orientation = getOrientation(arg1, mCameraFacing == CAMERA_FACING_FRONT);
        if (orientation == -1) return BAD_VALUE;

        if (mOrientation != orientation) {
            mOrientation = orientation;
            if (mPreviewWindow != 0) {
                mHardware->setPreviewTransform(mOrientation);
            }
        }
        //!++
        if(mHardware != 0)
            mHardware->sendCommand(cmd, mOrientation, arg2);
        //!--
        return OK;
    } else if (cmd == CAMERA_CMD_ENABLE_SHUTTER_SOUND) {
        switch (arg1) {
            case 0:
                return enableShutterSound(false);
            case 1:
                return enableShutterSound(true);
            default:
                return BAD_VALUE;
        }
        return OK;
    } else if (cmd == CAMERA_CMD_PLAY_RECORDING_SOUND) {  // 拍照音
        sCameraService->playSound(CameraService::SOUND_RECORDING_START);
    } else if (cmd == CAMERA_CMD_SET_VIDEO_BUFFER_COUNT) {
        // Silently ignore this command
        return INVALID_OPERATION;
    } else if (cmd == CAMERA_CMD_PING) {
        // If mHardware is 0, checkPidAndHardware will return error.
        return OK;
    }

    return mHardware->sendCommand(cmd, arg1, arg2);
}

定位到  sCameraService->playSound(CameraService::SOUND_RECORDING_START);

查找 sCameraService 的声明

在 CameraService.h 声明类 class BasicClient 中声明了  static sp<CameraService>  sCameraService;

接下来分析到类 CameraService 定位到 playSound 方法

// frameworks\av\services\camera\libcameraservice\CameraService.cpp
//!++  加载相机播放的声音
void CameraService::loadSoundImp() {
    LOG1("[CameraService::loadSoundImp] E");
    mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
    mSoundPlayer[SOUND_RECORDING_START] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
    mSoundPlayer[SOUND_RECORDING_STOP] = newMediaPlayer("/system/media/audio/ui/VideoStop.ogg");
    LOG1("[CameraService::loadSoundImp] X");
}

void* CameraService::loadSoundThread(void* arg) {
    LOG1("[CameraService::loadSoundThread]");
    CameraService* pCameraService = (CameraService*)arg;
    pCameraService->loadSoundImp();
    pthread_exit(NULL);
    return NULL;
}
//!--

void CameraService::releaseSound() {
    Mutex::Autolock lock(mSoundLock);
    LOG1("CameraService::releaseSound ref=%d", mSoundRef);
    if (--mSoundRef) return;

    //!++
    waitloadSoundDone();
    //!--
    for (int i = 0; i < NUM_SOUNDS; i++) {
        if (mSoundPlayer[i] != 0) {
            mSoundPlayer[i]->disconnect();
            mSoundPlayer[i].clear();
        }
    }
}

void CameraService::playSound(sound_kind kind) {
    ATRACE_CALL();
	ALOGD("AAAAA bbbplaySound");
//	return;
    LOG1("playSound(%d)", kind);
    Mutex::Autolock lock(mSoundLock);
    //!++
    waitloadSoundDone();
    //!--
    sp<MediaPlayer> player = mSoundPlayer[kind];
    if (player != 0) {
        player->seekTo(0);
        player->start();  // 播放声音
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值