2024年Android最新Camera 入门第一篇,安卓app开发面试题

结尾

最后,针对上面谈的内容,给大家推荐一个Android资料,应该对大家有用。

首先是一个知识清单:(对于现在的Android及移动互联网来说,我们需要掌握的技术)

泛型原理丶反射原理丶Java虚拟机原理丶线程池原理丶
注解原理丶注解原理丶序列化
Activity知识体系(Activity的生命周期丶Activity的任务栈丶Activity的启动模式丶View源码丶Fragment内核相关丶service原理等)
代码框架结构优化(数据结构丶排序算法丶设计模式)
APP性能优化(用户体验优化丶适配丶代码调优)
热修复丶热升级丶Hook技术丶IOC架构设计
NDK(c编程丶C++丶JNI丶LINUX)
如何提高开发效率?
MVC丶MVP丶MVVM
微信小程序
Hybrid
Flutter

接下来是资料清单:(敲黑板!!!


1.数据结构和算法

2.设计模式

3.全套体系化高级架构视频;七大主流技术模块,视频+源码+笔记

4.面试专题资料包(怎么能少了一份全面的面试题总结呢~)

不论遇到什么困难,都不应该成为我们放弃的理由!共勉~

如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

        cameraInfo->clear();

        return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Failed to remove camera"

                " characteristics needing camera permission for device %s: %s (%d)",

                String8(cameraId).string(), strerror(-res), res);

    }

}



if (!tagsRemoved.empty()) {

    res = cameraInfo->update(ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION,

            tagsRemoved.data(), tagsRemoved.size());

    if (res != OK) {

        cameraInfo->clear();

        return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Failed to insert camera "

                "keys needing permission for device %s: %s (%d)", String8(cameraId).string(),

                strerror(-res), res);

    }

}



return ret;

}




2.2 CameraProviderManager::getCameraCharacteristics 函数

------------------------------------------------------



CameraProviderManager.cpp `frameworks\av\services\camera\libcameraservice\common`



status_t CameraProviderManager::getCameraCharacteristics(const std::string &id,

    CameraMetadata* characteristics) const {

std::lock_guard<std::mutex> lock(mInterfaceMutex);

// 调用 CameraProviderManger 获取去Camera 设备信息方法

// 参考 2.3 CameraProviderManger.getCameraCharacteristicsLocked

return getCameraCharacteristicsLocked(id, characteristics);

}




2.3 CameraProviderManger::getCameraCharacteristicsLocked

--------------------------------------------------------



status_t CameraProviderManager::getCameraCharacteristicsLocked(const std::string &id,

    CameraMetadata* characteristics) const {

// 通过deviceinfo3 获取设备getCameraCharacteristics

// 参考 2.4 CPM.findDeviceInfoLocked函数

auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ {3,0}, /*maxVersion*/ {5,0});

if (deviceInfo != nullptr) {

    return deviceInfo->getCameraCharacteristics(characteristics);

}



// Find hidden physical camera characteristics

for (auto& provider : mProviders) {

    for (auto& deviceInfo : provider->mDevices) {

        status_t res = deviceInfo->getPhysicalCameraCharacteristics(id, characteristics);

        if (res != NAME_NOT_FOUND) return res;

    }

}



return NAME_NOT_FOUND;

}




2.4 CameraProviderManger::findDeviceInfoLocked

----------------------------------------------



CameraProviderManager::ProviderInfo::DeviceInfo* CameraProviderManager::findDeviceInfoLocked(

    const std::string& id,

    hardware::hidl_version minVersion, hardware::hidl_version maxVersion) const {

// 通过   deviceinfo3 queryPhysicalCameraIds 查询对应id的Camera 信息

// 见 2.5 CMP.queryPhysicalCameraIds  函数

for (auto& provider : mProviders) {

    for (auto& deviceInfo : provider->mDevices) {

        if (deviceInfo->mId == id &&

                minVersion <= deviceInfo->mVersion && maxVersion >= deviceInfo->mVersion) {

            return deviceInfo.get();

        }

    }

}

return nullptr;

}




2.5 CameraProviderManger::queryPhysicalCameraIds 函数

---------------------------------------------------



void CameraProviderManager::ProviderInfo::DeviceInfo3::queryPhysicalCameraIds() {

camera_metadata_entry_t entryCap;



entryCap = mCameraCharacteristics.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);

for (size_t i = 0; i < entryCap.count; ++i) {

    uint8_t capability = entryCap.data.u8[i];

    if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {

        mIsLogicalCamera = true;

        break;

    }

}

if (!mIsLogicalCamera) {

    return;

}



camera_metadata_entry_t entryIds = mCameraCharacteristics.find(

        ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS);

const uint8_t* ids = entryIds.data.u8;

size_t start = 0;

for (size_t i = 0; i < entryIds.count; ++i) {

    if (ids[i] == '\0') {

        if (start != i) {

            mPhysicalIds.push_back((const char*)ids+start);

        }

        start = i+1;

    }

}

}




2.6 getCameraCharacteristics 大致时序图

----------------------------------



![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6L0tOMUZ1NWR6dzhxcHZvSXk0UkowbVA5Q3B1b0ZOSjVLdmwxZWliVkFqU3hpYlQzRFFTajRCWHNGemdoU1A3aWNuZkR5TWlhbHFsZWliOXdSVk1DdDNOOE96aWN3LzY0MA?x-oss-process=image/format,png)



getCameraCharacteristics



三、supportsCamera2ApiLocked

==========================



当前CameraService 是否支持Camera2Api,如果支持,返回true,如果不支持,返回false。



supportsCamera2ApiLocked(cameraId)方法实现如下:



private boolean supportsCamera2ApiLocked(String cameraId) {

    // 参考 3.1 supportsCameraApiLocked

    return supportsCameraApiLocked(cameraId, API_VERSION_2);

}



3.1 CameraManager.supportsCameraApiLocked

-----------------------------------------



private boolean supportsCameraApiLocked(String cameraId, int apiVersion) {

    /*

     * Possible return values:

     * - NO_ERROR => CameraX API is supported

     * - CAMERA_DEPRECATED_HAL => CameraX API is *not* supported (thrown as an exception)

     * - Remote exception => If the camera service died

     *

     * Anything else is an unexpected error we don't want to recover from.

     */

    try {

        ICameraService cameraService = CameraManagerGlobal.get().getCameraService();

        // If no camera service, no support

       // 参考 3.2 CameraService supportsCameraApi 的方法

        if (cameraService == null) return false;



        return cameraService.supportsCameraApi(cameraId, apiVersion);

    } catch (RemoteException e) {

        // Camera service is now down, no support for any API level

    }

    return false;

}



3.2 CameraService::supportsCameraApi

------------------------------------



Status CameraService::supportsCameraApi(const String16& cameraId, int apiVersion,

    /*out*/ bool *isSupported) {

ATRACE_CALL();



const String8 id = String8(cameraId);



ALOGV("%s: for camera ID = %s", __FUNCTION__, id.string());



switch (apiVersion) {

    case API_VERSION_1:

    case API_VERSION_2:

        break;

    default:

        String8 msg = String8::format("Unknown API version %d", apiVersion);

        ALOGE("%s: %s", __FUNCTION__, msg.string());

        return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.string());

}



int deviceVersion = getDeviceVersion(id);

switch (deviceVersion) {

    case CAMERA_DEVICE_API_VERSION_1_0:

    case CAMERA_DEVICE_API_VERSION_3_0:

    case CAMERA_DEVICE_API_VERSION_3_1:

        if (apiVersion == API_VERSION_2) {

            ALOGV("%s: Camera id %s uses HAL version %d <3.2, doesn't support api2 without shim",

                    __FUNCTION__, id.string(), deviceVersion);

            *isSupported = false;

        } else { // if (apiVersion == API_VERSION_1) {

            ALOGV("%s: Camera id %s uses older HAL before 3.2, but api1 is always supported",

                    __FUNCTION__, id.string());

            *isSupported = true;

        }

        break;

    case CAMERA_DEVICE_API_VERSION_3_2:

    case CAMERA_DEVICE_API_VERSION_3_3:

    case CAMERA_DEVICE_API_VERSION_3_4:

    case CAMERA_DEVICE_API_VERSION_3_5:

        ALOGV("%s: Camera id %s uses HAL3.2 or newer, supports api1/api2 directly",

                __FUNCTION__, id.string());

        *isSupported = true;

        break;

    case -1: {

        String8 msg = String8::format("Unknown camera ID %s", id.string());

        ALOGE("%s: %s", __FUNCTION__, msg.string());

        return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.string());

    }

    default: {

        String8 msg = String8::format("Unknown device version %x for device %s",

                deviceVersion, id.string());

        ALOGE("%s: %s", __FUNCTION__, msg.string());

        return STATUS_ERROR(ERROR_INVALID_OPERATION, msg.string());

    }

}



return Status::ok();

}




四、CameraService.connectDevice

=============================



`cameraService.connectDevice` 会通过AIDL 调用到CameraService.cpp`frameworks\av\services\camera\libcameraservice`



4.1 CameraService::connectDevice

--------------------------------



连接当前的cameraDevice设备



Status CameraService::connectDevice(

    const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,

    const String16& cameraId,

    const String16& clientPackageName,

    int clientUid,

    /*out*/

    sp<hardware::camera2::ICameraDeviceUser>* device) {



ATRACE_CALL();

Status ret = Status::ok();

String8 id = String8(cameraId);

sp<CameraDeviceClient> client = nullptr;

String16 clientPackageNameAdj = clientPackageName;



if (getCurrentServingCall() == BinderCallType::HWBINDER) {

    std::string vendorClient =

            StringPrintf("vendor.client.pid<%d>", CameraThreadState::getCallingPid());

    clientPackageNameAdj = String16(vendorClient.c_str());

}

// connectHelper  链接助手,处理连接的一些情况 比如Camera 独占,flash 预打开等

// 具体实现情况 4.2  CameraService::connectHelper

ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,

        /*api1CameraId*/-1,

        CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageNameAdj,

        clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, /*out*/client);



if(!ret.isOk()) {

    logRejected(id, CameraThreadState::getCallingPid(), String8(clientPackageNameAdj),

            ret.toString8());

    return ret;

}



*device = client;

return ret;

}




4.2 CameraService::connectHelper

--------------------------------



Status CameraService::connectHelper(const sp& cameraCb, const String8& cameraId,

    int api1CameraId, int halVersion, const String16& clientPackageName, int clientUid,

    int clientPid, apiLevel effectiveApiLevel, bool shimUpdateOnly,

    /*out*/sp<CLIENT>& device) {

binder::Status ret = binder::Status::ok();



String8 clientName8(clientPackageName);



int originalClientPid = 0;







if (shouldRejectHiddenCameraConnection(cameraId)) {

    ALOGW("Attempting to connect to system-only camera id %s, connection rejected",

          cameraId.c_str());

    return STATUS_ERROR_FMT(ERROR_DISCONNECTED,

                            "No camera device with ID \"%s\" currently available",

                            cameraId.string());



}

sp<CLIENT> client = nullptr;

{

    // Acquire mServiceLock and prevent other clients from connecting

    std::unique_ptr<AutoConditionLock> lock =

            AutoConditionLock::waitAndAcquire(mServiceLockWrapper, DEFAULT_CONNECT_TIMEOUT_NS);





    // 检查当前的camera device是否可用,这儿的判断比较简单,只是简单判断当前设备是否存在

    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;

    // 处理camera独占情况

    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;

    }



    // 预备链接CameraDevices 必要时给手电筒关闭设备的机会.

    mFlashlight->prepareDeviceOpen(cameraId);



    int facing = -1;

    //获取当前的camera device的version 版本

    int deviceVersion = getDeviceVersion(cameraId, /*out*/&facing);





    sp<BasicClient> tmp = nullptr;

    // 我们采用的client都是CameraDeviceClient

    if(!(ret = makeClient(this, cameraCb, clientPackageName,

            cameraId, api1CameraId, facing,

            clientPid, clientUid, getpid(),

            halVersion, deviceVersion, effectiveApiLevel,

            /*out*/&tmp)).isOk()) {

        return ret;

    }

    client = static_cast<CLIENT*>(tmp.get());



    ... ...



    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;

}




### 4.3 connectDevices 调用流程



connectdevices.jpg





### Android进阶资料

以下的资料是近年来,我和一些朋友面试收集整理了很多大厂的面试真题和资料,还有来自如阿里、小米、爱奇艺等一线大厂的大牛整理的架构进阶资料。希望可以帮助到大家。

**Android进阶核心笔记**

![](https://img-blog.csdnimg.cn/img_convert/0a6a5d72f31b81ac7b2d53980c4a6eae.webp?x-oss-process=image/format,png)



**百万年薪必刷面试题**

![](https://img-blog.csdnimg.cn/img_convert/397f0f6a5e4f6722e3bbffd46b562d70.webp?x-oss-process=image/format,png)


**最全Android进阶学习视频**



**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

inishConnectLocked(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;

}





4.3 connectDevices 调用流程

connectdevices.jpg

Android进阶资料

以下的资料是近年来,我和一些朋友面试收集整理了很多大厂的面试真题和资料,还有来自如阿里、小米、爱奇艺等一线大厂的大牛整理的架构进阶资料。希望可以帮助到大家。

Android进阶核心笔记

[外链图片转存中…(img-YzLE4lqC-1715665458796)]

百万年薪必刷面试题

[外链图片转存中…(img-vnC4Zm6c-1715665458796)]

最全Android进阶学习视频

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 9
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值