[安卓相機系列] 零、CameraServer和CameraProvider的啓動初始化

[安卓相機系列] 零、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()函數。那麼,先來找到CameraServermain()函數吧。

文件路徑: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這個進程當中。(應當注意CameraServerCameraService的區別)

文件路徑: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,註冊UIDSensor的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的狀態。

寫到這裏,好像CameraServiceCameraProvider還沒有產生交集呀,它們之間開始交流發生在哪個地方呢?等等,在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 managerproxy拿到所有註冊成功的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 managerproxygetService()方法,獲取到當前傳入名字對應的CameraProvider服務。
  • 接着,將該CameraProvider服務和當前類CameraProviderManagerthis指針作爲參數傳入類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,並保存進mTypemId。然後判斷次版本號(目前CameraProvider有2.4和2.5兩個版本,Android 10上用的2.4)。再將CameraProviderManager的指針作爲參數,註冊爲CameraProvider的Callback,檢查是否註冊成功,綁定生命週期,再檢查是否綁定成功。然後根據是否啓用了Lazy HAL,將CameraProvider保存到ProviderInfomActiveInterface(如果啓用)或mSavedInterface(如果沒啓用)。然後通知設備狀態的改變,初始化VendorTag。接着一大串是爲了獲取CameraDevice(與CameraId一一映射)並保存。再檢查有沒有閃光燈,判斷是不是remote服務。獲取狀態監聽器,然後執行addDevice()添加CameraDevice。一切OK的話,將成員變量mInitialized置爲true,最後返回OK。

執行完這些,返回到CameraSeviceCameraService繼續執行後續流程,就是剛纔的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特性選擇走哪個註冊服務的實現。這裏的代碼與其他位置服務的註冊流程大同小異,本文暫不深入了。

三、回顧思考

  1. CameraServer進程由誰啓動?

一般native進程要麼由shell啓動,要麼由init進程啓動。

  1. CameraServerCameraProvider的啓動順序?

從代碼流程上看,顯然CameraProvider先於CameraService啓動,要比CameraService先註冊服務。很遺憾,暫時沒有打算去分析爲什麼如此,但猜測可能是在init進程裏面的邏輯。

  1. CameraServermain()函數中,第一句signal(SIGPIPE, SIG_IGN);是幹嘛的?
  2. 目前Android 10用的是2.4版本的CameraProvider,那麼如何更改CameraProvider的版本?比如更改爲2.5的?

四、資源列表

五、參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章