Android8.0相机源码深入解析(四)

正文

上一篇介绍了相机hal到app的数据传递,通过前面三篇对相机数据传输流程弄清楚了,相机各层结构也梳理清除.本篇继续介绍相机启动流程.

相机服务过程

服务注册及启动

CameraServer在7.0之前是在MediaServer里,7.0改成了单独的Server.我们看最新的8.0的代码.
CameraServer定义在framework/av/camera/cameraserver.看cameraserver的make文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
main_cameraserver.cpp

LOCAL_SHARED_LIBRARIES := \
libcameraservice \
liblog \
libutils \
libui \
libgui \
libbinder \
libhidltransport \
android.hardware.camera.common@1.0 \
android.hardware.camera.provider@2.4 \
android.hardware.camera.device@1.0 \
vendor.qti.hardware.camera.device@1.0 \
android.hardware.camera.device@3.2

LOCAL_MODULE:= cameraserver
LOCAL_32_BIT_ONLY := true

LOCAL_CFLAGS += -Wall -Wextra -Werror -Wno-unused-parameter

LOCAL_INIT_RC := cameraserver.rc

include $(BUILD_EXECUTABLE)

LOCAL_SHARED_LIBRARIES包括了此前一直讲到的libcameraservice,再加上工具类,provide,device1,device2,device3.2等.aidl的定义也写在这里.
这里我们看到很重要的信息LOCAL_INIT_RC := cameraserver.rc,这个就是进程启动地方了.init进程启动后会加载init.rc(system\core\rootdir\init.rc)脚本,当它执行mount_all指令挂载分区时,会加载/{system,vendor,odm}/etc/init目录下的所有rc脚本,这样就会启动cameraserver进程.
找到了启动位置,也知道了启动流程,再看启动时做了些什么.看下main_cameraserver.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main(int argc __unused, char** argv __unused)
{
signal(SIGPIPE, SIG_IGN);

// Set 3 threads for HIDL calls
hardware::configureRpcThreadpool(3, /*willjoin*/ false);

sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p", sm.get());
CameraService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}

就一个main方法,让CameraService实例化,然后是让自己启动和加入线程池,这个不细看了.CameraService继承了模板类BinderService,我们找到instantiate方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
template<typename SERVICE>
class BinderService
{
public:
static status_t publish(bool allowIsolated = false) {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(
String16(SERVICE::getServiceName()),
new SERVICE(), allowIsolated);
}

static void publishAndJoinThreadPool(bool allowIsolated = false) {
publish(allowIsolated);
joinThreadPool();
}

static void instantiate() { publish(); }

static status_t shutdown() { return NO_ERROR; }

private:
static void joinThreadPool() {
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
ps->giveThreadPoolName();
IPCThreadState::self()->joinThreadPool();
}
};

instantiate调用了publish方法,就是发布,通过ServiceManager添加一个服务.

在IServiceManager找到addService方法:

1
2
3
4
5
6
7
8
9
10
11
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated)
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}

service是强指针sp&,初始化时会调用其引用对象的onFirstRef方法.
继续看CameraService代码,在服务添加后做了什么:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
CameraService::CameraService() :
mEventLog(DEFAULT_EVENT_LOG_LENGTH),
mNumberOfCameras(0), mNumberOfNormalCameras(0),
mSoundRef(0), mInitialized(false) {
ALOGI("CameraService started (pid=%d)", getpid());

this->camera_device_status_change = android::camera_device_status_change;
this->torch_mode_status_change = android::torch_mode_status_change;

mServiceLockWrapper = std::make_shared<WaitableMutexWrapper>(&mServiceLock);
}

void CameraService::onFirstRef()
{
ALOGI("CameraService process starting");

BnCameraService::onFirstRef();

// Update battery life tracking if service is restarting
BatteryNotifier& notifier(BatteryNotifier::getInstance());
notifier.noteResetCamera();
notifier.noteResetFlashlight();

status_t res = INVALID_OPERATION;

res = enumerateProviders();
if (res == OK) {
mInitialized = true;
}

CameraService::pingCameraServiceProxy();
}

实例方法里面没有做什么,另外果然看到了onFirstRef方法.这里调用了BnCameraService的onFirstRef方法,然后电池通知,和主线无关,不管.然后枚举providers,最后连接CameraServiceProxy服务.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
status_t CameraService::enumerateProviders() {
status_t res;
Mutex::Autolock l(mServiceLock);

if (nullptr == mCameraProviderManager.get()) {
mCameraProviderManager = new CameraProviderManager();
res = mCameraProviderManager->initialize(this);
if (res != OK) {
ALOGE("%s: Unable to initialize camera provider manager: %s (%d)",
__FUNCTION__, strerror(-res), res);
return res;
}
}

mNumberOfCameras = mCameraProviderManager->getCameraCount();
mNumberOfNormalCameras =
mCameraProviderManager->getAPI1CompatibleCameraCount();

// Setup vendor tags before we call get_camera_info the first time
// because HAL might need to setup static vendor keys in get_camera_info
// TODO: maybe put this into CameraProviderManager::initialize()?
mCameraProviderManager->setUpVendorTags();

if (nullptr == mFlashlight.get()) {
mFlashlight = new CameraFlashlight(mCameraProviderManager, this);
}

res = mFlashlight->findFlashUnits();
if (res != OK) {
ALOGE("Failed to enumerate flash units: %s (%d)", strerror(-res), res);
}

for (auto& cameraId : mCameraProviderManager->getCameraDeviceIds()) {
String8 id8 = String8(cameraId.c_str());
{
Mutex::Autolock lock(mCameraStatesLock);
auto iter = mCameraStates.find(id8);
if (iter != mCameraStates.end()) {
continue;
}
}

hardware::camera::common::V1_0::CameraResourceCost cost;
res = mCameraProviderManager->getResourceCost(cameraId, &cost);
if (res != OK) {
ALOGE("Failed to query device resource cost: %s (%d)", strerror(-res), res);
continue;
}
std::set<String8> conflicting;
for (size_t i = 0; i < cost.conflictingDevices.size(); i++) {
conflicting.emplace(String8(cost.conflictingDevices[i].c_str()));
}

{
Mutex::Autolock lock(mCameraStatesLock);
mCameraStates.emplace(id8,
std::make_shared<CameraState>(id8, cost.resourceCost, conflicting));
}

onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT);

if (mFlashlight->hasFlashUnit(id8)) {
mTorchStatusMap.add(id8, TorchModeStatus::AVAILABLE_OFF);
}
}

return OK;
}

单独做了flashlight闪光灯的初始化操作,不细看.然后获取所有deviceids,遍历调用getResourceCost方法,这个是返回device消耗的资源,然后做对应操作,最后onDeviceStatusChanged状态改变.

连接hal层相机设备

在types.hal里找到了状态值的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
enum CameraDeviceStatus : uint32_t {
/**
* The camera device is not currently connected, and trying to reference it
* in provider method calls must return status code ILLEGAL_ARGUMENT.
*
*/
NOT_PRESENT = 0,

/**
* The camera device is connected, and opening it is possible, as long as
* sufficient resources are available.
*
* By default, the framework must assume all devices returned by
* ICameraProvider::getCameraIdList() are in this state.
*/
PRESENT = 1,

/**
* The camera device is connected, but it is undergoing enumeration and
* startup, and so opening the device must return CAMERA_IN_USE.
*
* Attempting to call ICameraProvider::getCameraCharacteristics() must
* succeed, however.
*/
ENUMERATING = 2,

};

NOT_PRESENT是未连接,PRESENT是连接,ENUMERATING就是占用,那经过enumerateProviders就连接到了相机设备.enumerateProviders调用了mCameraProviderManager的初始化方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
CameraProviderManager::HardwareServiceInteractionProxy
CameraProviderManager::sHardwareServiceInteractionProxy{};

CameraProviderManager::~CameraProviderManager() {
}

status_t CameraProviderManager::initialize(wp<CameraProviderManager::StatusListener> listener,
ServiceInteractionProxy* proxy) {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
if (proxy == nullptr) {
ALOGE("%s: No valid service interaction proxy provided", __FUNCTION__);
return BAD_VALUE;
}
mListener = listener;
mServiceProxy = proxy;

// Registering will trigger notifications for all already-known providers
bool success = mServiceProxy->registerForNotifications(
/* instance name, empty means no filter */ "",
this);
if (!success) {
ALOGE("%s: Unable to register with hardware service manager for notifications "
"about camera providers", __FUNCTION__);
return INVALID_OPERATION;
}

// See if there's a passthrough HAL, but let's not complain if there's not
addProviderLocked(kLegacyProviderName, /*expected*/ false);

auto pDeviceInfo = pFindDeviceInfoLocked(
/*minVersion*/ {1,0}, /*maxVersion*/ {2,0});
auto *pDeviceInfo1 = static_cast<ProviderInfo::DeviceInfo1*>(pDeviceInfo);
gSession = pDeviceInfo1->mInterface;

if(gSession != nullptr)
mQHidlDevice = vendor::qti::hardware::camera::device::V1_0::IQCameraDevice::castFrom(gSession);

mQHidlDevice->addParallelProcessListener(mHidlParallList);

return OK;
}

CameraProviderManager是一个hidl代理,那肯定就是这里连接到了hal层方法了.先注册了一个通知,通过addProviderLocked连接到hal,然后获取deviceInfo,再获得mQHidlDevice,就可以调到hal层方法了.看下addProviderLocked方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) {
for (const auto& providerInfo : mProviders) {
if (providerInfo->mProviderName == newProvider) {
ALOGW("%s: Camera provider HAL with name '%s' already registered", __FUNCTION__,
newProvider.c_str());
return ALREADY_EXISTS;
}
}

sp<provider::V2_4::ICameraProvider> interface;
interface = mServiceProxy->getService(newProvider);

if (interface == nullptr) {
if (expected) {
ALOGE("%s: Camera provider HAL '%s' is not actually available", __FUNCTION__,
newProvider.c_str());
return BAD_VALUE;
} else {
return OK;
}
}

sp<ProviderInfo> providerInfo =
new ProviderInfo(newProvider, interface, this);
status_t res = providerInfo->initialize();
if (res != OK) {
return res;
}

mProviders.push_back(providerInfo);

return OK;
}

获取hidl的代理服务,关键是ProviderInfo的initialize方法,然后添加进mProviders里,继续看initialize方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
status_t CameraProviderManager::ProviderInfo::initialize() {
status_t res = parseProviderName(mProviderName, &mType, &mId);
if (res != OK) {
ALOGE("%s: Invalid provider name, ignoring", __FUNCTION__);
return BAD_VALUE;
}
ALOGI("Connecting to new camera provider: %s, isRemote? %d",
mProviderName.c_str(), mInterface->isRemote());
hardware::Return<Status> status = mInterface->setCallback(this);
if (!status.isOk()) {
ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
__FUNCTION__, mProviderName.c_str(), status.description().c_str());
return DEAD_OBJECT;
}
if (status != Status::OK) {
ALOGE("%s: Unable to register callbacks with camera provider '%s'",
__FUNCTION__, mProviderName.c_str());
return mapToStatusT(status);
}

hardware::Return<bool> linked = mInterface->linkToDeath(this, /*cookie*/ mId);
if (!linked.isOk()) {
ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
__FUNCTION__, mProviderName.c_str(), linked.description().c_str());
return DEAD_OBJECT;
} else if (!linked) {
ALOGW("%s: Unable to link to provider '%s' death notifications",
__FUNCTION__, mProviderName.c_str());
}

// Get initial list of camera devices, if any
std::vector<std::string> devices;
hardware::Return<void> ret = mInterface->getCameraIdList([&status, &devices](
Status idStatus,
const hardware::hidl_vec<hardware::hidl_string>& cameraDeviceNames) {
status = idStatus;
if (status == Status::OK) {
for (size_t i = 0; i < cameraDeviceNames.size(); i++) {
devices.push_back(cameraDeviceNames[i]);
}
} });
if (!ret.isOk()) {
ALOGE("%s: Transaction error in getting camera ID list from provider '%s': %s",
__FUNCTION__, mProviderName.c_str(), linked.description().c_str());
return DEAD_OBJECT;
}
if (status != Status::OK) {
ALOGE("%s: Unable to query for camera devices from provider '%s'",
__FUNCTION__, mProviderName.c_str());
return mapToStatusT(status);
}

sp<StatusListener> listener = mManager->getStatusListener();
for (auto& device : devices) {
std::string id;
status_t res = addDevice(device,
hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT, &id);
if (res != OK) {
ALOGE("%s: Unable to enumerate camera device '%s': %s (%d)",
__FUNCTION__, device.c_str(), strerror(-res), res);
continue;
}
}

for (auto& device : mDevices) {
mUniqueCameraIds.insert(device->mId);
if (device->isAPI1Compatible()) {
mUniqueAPI1CompatibleCameraIds.insert(device->mId);
}
}
mUniqueDeviceCount = mUniqueCameraIds.size();

ALOGI("Camera provider %s ready with %zu camera devices",
mProviderName.c_str(), mDevices.size());

return OK;
}

这里获取到camera设备,有device1,2,3,4,然后遍历调用addDevice方法,看addDevice方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
status_t CameraProviderManager::ProviderInfo::addDevice(const std::string& name,
CameraDeviceStatus initialStatus, /*out*/ std::string* parsedId) {
ALOGI("Enumerating new camera device: %s", name.c_str());

uint16_t major, minor;
std::string type, id;

status_t res = parseDeviceName(name, &major, &minor, &type, &id);
if (res != OK) {
return res;
}
if (type != mType) {
ALOGE("%s: Device type %s does not match provider type %s", __FUNCTION__,
type.c_str(), mType.c_str());
return BAD_VALUE;
}
if (mManager->isValidDeviceLocked(id, major)) {
ALOGE("%s: Device %s: ID %s is already in use for device major version %d", __FUNCTION__,
name.c_str(), id.c_str(), major);
return BAD_VALUE;
}

std::unique_ptr<DeviceInfo> deviceInfo;
switch (major) {
case 1:
deviceInfo = initializeDeviceInfo<DeviceInfo1>(name, mProviderTagid,
id, minor);
break;
case 3:
deviceInfo = initializeDeviceInfo<DeviceInfo3>(name, mProviderTagid,
id, minor);
break;
default:
ALOGE("%s: Device %s: Unknown HIDL device HAL major version %d:", __FUNCTION__,
name.c_str(), major);
return BAD_VALUE;
}
if (deviceInfo == nullptr) return BAD_VALUE;
deviceInfo->mStatus = initialStatus;

mDevices.push_back(std::move(deviceInfo));

if (parsedId != nullptr) {
*parsedId = id;
}
return OK;
}

通过initializeDeviceInfo获取到deviceInfo,看initializeDeviceInfo方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
template<class DeviceInfoT>
std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
CameraProviderManager::ProviderInfo::initializeDeviceInfo(
const std::string &name, const metadata_vendor_id_t tagId,
const std::string &id, uint16_t minorVersion) const {
Status status;

auto cameraInterface =
getDeviceInterface<typename DeviceInfoT::InterfaceT>(name);
if (cameraInterface == nullptr) return nullptr;

CameraResourceCost resourceCost;
cameraInterface->getResourceCost([&status, &resourceCost](
Status s, CameraResourceCost cost) {
status = s;
resourceCost = cost;
});
if (status != Status::OK) {
ALOGE("%s: Unable to obtain resource costs for camera device %s: %s", __FUNCTION__,
name.c_str(), statusToString(status));
return nullptr;
}
return std::unique_ptr<DeviceInfo>(
new DeviceInfoT(name, tagId, id, minorVersion, resourceCost,
cameraInterface));
}

DeviceInfoT是一个模板类,找到DeviceInfo1的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct DeviceInfo1 : public DeviceInfo {
typedef hardware::camera::device::V1_0::ICameraDevice InterfaceT;
const sp<InterfaceT> mInterface;

virtual status_t setTorchMode(bool enabled) override;
virtual status_t getCameraInfo(hardware::CameraInfo *info) const override;
//In case of Device1Info assume that we are always API1 compatible
virtual bool isAPI1Compatible() const override { return true; }
DeviceInfo1(const std::string& name, const metadata_vendor_id_t tagId,
const std::string &id, uint16_t minorVersion,
const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
sp<InterfaceT> interface);
virtual ~DeviceInfo1();
private:
CameraParameters2 mDefaultParameters;
};

DeviceInfo1的mInterface就是一个ICameraDevice接口,可以用来调用hal层方法,看DeviceInfo1的实例方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
CameraProviderManager::ProviderInfo::DeviceInfo1::DeviceInfo1(const std::string& name,
const metadata_vendor_id_t tagId, const std::string &id,
uint16_t minorVersion,
const CameraResourceCost& resourceCost,
sp<InterfaceT> interface) :
DeviceInfo(name, tagId, id, hardware::hidl_version{1, minorVersion},
resourceCost),
mInterface(interface) {
// Get default parameters and initialize flash unit availability
// Requires powering on the camera device
hardware::Return<Status> status = mInterface->open(nullptr);
if (!status.isOk()) {
ALOGE("%s: Transaction error opening camera device %s to check for a flash unit: %s",
__FUNCTION__, mId.c_str(), status.description().c_str());
return;
}
if (status != Status::OK) {
ALOGE("%s: Unable to open camera device %s to check for a flash unit: %s", __FUNCTION__,
mId.c_str(), CameraProviderManager::statusToString(status));
return;
}
hardware::Return<void> ret;
ret = mInterface->getParameters([this](const hardware::hidl_string& parms) {
mDefaultParameters.unflatten(String8(parms.c_str()));
});
if (!ret.isOk()) {
ALOGE("%s: Transaction error reading camera device %s params to check for a flash unit: %s",
__FUNCTION__, mId.c_str(), status.description().c_str());
return;
}
const char *flashMode =
mDefaultParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
mHasFlashUnit = true;
}

ret = mInterface->close();
if (!ret.isOk()) {
ALOGE("%s: Transaction error closing camera device %s after check for a flash unit: %s",
__FUNCTION__, mId.c_str(), status.description().c_str());
}
}

这里调用了mInterface的open方法,就调用到了相机hal的启动方法了.hal层方法留到之后单独分析.

流程总结

相机库的启动过程大概就是这样了.总结一下.

相机服务启动流程:

  1. init进程启动后启动其它系统服务,包括相机服务,调用cameraserver.rc的main方法
  2. cameraserver.rc通过ServiceManager启动CameraService
  3. CameraService被被创建后调用onFirstRef方法,创建CameraProviderManager
  4. CameraProviderManager的创建一个ProviderInfo并初始化
  5. ProviderInfo创建DeviceInfo并初始化
  6. DeviceInfo初始化时调用ICameraDevice实例的open方法,调用到hal层方法
  7. CameraService调用pingCameraServiceProxy连接到一个服务代理

打开相机

从framework到native

服务启动后再看下打开相机方法.还是从上层看起,在android.hardare.Camera里找相机启动方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
 /**
* Creates a new Camera object to access the first back-facing camera on the
* device. If the device does not have a back-facing camera, this returns
* null.
* @see #open(int)
*/
public static Camera open() {
int numberOfCameras = getNumberOfCameras();
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
return new Camera(i);
}
}
return null;
}
/**
* Create a legacy camera object.
*
* @param cameraId The hardware camera to access, between 0 and
* {@link #getNumberOfCameras()}-1.
* @param halVersion The HAL API version this camera device to be opened as.
*/
private Camera(int cameraId, int halVersion) {
int err = cameraInitVersion(cameraId, halVersion);
if (checkInitErrors(err)) {
if (err == -EACCES) {
throw new RuntimeException("Fail to connect to camera service");
} else if (err == -ENODEV) {
throw new RuntimeException("Camera initialization failed");
} else if (err == -ENOSYS) {
throw new RuntimeException("Camera initialization failed because some methods"
+ " are not implemented");
} else if (err == -EOPNOTSUPP) {
throw new RuntimeException("Camera initialization failed because the hal"
+ " version is not supported by this device");
} else if (err == -EINVAL) {
throw new RuntimeException("Camera initialization failed because the input"
+ " arugments are invalid");
} else if (err == -EBUSY) {
throw new RuntimeException("Camera initialization failed because the camera"
+ " device was already opened");
} else if (err == -EUSERS) {
throw new RuntimeException("Camera initialization failed because the max"
+ " number of camera devices were already opened");
}
// Should never hit this.
throw new RuntimeException("Unknown camera error");
}
}

private int cameraInitVersion(int cameraId, int halVersion) {
mShutterCallback = null;
mRawImageCallback = null;
mJpegCallback = null;
mPreviewCallback = 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;
}

return native_setup(new WeakReference<Camera>(this), cameraId, halVersion,
ActivityThread.currentOpPackageName());
}

open方法会去获取相机数量,一般就是前置相机和后置相机.然后调用私有实例方法,检查相机版本,在这个方法里创建了前面几篇一致介绍的mEventHandler,用来接受相机消息.然后就是调用native_setup,jni方法,我们在android_hardware_Camera.cpp找到其实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// 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 = reinterpret_cast<const char16_t*>(
env->GetStringChars(clientPackageName, NULL));
jsize rawClientNameLen = env->GetStringLength(clientPackageName);
String16 clientName(rawClientName, rawClientNameLen);
env->ReleaseStringChars(clientPackageName,
reinterpret_cast<const jchar*>(rawClientName));

sp<Camera> camera;
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, Camera::USE_CALLING_PID);
} 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.
sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
context->incStrong((void*)android_hardware_Camera_native_setup);
camera->setListener(context);

// save context in opaque field
env->SetLongField(thiz, fields.context, (jlong)context.get());

// Update default display orientation in case the sensor is reverse-landscape
CameraInfo cameraInfo;
status_t rc = Camera::getCameraInfo(cameraId, &cameraInfo);
if (rc != NO_ERROR) {
return rc;
}
int defaultOrientation = 0;
switch (cameraInfo.orientation) {
case 0:
break;
case 90:
if (cameraInfo.facing == CAMERA_FACING_FRONT) {
defaultOrientation = 180;
}
break;
case 180:
defaultOrientation = 180;
break;
case 270:
if (cameraInfo.facing != CAMERA_FACING_FRONT) {
defaultOrientation = 180;
}
break;
default:
ALOGE("Unexpected camera orientation %d!", cameraInfo.orientation);
break;
}
if (defaultOrientation != 0) {
ALOGV("Setting default display orientation to %d", defaultOrientation);
rc = camera->sendCommand(CAMERA_CMD_SET_DISPLAY_ORIENTATION,
defaultOrientation, 0);
if (rc != NO_ERROR) {
ALOGE("Unable to update default orientation: %s (%d)",
strerror(-rc), rc);
return rc;
}
}

return NO_ERROR;
}

这个方法就是连接到相机服务,获取状态,设置监听等.我们只看连接方法,就是Camera::connect方法.

连接到相机服务

在Camera.cpp中找到connect方法:

1
2
3
4
5
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
int clientUid, int clientPid)
{
return CameraBaseT::connect(cameraId, clientPackageName, clientUid, clientPid);
}

找到CameraBaseT的定义:

1
typedef CameraBase<TCam>         CameraBaseT;

CameraBaseT等同于CameraBase,在CameraBase.cpp里找到connect方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
template <typename TCam, typename TCamTraits>
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
const String16& clientPackageName,
int clientUid, int clientPid)
{
ALOGV("%s: connect", __FUNCTION__);
sp<TCam> c = new TCam(cameraId);
sp<TCamCallbacks> cl = c;
const sp<::android::hardware::ICameraService> cs = getCameraService();

binder::Status ret;
if (cs != nullptr) {
TCamConnectService fnConnectService = TCamTraits::fnConnectService;
ret = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
clientPid, /*out*/ &c->mCamera);
}
if (ret.isOk() && c->mCamera != nullptr) {
IInterface::asBinder(c->mCamera)->linkToDeath(c);
c->mStatus = NO_ERROR;
} else {
ALOGW("An error occurred while connecting to camera %d: %s", cameraId,
(cs == nullptr) ? "Service not available" : ret.toString8().string());
c.clear();
}
return c;
}

这里获取了相机服务,然后调用TCamConnectService的fnConnectService方法,找到方法定义:

1
2
CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService =
&::android::hardware::ICameraService::connect;

connect这是一个远程调用,在aidl找到定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* Open a camera device through the old camera API
*/
ICamera connect(ICameraClient client,
int cameraId,
String opPackageName,
int clientUid, int clientPid);

/**
* Open a camera device through the new camera API
* Only supported for device HAL versions >= 3.2
*/
ICameraDeviceUser connectDevice(ICameraDeviceCallbacks callbacks,
String cameraId,
String opPackageName,
int clientUid);

在CameraService找到connect方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Status CameraService::connect(
const sp<ICameraClient>& cameraClient,
int cameraId,
const String16& clientPackageName,
int clientUid,
int clientPid,
/*out*/
sp<ICamera>* device) {

ATRACE_CALL();
Status ret = Status::ok();
String8 id = String8::format("%d", cameraId);
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, id,
CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, clientUid, clientPid, API_1,
/*legacyMode*/ false, /*shimUpdateOnly*/ false,
/*out*/client);

if(!ret.isOk()) {
logRejected(id, getCallingPid(), String8(clientPackageName),
ret.toString8());
return ret;
}

*device = client;
return ret;
}

继续看connectHelper方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
template<class CALLBACK, class CLIENT>
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
int halVersion, const String16& clientPackageName, int clientUid, int clientPid,
apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
/*out*/sp<CLIENT>& device) {
binder::Status ret = binder::Status::ok();

String8 clientName8(clientPackageName);

int originalClientPid = 0;

ALOGI("CameraService::connect call (PID %d \"%s\", camera ID %s) for HAL version %s and "
"Camera API version %d", clientPid, clientName8.string(), cameraId.string(),
(halVersion == -1) ? "default" : std::to_string(halVersion).c_str(),
static_cast<int>(effectiveApiLevel));

sp<CLIENT> client = nullptr;
{
// Acquire mServiceLock and prevent other clients from connecting
std::unique_ptr<AutoConditionLock> lock =
AutoConditionLock::waitAndAcquire(mServiceLockWrapper, DEFAULT_CONNECT_TIMEOUT_NS);

if (lock == nullptr) {
ALOGE("CameraService::connect (PID %d) rejected (too many other clients connecting)."
, clientPid);
return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
"Cannot open camera %s for \"%s\" (PID %d): Too many other clients connecting",
cameraId.string(), clientName8.string(), clientPid);
}

// Enforce client permissions and do basic sanity checks
if(!(ret = validateConnectLocked(cameraId, clientName8,
/*inout*/clientUid, /*inout*/clientPid, /*out*/originalClientPid)).isOk()) {
return ret;
}

// Check the shim parameters after acquiring lock, if they have already been updated and
// we were doing a shim update, return immediately
if (shimUpdateOnly) {
auto cameraState = getCameraState(cameraId);
if (cameraState != nullptr) {
if (!cameraState->getShimParams().isEmpty()) return ret;
}
}

status_t err;

sp<BasicClient> clientTmp = nullptr;
std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>> partial;
if ((err = handleEvictionsLocked(cameraId, originalClientPid, effectiveApiLevel,
IInterface::asBinder(cameraCb), clientName8, /*out*/&clientTmp,
/*out*/&partial)) != NO_ERROR) {
switch (err) {
case -ENODEV:
return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
"No camera device with ID \"%s\" currently available",
cameraId.string());
case -EBUSY:
return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
"Higher-priority client using camera, ID \"%s\" currently unavailable",
cameraId.string());
default:
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Unexpected error %s (%d) opening camera \"%s\"",
strerror(-err), err, cameraId.string());
}
}

if (clientTmp.get() != nullptr) {
// Handle special case for API1 MediaRecorder where the existing client is returned
device = static_cast<CLIENT*>(clientTmp.get());
return ret;
}

// give flashlight a chance to close devices if necessary.
mFlashlight->prepareDeviceOpen(cameraId);

int facing = -1;
int deviceVersion = getDeviceVersion(cameraId, /*out*/&facing);
if (facing == -1) {
ALOGE("%s: Unable to get camera device \"%s\" facing", __FUNCTION__, cameraId.string());
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Unable to get camera device \"%s\" facing", cameraId.string());
}

sp<BasicClient> tmp = nullptr;
if(!(ret = makeClient(this, cameraCb, clientPackageName, cameraId, facing, clientPid,
clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
/*out*/&tmp)).isOk()) {
return ret;
}
client = static_cast<CLIENT*>(tmp.get());

LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
__FUNCTION__);

err = client->initialize(mCameraProviderManager);
if (err != OK) {
ALOGE("%s: Could not initialize client from HAL.", __FUNCTION__);
// Errors could be from the HAL module open call or from AppOpsManager
switch(err) {
case BAD_VALUE:
return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
"Illegal argument to HAL module for camera \"%s\"", cameraId.string());
case -EBUSY:
return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
"Camera \"%s\" is already open", cameraId.string());
case -EUSERS:
return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
"Too many cameras already open, cannot open camera \"%s\"",
cameraId.string());
case PERMISSION_DENIED:
return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
"No permission to open camera \"%s\"", cameraId.string());
case -EACCES:
return STATUS_ERROR_FMT(ERROR_DISABLED,
"Camera \"%s\" disabled by policy", cameraId.string());
case -ENODEV:
default:
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Failed to initialize camera \"%s\": %s (%d)", cameraId.string(),
strerror(-err), err);
}
}

// Update shim paremeters for legacy clients
if (effectiveApiLevel == API_1) {
// Assume we have always received a Client subclass for API1
sp<Client> shimClient = reinterpret_cast<Client*>(client.get());
String8 rawParams = shimClient->getParameters();
CameraParameters params(rawParams);

auto cameraState = getCameraState(cameraId);
if (cameraState != nullptr) {
cameraState->setShimParams(params);
} else {
ALOGE("%s: Cannot update shim parameters for camera %s, no such device exists.",
__FUNCTION__, cameraId.string());
}
}

if (shimUpdateOnly) {
// If only updating legacy shim parameters, immediately disconnect client
mServiceLock.unlock();
client->disconnect();
mServiceLock.lock();
} else {
// Otherwise, add client to active clients list
finishConnectLocked(client, partial);
}
} // lock is destroyed, allow further connect calls

// 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 ret;
}

这里创建了BasicClient作为代理调用到hal方法,BasicClient实际是Client.

连接到hal

找到CameraService.h中Client的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Client : public hardware::BnCamera, public BasicClient
{
public:
typedef hardware::ICameraClient TCamCallbacks;

// ICamera interface (see ICamera for details)
virtual binder::Status disconnect();
virtual status_t connect(const sp<hardware::ICameraClient>& client) = 0;
virtual status_t lock() = 0;
virtual status_t unlock() = 0;
virtual status_t setPreviewTarget(const sp<IGraphicBufferProducer>& bufferProducer)=0;
virtual void setPreviewCallbackFlag(int flag) = 0;
virtual status_t setPreviewCallbackTarget(
const sp<IGraphicBufferProducer>& callbackProducer) = 0;
virtual status_t startPreview() = 0;
virtual void stopPreview() = 0;
virtual bool previewEnabled() = 0;
virtual status_t setVideoBufferMode(int32_t videoBufferMode) = 0;
virtual status_t startRecording() = 0;
virtual void stopRecording() = 0;
virtual bool recordingEnabled() = 0;
virtual void releaseRecordingFrame(const sp<IMemory>& mem) = 0;
virtual status_t autoFocus() = 0;
virtual status_t cancelAutoFocus() = 0;
virtual status_t takePicture(int msgType) = 0;
virtual status_t setParameters(const String8& params) = 0;
virtual String8 getParameters() const = 0;
virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;
virtual status_t setVideoTarget(const sp<IGraphicBufferProducer>& bufferProducer) = 0;

// Interface used by CameraService
Client(const sp<CameraService>& cameraService,
const sp<hardware::ICameraClient>& cameraClient,
const String16& clientPackageName,
const String8& cameraIdStr,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid);
~Client();

这里看到了我们很多熟悉的方法包括connect,startPreview,setParameters等等.像前篇介绍的,最后Client的实现在CameraClient中,在CameraClient找到initialize方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
status_t CameraClient::initialize(sp<CameraProviderManager> manager) {
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(manager);
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,
handleCallbackTimestampBatch,
(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);

LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
return OK;
}

看到这里创建了一个CameraHardwareInterface,这个属于device1的类,调用其初始化,然后设置监听,最后设置可用的消息类型,再看下CameraHardwareInterface的初始化方法:

1
2
3
4
5
6
7
8
9
status_t CameraHardwareInterface::initialize(sp<CameraProviderManager> manager) {
ALOGI("Opening camera %s", mName.string());

status_t ret = manager->openSession(mName.string(), this, &mHidlDevice);
if (ret != OK) {
ALOGE("%s: openSession failed! %s (%d)", __FUNCTION__, strerror(-ret), ret);
}
return ret;
}

这里也调用了CameraProviderManager,通过openSession方法获得一个hidlDevice,Client里面定义的方法都是通过hidlDevice调用到hal层方法的.

流程总结

总结一下打开相机整体流程:

  1. Camera.java调用android_hardware_Camera.cpp中的jni方法打开相机
  2. native层通过binder代理连接到CameraService
  3. CameraService生成一个CameraClient
  4. CameraClient生成一个CameraHardwareInterface
  5. CameraHardwareInterface通过CameraProviderManager的openSession获得hidlDevice调用到hal方法