android8,Android开发必看

**status_t CameraService::enumerateProviders() {

status_t res;

Mutex::Autolock l(mServiceLock);

if (nullptr == mCameraProviderManager.get()) {

mCameraProviderManager = new CameraProviderManager();

res = mCameraProviderManager->initialize(this);

}

}

这个函数里,创建了一个CameraProviderManager对象,并调进行了初始化.**

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

status_t CameraProviderManager::initialize(wpCameraProviderManager::StatusListener listener,

ServiceInteractionProxy* proxy) {

std::lock_guardstd::mutex lock(mInterfaceMutex);

if (proxy == nullptr) {

ALOGE(“%s: No valid service interaction proxy provided”, __FUNCTION__);

return BAD_VALUE;

}

mListener = listener;

mServiceProxy = proxy;

// 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;

}

// See if there’s a passthrough HAL, but let’s not complain if there’s not

addProviderLocked(kLegacyProviderName, /*expected*/ false);

return OK;

}

在这个初始化函数里,我们只关注addProviderLocked, 我们可以看到,这个函数传进了一个kLegacyProviderName, 它的值定义在这个文件的上面:**

const std::string kLegacyProviderName(“legacy/0”);

大家注意到了没有,它的值和我们之前hardware\interfaces\camera\provider\2.4\default\service.cpp里注册服务时return defaultPassthroughServiceImplementation(“legacy/0”, /*maxThreads*/ 6); 以及manifest.xml里legacy/0的值都是一致的. 如果这个值不致,则会调用不成功.

好了,再回到addProviderLocked这个函数来, 这个函数的作用, 就是去加载camera对应的hal层代码, 并将它的信息保存在ProviderInfo里,后面我们就可以通过这个ProviderInfo, 去实行addDevice、getCameraInfo等操作。

**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;

}

}

spprovider::V2\_4::ICameraProvider interface;

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 =

new ProviderInfo(newProvider, interface, this);

status_t res = providerInfo->initialize();

if (res != OK) {

return res;

}

mProviders.push_back(providerInfo);

return OK;

}

这里先检查一下,传进来的newProvider是不是已经添加过,如果已经添加了,就不再处理,直接返回。如果没添加过,就会进行下一步的操作。这里的interface = mServiceProxy->getService(newProvider);,会调用到hardware\interfaces\camera\provider\2.4\default\CameraProvider.cpp的HIDL_FETCH_ICameraProvider函数。**

**ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name) {

if (strcmp(name, kLegacyProviderName) != 0) {

return nullptr;

}

CameraProvider* provider = new CameraProvider();

if (provider == nullptr) {

ALOGE(“%s: cannot allocate camera provider!”, __FUNCTION__);

return nullptr;

}

if (provider->isInitFailed()) {

ALOGE(“%s: camera provider init failed!”, __FUNCTION__);

delete provider;

return nullptr;

}

return provider;

}

在这个函数里,会创建一个CameraProvider对象。**

**CameraProvider::CameraProvider() :

camera_module_callbacks_t({sCameraDeviceStatusChange,

sTorchModeStatusChange}) {

mInitFailed = initialize();

}

bool CameraProvider::initialize() {

camera_module_t *rawModule;

int err = hw_get_module(“camera”, (const hw_module_t **)&rawModule);

if (err < 0) {

ALOGE(“Could not load camera HAL module: %d (%s)”, err, strerror(-err));

return true;

}

mModule = new CameraModule(rawModule);

err = mModule->init();

}

在这个初始化函数中,会看到一个我们非常熟悉的函数hw_get_module。到这里,就跟我们android8.0之前的流程一模一样的了,都是去直接和hal层打交道了。**

在CameraProvider里有一个地方值得大家注意

**std::string cameraId, int deviceVersion) {

// Maybe consider create a version check method and SortedVec to speed up?

if (deviceVersion != CAMERA_DEVICE_API_VERSION_1_0 &&

deviceVersion != CAMERA_DEVICE_API_VERSION_3_2 &&

deviceVersion != CAMERA_DEVICE_API_VERSION_3_3 &&

deviceVersion != CAMERA_DEVICE_API_VERSION_3_4 ) {

return hidl_string(“”);

}

bool isV1 = deviceVersion == CAMERA_DEVICE_API_VERSION_1_0;

int versionMajor = isV1 ? 1 : 3;

int versionMinor = isV1 ? 0 : mPreferredHal3MinorVersion;

char deviceName[kMaxCameraDeviceNameLen];

snprintf(deviceName, sizeof(deviceName), “device@%d.%d/legacy/%s”,

versionMajor, versionMinor, cameraId.c_str());

return deviceName;

}

从这里看来,如果我们的camera使用了hidl和hal打交道的话,我们hal里的版本号,必须是1.0或者是大于3.2的,如果我们的hal层的的版本号为3.0或3.1的话,是不能正确的加载成功的。**

上面用到的图片,引用了https://blog.csdn.net/qq_16775897/article/details/81240600这个博客的,大家也可以去这篇博客看看。启动流程都是一致的,这博主也讲得比较详细。

好了,上面就将android8.0上camera hal层代码的加载流程基本讲完了。有了上面的基础,下面我们再来一步步的讲下,怎么去新增一个camera hal。

###############################################################################################################################################################################################################################################################################################################

移植一个camera hal,需要做的有以下几点:

1.)在device\mediatek\mt6580\manifest.xml里新增要增加的camera的instance

2.)在frameworks\av\services\camera\libcameraservice\common\CameraProviderManager.cpp里,将要添加的camera provider给addProviderLocked进来

3.)在hardware\interfaces\camera\provider\2.4\default\CameraProvider.cpp里将要增加的camera,通过hw_get_module这样给load进来。

4.)准备好对应的camera hal代码

配置manifest.xml

**

android.hardware.camera.provider

hwbinder

2.4

ICameraProvider

internal/0

legacy/1

 

因为mtkcamera已经有了一个camera hal1,名字为internal/0, 所以我们的usbcamera对应的名字跟在它的后面即可。注意,“legacy/1”这个名字的前面“legacy”这串,可以随便取,比如可以叫”abc/1",只要其他用到的地方都叫这个名字就可以。但是这个后面的“1”,不能弄错。前面已经为0了,这个就必须为1,同理,如果还有一个摄像头,就要为2了。因为在CameraProviderManager.cpp里的ProviderInfo::parseDeviceName,是通过后面这个数字,来取对应的id值的。如果我们将这个usbcamera的id也写为0,即名字为“legacy/0”,那么在ProviderInfo::parseDeviceName这里取出来的id,就会和前面的已经有了的主摄冲突。**

添加camera的ProviderInfo

在frameworks\av\services\camera\libcameraservice\common\CameraProviderManager.cpp的initialize函数里,将kLegacyProviderName改成"legacy/1"

**status_t CameraProviderManager::initialize(wpCameraProviderManager::StatusListener listener,

ServiceInteractionProxy* proxy) {

// See if there’s a passthrough HAL, but let’s not complain if there’s not

addProviderLocked(“legacy/1”, /*expected*/ false);

return OK;

}

在hardware\interfaces\camera\provider\2.4\default\service.cpp里的main函数里,将"legacy/1"注册上来**

**int main()

{

ALOGI(“Camera provider Service is starting.”);

// The camera HAL may communicate to other vendor components via

// /dev/vndbinder

android::ProcessState::initWithDriver(“/dev/vndbinder”);

return defaultPassthroughServiceImplementation(“legacy/1”, /*maxThreads*/ 6);

}

在hardware\interfaces\camera\provider\2.4\default\CameraProvider.cpp里,将kLegacyProviderName改成"legacy/1";它会被HIDL_FETCH_ICameraProvider调用。**

hw_get_module对应camera的hal代码

在hardware\interfaces\camera\provider\2.4\default\CameraProvider.cpp里的initialize()函数里,hw_get_module参数传进去的名字,改成我们usbcamera hal里指定的名字

int err = hw_get_module(“usbcamera”, (const hw_module_t **)&rawModule);

准备好对应的camera hal代码

我们的usbcamera hal代码,我们放在hardware\libhardware\modules\camera\libuvccamera下面。在这个目录里,有个HalModule.cpp文件,里面定义了camera_module_t的结构体,它的id就是"usbcamera", 在CameraProvider.cpp里hw_get_module时,发现这里定义的id和它要找的id一致,就会load到我们的usbcamera了。

**#include <hardware/camera_common.h>

#include <cutils/log.h>

#include <utils/misc.h>

#include

#include

#include “Camera.h”

/******************************************************************************\

DECLARATIONS

Not used in any other project source files, header file is redundant

\******************************************************************************/

extern camera_module_t HAL_MODULE_INFO_SYM;

namespace android {

namespace HalModule {

/* Available cameras */

extern Camera *cams[];

static int getNumberOfCameras();

static int getCameraInfo(int cameraId, struct camera_info *info);

static int setCallbacks(const camera_module_callbacks_t *callbacks);

static void getVendorTagOps(vendor_tag_ops_t* ops);

static int openDevice(const hw_module_t *module, const char *name, hw_device_t **device);

static struct hw_module_methods_t moduleMethods = {

.open = openDevice

};

}; /* namespace HalModule */

}; /* namespace android */

/******************************************************************************\

DEFINITIONS

\******************************************************************************/

camera_module_t HAL_MODULE_INFO_SYM = {

.common = {

.tag                = HARDWARE_MODULE_TAG,

.module_api_version = CAMERA_MODULE_API_VERSION_2_3,

.hal_api_version    = HARDWARE_HAL_API_VERSION,

.id                 = “usbcamera”,

.name               = “V4l2 Camera”,

.author             = “Antmicro Ltd.”,

.methods            = &android::HalModule::moduleMethods,

.dso                = NULL,

.reserved           = {0}

},

.get_number_of_cameras  = android::HalModule::getNumberOfCameras,

.get_camera_info        = android::HalModule::getCameraInfo,

.set_callbacks          = android::HalModule::setCallbacks,

};

namespace android {

namespace HalModule {

static Camera mainCamera;

Camera *cams[] = {

&mainCamera

};

static int getNumberOfCameras() {

return NELEM(cams);

};

static int getCameraInfo(int cameraId, struct camera_info *info) {

cameraId = 0;//cameraId - 1;

if(cameraId < 0 || cameraId >= getNumberOfCameras()) {

return -ENODEV;

}

if(!cams[cameraId]->isValid()) {

return -ENODEV;

}

return cams[cameraId]->cameraInfo(info);

}

int setCallbacks(const camera_module_callbacks_t * /*callbacks*/) {

ALOGI(“%s: lihb setCallbacks”, __FUNCTION__);

/* TODO: Implement for hotplug support */

return OK;

}

static int openDevice(const hw_module_t *module, const char *name, hw_device_t **device) {

if (module != &HAL_MODULE_INFO_SYM.common) {

return -EINVAL;

}

if (name == NULL) {

return -EINVAL;

}

errno = 0;

int cameraId = (int)strtol(name, NULL, 10);

cameraId = 0;

if(errno || cameraId < 0 || cameraId >= getNumberOfCameras()) {

return -EINVAL;

}

if(!cams[cameraId]->isValid()) {

*device = NULL;

return -ENODEV;

}

return cams[cameraId]->openDevice(device);

}

}; /* namespace HalModule */

}; /* namespace android */

大家可能会发现,在getCameraInfo函数里,我将cameraId写死成了0,但是前面我们不是刚说过,我们的usbcamera是第二个摄像头,id要为1么?其实这里的id,和前面说的那个id,不是同一个意思。在这里之所以写成0,是因为我们这套usbcamera hal代码上面,只挂了一个摄像头,这个摄像头对应的代码放在Camera *cams[]数组里,这个数组里只放了一个对象,所以id自然就要为0了。然后我们在我们的halModule.cpp里操作getCameraInfo或openDevice时,就会通过这个数组调用到static Camera mainCamera;这里定义的这个Camera对象了。这个Camera,也是我们自己写的代码:**

**//Camera.h

#ifndef CAMERA_H

#define CAMERA_H

#include <utils/Errors.h>

#include <hardware/camera_common.h>

#include <V4l2Device.h>

#include <hardware/camera3.h>

#include <camera/CameraMetadata.h>

#include <utils/Mutex.h>

#include “Workers.h”

#include “ImageConverter.h”

#include “DbgUtils.h”

#include <cutils/ashmem.h>

#include <cutils/log.h>

#include <sys/mman.h>

#include “VGA_YUV422.h”

namespace android {

class Camera: public camera3_device {

public:

Camera();

virtual ~Camera();

bool isValid() { return mValid; }

virtual status_t cameraInfo(struct camera_info *info);

virtual int openDevice(hw_device_t **device);

virtual int closeDevice();

protected:

virtual camera_metadata_t * staticCharacteristics();

virtual int initialize(const camera3_callback_ops_t *callbackOps);

virtual int configureStreams(camera3_stream_configuration_t *streamList);

virtual const camera_metadata_t * constructDefaultRequestSettings(int type);

virtual int registerStreamBuffers(const camera3_stream_buffer_set_t *bufferSet);

virtual int processCaptureRequest(camera3_capture_request_t *request);

/* HELPERS/SUBPROCEDURES */

void notifyShutter(uint32_t frameNumber, uint64_t timestamp);

void processCaptureResult(uint32_t frameNumber, const camera_metadata_t *result, const Vector<camera3_stream_buffer> &buffers);

camera_metadata_t *mStaticCharacteristics;

camera_metadata_t *mDefaultRequestSettings[CAMERA3_TEMPLATE_COUNT];

CameraMetadata mLastRequestSettings;

V4l2Device *mDev;

bool mValid;

const camera3_callback_ops_t *mCallbackOps;

size_t mJpegBufferSize;

private:

ImageConverter mConverter;

Mutex mMutex;

uint8_t* mFrameBuffer;

uint8_t* rszbuffer;

int mProperty_enableTimesTamp = -1;

/* STATIC WRAPPERS */

static int sClose(hw_device_t *device);

static int sInitialize(const struct camera3_device *device, const camera3_callback_ops_t *callback_ops);

static int sConfigureStreams(const struct camera3_device *device, camera3_stream_configuration_t *stream_list);

static int sRegisterStreamBuffers(const struct camera3_device *device, const camera3_stream_buffer_set_t *buffer_set);

static const camera_metadata_t * sConstructDefaultRequestSettings(const struct camera3_device *device, int type);

static int sProcessCaptureRequest(const struct camera3_device *device, camera3_capture_request_t *request);

static void sGetMetadataVendorTagOps(const struct camera3_device *device, vendor_tag_query_ops_t* ops);

static void sDump(const struct camera3_device *device, int fd);

static int sFlush(const struct camera3_device *device);

static void _AddTimesTamp(uint8_t* buffer, int32_t width, int32_t height);

static camera3_device_ops_t sOps;

};

}; /* namespace android */

#endif // CAMERA_H**

**/*

* Copyright © 2015-2016 Antmicro

*

* Licensed under the Apache License, Version 2.0 (the “License”);

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

*      http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an “AS IS” BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

#define LOG_TAG “usb-Camera”

#define LOG_NDEBUG 0

#include <hardware/camera3.h>

#include <camera/CameraMetadata.h>

#include <utils/misc.h>

#include <utils/Log.h>

#include <hardware/gralloc.h>

#include <ui/Rect.h>

#include <ui/GraphicBufferMapper.h>

#include <ui/Fence.h>

#include <assert.h>

#include “DbgUtils.h”

#include “Camera.h”

#include “ImageConverter.h”

#include “libyuv.h”

//#include <sprd_exvideo.h>

#include <cutils/properties.h>

#include

#include

namespace android {

/**

* \class Camera

*

* Android’s Camera 3 device implementation.

*

* Declaration of camera capabilities, frame request handling, etc. This code

* is what Android framework talks to.

*/

Camera::Camera()
mStaticCharacteristics(NULL)

, mCallbackOps(NULL)

, mJpegBufferSize(0) {

ALOGI(“Camera() start”);

DBGUTILS_AUTOLOGCALL(__func__);

for(size_t i = 0; i < NELEM(mDefaultRequestSettings); i++) {

mDefaultRequestSettings[i] = NULL;

}

common.tag      = HARDWARE_DEVICE_TAG;

common.version  = CAMERA_DEVICE_API_VERSION_3_2;//CAMERA_DEVICE_API_VERSION_3_0;

common.module   = &HAL_MODULE_INFO_SYM.common;

common.close    = Camera::sClose;

ops             = &sOps;

priv            = NULL;

mValid = true;

mFrameBuffer = new uint8_t[640*480*4];

rszbuffer = new uint8_t[640*480*4];

mDev = new V4l2Device();

if(!mDev) {

mValid = false;

}

}

Camera::~Camera() {

DBGUTILS_AUTOLOGCALL(__func__);

gWorkers.stop();

mDev->disconnect();

delete[] mFrameBuffer;

delete[] rszbuffer;

delete mDev;

}

status_t Camera::cameraInfo(struct camera_info *info) {

DBGUTILS_AUTOLOGCALL(__func__);

ALOGI(“Camera::cameraInfo entry”);

ALOGE(“Camera::cameraInfo entry”);

Mutex::Autolock lock(mMutex);

info->facing = CAMERA_FACING_FRONT;//BACK;//FRONT;

info->orientation = 0;

info->device_version = CAMERA_DEVICE_API_VERSION_3_2;//CAMERA_DEVICE_API_VERSION_3_0;//CAMERA_DEVICE_API_VERSION_3_4;

info->static_camera_characteristics = staticCharacteristics();

return NO_ERROR;

}

int Camera::openDevice(hw_device_t **device) {

ALOGI(“%s”,__FUNCTION__);

DBGUTILS_AUTOLOGCALL(__func__);

Mutex::Autolock lock(mMutex);

char enableTimesTamp[PROPERTY_VALUE_MAX];

char enableAVI[PROPERTY_VALUE_MAX];

mDev->connect();

*device = &common;

gWorkers.start();

return NO_ERROR;

}

int Camera::closeDevice() {

ALOGI(“%s”,__FUNCTION__);

DBGUTILS_AUTOLOGCALL(__func__);

Mutex::Autolock lock(mMutex);

gWorkers.stop();

mDev->disconnect();

return NO_ERROR;

}

camera_metadata_t *Camera::staticCharacteristics() {

if(mStaticCharacteristics)

return mStaticCharacteristics;

CameraMetadata cm;

auto &resolutions = mDev->availableResolutions();

auto &previewResolutions = resolutions;

auto sensorRes = mDev->sensorResolution();

/***********************************\

|* START OF CAMERA CHARACTERISTICS *|

\***********************************/

/* fake, but valid aspect ratio */

const float sensorInfoPhysicalSize[] = {

5.0f,

5.0f * (float)sensorRes.height / (float)sensorRes.width

};

cm.update(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, sensorInfoPhysicalSize, NELEM(sensorInfoPhysicalSize));

/* fake */

static const float lensInfoAvailableFocalLengths[] = {3.30f};

cm.update(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, lensInfoAvailableFocalLengths, NELEM(lensInfoAvailableFocalLengths));

static const uint8_t lensFacing = ANDROID_LENS_FACING_FRONT;

cm.update(ANDROID_LENS_FACING, &lensFacing, 1);

const int32_t sensorInfoPixelArraySize[] = {

(int32_t)sensorRes.width,

(int32_t)sensorRes.height

};

cm.update(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, sensorInfoPixelArraySize, NELEM(sensorInfoPixelArraySize));

const int32_t sensorInfoActiveArraySize[] = {

0,                          0,

(int32_t)sensorRes.width,   (int32_t)sensorRes.height

};

cm.update(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, sensorInfoActiveArraySize, NELEM(sensorInfoActiveArraySize));

static const int32_t scalerAvailableFormats[] = {

HAL_PIXEL_FORMAT_RGBA_8888, //预览流

HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,//预览流

/* Non-preview one, must be last - see following code */

HAL_PIXEL_FORMAT_BLOB//拍照流

};

cm.update(ANDROID_SCALER_AVAILABLE_FORMATS, scalerAvailableFormats, NELEM(scalerAvailableFormats));

/* Only for HAL_PIXEL_FORMAT_BLOB */

const size_t mainStreamConfigsCount = resolutions.size();

/* For all other supported pixel formats */

const size_t previewStreamConfigsCount = previewResolutions.size() * (NELEM(scalerAvailableFormats) - 1);

const size_t streamConfigsCount = mainStreamConfigsCount + previewStreamConfigsCount;

int32_t scalerAvailableStreamConfigurations[streamConfigsCount * 4];

int64_t scalerAvailableMinFrameDurations[streamConfigsCount * 4];

int32_t scalerAvailableProcessedSizes[previewResolutions.size() * 2];

int64_t scalerAvailableProcessedMinDurations[previewResolutions.size()];

int32_t scalerAvailableJpegSizes[resolutions.size() * 2];

int64_t scalerAvailableJpegMinDurations[resolutions.size()];

size_t i4 = 0;

size_t i2 = 0;

size_t i1 = 0;

/* Main stream configurations */

for(size_t resId = 0; resId < resolutions.size(); ++resId) {

scalerAvailableStreamConfigurations[i4 + 0] = HAL_PIXEL_FORMAT_BLOB;

scalerAvailableStreamConfigurations[i4 + 1] = (int32_t)resolutions[resId].width;

scalerAvailableStreamConfigurations[i4 + 2] = (int32_t)resolutions[resId].height;

scalerAvailableStreamConfigurations[i4 + 3] = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT;

scalerAvailableMinFrameDurations[i4 + 0] = HAL_PIXEL_FORMAT_BLOB;

scalerAvailableMinFrameDurations[i4 + 1] = (int32_t)resolutions[resId].width;

scalerAvailableMinFrameDurations[i4 + 2] = (int32_t)resolutions[resId].height;

scalerAvailableMinFrameDurations[i4 + 3] = 1000000000 / 30; /* TODO: read from the device */

scalerAvailableJpegSizes[i2 + 0] = (int32_t)resolutions[resId].width;

scalerAvailableJpegSizes[i2 + 1] = (int32_t)resolutions[resId].height;

scalerAvailableJpegMinDurations[i1] = 1000000000 / 30; /* TODO: read from the device */

i4 += 4;

i2 += 2;

i1 += 1;

}

i2 = 0;

i1 = 0;

/* Preview stream configurations */

for(size_t resId = 0; resId < previewResolutions.size(); ++resId) {

for(size_t fmtId = 0; fmtId < NELEM(scalerAvailableFormats) - 1; ++fmtId) {

scalerAvailableStreamConfigurations[i4 + 0] = scalerAvailableFormats[fmtId];

scalerAvailableStreamConfigurations[i4 + 1] = (int32_t)previewResolutions[resId].width;

scalerAvailableStreamConfigurations[i4 + 2] = (int32_t)previewResolutions[resId].height;

scalerAvailableStreamConfigurations[i4 + 3] = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT;

scalerAvailableMinFrameDurations[i4 + 0] = scalerAvailableFormats[fmtId];

scalerAvailableMinFrameDurations[i4 + 1] = (int32_t)previewResolutions[resId].width;

scalerAvailableMinFrameDurations[i4 + 2] = (int32_t)previewResolutions[resId].height;

scalerAvailableMinFrameDurations[i4 + 3] = 1000000000 / 10; /* TODO: read from the device */

i4 += 4;

}

scalerAvailableProcessedSizes[i2 + 0] = (int32_t)previewResolutions[resId].width;

scalerAvailableProcessedSizes[i2 + 1] = (int32_t)previewResolutions[resId].height;

scalerAvailableProcessedMinDurations[i1] = 1000000000 / 10; /* TODO: read from the device */

i2 += 2;

i1 += 1;

}

cm.update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, scalerAvailableStreamConfigurations, (size_t)NELEM(scalerAvailableStreamConfigurations));

cm.update(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS, scalerAvailableMinFrameDurations, (size_t)NELEM(scalerAvailableMinFrameDurations));

/* Probably fake */

cm.update(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, scalerAvailableMinFrameDurations, (size_t)NELEM(scalerAvailableMinFrameDurations));

cm.update(ANDROID_SCALER_AVAILABLE_JPEG_SIZES, scalerAvailableJpegSizes, (size_t)NELEM(scalerAvailableJpegSizes));

cm.update(ANDROID_SCALER_AVAILABLE_JPEG_MIN_DURATIONS, scalerAvailableJpegMinDurations, (size_t)NELEM(scalerAvailableJpegMinDurations));

cm.update(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES, scalerAvailableProcessedSizes, (size_t)NELEM(scalerAvailableProcessedSizes));

cm.update(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS, scalerAvailableProcessedMinDurations, (size_t)NELEM(scalerAvailableProcessedMinDurations));

//添加capabilities集,否则api2的接口,在调用getStreamConfigurationMap去获取REQUEST_AVAILABLE_CAPABILITIES值时会失败。

Vector<uint8_t> available_capabilities;

available_capabilities.add(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS);

available_capabilities.add(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING);

available_capabilities.add(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING);

cm.update(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,

available_capabilities.array(),

available_capabilities.size());

/* ~8.25 bit/px (https://en.wikipedia.org/wiki/JPEG#Sample_photographs) */

/* Use 9 bit/px, add buffer info struct size, round up to page size */

mJpegBufferSize = sensorRes.width * sensorRes.height * 9 + sizeof(camera3_jpeg_blob);

mJpegBufferSize = (mJpegBufferSize + PAGE_SIZE - 1u) & ~(PAGE_SIZE - 1u);

const int32_t jpegMaxSize = (int32_t)mJpegBufferSize;

cm.update(ANDROID_JPEG_MAX_SIZE, &jpegMaxSize, 1);

static const int32_t jpegAvailableThumbnailSizes[] = {

0, 0,

320, 240

};

cm.update(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, jpegAvailableThumbnailSizes, NELEM(jpegAvailableThumbnailSizes));

static const int32_t sensorOrientation = 90;

cm.update(ANDROID_SENSOR_ORIENTATION, &sensorOrientation, 1);

static const uint8_t flashInfoAvailable = ANDROID_FLASH_INFO_AVAILABLE_FALSE;

cm.update(ANDROID_FLASH_INFO_AVAILABLE, &flashInfoAvailable, 1);

static const float scalerAvailableMaxDigitalZoom = 1;

cm.update(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, &scalerAvailableMaxDigitalZoom, 1);

static const uint8_t statisticsFaceDetectModes[] = {

ANDROID_STATISTICS_FACE_DETECT_MODE_OFF

};

cm.update(ANDROID_STATISTICS_FACE_DETECT_MODE, statisticsFaceDetectModes, NELEM(statisticsFaceDetectModes));

static const int32_t statisticsInfoMaxFaceCount = 0;

cm.update(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, &statisticsInfoMaxFaceCount, 1);

static const uint8_t controlAvailableSceneModes[] = {

ANDROID_CONTROL_SCENE_MODE_DISABLED

};

cm.update(ANDROID_CONTROL_AVAILABLE_SCENE_MODES, controlAvailableSceneModes, NELEM(controlAvailableSceneModes));

static const uint8_t controlAvailableEffects[] = {

ANDROID_CONTROL_EFFECT_MODE_OFF

};

cm.update(ANDROID_CONTROL_AVAILABLE_EFFECTS, controlAvailableEffects, NELEM(controlAvailableEffects));

static const int32_t controlMaxRegions[] = {

0, /* AE */

0, /* AWB */

0  /* AF */

};

cm.update(ANDROID_CONTROL_MAX_REGIONS, controlMaxRegions, NELEM(controlMaxRegions));

static const uint8_t controlAeAvailableModes[] = {

ANDROID_CONTROL_AE_MODE_OFF

};

cm.update(ANDROID_CONTROL_AE_AVAILABLE_MODES, controlAeAvailableModes, NELEM(controlAeAvailableModes));

static const camera_metadata_rational controlAeCompensationStep = {1, 3};

cm.update(ANDROID_CONTROL_AE_COMPENSATION_STEP, &controlAeCompensationStep, 1);

int32_t controlAeCompensationRange[] = {-9, 9};

cm.update(ANDROID_CONTROL_AE_COMPENSATION_RANGE, controlAeCompensationRange, NELEM(controlAeCompensationRange));

static const int32_t controlAeAvailableTargetFpsRanges[] = {

10, 20

};

cm.update(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, controlAeAvailableTargetFpsRanges, NELEM(controlAeAvailableTargetFpsRanges));

static const uint8_t controlAeAvailableAntibandingModes[] = {

ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF

};

cm.update(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, controlAeAvailableAntibandingModes, NELEM(controlAeAvailableAntibandingModes));

static const uint8_t controlAwbAvailableModes[] = {

ANDROID_CONTROL_AWB_MODE_AUTO,

ANDROID_CONTROL_AWB_MODE_OFF

};

cm.update(ANDROID_CONTROL_AWB_AVAILABLE_MODES, controlAwbAvailableModes, NELEM(controlAwbAvailableModes));

static const uint8_t controlAfAvailableModes[] = {

ANDROID_CONTROL_AF_MODE_OFF

};

cm.update(ANDROID_CONTROL_AF_AVAILABLE_MODES, controlAfAvailableModes, NELEM(controlAfAvailableModes));

static const uint8_t controlAvailableVideoStabilizationModes[] = {

ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF

};

cm.update(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES, controlAvailableVideoStabilizationModes, NELEM(controlAvailableVideoStabilizationModes));

const uint8_t infoSupportedHardwareLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;

cm.update(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &infoSupportedHardwareLevel, 1);

/***********************************\

|*  END OF CAMERA CHARACTERISTICS  *|

\***********************************/

mStaticCharacteristics = cm.release();

return mStaticCharacteristics;

}

int Camera::initialize(const camera3_callback_ops_t *callbackOps) {

DBGUTILS_AUTOLOGCALL(__func__);

Mutex::Autolock lock(mMutex);

mCallbackOps = callbackOps;

return NO_ERROR;

}

const camera_metadata_t * Camera::constructDefaultRequestSettings(int type) {

DBGUTILS_AUTOLOGCALL(__func__);

Mutex::Autolock lock(mMutex);

/* TODO: validate type */

最后

答应大伙的备战金三银四,大厂面试真题来啦!

这份资料我从春招开始,就会将各博客、论坛。网站上等优质的Android开发中高级面试题收集起来,然后全网寻找最优的解答方案。每一道面试题都是百分百的大厂面经真题+最优解答。包知识脉络 + 诸多细节。
节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
给文章留个小赞,就可以免费领取啦~

戳我领取:3000页Android开发者架构师核心知识笔记

《960全网最全Android开发笔记》

《379页Android开发面试宝典》

包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

如何使用它?
1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

腾讯、字节跳动、阿里、百度等BAT大厂 2020-2021面试真题解析

资料收集不易,如果大家喜欢这篇文章,或者对你有帮助不妨多多点赞转发关注哦。文章会持续更新的。绝对干货!!!

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

Mutex::Autolock lock(mMutex);

/* TODO: validate type */

最后

答应大伙的备战金三银四,大厂面试真题来啦!

这份资料我从春招开始,就会将各博客、论坛。网站上等优质的Android开发中高级面试题收集起来,然后全网寻找最优的解答方案。每一道面试题都是百分百的大厂面经真题+最优解答。包知识脉络 + 诸多细节。
节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
给文章留个小赞,就可以免费领取啦~

戳我领取:3000页Android开发者架构师核心知识笔记

《960全网最全Android开发笔记》

[外链图片转存中…(img-rqXVx3Ks-1710960041058)]

《379页Android开发面试宝典》

包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

如何使用它?
1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数

[外链图片转存中…(img-erJgnuZR-1710960041059)]

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

[外链图片转存中…(img-jY1pzbU2-1710960041059)]

腾讯、字节跳动、阿里、百度等BAT大厂 2020-2021面试真题解析

[外链图片转存中…(img-Gpn9TUZD-1710960041060)]

资料收集不易,如果大家喜欢这篇文章,或者对你有帮助不妨多多点赞转发关注哦。文章会持续更新的。绝对干货!!!

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-Tv6oKspz-1710960041060)]
[外链图片转存中…(img-74W8PVdV-1710960041060)]
[外链图片转存中…(img-YtfvIeL6-1710960041061)]
[外链图片转存中…(img-Oydeqeaq-1710960041061)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-HwXZQdoL-1710960041061)]

  • 23
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值