在android系統啓動的過程中,CameraProvider服務啓動之後,接着將會啓動CameraService服務,它將負責與CameraClient進行通信,滿足應用需求。
下面以Android P進行相應的學習分析。
CameraService 啓動
-
android/frameworks/av/camera/cameraserver/cameraserver.rc
service cameraserver /system/bin/cameraserver class main user cameraserver group audio camera input drmrpc ioprio rt 4 writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks
在android啓動的過程中,init進程調用該腳本啓動 CameraService 服務。根據該目錄下的 Android.mk 可以知道,其實就是運行該目錄下 main_cameraserver.cpp 編譯的可執行文件。
main_cameraserver.cpp
文件路徑:android/frameworks/av/camera/cameraserver
main_cameraserver.cpp 內容如下:
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();
}
從內容可以看到,很多都是一些線程池的配置,主要是CameraService::instantiate()
。instantiate() 接口並不是定義在CameraService類中,而是定義在 BinderService 類(而CameraService繼承它,instantiate() 定義在android/frameworks/native/libs/binder/include/binder/BinderService.h)。在此處,它的作用是創建一個 CameraService(通過 new
的方式),並將其加入到 ServiceManager 中(注意,在這一過程中,CameraService 被強指針引用了)。注意這裏的ServiceName,這裏是CameraService.getServiceName(),返回的是 “media.camera”。後續應用將會通過這個ServiceName獲取CameraService的代理。
爲什麼會被強指針引用?
查看 IServiceManager::addService() 的聲明如下:
[android/frameworks/native/libs/binder/include/binder/IServiceManager.h]
/**
* Register a service.
*/
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated = false,
int dumpsysFlags = DUMP_FLAG_PRIORITY_DEFAULT) = 0;
最終是 new CameraService() 賦值給 service 參數,而該參數是強指針引用,所以,將會調用 CameraService::onFirstRef() 函數。
CameraService.cpp
文件路徑:android/frameworks/av/services/camera/libcameraservice
在 CameraService::onFirstRef() 函數中,主要是調用 enumerateProviders() 函數獲取CameraProvider信息。
status_t CameraService::enumerateProviders() {
status_t res;
std::vector<std::string> deviceIds;
{
Mutex::Autolock l(mServiceLock);
if (nullptr == mCameraProviderManager.get()) {
mCameraProviderManager = new CameraProviderManager();
/* 創建一個 CameraProviderManager 對象之後調用 initialize(),
* 其實就是將CameraService設置爲 CameraProviderManager 的監聽者
*/
res = mCameraProviderManager->initialize(this);
if (res != OK) {
ALOGE("%s: Unable to initialize camera provider manager: %s (%d)",
__FUNCTION__, strerror(-res), res);
return res;
}
}
...
deviceIds = mCameraProviderManager->getCameraDeviceIds();
}
for (auto& cameraId : deviceIds) {
String8 id8 = String8(cameraId.c_str());
onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT);
}
return OK;
}
CameraProviderManager.cpp
文件路徑:android/frameworks/av/services/camera/libcameraservice/common
/**
* Initialize the manager and give it a status listener; optionally accepts a service
* interaction proxy.
*
* The default proxy communicates via the hardware service manager; alternate proxies can be
* used for testing. The lifetime of the proxy must exceed the lifetime of the manager.
*/
status_t initialize(wp<StatusListener> listener,
ServiceInteractionProxy *proxy = &sHardwareServiceInteractionProxy);
CameraProviderManager::initialize() 主要完成以下操作:
- 用於初始化管理器,並給它設置一個狀態監聽(即 CameraService 實例)。選擇性地接受一個與服務交互的代理。
- 默認的代理通過 Hardware 服務管理器進行通信。備用的代理可以用來進行測試。代理的生命週期必須要超過管理器的生命週期。
- 注意到在 enumerateProviders 中調用該接口時,只有一個入參,說明當前用的是默認代理。
- 通過 mServiceProxy->registerForNotifications() 作出一個註冊的動作,註冊會觸發一個給所有已知 Provider 進行通知的動作。
- 通過 CameraProviderManager::addProviderLocked() 獲得相應的 provider 代理信息(從實現來看,分別獲取 “legacy/0” 和 “external/0” 的代理信息)。
/* 調用參數:
* newProvider 參數分別是 "legacy/0" 和 "external/0"
* expected 參數爲 false
*/
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;
/* mServiceProxy 爲 sHardwareServiceInteractionProxy,根據同一目錄下的
* CameraProviderManager.h 中 HardwareServiceInteractionProxy 定義可以
* 知道,getService() 將會調用
* hardware::camera::provider::V2_4::ICameraProvider::getService(serviceName)
* 在這裏,CameraService已經獲得 CameraProvider
*/
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);
/* 在獲得CameraProvider代理之後,將會根據 ICameraProvider 填充相應的 providerInfo */
status_t res = providerInfo->initialize();
if (res != OK) {
return res;
}
mProviders.push_back(providerInfo);
return OK;
}
上述的 interface = mServiceProxy->getService(newProvider) 函數將會調用 hardware::camera::provider::V2_4::ICameraProvider::getService(serviceName)
獲取CameraProvider 代理,該函數將會調用到
android/out/soong/.intermediates/hardware/interfaces/camera/provider/2.4/[email protected]_genc++/gen/android/hardware/camera/provider/2.4 目錄下的CameraProviderAll.cpp文件,而在該文件中,也是通過 getRawServiceInternal( getStub = false) 獲取CameraProvider 代理,注意,此處的 getRawServiceInternal() 調用參數爲 false,getRawServiceInternal() 函數在 CameraProvider 註冊爲服務的時候調用了,只是調用參數不一致,所以,這裏返回的將會是 CameraProvider 代理。
status_t CameraProviderManager::ProviderInfo::initialize() {
...
// Get initial list of camera devices, if any
std::vector<std::string> devices;
/* 獲取 CameraProvider 中的camera設備信息,這裏獲取的就是
* CameraProvider服務在啓動時通過HAL層的 getCameraInfo() 得到的信息
*/
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]);
}
} });
...
for (auto& device : devices) {
std::string id;
/* 將上述獲取得到的camera信息保存到 mDevices,
* 至此,CameraService與CameraProvider聯繫起來。
* device的值一般類似以下: [email protected]/legacy/0
* 該device的值,是CameraProvider服務獲取device之後,添加到 mCameraDeviceNames,
* 該變量的含義如下:@3. : 3 是與camera HAL的版本號相關,
* 只要不是 CAMERA_DEVICE_API_VERSION_1_0,都是3
* 3.3 :第二個 3 是從系統屬性
* ro.vendor.camera.wrapper.hal3TrebleMinorVersion 獲取的,沒有則是3
* legacy/0 : 則與 CameraProvider 服務相關
*/
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;
}
}
ALOGI("Camera provider %s ready with %zu camera devices",
mProviderName.c_str(), mDevices.size());
mInitialized = true;
return OK;
}
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);
...
/* 根據HAL版本,創建相應的 DeviceInfo */
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;
}
...
mDevices.push_back(std::move(deviceInfo));
...
return OK;
}
最後
至此,CameraService與CameraProvider聯繫起來,可以通過CameraService操作影響到camera HAL層。下圖爲在跟蹤代碼過程中,記錄的UML圖。
參考文章
在瞭解學習CameraService服務的過程中,參考了網上很多的優秀文章,感謝!