Camera open process
一.上层调用
CameraActivity.java (src\com\android\camera) 101442 2015-7-23
@Override
public void onCreate(Bundle icicle) {
............
mCameraDeviceCtrl.openCamera();
}
CameraDeviceCtrl.java (src\com\android\camera\bridge) 64825 2015-10-16
public void openCamera() {
Log.d(TAG, "[openCamera] cameraState:" + getCameraState());//D/CAM_ori/CameraDeviceCtrl( 3621): [openCamera] cameraState:STATE_OPENING_CAMERA
if (getCameraState() != CameraState.STATE_CAMERA_CLOSED) {
return;
}
mCameraStartUpThread.openCamera();
setCameraState(CameraState.STATE_OPENING_CAMERA);
}
public synchronized void openCamera() {
mOpenCamera = true;
mCancel = false;
notifyAll();
}
private int openCamera(boolean isDualCamera) {
Log.i(TAG, "[openCamera] isDualCamera:" + isDualCamera + "mCameraId:" + mCameraId);//I/CAM_ori/CameraDeviceCtrl( 3621): [openCamera] isDualCamera:falsemCameraId:0
int cameraId = getPreferredCameraId(mPreferences);
if (mCameraId != cameraId) {
SettingUtils.writePreferredCameraId(mPreferences, mCameraId);
}
try {
// TODO will delete this
if (mCameraActivity.isNeedOpenStereoCamera()) {
String ROPERTY_KEY_CLIENT_APPMODE = "client.appmode";
String APP_MODE_NAME_MTK_DUAL_CAMERA = "MtkStereo";
android.hardware.Camera.setProperty(ROPERTY_KEY_CLIENT_APPMODE,
APP_MODE_NAME_MTK_DUAL_CAMERA);
}
Util.openCamera(mCameraActivity, isDualCamera, mCameraId);
mCameraDevice = CameraHolder.instance().getCameraProxy(mCameraId);
mTopCamId = (mCameraId == CameraHolder.instance().getBackCameraId()) ? CameraHolder
.instance().getFrontCameraId() : CameraHolder.instance().getBackCameraId();
mTopCamDevice = CameraHolder.instance().getCameraProxy(mTopCamId);
// M: added for mock camera
prepareMockCamera();
// mIsCameraOpened = true;
} catch (CameraHardwareException e) {
Log.i(TAG, "[openCamera]CameraHardwareException e:" + e);
mIsOpenCameraFail = true;
mMainHandler.sendEmptyMessage(MSG_OPEN_CAMERA_FAIL);
return CAMERA_HARDWARE_EXCEPTION;
} catch (CameraDisabledException e) {
Log.i(TAG, "[openCamera]CameraDisabledException e:" + e);
mIsOpenCameraFail = true;
mMainHandler.sendEmptyMessage(MSG_OPEN_CAMERA_DISABLED);
return CAMERA_DISABLED_EXCEPTION;
}
mParameters = (mCameraDevice == null) ? null : CameraHolder.instance()
.getOriginalParameters(mCameraId);
mTopCamParameters = (mTopCamDevice == null) ? null : CameraHolder.instance()
.getOriginalParameters(mTopCamId);
mCameraActor.onCameraOpenDone();
if (mCameraDevice != null && mParameters != null) {
mCurCameraDevice = new CameraDeviceExt(mCameraActivity, mCameraDevice, mParameters,
mCameraId, mPreferences);
} else {
Log.d(TAG, "[openCamera fail],mCameraDevice:" + mCameraDevice + ",mParameters:"
+ mParameters);
}
if (mTopCamDevice != null && mTopCamParameters != null) {
mTopCameraDevice = new CameraDeviceExt(mCameraActivity, mTopCamDevice,
mTopCamParameters, mTopCamId, mPreferences);
} else {
Log.d(TAG, "[openCamera fail],mTopCamDevice:" + mTopCamDevice
+ ",mTopCamParameters:" + mTopCamParameters);
}
mIsOpenCameraFail = false;
mModuleManager.onCameraOpen();
return CAMERA_OPEN_SUCEESS;
}
Util.java (src\com\android\camera) 45751 2015-7-16
public static void openCamera(Activity activity, boolean isPIP, int cameraId) throws CameraHardwareException,
CameraDisabledException {
Log.i(TAG, "openCamera begin isPIP = " + isPIP);//I/CAM_ori/Util( 3621): openCamera begin isPIP = false
// Check if device policy has disabled the camera.
DevicePolicyManager dpm = (DevicePolicyManager) activity
.getSystemService(Context.DEVICE_POLICY_SERVICE);
if (dpm.getCameraDisabled(null)) {
throw new CameraDisabledException();
}
try {
if (isPIP) {
MMProfileManager.startProfilePIPBottomOpen();
retryOpen(activity, OPEN_RETRY_COUNT, CameraHolder.instance().getBackCameraId());
MMProfileManager.stopProfilePIPBottomOpen();
MMProfileManager.startProfilePIPTopOpen();
retryOpen(activity, OPEN_RETRY_COUNT, CameraHolder.instance().getFrontCameraId());
MMProfileManager.stopProfilePIPTopOpen();
} else {
retryOpen(activity, OPEN_RETRY_COUNT, cameraId);
}
} catch (CameraHardwareException e) {
CameraHolder.instance().release();
throw e;
}
Log.i(TAG, "openCamera end");
}
private static CameraManager.CameraProxy retryOpen(Activity activity, int count, int cameraId)
throws CameraHardwareException {
for (int i = 0; i < count; i++) {
try {
if (activity instanceof ActivityBase) {
Log.i(TAG, "[retryOpen] cameraId = " + cameraId);//I/CAM_ori/Util( 3621): [retryOpen] cameraId = 0
CameraProxy cameraProxy = CameraHolder.instance().open(cameraId);
return cameraProxy;
} else {
return CameraHolder.instance().open(cameraId);
}
} catch (CameraHardwareException e) {
if (i == 0) {
try {
// wait some time, and try another time
// Camera device may be using by VT or atv.
Thread.sleep(1000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
continue;
} else {
// In eng build, we throw the exception so that test tool
// can detect it and report it
if ("eng".equals(Build.TYPE)) {
Log.i(TAG, "Open Camera fail", e);
throw e;
// QA will always consider JE as bug, so..
// throw new RuntimeException("openCamera failed", e);
} else {
throw e;
}
}
}
}
// just for build pass
throw new CameraHardwareException(new RuntimeException("Should never get here"));
}
CameraHolder.java (src\com\android\camera) 13558 2015-7-16
public CameraProxy open(int cameraId) throws CameraHardwareException {
Log.i(TAG, "CameraHolder open cameraId = " + cameraId);//I/CAM_ext/CameraHolder( 3621): CameraHolder open cameraId = 0
assertError(cameraId != UNKONW_ID);
if (mMockCameraInfo == null) {
return getCameraProxyWrapper(cameraId).open();
} else {
if (mMockCamera == null) {
throw new RuntimeException();
}
getCameraProxyWrapper(cameraId).insertMockCameraProxy(mMockCamera[cameraId]);
return mMockCamera[cameraId];
}
}
private CameraProxyWrapper getCameraProxyWrapper(int cameraId) {
if (cameraId == mBackCameraId) {
if (sBackCamProxyWrapper == null) {
sBackCameraManager = new CameraManager("BackCam");
sBackCamProxyWrapper = new CameraProxyWrapper(cameraId, sBackCameraManager);
}
return sBackCamProxyWrapper;
} else {
if (sFrontCamProxyWrapper == null) {
sFrontCameraManager = new CameraManager("FrontCam");
sFrontCamProxyWrapper = new CameraProxyWrapper(cameraId, sFrontCameraManager);
}
return sFrontCamProxyWrapper;
}
}
private CameraProxyWrapper(int cameraId, CameraManager manager) {
Log.i(TAG, "[CameraProxyWrapper]constructor, cameraId = " + cameraId);
mCameraId = cameraId;
mCameraManager = manager;
HandlerThread ht = new HandlerThread(cameraId + "'s CameraHolder ");
ht.start();
mHandler = new MyHandler(ht.getLooper());
}
public synchronized CameraProxy open() throws CameraHardwareException {
Log.i(TAG, "CameraProxyWrapper open mCameraOpened = " + mCameraOpened + " mCameraId = "
+ mCameraId);//I/CAM_ext/CameraHolder( 3621): CameraProxyWrapper open mCameraOpened = false mCameraId = 0
assertError(!mCameraOpened);
if (mCameraProxy == null) {
try {
Log.i(TAG, "open camera " + mCameraId);
mCameraProxy = mCameraManager.cameraOpen(mCameraId);
} catch (RuntimeException e) {
Log.i(TAG, "fail to connect Camera", e);
throw new CameraHardwareException(e);
}
mParameters = mCameraProxy.getParameters();
} else {
try {
mCameraProxy.reconnect();
} catch (IOException e) {
Log.e(TAG, "reconnect failed.");
throw new CameraHardwareException(e);
}
mCameraProxy.setParameters(mParameters);
}
mCameraOpened = true;
mHandler.removeMessages(RELEASE_CAMERA);
mKeepBeforeTime = 0;
Log.i(TAG, "open camera " + mCameraId + " end" + " mCameraProxy = " + mCameraProxy);
return mCameraProxy;
}
CameraManager.java (src\com\android\camera) 44919 2015-11-2
// Open camera synchronously. This method is invoked in the context of a
// background thread.
CameraProxy cameraOpen(int cameraId) {
// Cannot open camera in mCameraHandler, otherwise all camera events
// will be routed to mCameraHandler looper, which in turn will call
// event handler like Camera.onFaceDetection, which in turn will modify
// UI and cause exception like this:
// CalledFromWrongThreadException: Only the original thread that created
// a view hierarchy can touch its views.
MMProfileManager.startProfileCameraOpen();
mCamera = FrameworksClassFactory.openCamera(cameraId);
Log.i(mSubTag, "openCamera cameraId = " + cameraId + " camera device = " + mCamera);//I/CAM_ori/CameraManager/FrontCam( 3621): openCamera cameraId = 0 camera device = com.android.camera.AndroidCamera@2e9153e8
MMProfileManager.stopProfileCameraOpen();
if (mCamera != null) {
mParametersIsDirty = true;
if (mParamsToSet == null) {
mParamsToSet = mCamera.getParameters();
}
mCameraProxy = new CameraProxy();
return mCameraProxy;
} else {
return null;
}
}
FrameworksClassFactory.java (src\com\android\camera) 4984 2015-7-16
import android.hardware.Camera;
public static ICamera openCamera(int cameraId) {
if (MOCK_CAMERA) {
return MockCamera.open(cameraId);
} else {
Camera camera = null;
if (sTrySwitchToLegacyMode > 0) {
// choose legacy mode in order to enter cam hal 1.0
camera = Camera.openLegacy(cameraId, Camera.CAMERA_HAL_API_VERSION_1_0);
} else {
camera = Camera.open(cameraId);
}
if (null == camera) {
Log.e(TAG, "openCamera:got null hardware camera!");
return null;
}
// wrap it with ICamera
return new AndroidCamera(camera);
}
}
二、Framework 层
Camera.java (framework\base\core\android\hardware) 249186 2015-7-16
public static Camera open(int cameraId) {
if (!isPermissionGranted()) {
return null;
}
return new Camera(cameraId);
}
Camera(int cameraId) {
int err = cameraInitNormal(cameraId);
if (checkInitErrors(err)) {
switch(err) {
case EACCESS:
throw new RuntimeException("Fail to connect to camera service");
case ENODEV:
throw new RuntimeException("Camera initialization failed");
default:
// Should never hit this.
throw new RuntimeException("Unknown camera error");
}
}
}
private int cameraInitNormal(int cameraId) {
return cameraInitVersion(cameraId, CAMERA_HAL_API_VERSION_NORMAL_CONNECT);
}
private int cameraInitVersion(int cameraId, int halVersion) {
mShutterCallback = null;
mRawImageCallback = null;
mJpegCallback = null;
mPreviewCallback = null;
mPreviewRawDumpCallback = null;
mPostviewCallback = null;
mUsingPreviewAllocation = false;
mZoomListener = null;
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else if ((looper = Looper.getMainLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else {
mEventHandler = null;
}
String packageName = ActivityThread.currentPackageName();
return native_setup(new WeakReference
}
private native final int native_setup(Object camera_this, int cameraId, int halVersion,String packageName);
三、jni层
// connect to camera service
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{
// Convert jstring to String16
const char16_t *rawClientName = env->GetStringChars(clientPackageName, NULL);
jsize rawClientNameLen = env->GetStringLength(clientPackageName);
String16 clientName(rawClientName, rawClientNameLen);
env->ReleaseStringChars(clientPackageName, rawClientName);
sp
if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) {
// Default path: hal version is don't care, do normal camera connect.
camera = Camera::connect(cameraId, clientName,
Camera::USE_CALLING_UID);
} else {
jint status = Camera::connectLegacy(cameraId, halVersion, clientName,
Camera::USE_CALLING_UID, camera);
if (status != NO_ERROR) {
return status;
}
}
if (camera == NULL) {
return -EACCES;
}
// make sure camera hardware is alive
if (camera->getStatus() != NO_ERROR) {
return NO_INIT;
}
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
// This should never happen
jniThrowRuntimeException(env, "Can't find android/hardware/Camera");
return INVALID_OPERATION;
}
// We use a weak reference so the Camera object can be garbage collected.
// The reference is only used as a proxy for callbacks.
//!++
#if 1 // defined(MTK_CAMERA_BSP_SUPPORT)
sp
#else
sp
#endif
//!--
context->incStrong((void*)android_hardware_Camera_native_setup);
camera->setListener(context);
// save context in opaque field
env->SetLongField(thiz, fields.context, (jlong)context.get());
return NO_ERROR;
}
/framework/av/camera/Camera.cpp
sp
int clientUid)
{
return CameraBaseT::connect(cameraId, clientPackageName, clientUid);
}
/framework/av/camera/CameraBase.cpp
template
sp
const String16& clientPackageName,
int clientUid)
{
ALOGV("%s: connect", __FUNCTION__);
sp
sp
status_t status = NO_ERROR;
const sp
if (cs != 0) {
TCamConnectService fnConnectService = TCamTraits::fnConnectService;
status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
/*out*/ c->mCamera);
}
if (status == OK && c->mCamera != 0) {
c->mCamera->asBinder()->linkToDeath(c);
c->mStatus = NO_ERROR;
} else {
ALOGW("An error occurred while connecting to camera: %d", cameraId);
c.clear();
}
return c;
}
三、Services section
/framework/av/camera/CameraBase.cpp
// establish binder interface to camera service
template
const sp
{
Mutex::Autolock _l(gLock);
if (gCameraService.get() == 0) {
sp
sp
do {
binder = sm->getService(String16(kCameraServiceName)); //无法自动定位,搜索符号getService,定位到ServiceManager.java 49
if (binder != 0) {
break;
}
ALOGW("CameraService not published, waiting...");
usleep(kCameraServicePollDelay);
} while(true);
if (gDeathNotifier == NULL) {
gDeathNotifier = new DeathNotifier();
}
binder->linkToDeath(gDeathNotifier);
gCameraService = interface_cast
}
ALOGE_IF(gCameraService == 0, "no CameraService!?");
return gCameraService;
}
framework/native/libs/binder/IServiceManager.cpp
sp
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast
ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
return gDefaultServiceManager;
}
frameworks/base/core/java/android/os/ServiceManager.java
/**
* Returns a reference to a service with the given name.
*
* @param name the name of the service to get
* @return a reference to the service, or null
if the service doesn't exist
*/
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name); //sCache是个Hashmap
//那么,这个media.camera是源代码里配置好的还是开机后添加进去的?何时添加的?
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
frameworks\av\services\camera\libcameraservice\CameraService.cpp
status_t CameraService::connect( //服务端connect()
const sp
int cameraId,
const String16& clientPackageName,
int clientUid,
/*out*/
sp
String8 clientName8(clientPackageName);
int callingPid = getCallingPid();
LOG1("CameraService::connect E (pid %d \"%s\", id %d)", callingPid,
clientName8.string(), cameraId);
status_t status = validateConnect(cameraId, /*inout*/clientUid);
if (status != OK) {
return status;
}
sp
{
Mutex::Autolock lock(mServiceLock);
sp
if (!canConnectUnsafe(cameraId, clientPackageName,
cameraClient->asBinder(),
/*out*/clientTmp)) {
return -EBUSY;
} else if (client.get() != NULL) {
device = static_cast
return OK;
}
status = connectHelperLocked(/*out*/client,
cameraClient,
cameraId,
clientPackageName,
clientUid,
callingPid);
if (status != OK) {
return status;
}
}
// important: release the mutex here so the client can call back
// into the service from its destructor (can be at the end of the call)
device = client;
return OK;
}
status_t CameraService::connectHelperLocked(
/*out*/
sp
/*in*/
const sp
int cameraId,
const String16& clientPackageName,
int clientUid,
int callingPid,
int halVersion,
bool legacyMode) {
int facing = -1;
int deviceVersion = getDeviceVersion(cameraId, &facing);
if (halVersion < 0 || halVersion == deviceVersion) {
// Default path: HAL version is unspecified by caller, create CameraClient
// based on device version reported by the HAL.
switch(deviceVersion) {
case CAMERA_DEVICE_API_VERSION_1_0:
client = new CameraClient(this, cameraClient,
clientPackageName, cameraId,
facing, callingPid, clientUid, getpid(), legacyMode);
break;
case CAMERA_DEVICE_API_VERSION_2_0:
case CAMERA_DEVICE_API_VERSION_2_1:
case CAMERA_DEVICE_API_VERSION_3_0:
case CAMERA_DEVICE_API_VERSION_3_1:
case CAMERA_DEVICE_API_VERSION_3_2:
client = new Camera2Client(this, cameraClient,
clientPackageName, cameraId,
facing, callingPid, clientUid, getpid(), legacyMode);
break;
case -1:
ALOGE("Invalid camera id %d", cameraId);
return BAD_VALUE;
default:
ALOGE("Unknown camera device HAL version: %d", deviceVersion);
return INVALID_OPERATION;
}
} else {
// A particular HAL version is requested by caller. Create CameraClient
// based on the requested HAL version.
if (deviceVersion > CAMERA_DEVICE_API_VERSION_1_0 &&
halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
// Only support higher HAL version device opened as HAL1.0 device.
client = new CameraClient(this, cameraClient,
clientPackageName, cameraId,
facing, callingPid, clientUid, getpid(), legacyMode);
} else {
// Other combinations (e.g. HAL3.x open as HAL2.x) are not supported yet.
ALOGE("Invalid camera HAL version %x: HAL %x device can only be"
" opened as HAL %x device", halVersion, deviceVersion,
CAMERA_DEVICE_API_VERSION_1_0);
return INVALID_OPERATION;
}
}
status_t status = connectFinishUnsafe(client, client->getRemote());
if (status != OK) {
// this is probably not recoverable.. maybe the client can try again
return status;
}
mClient[cameraId] = client;
LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId,
getpid());
return OK;
}
status_t CameraService::connectFinishUnsafe(const sp
const sp
status_t status = client->initialize(mModule);
if (status != OK) {
return status;
}
if (remoteCallback != NULL) {
remoteCallback->linkToDeath(this);
}
return OK;
}
frameworks\av\services\camera\libcameraservice\api1\CameraClient.cpp
status_t CameraClient::initialize(camera_module_t *module) {
int callingPid = getCallingPid();
status_t res;
LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);
// Verify ops permissions
res = startCameraOps();
if (res != OK) {
return res;
}
char camera_device_name[10];
snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
mHardware = new CameraHardwareInterface(camera_device_name);
res = mHardware->initialize(&module->common);
if (res != OK) {
ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
mHardware.clear();
return res;
}
mHardware->setCallbacks(notifyCallback,
dataCallback,
dataCallbackTimestamp,
(void *)(uintptr_t)mCameraId);
// Enable zoom, error, focus, and metadata messages by default
enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);
//!++
#if 1
// Enable MTK-extended messages by default
enableMsgType(MTK_CAMERA_MSG_EXT_NOTIFY | MTK_CAMERA_MSG_EXT_DATA);
#endif
//!--
LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
return OK;
}
frameworks\av\services\camera\libcameraservice\device1\CameraHardwareInterface.h
status_t initialize(hw_module_t *module)
{
ALOGI("Opening camera %s", mName.string());
camera_module_t *cameraModule = reinterpret_cast
camera_info info;
status_t res = cameraModule->get_camera_info(atoi(mName.string()), &info);
if (res != OK) return res;
int rc = OK;
if (module->module_api_version >= CAMERA_MODULE_API_VERSION_2_3 &&
info.device_version > CAMERA_DEVICE_API_VERSION_1_0) {
// Open higher version camera device as HAL1.0 device.
rc = cameraModule->open_legacy(module, mName.string(),
CAMERA_DEVICE_API_VERSION_1_0,
(hw_device_t **)&mDevice);
} else {
rc = CameraService::filterOpenErrorCode(module->methods->open(
module, mName.string(), (hw_device_t **)&mDevice));
}
if (rc != OK) {
ALOGE("Could not open camera %s: %d", mName.string(), rc);
return rc;
}
initHalPreviewWindow();
return rc;
}
这里进行初始化Camera的相关信息, 我们所需要的情景模式保存在结构体 camera_info中
在CameraService.cpp中getCameraCharacteristics()方法中获取CameraInfo信息
status_t CameraService::getCameraCharacteristics(int cameraId,
CameraMetadata* cameraInfo) {
if (!cameraInfo) {
ALOGE("%s: cameraInfo is NULL", __FUNCTION__);
return BAD_VALUE;
}
if (!mModule) {
ALOGE("%s: camera hardware module doesn't exist", __FUNCTION__);
return -ENODEV;
}
if (cameraId < 0 || cameraId >= mNumberOfCameras) {
ALOGE("%s: Invalid camera id: %d", __FUNCTION__, cameraId);
return BAD_VALUE;
}
int facing;
status_t ret = OK;
if (mModule->common.module_api_version < CAMERA_MODULE_API_VERSION_2_0 ||
getDeviceVersion(cameraId, &facing) <= CAMERA_DEVICE_API_VERSION_2_1 ) {
/**
* Backwards compatibility mode for old HALs:
* - Convert CameraInfo into static CameraMetadata properties.
* - Retrieve cached CameraParameters for this camera. If none exist,
* attempt to open CameraClient and retrieve the CameraParameters.
* - Convert cached CameraParameters into static CameraMetadata
* properties.
*/
ALOGI("%s: Switching to HAL1 shim implementation...", __FUNCTION__);
if ((ret = generateShimMetadata(cameraId, cameraInfo)) != OK) {
return ret;
}
} else {
/**
* Normal HAL 2.1+ codepath.
*/
struct camera_info info;
ret = filterGetInfoErrorCode(mModule->get_camera_info(cameraId, &info));
*cameraInfo = info.static_camera_characteristics;
}
return ret;
}