1.1、APP層傳遞攝像頭id來打開攝像頭
//這里的callback是回調(diào)給APP的攝像頭打開的結果
//handler這里主要是設置上面的回調(diào)所在的線程度气。該參數(shù)可以為空,為空framework會內(nèi)部創(chuàng)建一個當前線程的Handler膨报。
openCamera(@NonNull String cameraId, @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)
1.2磷籍、調(diào)用到CameraManager內(nèi)部的openCameraForUid
openCameraForUid(cameraId, callback, CameraDeviceImpl.checkAndWrapHandler(handler), USE_CALLING_UID);
1.3、進一步調(diào)用內(nèi)部函數(shù)openCameraDeviceUserAsync (只貼了相關的部分代碼)**
//uid在這里是USE_CALLING_UID的值為-1
private CameraDevice openCameraDeviceUserAsync(String cameraId,CameraDevice.StateCallback callback, Executor executor, final int uid)
throws CameraAccessException {
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
CameraDevice device = null;
synchronized (mLock) { //同步
//這里是ICameraDeviceCallbacks的服務端的實現(xiàn)對象现柠,傳遞給CameraService進程用來傳遞信息給framework
ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
if (supportsCamera2ApiLocked(cameraId)) {
// Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
// 通過ServiceManager對象獲取CameraService進程的Binder
ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
//獲取到CameraService的代理過后就調(diào)用connectDevice()函數(shù)來打開攝像頭
cameraUser = cameraService.connectDevice(callbacks, cameraId,mContext.getOpPackageName(), uid);
} else { // Use legacy camera implementation for HAL1 devices
int id;
id = Integer.parseInt(cameraId);
Log.i(TAG, "Using legacy camera HAL.");
cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
}
// 將CameraService進程返回的ICameraDeviceUser的具體實現(xiàn)對象傳遞給CameraDeviceImpl對象院领。
// 這樣可以在CameraDeviceImpl對象中調(diào)用CameraService進程的CameraDeviceClient對象
deviceImpl.setRemoteDevice(cameraUser);
device = deviceImpl;
}
return device;
}
framework層的API中最后通過AIDL機制通過代碼cameraService.connectDevice() 讓軟件執(zhí)行到了CameraService進程中的CameraService.cpp中
2.1、cameraService.connectDevice()
framework層的API中最后通過調(diào)用到了下面:
//這里的cameraCb是一個AIDL文件 它的實現(xiàn)(服務端)是在上面Framework中的CameraDeviceImpl中
Status CameraService::connectDevice(const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb, const String16& cameraId,
const String16& clientPackageName,int clientUid,
/*out 函數(shù)的輸出對象*/
sp<hardware::camera2::ICameraDeviceUser>* device) {
ATRACE_CALL();
Status ret = Status::ok();
String8 id = String8(cameraId);
sp<CameraDeviceClient> client = nullptr;
//此處調(diào)用的 connectHelper 方法才真正實現(xiàn)了連接邏輯(HAL1 時最終也調(diào)用到這個方法)
ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
/*api1CameraId*/-1,
CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName,
clientUid, USE_CALLING_PID, API_2,
/*legacyMode*/ false,
/*shimUpdateOnly*/ false,
/*out*/client);
if(!ret.isOk()) { //connect失敗的情況
logRejected(id, getCallingPid(), String8(clientPackageName),
ret.toString8());
return ret;
}
*device = client;
return ret;
}
上面的函數(shù)主要是做了一些聲明和初始化的操作够吩。
2.2比然、CameraService::connectHelper()
繼續(xù)往下分析就來到了connectHelper()
template<class CALLBACK, class CLIENT> //模板類 <ICameraDeviceCallbacks,CameraDeviceClient>
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId, int api1CameraId, 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;
sp<CLIENT> client = nullptr;
{
// 同步鎖防止不同進程同一時刻都在打開攝像頭
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);
}
// 對客戶端的攝像頭權限進行檢查
if(!(ret = validateConnectLocked(cameraId, clientName8,/*inout*/clientUid, /*inout*/clientPid, /*out*/originalClientPid)).isOk()) {
return ret;
}
status_t err;
sp<BasicClient> clientTmp = nullptr;
std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>> partial;
//1周循、handleEvictionsLocked就是在這里處理多進程打開攝像頭沖突的
if ((err = handleEvictionsLocked(cameraId, originalClientPid, effectiveApiLevel,IInterface::asBinder(cameraCb), clientName8,
/*out*/&clientTmp, //使用camera2的api的時候這個對象為空
/*out*/&partial)
) != NO_ERROR) {
// 條件里面主要是return error 流程到此就結束了
}
if (clientTmp.get() != nullptr) {
device = static_cast<CLIENT*>(clientTmp.get());
return ret;
}
sp<BasicClient> tmp = nullptr;
//2强法、調(diào)用 makeClient 生成 CameraDeviceClient 實例。
if(!(ret = makeClient(this, cameraCb, clientPackageName,cameraId, api1CameraId, facing, clientPid, clientUid, getpid(), legacyMode,
halVersion, deviceVersion, effectiveApiLevel, /*out*/&tmp)).isOk()) {
return ret; //返回失敗
}
client = static_cast<CLIENT*>(tmp.get()); //將makeClient()函數(shù)生成的tmp對象強轉(zhuǎn)成CLIENT*也就是CameraDeviceClient*
//3湾笛、這里會調(diào)用到CameraDeviceClient::initialize() ---> CameraDeviceClient::initializeImpl() ---> Camera2ClientBase::initialize() --->
// Camera2ClientBase::initializeImpl() ---> Camera3Device::initialize()
err = client->initialize(mCameraProviderManager, mMonitorTags);
if (err != OK) {
ALOGE("%s: Could not initialize client from HAL.", __FUNCTION__);
// 到這會返回錯誤信息打開失敗 流程終止 return error
}
if (shimUpdateOnly) { //該值是上一個函數(shù)傳遞過來的該值為false
// If only updating legacy shim parameters, immediately disconnect client
mServiceLock.unlock();
client->disconnect();
mServiceLock.lock();
} else {
//4饮怯、add client to active clients list 將打開攝像頭成功后的client轉(zhuǎn)換成ClientDescriptor添加到ClientManager對象中的mClients列表中
finishConnectLocked(client, partial);
}
} // lock is destroyed, allow further connect calls
device = client;
return ret;
}
上面函數(shù)進來首先做一些同步機制和權限驗證,然后調(diào)用到handleEvictionsLocked()函數(shù)嚎研。這個函數(shù)主要是來處理Camera多進程使用攝像頭沖突的蓖墅。在執(zhí)行完handleEvictionsLocked()函數(shù)后,和當前客戶端打開攝像頭的操作沖突的進程會去關閉或者斷開攝像頭的操作嘉赎。然后去調(diào)用makeClient()函數(shù)去創(chuàng)建一個CameraDeviceClient對象置媳。然后會調(diào)用client->initialize()函數(shù)對創(chuàng)建的CameraDeviceClient這個對象去進行一些初始化(主要是和CameraProvider進程的操作)和驗證于樟。如果驗證OK就會將該對象返回給上層函數(shù)最后通過IPC返回給上層APP(這里使用了匿名Binder的機制 -- framework層的ICameraDeviceUser是客戶端公条,CameraService進程中的ClientDeviceClient繼承了BnCameraDeviceUser所以是服務端)。
2.2.1迂曲、handleEvictionsLocked()
接下來我們看看這個函數(shù)是如何處理攝像頭沖突的靶橱。
status_t CameraService::handleEvictionsLocked(const String8& , int clientPid,
apiLevel effectiveApiLevel, const sp<IBinder>& remoteCallback, const String8& packageName,
/*out*/
sp<BasicClient>* client,
std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>* partial) {
ATRACE_CALL();
status_t ret = NO_ERROR;
//std::shared_ptr<resource_policy::ClientDescriptor<String8,sp<CameraService::BasicClient>>> shared_ptr 是一種智能指針
std::vector<DescriptorPtr> evictedClients;
DescriptorPtr clientDescriptor;
{
if (effectiveApiLevel == API_1) { //API1的邏輯 這里不分析
}
//通過遍歷CameraManager中的mClients列表遍歷來獲取所有打開相機的進程的pid
std::vector<int> ownerPids(mActiveClientManager.getAllOwners());
ownerPids.push_back(clientPid); // 將當前需要打開相機的進程的pid push到這個數(shù)組中
std::vector<int> priorityScores(ownerPids.size()); //優(yōu)先級列表
std::vector<int> states(ownerPids.size()); //狀態(tài)列表
// 調(diào)用到了IProcessInfoService里面,這個里面會進行IPC機制調(diào)用到系統(tǒng)服務,來給這些進程進行優(yōu)先級和狀態(tài)的賦值 关霸。
// 一般不 會這里面的邏輯去修改來改變進程的優(yōu)先級传黄,一般是處理返回回來的優(yōu)先級和狀態(tài)來進行修改
status_t err = ProcessInfoService::getProcessStatesScoresFromPids(
ownerPids.size(), &ownerPids[0], /*out*/&states[0],
/*out*/&priorityScores[0]);
if (err != OK) {
ALOGE("%s: Priority score query failed: %d", __FUNCTION__, err);
return err;
}
// 將本地已經(jīng)打開了攝像頭的進程(不包含即將打開攝像頭的進程)的優(yōu)先級和狀態(tài)賦值給一個新的集合pidToPriorityMap
for (size_t i = 0; i < ownerPids.size() - 1; i++) { //這里的 ownerPids.size() - 1 排除了即將打開攝像頭的進程
pidToPriorityMap.emplace(ownerPids[i],resource_policy::ClientPriority(priorityScores[i], states[i]));
}
mActiveClientManager.updatePriorities(pidToPriorityMap); //將pidToPriorityMap
// 從本地mCameraStates集合中獲取要打開相機的狀態(tài)信息
auto state = getCameraState(cameraId);
if (state == nullptr) {
ALOGE("CameraService::connect X (PID %d) rejected (no camera device with ID %s)",clientPid, cameraId.string());
// Should never get here because validateConnectLocked should have errored out
return BAD_VALUE;
}
// 會使用std::make_share 調(diào)用到ClientDescriptor的構造函數(shù),因為是即將打開攝像頭的進程所以這里的BasicClient是空的队寇。
clientDescriptor = CameraClientManager::makeClientDescriptor(cameraId,
sp<BasicClient>{nullptr}, static_cast<int32_t>(state->getCost()),
state->getConflicting(),
priorityScores[priorityScores.size() - 1],
clientPid,
states[states.size() - 1]);
// 通過和當前的進程的clientDescriptor 對象對比膘掰,判斷本地的mClients列表中哪些進程是沖突的
auto evicted = mActiveClientManager.wouldEvict(clientDescriptor);//返回的std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
// 如果沖突列表中有即將開啟的進程,那么就說明有其他優(yōu)先級更高的進程正在使用攝像頭佳遣,所以當前進程就會打開失敗识埋。
if (std::find(evicted.begin(), evicted.end(), clientDescriptor) != evicted.end()) {
ALOGE("CameraService::connect X (PID %d) rejected (existing client(s) with higher" " priority).", clientPid);
sp<BasicClient> clientSp = clientDescriptor->getValue();
String8 curTime = getFormattedCurrentTime();
auto incompatibleClients = mActiveClientManager.getIncompatibleClients(clientDescriptor);
........................... //省略代碼 主要是構建錯誤信息msg
for (auto& i : incompatibleClients) {
.................... //省略代碼 主要是構建錯誤信息msg和打印錯誤
}
// Log the client's attempt
Mutex::Autolock l(mLogLock);
mEventLog.add(msg);
return -EBUSY;
}
//即將開啟的進程優(yōu)先級高可以開啟攝像頭 那么就把沖突列表中開了攝像頭的進程一一關閉其打開的攝像頭
for (auto& i : evicted) {
sp<BasicClient> clientSp = i->getValue();
if (clientSp.get() == nullptr) {
ALOGE("%s: Invalid state: Null client in active client list.", __FUNCTION__);
// TODO: Remove this
LOG_ALWAYS_FATAL("%s: Invalid state for CameraService, null client in active list", __FUNCTION__);
mActiveClientManager.remove(i);
continue;
}
ALOGE("CameraService::connect evicting conflicting client for camera ID %s",
i->getKey().string());
evictedClients.push_back(i);
// Notify the client of disconnection
clientSp->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED,
CaptureResultExtras());
}
}
mServiceLock.unlock();
// Clear caller identity temporarily so client disconnect PID checks work correctly
int64_t token = IPCThreadState::self()->clearCallingIdentity();
// Destroy evicted clients
for (auto& i : evictedClients) {
// Disconnect is blocking, and should only have returned when HAL has cleaned up
i->getValue()->disconnect(); // Clients will remove themselves from the active client list
}
IPCThreadState::self()->restoreCallingIdentity(token);
for (const auto& i : evictedClients) {
ALOGV("%s: Waiting for disconnect to complete for client for device %s (PID %" PRId32 ")", __FUNCTION__, i->getKey().string(), i->getOwnerId());
ret = mActiveClientManager.waitUntilRemoved(i, DEFAULT_DISCONNECT_TIMEOUT_NS);
if (ret == TIMED_OUT) {
ALOGE("%s: Timed out waiting for client for device %s to disconnect, " "current clients:\n%s", __FUNCTION__, i->getKey().string(), mActiveClientManager.toString().string());
return -EBUSY;
}
if (ret != NO_ERROR) {
ALOGE("%s: Received error waiting for client for device %s to disconnect: %s (%d), ""current clients:\n%s", __FUNCTION__, i->getKey().string(), strerror(-ret),ret, mActiveClientManager.toString().string());
return ret;
}
}
evictedClients.clear();
// Once clients have been disconnected, relock
mServiceLock.lock();
// Check again if the device was unplugged or something while we weren't holding mServiceLock
if ((ret = checkIfDeviceIsUsable(cameraId)) != NO_ERROR) {
return ret;
}
*partial = clientDescriptor;
return NO_ERROR;
}
首先給ownerPids向量進行賦值,這里會調(diào)用mActiveClientManager.getAllOwners()函數(shù)零渐,這里的mActiveClientManager是CameraService::CameraClientManager它繼承了ClientManager對象窒舟。所以這里的getAllOwners()會調(diào)用到ClientManager中:
// 通過遍歷ClientManager中的全局變量mClients(std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> mClients;)列表。
// 將列表元素ClientDescriptor中的mOwnerId(也就是pid)創(chuàng)建成一個集合返回
std::vector<int32_t> ClientManager<KEY, VALUE, LISTENER>::getAllOwners() const {
Mutex::Autolock lock(mLock);
std::set<int32_t> owners;
for (const auto& i : mClients) {
owners.emplace(i->getOwnerId());
}
return std::vector<int32_t>(owners.begin(), owners.end());
}
在獲取到CameraService本地保存的已開啟攝像頭的進程和將要開啟攝像頭的進程的pid列表后诵盼,調(diào)用到IProcessInfoService對應的系統(tǒng)服務來給這些進程進行優(yōu)先級和狀態(tài)進行賦值惠豺,并存放到priorityScores和states向量中。然后將進程向量ownerPids风宁、優(yōu)先級向量priorityScores和狀態(tài)向量states等信息中除了即將打開攝像頭的進程的其他進程的狀態(tài)和優(yōu)先級賦值到pidToPriorityMap集合中洁墙,并將這個集合給到mActiveClientManager(CameraManager)對象,用來更新其內(nèi)部的mClients列表中元素的優(yōu)先級的值戒财。
然后進一步通過本地的mCameraStates列表獲取即將開啟攝像頭的狀態(tài)信息扫俺。并通過上面的信息,來創(chuàng)建即將開啟攝像頭進程對ClientDescriptor對象 clientDescriptor = CameraClientManager::makeClientDescriptor()固翰。
2.2.1.1 mActiveClientManager.wouldEvict(clientDescriptor)
創(chuàng)建完成之后會調(diào)用mActiveClientManager.wouldEvict(clientDescriptor)將該對象給到mActiveClientManager對象調(diào)用進行計算狼纬,得到一個攝像頭使用沖突列表。計算代碼如下:
// KEY--string8(cameraId) VALUE--BasicClient(CameraDeviceClient)
template<class KEY, class VALUE, class LISTENER>
std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
ClientManager<KEY, VALUE, LISTENER>::wouldEvictLocked(const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client,
bool returnIncompatibleClients) const {
//初始化沖突列表
std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> evictList;
// Disallow null clients, return input
if (client == nullptr) {
evictList.push_back(client);
return evictList;
}
//這里的client是在上面函數(shù)傳遞過來的 是即將開啟攝像頭進程匹配的ClientDescriptor對象
const KEY& key = client->getKey(); //將要開啟攝像頭的cameraId
int32_t cost = client->getCost(); //對應的攝像頭支持的最大數(shù)骂际,通過CameraState獲取到的
ClientPriority priority = client->getPriority();//通過CameraState獲取到的
int32_t owner = client->getOwnerId();//上層app的pid
int64_t totalCost = getCurrentCostLocked() + cost;
// Determine the MRU of the owners tied for having the highest priority
int32_t highestPriorityOwner = owner;
ClientPriority highestPriority = priority;
for (const auto& i : mClients) { //遍歷所有的Client 將沖突的Client放到?jīng)_突列表中
ClientPriority curPriority = i->getPriority();
if (curPriority <= highestPriority) {
highestPriority = curPriority;
highestPriorityOwner = i->getOwnerId();
}
}
if (highestPriority == priority) {
// Switch back owner if the incoming client has the highest priority, as it is MRU
highestPriorityOwner = owner;
}
// Build eviction list of clients to remove
for (const auto& i : mClients) {
const KEY& curKey = i->getKey();
int32_t curCost = i->getCost();
ClientPriority curPriority = i->getPriority();
int32_t curOwner = i->getOwnerId();
bool conflicting = (curKey == key || i->isConflicting(key) ||client->isConflicting(curKey));
if (!returnIncompatibleClients) {
// Find evicted clients
if (conflicting && curPriority < priority) {
// Pre-existing conflicting client with higher priority exists
evictList.clear();
evictList.push_back(client);
return evictList;
} else if (conflicting || ((totalCost > mMaxCost && curCost > 0) &&(curPriority >= priority) && !(highestPriorityOwner == owner && owner == curOwner))) {
evictList.push_back(i);
totalCost -= curCost;
}
} else {
// Find clients preventing the incoming client from being added
if (curPriority < priority && (conflicting || (totalCost > mMaxCost && curCost > 0))) {
// Pre-existing conflicting client with higher priority exists
evictList.push_back(i);
}
}
}
// Immediately return the incompatible clients if we are calculating these instead
if (returnIncompatibleClients) {
return evictList;
}
// If the total cost is too high, return the input unless the input has the highest priority
if (totalCost > mMaxCost && highestPriorityOwner != owner) {
evictList.clear();
evictList.push_back(client);
return evictList;
}
return evictList;
}
該函數(shù)主要是將當前應用的ClientDescriptor對象通過和本地已經(jīng)打開了攝像頭的應用對應的ClientDescriptor對象列表(該列表在上面connectHelper()中打開攝像頭成功過后就會調(diào)用finishConnectLocked(client, partial)保存到本地的mClients中) 進行對比來得到一個沖突列表(意思是這個列表里面可能有當前應用)疗琉。
得到這個當前列表之后繼續(xù)回到上面2.2.1 handleEvictionsLocked()的代碼流程中,然后繼續(xù)往下執(zhí)行歉铝。在得到了沖突列表之后盈简,如果當前進程在沖突列表中,就會返回失敗太示,整個openCamera流程就到這結束了柠贤。如果當前進程不在沖突列表中,就遍歷沖突列表把其中的進程操作的攝像頭流程進行終止类缤。
解決萬沖突之后臼勉,就會去創(chuàng)建ICameraDeviceUser的實例。
2.2.2 CameraService::makeClient()**
解決沖突過后就是去新建一個CameraDeviceClient(CameraDeviceClient是ICameraDeviceClient的實現(xiàn))對象餐弱。
/ 主要是根據(jù) API 版本以及 HAL 版本來選擇生成具體的 Client 實例宴霸,
// Client 就沿著前面分析下來的路徑返回到 CameraDeviceImpl 實例中囱晴,被保存到 mRemoteDevice。
Status CameraService::makeClient(const sp<CameraService>& cameraService,
const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
int api1CameraId, int facing, int clientPid, uid_t clientUid, int servicePid,
bool legacyMode, int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
/*out*/sp<BasicClient>* client) {
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:
if (effectiveApiLevel == API_1) { // Camera1 API route
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new CameraClient(cameraService, tmp, packageName,
api1CameraId, facing, clientPid, clientUid,
getpid(), legacyMode);
} else { // Camera2 API route
ALOGW("Camera using old HAL version: %d", deviceVersion);
return STATUS_ERROR_FMT(ERROR_DEPRECATED_HAL,
"Camera device \"%s\" HAL version %d does not support camera2 API",
cameraId.string(), deviceVersion);
}
break;
case CAMERA_DEVICE_API_VERSION_3_0:
case CAMERA_DEVICE_API_VERSION_3_1:
case CAMERA_DEVICE_API_VERSION_3_2:
case CAMERA_DEVICE_API_VERSION_3_3:
case CAMERA_DEVICE_API_VERSION_3_4:
if (effectiveApiLevel == API_1) { // Camera1 API route
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new Camera2Client(cameraService, tmp, packageName,
cameraId, api1CameraId,
facing, clientPid, clientUid,
servicePid, legacyMode);
} else { // Camera2 API route
sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
*client = new CameraDeviceClient(cameraService, tmp, packageName, cameraId,
facing, clientPid, clientUid, servicePid);
}
break;
default:
// Should not be reachable
ALOGE("Unknown camera device HAL version: %d", deviceVersion);
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Camera device \"%s\" has unknown HAL version %d",
cameraId.string(), deviceVersion);
}
} 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.
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new CameraClient(cameraService, tmp, packageName,
api1CameraId, facing, clientPid, clientUid,
servicePid, 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 STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
"Camera device \"%s\" (HAL version %d) cannot be opened as HAL version %d",
cameraId.string(), deviceVersion, halVersion);
}
}
return Status::ok();
}
這個里面的邏輯比較簡單就是根據(jù)當前使用的API的版本來創(chuàng)建一個ICameraDeviceUser的實例對象瓢谢,這里創(chuàng)建的是CameraDeviceClient這個對象畸写。
2.2.2.1 CameraDeviceClient()的構造函數(shù)
這里結合類圖我們可以知道下面的這一層繼承關系
CameraDeviceClient --|> Camera2ClientBase:繼承
Camera2ClientBase --|> CameraDeviceClientBase:繼承
CameraDeviceClientBase --|> CameraService::BasicClient
CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid) :
Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, /*API1 camera ID*/ -1,
cameraFacing, clientPid, clientUid, servicePid),
mInputStream(),
mStreamingRequestId(REQUEST_ID_NONE),
mRequestIdCounter(0) {
ATRACE_CALL();
ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
}
------------------------------------------------------------------------------------------------
上面的構造函數(shù)中主動調(diào)用了其父類Camera2ClientBase的構造函數(shù)
template <typename TClientBase> //CameraDeviceClientBase
Camera2ClientBase<TClientBase>::Camera2ClientBase(
const sp<CameraService>& cameraService,
const sp<TCamCallbacks>& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid):
TClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, api1CameraId, cameraFacing, clientPid, clientUid, servicePid),
mSharedCameraCallbacks(remoteCallback),
mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
mDeviceActive(false), mApi1CameraId(api1CameraId)
{
ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
String8(clientPackageName).string(), clientPid, clientUid);
mInitialClientPid = clientPid;
// 就是在這里創(chuàng)建了一個Camera3Device對象 這個對象對后面的Session和Capture的流程起到關鍵作用
mDevice = new Camera3Device(cameraId);
LOG_ALWAYS_FATAL_IF(mDevice == 0, "Device should never be NULL here.");
}
-------------------------------------------------------------------------------------------------------------
上面的代碼有執(zhí)行了其父類CameraDeviceClientBase的構造函數(shù)
CameraDeviceClientBase::CameraDeviceClientBase(
const sp<CameraService>& cameraService,
const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid) :
BasicClient(cameraService,
IInterface::asBinder(remoteCallback),
clientPackageName,
cameraId,
cameraFacing,
clientPid,
clientUid,
servicePid),
mRemoteCallback(remoteCallback) {
// We don't need it for API2 clients, but Camera2ClientBase requires it.
(void) api1CameraId;
}
-------------------------------------------------------------------------------------------------
然后繼續(xù)調(diào)用父類BaseClient的構造函數(shù)
CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService,
const sp<IBinder>& remoteCallback,
const String16& clientPackageName,
const String8& cameraIdStr, int cameraFacing,
int clientPid, uid_t clientUid,
int servicePid):
mCameraIdStr(cameraIdStr), mCameraFacing(cameraFacing),
mClientPackageName(clientPackageName), mClientPid(clientPid), mClientUid(clientUid),
mServicePid(servicePid),
mDisconnected(false),
mRemoteBinder(remoteCallback)
{
if (sCameraService == nullptr) {
sCameraService = cameraService;
}
mOpsActive = false;
mDestructionStarted = false;
if (mClientPackageName.size() <= 0) { // 如果沒有包名 通過Binder獲取應用層的包名信息
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16(kPermissionServiceName));
if (binder == 0) {
ALOGE("Cannot get permission service");
// Leave mClientPackageName unchanged (empty) and the further interaction
// with camera will fail in BasicClient::startCameraOps
return;
}
sp<IPermissionController> permCtrl = interface_cast<IPermissionController>(binder);
Vector<String16> packages;
permCtrl->getPackagesForUid(mClientUid, packages);
if (packages.isEmpty()) {
ALOGE("No packages for calling UID");
// Leave mClientPackageName unchanged (empty) and the further interaction
// with camera will fail in BasicClient::startCameraOps
return;
}
mClientPackageName = packages[0];
}
}
執(zhí)行完上面的構造函數(shù)之后就可以獲取生成CameraDeviceClient對象。以上構造函數(shù)沒有什么特別的邏輯主要是將構造函數(shù)中的參數(shù)進行保存和一些變量的初始化氓扛。最重要的一個操作就是在Camera2ClientBase的構造函數(shù)中new了一個Camera3Device對象枯芬。cmaeraid --- CameraDeviceClient --- Camera3Device 這是1對1的關系。
對象創(chuàng)建完成之后讓我們繼續(xù)回調(diào)2.2 connectHelper() 函數(shù)中繼續(xù)分析下面的代碼會執(zhí)行到 client->initialize(mCameraProviderManager, mMonitorTags)對上面創(chuàng)建的CameraDeviceClient進行初始化采郎。
2.2.3 CameraDeviceClient::initialize(sp<CameraProviderManager> manager,const String8& monitorTags)**
開始CameraDeviceClient的初始化流程
status_t CameraDeviceClient::initialize(sp<CameraProviderManager> manager,
const String8& monitorTags) {
return initializeImpl(manager, monitorTags);
}
template<typename TProviderPtr>
status_t CameraDeviceClient::initializeImpl(TProviderPtr providerPtr, const String8& monitorTags) {
ATRACE_CALL();
status_t res;
res = Camera2ClientBase::initialize(providerPtr, monitorTags);
if (res != OK) {
return res;
}
String8 threadName;
mFrameProcessor = new FrameProcessorBase(mDevice);
threadName = String8::format("CDU-%s-FrameProc", mCameraIdStr.string());
mFrameProcessor->run(threadName.string());
mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
FRAME_PROCESSOR_LISTENER_MAX_ID,
/*listener*/this,
/*sendPartials*/true);
auto deviceInfo = mDevice->info();
camera_metadata_entry_t physicalKeysEntry = deviceInfo.find(
ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS);
if (physicalKeysEntry.count > 0) {
mSupportedPhysicalRequestKeys.insert(mSupportedPhysicalRequestKeys.begin(),
physicalKeysEntry.data.i32,
physicalKeysEntry.data.i32 + physicalKeysEntry.count);
}
return OK;
}
該函數(shù)第一個就是調(diào)用 Camera2ClientBase::initialize(providerPtr, monitorTags);
<>2.2.3.1 Camera2ClientBase<TClientBase>::initialize(sp<CameraProviderManager> manager,const String8& monitorTags)
template <typename TClientBase>
status_t Camera2ClientBase<TClientBase>::initialize(sp<CameraProviderManager> manager,
const String8& monitorTags) {
return initializeImpl(manager, monitorTags);
}
// TClientBase--CameraDeviceClientBase TProviderPtr--CameraProviderManager
template <typename TClientBase>
template <typename TProviderPtr>
status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr, const String8& monitorTags) {
ATRACE_CALL();
ALOGV("%s: Initializing client for camera %s", __FUNCTION__,TClientBase::mCameraIdStr.string());
status_t res;
// Verify ops permissions 調(diào)用到CameraService::BasicClient::startCameraOps()里面主要是檢查APP有沒有相機操作權限
res = TClientBase::startCameraOps();
if (res != OK) {
return res;
}
if (mDevice == NULL) {
ALOGE("%s: Camera %s: No device connected", __FUNCTION__, TClientBase::mCameraIdStr.string());
return NO_INIT;
}
res = mDevice->initialize(providerPtr, monitorTags);
if (res != OK) {
ALOGE("%s: Camera %s: unable to initialize device: %s (%d)", __FUNCTION__, TClientBase::mCameraIdStr.string(), strerror(-res), res);
return res;
}
wp<CameraDeviceBase::NotificationListener> weakThis(this);
res = mDevice->setNotifyCallback(weakThis);
return OK;
}
上面首先就是對當前應用打開攝像頭這一操作進行權限鑒權破停,然后調(diào)用了mDevice->initialize(providerPtr, monitorTags);繼續(xù)進行初始化的操作,這樣程序就來到了我們上面說的比較重要的一個對象Camera3Device對象中了尉剩。
2.2.4.2 Camera3Device::initialize
status_t Camera3Device::initialize(sp<CameraProviderManager> manager, const String8& monitorTags) {
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
if (mStatus != STATUS_UNINITIALIZED) {
CLOGE("Already initialized!");
return INVALID_OPERATION;
}
if (manager == nullptr) return INVALID_OPERATION;
//這里對應了CameraProvider進程中的 ICameraDeviceSession.hal (匿名Binder) 其服務端是在CameraProvider中的CameraDeviceSession.cpp
sp<ICameraDeviceSession> session;
ATRACE_BEGIN("CameraHal::openSession");
// 這里調(diào)用到CameraProviderManager的openSession主要是給session賦值(在這里面會去打開攝像頭)
// this 在這是ICameraDeviceCallback.hal 回調(diào)接口的數(shù)據(jù)接收端 因為Camera3Device繼承了ICameraDeviceCallback
status_t res = manager->openSession(mId.string(), this, /*out*/ &session);
ATRACE_END();
if (res != OK) {
SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
return res;
}
// 調(diào)用 CameraDeviceClient中的getCameraCharacteristics() 給mDeviceInfo賦值
res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo);
if (res != OK) {
SET_ERR_L("Could not retrive camera characteristics: %s (%d)", strerror(-res), res);
session->close();
return res;
}
std::shared_ptr<RequestMetadataQueue> queue;
auto requestQueueRet = session->getCaptureRequestMetadataQueue(
[&queue](const auto& descriptor) {
queue = std::make_shared<RequestMetadataQueue>(descriptor);
if (!queue->isValid() || queue->availableToWrite() <= 0) {
ALOGE("HAL returns empty request metadata fmq, not use it");
queue = nullptr;
// don't use the queue onwards.
}
});
if (!requestQueueRet.isOk()) {
ALOGE("Transaction error when getting request metadata fmq: %s, not use it",
requestQueueRet.description().c_str());
return DEAD_OBJECT;
}
std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
auto resultQueueRet = session->getCaptureResultMetadataQueue(
[&resQueue](const auto& descriptor) {
resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
ALOGE("HAL returns empty result metadata fmq, not use it");
resQueue = nullptr;
// Don't use the resQueue onwards.
}
});
if (!resultQueueRet.isOk()) {
ALOGE("Transaction error when getting result metadata queue from camera session: %s",
resultQueueRet.description().c_str());
return DEAD_OBJECT;
}
IF_ALOGV() {
session->interfaceChain([](
::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
ALOGV("Session interface chain:");
for (auto iface : interfaceChain) {
ALOGV(" %s", iface.c_str());
}
});
}
mInterface = new HalInterface(session, queue);
std::string providerType;
mVendorTagId = manager->getProviderTagIdLocked(mId.string());
mTagMonitor.initialize(mVendorTagId);
if (!monitorTags.isEmpty()) {
mTagMonitor.parseTagsToMonitor(String8(monitorTags));
}
return initializeCommonLocked();
}
status_t Camera3Device::initializeCommonLocked() {
/** Start up status tracker thread */
mStatusTracker = new StatusTracker(this);
status_t res = mStatusTracker->run(String8::format("C3Dev-%s-Status", mId.string()).string());
if (res != OK) {
SET_ERR_L("Unable to start status tracking thread: %s (%d)",strerror(-res), res);
mInterface->close();
mStatusTracker.clear();
return res;
}
/** Register in-flight map to the status tracker */
mInFlightStatusId = mStatusTracker->addComponent();
/** Create buffer manager */
mBufferManager = new Camera3BufferManager();
Vector<int32_t> sessionParamKeys;
camera_metadata_entry_t sessionKeysEntry = mDeviceInfo.find(
ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
if (sessionKeysEntry.count > 0) {
sessionParamKeys.insertArrayAt(sessionKeysEntry.data.i32, 0, sessionKeysEntry.count);
}
/** Start up request queue thread */
mRequestThread = new RequestThread(this, mStatusTracker, mInterface, sessionParamKeys);
res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string());
if (res != OK) {
SET_ERR_L("Unable to start request queue thread: %s (%d)",
strerror(-res), res);
mInterface->close();
mRequestThread.clear();
return res;
}
mPreparerThread = new PreparerThread();
internalUpdateStatusLocked(STATUS_UNCONFIGURED);
mNextStreamId = 0;
mDummyStreamId = NO_STREAM;
mNeedConfig = true;
mPauseStateNotify = false;
// Measure the clock domain offset between camera and video/hw_composer
camera_metadata_entry timestampSource =
mDeviceInfo.find(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE);
if (timestampSource.count > 0 && timestampSource.data.u8[0] ==
ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME) {
mTimestampOffset = getMonoToBoottimeOffset();
}
// Will the HAL be sending in early partial result metadata?
camera_metadata_entry partialResultsCount =mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
if (partialResultsCount.count > 0) {
mNumPartialResults = partialResultsCount.data.i32[0];
mUsePartialResult = (mNumPartialResults > 1);
}
camera_metadata_entry configs = mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
for (uint32_t i = 0; i < configs.count; i += 4) {
if (configs.data.i32[i] == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
configs.data.i32[i + 3] ==
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
mSupportedOpaqueInputSizes.add(Size(configs.data.i32[i + 1],configs.data.i32[i + 2]));
}
}
if (DistortionMapper::isDistortionSupported(mDeviceInfo)) {
res = mDistortionMapper.setupStaticInfo(mDeviceInfo);
if (res != OK) {
SET_ERR_L("Unable to read necessary calibration fields for distortion correction");
return res;
}
}
return OK;
}