[安卓相機系列] 零、CameraServer和CameraProvider的啓動初始化
一、前言
本文所使用代碼爲**android-10.0.0_r30
分支,可以通過Android Code Search在線瀏覽源碼,或通過repo
工具將代碼下載到本地。如何下載代碼,請參考下載源代碼,建議使用清華大學的Android鏡像**,使用幫助:Android 鏡像使用幫助。
在開始前,最好能掌握或瞭解以下基礎知識(別擔心,掌握最基礎的即可,剩下的可以在閱讀和理解源碼的過程中慢慢學):
-
編程語言基礎:C/C++、Java
-
Android中的智能指針:輕量指針、強引用指針、弱引用指針
-
Binder通信機制
-
AIDL與HIDL
-
Makefile
-
……(留坑,想到再補充)
另外最好能有以下工具或掌握以下技能:
- 一臺性能不錯、可以科學上網的電腦
vim
(_,我是vimer
)- Android Studio
二、開始分析
2.1 CameraService
的啓動初始化
2.1.1 CameraServer
的啓動
程序的執行,一定會有一個入口函數(更微觀地說,是入口地址)。一般來說,不做特殊指定的話,默認的入口函數爲main()
函數。那麼,先來找到CameraServer
的main()
函數吧。
文件路徑:frameworks/av/camera/cameraserver/main_cameraserver.cpp
int main(int argc __unused, char** argv __unused)
{
signal(SIGPIPE, SIG_IGN);
// Set 5 threads for HIDL calls. Now cameraserver will serve HIDL calls in
// addition to consuming them from the Camera HAL as well.
hardware::configureRpcThreadpool(5, /*willjoin*/ false);
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p", sm.get());
CameraService::instantiate();
ALOGI("ServiceManager: %p done instantiate", sm.get());
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
這裏面其實重要的是這麼一句:CameraService::instantiate();
,這句話完成了CameraService
服務的註冊以及初始化工作。方法instantiate()
是類CameraService
所繼承的模板父類BinderService
中的靜態方法,看以下它的實現。
文件路徑:frameworks/native/libs/binder/include/binder/BinderService.h
template<typename SERVICE>
class BinderService
{
public:
static status_t publish(bool allowIsolated = false, int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated, dumpFlags);
}
static void publishAndJoinThreadPool(
bool allowIsolated = false,
int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
publish(allowIsolated, dumpFlags);
joinThreadPool();
}
static void instantiate() { publish(); }
// ......
}
可以看到,instantiate()
方法的作用就是調用了BinderService
類自身的publish()
方法,獲取ServiceManager
服務,調用其addService()
方法將它註冊到ServiceManager
,這個過程中,創建了服務對象的實例。關於如何註冊ServiceManager
,這些細節此處不考慮,以後再出一篇文章文章詳細分析下。只需要瞭解,這一步,完成了CameraService
的啓動和初始化工作,並將CameraService
註冊到了ServiceManager
,那麼其他地方,就可以通過ServiceManager
去獲取這個服務。
服務CameraService
的啓動初始化在進程CameraServer
的啓動過程中,如果CameraService
啓動成功了,進程也就啓動成功了。但好像有些意猶未盡的感覺:這也太快了,沒深入多少吧。別急,下面看以下CameraService
的啓動與實例化。
2.1.2 CameraService
的啓動與實例化
CameraService
作爲一個服務存在於安卓系統當中,它運行在CameraServer
這個進程當中。(應當注意CameraServer
與CameraService
的區別)
文件路徑:frameworks/av/services/camera/libcameraservice/CameraService.cpp
CameraService::CameraService() :
mEventLog(DEFAULT_EVENT_LOG_LENGTH),
mNumberOfCameras(0),
mSoundRef(0), mInitialized(false) {
ALOGI("CameraService started (pid=%d)", getpid());
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;
}
mUidPolicy = new UidPolicy(this);
mUidPolicy->registerSelf();
mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
mSensorPrivacyPolicy->registerSelf();
sp<HidlCameraService> hcs = HidlCameraService::getInstance(this);
if (hcs->registerAsService() != android::OK) {
ALOGE("%s: Failed to register default [email protected]", __FUNCTION__);
}
// This needs to be last call in this function, so that it's as close to
// ServiceManager::addService() as possible.
CameraService::pingCameraServiceProxy();
ALOGI("CameraService pinged cameraservice proxy");
}
CameraService
在初始化過程中,初始化了一些成員變量的值;在onFirstRef()
(此函數繼承自類RefBase
,會在CameraService
第一次被引用時調用)中註冊了電池事件,枚舉CameraProvider
,註冊UID
和Sensor
的Policy,通過HIDL
檢查自身是否已經註冊成爲服務,最後檢查CameraServiceProxy
。
status_t CameraService::enumerateProviders() {
status_t res;
std::vector<std::string> deviceIds;
{
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;
}
}
// 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);
}
deviceIds = mCameraProviderManager->getCameraDeviceIds();
}
for (auto& cameraId : deviceIds) {
String8 id8 = String8(cameraId.c_str());
if (getCameraState(id8) == nullptr) {
onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT);
}
}
return OK;
}
這裏用一個vector
類型的成員變量cameraIds
保存**CameraDevice
**,每個邏輯camera id對應這裏的一個CameraDevice
。這裏做了什麼呢?創建CameraProviderManager
對象,並調用其initialize()
對它進行一些系列操作,然後設置VendorTag
,查找閃光燈資源,獲取CameraDevice
列表,最後檢查每個CameraDevice
的狀態並更新通知。
void CameraService::onDeviceStatusChanged(const String8& id,
CameraDeviceStatus newHalStatus) {
ALOGI("%s: Status changed for cameraId=%s, newStatus=%d", __FUNCTION__,
id.string(), newHalStatus);
StatusInternal newStatus = mapToInternal(newHalStatus);
std::shared_ptr<CameraState> state = getCameraState(id);
if (state == nullptr) {
if (newStatus == StatusInternal::PRESENT) {
ALOGI("%s: Unknown camera ID %s, a new camera is added",
__FUNCTION__, id.string());
// First add as absent to make sure clients are notified below
addStates(id);
updateStatus(newStatus, id);
} else {
ALOGE("%s: Bad camera ID %s", __FUNCTION__, id.string());
}
return;
}
StatusInternal oldStatus = state->getStatus();
if (oldStatus == newStatus) {
ALOGE("%s: State transition to the same status %#x not allowed", __FUNCTION__, newStatus);
return;
}
if (newStatus == StatusInternal::NOT_PRESENT) {
logDeviceRemoved(id, String8::format("Device status changed from %d to %d", oldStatus,
newStatus));
// Set the device status to NOT_PRESENT, clients will no longer be able to connect
// to this device until the status changes
updateStatus(StatusInternal::NOT_PRESENT, id);
sp<BasicClient> clientToDisconnect;
{
// Don't do this in updateStatus to avoid deadlock over mServiceLock
Mutex::Autolock lock(mServiceLock);
// Remove cached shim parameters
state->setShimParams(CameraParameters());
// Remove the client from the list of active clients, if there is one
clientToDisconnect = removeClientLocked(id);
}
// Disconnect client
if (clientToDisconnect.get() != nullptr) {
ALOGI("%s: Client for camera ID %s evicted due to device status change from HAL", __FUNCTION__, id.string());
// Notify the client of disconnection
clientToDisconnect->notifyError( hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED, CaptureResultExtras{});
// Ensure not in binder RPC so client disconnect PID checks work correctly
LOG_ALWAYS_FATAL_IF(CameraThreadState::getCallingPid() != getpid(), "onDeviceStatusChanged must be called from the camera service process!");
clientToDisconnect->disconnect();
}
removeStates(id);
} else {
if (oldStatus == StatusInternal::NOT_PRESENT) {
logDeviceAdded(id, String8::format("Device status changed from %d to %d", oldStatus, newStatus));
}
updateStatus(newStatus, id);
}
}
在onDeviceStatusChanged()
方法中,首先獲取對應當前id的CameraDevice
狀態:
- 如果爲空,判斷新狀態是不是
PRESENT
。如果是的話添加這個CameraDevice
,並通知所有client
。 - 如果不爲空,則獲取舊的狀態。如果新狀態與狀態相等,則沒有必要發出通知,直接
return
。 - 如果新狀態爲
NOT_PRESENT
,則更新對應的狀態,然後根據id查找需要移除的client
,通知,然後斷開連接。最後,移除該id。 - 如果新狀態不爲
NOT_PRESENT
,則打印一條log作提示,然後更新CameraDevice
的狀態。
寫到這裏,好像CameraService
和CameraProvider
還沒有產生交集呀,它們之間開始交流發生在哪個地方呢?等等,在enmurateProviders()
函數體的開頭,有個類CameraProviderManager
的創建和initialize()
沒有提到,是不是在這裏?
2.2 CameraProvider
的初始化
很好奇類CameraProviderManager
幹了什麼,先從CameraService
調它的兩個函數:構造和initialize()
開始。
類CameraProviderManager
沒有實現其構造函數,因此只看initialize()
函數。
文件路徑:frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp
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;
mDeviceState = static_cast<hardware::hidl_bitfield<provider::V2_5::DeviceState>>(
provider::V2_5::DeviceState::NORMAL);
// 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;
}
for (const auto& instance : mServiceProxy->listServices()) {
this->addProviderLocked(instance);
}
IPCThreadState::self()->flushCommands();
return OK;
}
可能有的小夥伴這裏會好奇,明明調用的時候只傳了一個參數呀,爲什麼這裏有兩個?是不是多態?是不是看錯了實現函數?其實這個函數在對應的頭文件中聲明的時候,第二個參數設置了一個缺省值,所以這裏只傳了一個參數也是對的。
這裏通過hardware service manager
的proxy
拿到所有註冊成功的CameraProvider
服務,然後調用addProviderLocked()
方法。
status_t CameraProviderManager::addProviderLocked(const std::string& newProvider) {
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) {
ALOGE("%s: Camera provider HAL '%s' is not actually available", __FUNCTION__,
newProvider.c_str());
return BAD_VALUE;
}
sp<ProviderInfo> providerInfo = new ProviderInfo(newProvider, this);
status_t res = providerInfo->initialize(interface, mDeviceState);
if (res != OK) {
return res;
}
mProviders.push_back(providerInfo);
return OK;
}
- 首先,遍歷已經獲取到的
CameraProvider
,判斷與當前傳入的、需要添加的服務的名字是否一致。如果一直,則返回ALREADY_EXISTS
;否則,繼續下面流程。 - 然後,還是通過
hardware service manager
的proxy
的getService()
方法,獲取到當前傳入名字對應的CameraProvider
服務。 - 接着,將該
CameraProvider
服務和當前類CameraProviderManager
的this
指針作爲參數傳入類ProviderInfo
的一個構造函數,再調用其initialize()
方法。 - 最後把實例成功的類
CameraInfo
對象保存到成員變量mProviders
中。
CameraProviderManager::ProviderInfo::ProviderInfo(
const std::string &providerName,
CameraProviderManager *manager) :
mProviderName(providerName),
mProviderTagid(generateVendorTagId(providerName)),
mUniqueDeviceCount(0),
mManager(manager) {
(void) mManager;
}
status_t CameraProviderManager::ProviderInfo::initialize(
sp<provider::V2_4::ICameraProvider>& interface,
hardware::hidl_bitfield<provider::V2_5::DeviceState> currentDeviceState) {
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(), interface->isRemote());
// Determine minor version
auto castResult = provider::V2_5::ICameraProvider::castFrom(interface);
if (castResult.isOk()) {
mMinorVersion = 5;
} else {
mMinorVersion = 4;
}
// cameraDeviceStatusChange callbacks may be called (and causing new devices added)
// before setCallback returns
hardware::Return<Status> status = interface->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 = interface->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());
}
if (!kEnableLazyHal) {
// Save HAL reference indefinitely
mSavedInterface = interface;
} else {
mActiveInterface = interface;
}
ALOGV("%s: Setting device state for %s: 0x%" PRIx64,
__FUNCTION__, mProviderName.c_str(), mDeviceState);
notifyDeviceStateChange(currentDeviceState);
res = setUpVendorTags();
if (res != OK) {
ALOGE("%s: Unable to set up vendor tags from provider '%s'",
__FUNCTION__, mProviderName.c_str());
return res;
}
// Get initial list of camera devices, if any
std::vector<std::string> devices;
hardware::Return<void> ret = interface->getCameraIdList([&status, this, &devices](
Status idStatus,
const hardware::hidl_vec<hardware::hidl_string>& cameraDeviceNames) {
status = idStatus;
if (status == Status::OK) {
for (auto& name : cameraDeviceNames) {
uint16_t major, minor;
std::string type, id;
status_t res = parseDeviceName(name, &major, &minor, &type, &id);
if (res != OK) {
ALOGE("%s: Error parsing deviceName: %s: %d", __FUNCTION__, name.c_str(), res);
status = Status::INTERNAL_ERROR;
} else {
devices.push_back(name);
mProviderPublicCameraIds.push_back(id);
}
}
} });
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);
}
ret = interface->isSetTorchModeSupported(
[this](auto status, bool supported) {
if (status == Status::OK) {
mSetTorchModeSupported = supported;
}
});
if (!ret.isOk()) {
ALOGE("%s: Transaction error checking torch mode support '%s': %s",
__FUNCTION__, mProviderName.c_str(), ret.description().c_str());
return DEAD_OBJECT;
}
mIsRemote = interface->isRemote();
sp<StatusListener> listener = mManager->getStatusListener();
for (auto& device : devices) {
std::string id;
status_t res = addDevice(device, 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;
}
在類ProviderInfo
的構造中,初始化一些變量,主要看initialize()
函數。
函數開始先根據mProviderName
解析CameraProvider
的類型和id,並保存進mType
、mId
。然後判斷次版本號(目前CameraProvider
有2.4和2.5兩個版本,Android 10上用的2.4)。再將CameraProviderManager
的指針作爲參數,註冊爲CameraProvider
的Callback,檢查是否註冊成功,綁定生命週期,再檢查是否綁定成功。然後根據是否啓用了Lazy HAL
,將CameraProvider
保存到ProviderInfo
的mActiveInterface
(如果啓用)或mSavedInterface
(如果沒啓用)。然後通知設備狀態的改變,初始化VendorTag
。接着一大串是爲了獲取CameraDevice
(與CameraId一一映射)並保存。再檢查有沒有閃光燈,判斷是不是remote
服務。獲取狀態監聽器,然後執行addDevice()
添加CameraDevice
。一切OK的話,將成員變量mInitialized
置爲true
,最後返回OK。
執行完這些,返回到CameraSevice
,CameraService
繼續執行後續流程,就是剛纔的onDeviceStatusChanged()
,最後回到CameraServer
,完成CameraService
的註冊(會打印出整個服務從開始註冊到完成註冊的耗時)。
2.2.1 CameraProvider
的啓動
好像之前一直沒有提到CameraProvider
是如何啓動的。首先,找到CameraProvider
的入口函數。
由於Android 10上用的還是2.4版本的CameraProvider
,那麼我們就看它吧。
文件路徑:hardware/interfaces/camera/provider/2.4/default/service.cpp
int main()
{
ALOGI("[email protected] legacy service is starting.");
// The camera HAL may communicate to other vendor components via
// /dev/vndbinder
android::ProcessState::initWithDriver("/dev/vndbinder");
status_t status;
if (kLazyService) {
status = defaultLazyPassthroughServiceImplementation<ICameraProvider>("legacy/0",
/*maxThreads*/ 6);
} else {
status = defaultPassthroughServiceImplementation<ICameraProvider>("legacy/0",
/*maxThreads*/ 6);
}
return status;
}
main()
函數第一行,表示CameraProvider
進程使用/dev/vndbinder
進行通信。然後根據是否啓用了LazyService
特性選擇走哪個註冊服務的實現。這裏的代碼與其他位置服務的註冊流程大同小異,本文暫不深入了。
三、回顧思考
CameraServer
進程由誰啓動?
一般native
進程要麼由shell
啓動,要麼由init
進程啓動。
CameraServer
與CameraProvider
的啓動順序?
從代碼流程上看,顯然CameraProvider
先於CameraService
啓動,要比CameraService
先註冊服務。很遺憾,暫時沒有打算去分析爲什麼如此,但猜測可能是在init
進程裏面的邏輯。
CameraServer
的main()
函數中,第一句signal(SIGPIPE, SIG_IGN);
是幹嘛的?- 目前Android 10用的是2.4版本的
CameraProvider
,那麼如何更改CameraProvider
的版本?比如更改爲2.5的?
四、資源列表
adb
工具:https://developer.android.com/studio/command-line/adb- 模擬器啓動時的log:https://download.csdn.net/download/qq_34908601/12281606(我設置了不收積分,如果收了,請聯繫我,直接郵箱發)
五、參考資料
- [Android O] Camera 服務啓動流程簡析:前輩寫的文章,最開始是看他寫的這篇文章入門的。