xref: /aosp_15_r20/hardware/libhardware/modules/usbcamera/Camera.cpp (revision e01b6f769022e40d0923dee176e8dc7cd1d52984)
1*e01b6f76SAndroid Build Coastguard Worker /*
2*e01b6f76SAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*e01b6f76SAndroid Build Coastguard Worker  *
4*e01b6f76SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*e01b6f76SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*e01b6f76SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*e01b6f76SAndroid Build Coastguard Worker  *
8*e01b6f76SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*e01b6f76SAndroid Build Coastguard Worker  *
10*e01b6f76SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*e01b6f76SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*e01b6f76SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e01b6f76SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*e01b6f76SAndroid Build Coastguard Worker  * limitations under the License.
15*e01b6f76SAndroid Build Coastguard Worker  */
16*e01b6f76SAndroid Build Coastguard Worker 
17*e01b6f76SAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*e01b6f76SAndroid Build Coastguard Worker #define LOG_TAG "Camera"
19*e01b6f76SAndroid Build Coastguard Worker 
20*e01b6f76SAndroid Build Coastguard Worker #include <errno.h>
21*e01b6f76SAndroid Build Coastguard Worker #include <stdio.h>
22*e01b6f76SAndroid Build Coastguard Worker #include <string.h>
23*e01b6f76SAndroid Build Coastguard Worker #include <time.h>
24*e01b6f76SAndroid Build Coastguard Worker 
25*e01b6f76SAndroid Build Coastguard Worker #include <cstdlib>
26*e01b6f76SAndroid Build Coastguard Worker 
27*e01b6f76SAndroid Build Coastguard Worker #include <log/log.h>
28*e01b6f76SAndroid Build Coastguard Worker #include <utils/Mutex.h>
29*e01b6f76SAndroid Build Coastguard Worker 
30*e01b6f76SAndroid Build Coastguard Worker #define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
31*e01b6f76SAndroid Build Coastguard Worker #include <utils/Trace.h>
32*e01b6f76SAndroid Build Coastguard Worker 
33*e01b6f76SAndroid Build Coastguard Worker #include <hardware/camera3.h>
34*e01b6f76SAndroid Build Coastguard Worker #include <system/camera_metadata.h>
35*e01b6f76SAndroid Build Coastguard Worker #include <system/graphics.h>
36*e01b6f76SAndroid Build Coastguard Worker 
37*e01b6f76SAndroid Build Coastguard Worker #include "CameraHAL.h"
38*e01b6f76SAndroid Build Coastguard Worker #include "Metadata.h"
39*e01b6f76SAndroid Build Coastguard Worker #include "Stream.h"
40*e01b6f76SAndroid Build Coastguard Worker 
41*e01b6f76SAndroid Build Coastguard Worker #include "Camera.h"
42*e01b6f76SAndroid Build Coastguard Worker 
43*e01b6f76SAndroid Build Coastguard Worker namespace usb_camera_hal {
44*e01b6f76SAndroid Build Coastguard Worker 
45*e01b6f76SAndroid Build Coastguard Worker extern "C" {
46*e01b6f76SAndroid Build Coastguard Worker // Shim passed to the framework to close an opened device.
close_device(hw_device_t * dev)47*e01b6f76SAndroid Build Coastguard Worker static int close_device(hw_device_t* dev) {
48*e01b6f76SAndroid Build Coastguard Worker     camera3_device_t* cam_dev = reinterpret_cast<camera3_device_t*>(dev);
49*e01b6f76SAndroid Build Coastguard Worker     Camera* cam = static_cast<Camera*>(cam_dev->priv);
50*e01b6f76SAndroid Build Coastguard Worker     return cam->close();
51*e01b6f76SAndroid Build Coastguard Worker }
52*e01b6f76SAndroid Build Coastguard Worker 
53*e01b6f76SAndroid Build Coastguard Worker // Get handle to camera from device priv data
camdev_to_camera(const camera3_device_t * dev)54*e01b6f76SAndroid Build Coastguard Worker static Camera *camdev_to_camera(const camera3_device_t *dev) {
55*e01b6f76SAndroid Build Coastguard Worker     return reinterpret_cast<Camera*>(dev->priv);
56*e01b6f76SAndroid Build Coastguard Worker }
57*e01b6f76SAndroid Build Coastguard Worker 
initialize(const camera3_device_t * dev,const camera3_callback_ops_t * callback_ops)58*e01b6f76SAndroid Build Coastguard Worker static int initialize(const camera3_device_t *dev,
59*e01b6f76SAndroid Build Coastguard Worker         const camera3_callback_ops_t *callback_ops) {
60*e01b6f76SAndroid Build Coastguard Worker     return camdev_to_camera(dev)->initialize(callback_ops);
61*e01b6f76SAndroid Build Coastguard Worker }
62*e01b6f76SAndroid Build Coastguard Worker 
configure_streams(const camera3_device_t * dev,camera3_stream_configuration_t * stream_list)63*e01b6f76SAndroid Build Coastguard Worker static int configure_streams(const camera3_device_t *dev,
64*e01b6f76SAndroid Build Coastguard Worker         camera3_stream_configuration_t *stream_list) {
65*e01b6f76SAndroid Build Coastguard Worker     return camdev_to_camera(dev)->configureStreams(stream_list);
66*e01b6f76SAndroid Build Coastguard Worker }
67*e01b6f76SAndroid Build Coastguard Worker 
construct_default_request_settings(const camera3_device_t * dev,int type)68*e01b6f76SAndroid Build Coastguard Worker static const camera_metadata_t *construct_default_request_settings(
69*e01b6f76SAndroid Build Coastguard Worker         const camera3_device_t *dev, int type) {
70*e01b6f76SAndroid Build Coastguard Worker     return camdev_to_camera(dev)->constructDefaultRequestSettings(type);
71*e01b6f76SAndroid Build Coastguard Worker }
72*e01b6f76SAndroid Build Coastguard Worker 
process_capture_request(const camera3_device_t * dev,camera3_capture_request_t * request)73*e01b6f76SAndroid Build Coastguard Worker static int process_capture_request(const camera3_device_t *dev,
74*e01b6f76SAndroid Build Coastguard Worker         camera3_capture_request_t *request) {
75*e01b6f76SAndroid Build Coastguard Worker     return camdev_to_camera(dev)->processCaptureRequest(request);
76*e01b6f76SAndroid Build Coastguard Worker }
77*e01b6f76SAndroid Build Coastguard Worker 
dump(const camera3_device_t * dev,int fd)78*e01b6f76SAndroid Build Coastguard Worker static void dump(const camera3_device_t *dev, int fd) {
79*e01b6f76SAndroid Build Coastguard Worker     camdev_to_camera(dev)->dump(fd);
80*e01b6f76SAndroid Build Coastguard Worker }
81*e01b6f76SAndroid Build Coastguard Worker 
flush(const camera3_device_t * dev)82*e01b6f76SAndroid Build Coastguard Worker static int flush(const camera3_device_t *dev) {
83*e01b6f76SAndroid Build Coastguard Worker     return camdev_to_camera(dev)->flush();
84*e01b6f76SAndroid Build Coastguard Worker }
85*e01b6f76SAndroid Build Coastguard Worker 
86*e01b6f76SAndroid Build Coastguard Worker } // extern "C"
87*e01b6f76SAndroid Build Coastguard Worker 
88*e01b6f76SAndroid Build Coastguard Worker const camera3_device_ops_t Camera::sOps = {
89*e01b6f76SAndroid Build Coastguard Worker     .initialize = usb_camera_hal::initialize,
90*e01b6f76SAndroid Build Coastguard Worker     .configure_streams = usb_camera_hal::configure_streams,
91*e01b6f76SAndroid Build Coastguard Worker     .register_stream_buffers = NULL,
92*e01b6f76SAndroid Build Coastguard Worker     .construct_default_request_settings
93*e01b6f76SAndroid Build Coastguard Worker         = usb_camera_hal::construct_default_request_settings,
94*e01b6f76SAndroid Build Coastguard Worker     .process_capture_request = usb_camera_hal::process_capture_request,
95*e01b6f76SAndroid Build Coastguard Worker     .get_metadata_vendor_tag_ops = NULL,
96*e01b6f76SAndroid Build Coastguard Worker     .dump = usb_camera_hal::dump,
97*e01b6f76SAndroid Build Coastguard Worker     .flush = usb_camera_hal::flush,
98*e01b6f76SAndroid Build Coastguard Worker     .reserved = {0},
99*e01b6f76SAndroid Build Coastguard Worker };
100*e01b6f76SAndroid Build Coastguard Worker 
Camera(int id)101*e01b6f76SAndroid Build Coastguard Worker Camera::Camera(int id)
102*e01b6f76SAndroid Build Coastguard Worker           : mId(id),
103*e01b6f76SAndroid Build Coastguard Worker             mStaticInfo(NULL),
104*e01b6f76SAndroid Build Coastguard Worker             mBusy(false),
105*e01b6f76SAndroid Build Coastguard Worker             mCallbackOps(NULL),
106*e01b6f76SAndroid Build Coastguard Worker             mSettings(NULL),
107*e01b6f76SAndroid Build Coastguard Worker             mIsInitialized(false) {
108*e01b6f76SAndroid Build Coastguard Worker     memset(&mTemplates, 0, sizeof(mTemplates));
109*e01b6f76SAndroid Build Coastguard Worker     memset(&mDevice, 0, sizeof(mDevice));
110*e01b6f76SAndroid Build Coastguard Worker     mDevice.common.tag    = HARDWARE_DEVICE_TAG;
111*e01b6f76SAndroid Build Coastguard Worker     // TODO: Upgrade to HAL3.3
112*e01b6f76SAndroid Build Coastguard Worker     mDevice.common.version = CAMERA_DEVICE_API_VERSION_3_2;
113*e01b6f76SAndroid Build Coastguard Worker     mDevice.common.close  = close_device;
114*e01b6f76SAndroid Build Coastguard Worker     mDevice.ops           = const_cast<camera3_device_ops_t*>(&sOps);
115*e01b6f76SAndroid Build Coastguard Worker     mDevice.priv          = this;
116*e01b6f76SAndroid Build Coastguard Worker }
117*e01b6f76SAndroid Build Coastguard Worker 
~Camera()118*e01b6f76SAndroid Build Coastguard Worker Camera::~Camera() {
119*e01b6f76SAndroid Build Coastguard Worker     if (mStaticInfo != NULL) {
120*e01b6f76SAndroid Build Coastguard Worker         free_camera_metadata(mStaticInfo);
121*e01b6f76SAndroid Build Coastguard Worker     }
122*e01b6f76SAndroid Build Coastguard Worker 
123*e01b6f76SAndroid Build Coastguard Worker     for (int i = 0; i < CAMERA3_TEMPLATE_COUNT; i++) {
124*e01b6f76SAndroid Build Coastguard Worker         free_camera_metadata(mTemplates[i]);
125*e01b6f76SAndroid Build Coastguard Worker     }
126*e01b6f76SAndroid Build Coastguard Worker 
127*e01b6f76SAndroid Build Coastguard Worker     if (mSettings != NULL) {
128*e01b6f76SAndroid Build Coastguard Worker         free_camera_metadata(mSettings);
129*e01b6f76SAndroid Build Coastguard Worker     }
130*e01b6f76SAndroid Build Coastguard Worker }
131*e01b6f76SAndroid Build Coastguard Worker 
open(const hw_module_t * module,hw_device_t ** device)132*e01b6f76SAndroid Build Coastguard Worker int Camera::open(const hw_module_t *module, hw_device_t **device) {
133*e01b6f76SAndroid Build Coastguard Worker     ALOGI("%s:%d: Opening camera device", __func__, mId);
134*e01b6f76SAndroid Build Coastguard Worker     ATRACE_CALL();
135*e01b6f76SAndroid Build Coastguard Worker     android::Mutex::Autolock al(mDeviceLock);
136*e01b6f76SAndroid Build Coastguard Worker 
137*e01b6f76SAndroid Build Coastguard Worker     if (mBusy) {
138*e01b6f76SAndroid Build Coastguard Worker         ALOGE("%s:%d: Error! Camera device already opened", __func__, mId);
139*e01b6f76SAndroid Build Coastguard Worker         return -EBUSY;
140*e01b6f76SAndroid Build Coastguard Worker     }
141*e01b6f76SAndroid Build Coastguard Worker 
142*e01b6f76SAndroid Build Coastguard Worker     mBusy = true;
143*e01b6f76SAndroid Build Coastguard Worker     mDevice.common.module = const_cast<hw_module_t*>(module);
144*e01b6f76SAndroid Build Coastguard Worker     *device = &mDevice.common;
145*e01b6f76SAndroid Build Coastguard Worker     return openDevice();
146*e01b6f76SAndroid Build Coastguard Worker }
147*e01b6f76SAndroid Build Coastguard Worker 
getInfo(struct camera_info * info)148*e01b6f76SAndroid Build Coastguard Worker int Camera::getInfo(struct camera_info *info) {
149*e01b6f76SAndroid Build Coastguard Worker     android::Mutex::Autolock al(mStaticInfoLock);
150*e01b6f76SAndroid Build Coastguard Worker 
151*e01b6f76SAndroid Build Coastguard Worker     // TODO: update to CAMERA_FACING_EXTERNAL once the HAL API changes are merged.
152*e01b6f76SAndroid Build Coastguard Worker     info->facing = CAMERA_FACING_FRONT;
153*e01b6f76SAndroid Build Coastguard Worker     info->orientation = 0;
154*e01b6f76SAndroid Build Coastguard Worker     info->device_version = mDevice.common.version;
155*e01b6f76SAndroid Build Coastguard Worker     if (mStaticInfo == NULL) {
156*e01b6f76SAndroid Build Coastguard Worker         initStaticInfo();
157*e01b6f76SAndroid Build Coastguard Worker     }
158*e01b6f76SAndroid Build Coastguard Worker     info->static_camera_characteristics = mStaticInfo;
159*e01b6f76SAndroid Build Coastguard Worker     return 0;
160*e01b6f76SAndroid Build Coastguard Worker }
161*e01b6f76SAndroid Build Coastguard Worker 
updateInfo()162*e01b6f76SAndroid Build Coastguard Worker void Camera::updateInfo() {
163*e01b6f76SAndroid Build Coastguard Worker     android::Mutex::Autolock al(mStaticInfoLock);
164*e01b6f76SAndroid Build Coastguard Worker     initStaticInfo();
165*e01b6f76SAndroid Build Coastguard Worker }
166*e01b6f76SAndroid Build Coastguard Worker 
close()167*e01b6f76SAndroid Build Coastguard Worker int Camera::close() {
168*e01b6f76SAndroid Build Coastguard Worker     ALOGI("%s:%d: Closing camera device", __func__, mId);
169*e01b6f76SAndroid Build Coastguard Worker     ATRACE_CALL();
170*e01b6f76SAndroid Build Coastguard Worker     android::Mutex::Autolock al(mDeviceLock);
171*e01b6f76SAndroid Build Coastguard Worker 
172*e01b6f76SAndroid Build Coastguard Worker     if (!mBusy) {
173*e01b6f76SAndroid Build Coastguard Worker         ALOGE("%s:%d: Error! Camera device not open", __func__, mId);
174*e01b6f76SAndroid Build Coastguard Worker         return -EINVAL;
175*e01b6f76SAndroid Build Coastguard Worker     }
176*e01b6f76SAndroid Build Coastguard Worker 
177*e01b6f76SAndroid Build Coastguard Worker     mBusy = false;
178*e01b6f76SAndroid Build Coastguard Worker     mIsInitialized = false;
179*e01b6f76SAndroid Build Coastguard Worker     return closeDevice();
180*e01b6f76SAndroid Build Coastguard Worker }
181*e01b6f76SAndroid Build Coastguard Worker 
initialize(const camera3_callback_ops_t * callback_ops)182*e01b6f76SAndroid Build Coastguard Worker int Camera::initialize(const camera3_callback_ops_t *callback_ops) {
183*e01b6f76SAndroid Build Coastguard Worker     int res;
184*e01b6f76SAndroid Build Coastguard Worker 
185*e01b6f76SAndroid Build Coastguard Worker     ALOGV("%s:%d: callback_ops=%p", __func__, mId, callback_ops);
186*e01b6f76SAndroid Build Coastguard Worker     ATRACE_CALL();
187*e01b6f76SAndroid Build Coastguard Worker     android::Mutex::Autolock al(mDeviceLock);
188*e01b6f76SAndroid Build Coastguard Worker 
189*e01b6f76SAndroid Build Coastguard Worker     mCallbackOps = callback_ops;
190*e01b6f76SAndroid Build Coastguard Worker     // per-device specific initialization
191*e01b6f76SAndroid Build Coastguard Worker     res = initDevice();
192*e01b6f76SAndroid Build Coastguard Worker     if (res != 0) {
193*e01b6f76SAndroid Build Coastguard Worker         ALOGE("%s:%d: Failed to initialize device!", __func__, mId);
194*e01b6f76SAndroid Build Coastguard Worker         return res;
195*e01b6f76SAndroid Build Coastguard Worker     }
196*e01b6f76SAndroid Build Coastguard Worker 
197*e01b6f76SAndroid Build Coastguard Worker     mIsInitialized = true;
198*e01b6f76SAndroid Build Coastguard Worker     return 0;
199*e01b6f76SAndroid Build Coastguard Worker }
200*e01b6f76SAndroid Build Coastguard Worker 
configureStreams(camera3_stream_configuration_t * stream_config)201*e01b6f76SAndroid Build Coastguard Worker int Camera::configureStreams(camera3_stream_configuration_t *stream_config) {
202*e01b6f76SAndroid Build Coastguard Worker     camera3_stream_t *astream;
203*e01b6f76SAndroid Build Coastguard Worker     android::Vector<Stream *> newStreams;
204*e01b6f76SAndroid Build Coastguard Worker 
205*e01b6f76SAndroid Build Coastguard Worker     ALOGV("%s:%d: stream_config=%p", __func__, mId, stream_config);
206*e01b6f76SAndroid Build Coastguard Worker     ATRACE_CALL();
207*e01b6f76SAndroid Build Coastguard Worker     android::Mutex::Autolock al(mDeviceLock);
208*e01b6f76SAndroid Build Coastguard Worker     if (!mIsInitialized) {
209*e01b6f76SAndroid Build Coastguard Worker         ALOGE("Device is not initialized yet");
210*e01b6f76SAndroid Build Coastguard Worker         return -EINVAL;
211*e01b6f76SAndroid Build Coastguard Worker     }
212*e01b6f76SAndroid Build Coastguard Worker 
213*e01b6f76SAndroid Build Coastguard Worker     if (stream_config == NULL) {
214*e01b6f76SAndroid Build Coastguard Worker         ALOGE("%s:%d: NULL stream configuration array", __func__, mId);
215*e01b6f76SAndroid Build Coastguard Worker         return -EINVAL;
216*e01b6f76SAndroid Build Coastguard Worker     }
217*e01b6f76SAndroid Build Coastguard Worker     if (stream_config->num_streams == 0) {
218*e01b6f76SAndroid Build Coastguard Worker         ALOGE("%s:%d: Empty stream configuration array", __func__, mId);
219*e01b6f76SAndroid Build Coastguard Worker         return -EINVAL;
220*e01b6f76SAndroid Build Coastguard Worker     }
221*e01b6f76SAndroid Build Coastguard Worker 
222*e01b6f76SAndroid Build Coastguard Worker     ALOGV("%s:%d: Number of Streams: %d", __func__, mId,
223*e01b6f76SAndroid Build Coastguard Worker             stream_config->num_streams);
224*e01b6f76SAndroid Build Coastguard Worker     // Mark all current streams unused for now
225*e01b6f76SAndroid Build Coastguard Worker     for (size_t i = 0; i < mStreams.size(); i++) {
226*e01b6f76SAndroid Build Coastguard Worker         mStreams[i]->mReuse = false;
227*e01b6f76SAndroid Build Coastguard Worker     }
228*e01b6f76SAndroid Build Coastguard Worker     // Fill new stream array with reused streams and new streams
229*e01b6f76SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < stream_config->num_streams; i++) {
230*e01b6f76SAndroid Build Coastguard Worker         astream = stream_config->streams[i];
231*e01b6f76SAndroid Build Coastguard Worker         if (astream->max_buffers > 0) {
232*e01b6f76SAndroid Build Coastguard Worker             ALOGV("%s:%d: Reusing stream %d", __func__, mId, i);
233*e01b6f76SAndroid Build Coastguard Worker             newStreams.add(reuseStreamLocked(astream));
234*e01b6f76SAndroid Build Coastguard Worker         } else {
235*e01b6f76SAndroid Build Coastguard Worker             ALOGV("%s:%d: Creating new stream %d", __func__, mId, i);
236*e01b6f76SAndroid Build Coastguard Worker             newStreams.add(new Stream(mId, astream));
237*e01b6f76SAndroid Build Coastguard Worker         }
238*e01b6f76SAndroid Build Coastguard Worker 
239*e01b6f76SAndroid Build Coastguard Worker         if (newStreams[i] == NULL) {
240*e01b6f76SAndroid Build Coastguard Worker             ALOGE("%s:%d: Error processing stream %d", __func__, mId, i);
241*e01b6f76SAndroid Build Coastguard Worker             goto err_out;
242*e01b6f76SAndroid Build Coastguard Worker         }
243*e01b6f76SAndroid Build Coastguard Worker         astream->priv = reinterpret_cast<void *>(newStreams[i]);
244*e01b6f76SAndroid Build Coastguard Worker     }
245*e01b6f76SAndroid Build Coastguard Worker 
246*e01b6f76SAndroid Build Coastguard Worker     // Verify the set of streams in aggregate
247*e01b6f76SAndroid Build Coastguard Worker     if (!isValidStreamSetLocked(newStreams)) {
248*e01b6f76SAndroid Build Coastguard Worker         ALOGE("%s:%d: Invalid stream set", __func__, mId);
249*e01b6f76SAndroid Build Coastguard Worker         goto err_out;
250*e01b6f76SAndroid Build Coastguard Worker     }
251*e01b6f76SAndroid Build Coastguard Worker 
252*e01b6f76SAndroid Build Coastguard Worker     // Set up all streams (calculate usage/max_buffers for each)
253*e01b6f76SAndroid Build Coastguard Worker     setupStreamsLocked(newStreams);
254*e01b6f76SAndroid Build Coastguard Worker 
255*e01b6f76SAndroid Build Coastguard Worker     // Destroy all old streams and replace stream array with new one
256*e01b6f76SAndroid Build Coastguard Worker     destroyStreamsLocked(mStreams);
257*e01b6f76SAndroid Build Coastguard Worker     mStreams = newStreams;
258*e01b6f76SAndroid Build Coastguard Worker 
259*e01b6f76SAndroid Build Coastguard Worker     // Clear out last seen settings metadata
260*e01b6f76SAndroid Build Coastguard Worker     updateSettingsLocked(NULL);
261*e01b6f76SAndroid Build Coastguard Worker     return 0;
262*e01b6f76SAndroid Build Coastguard Worker 
263*e01b6f76SAndroid Build Coastguard Worker err_out:
264*e01b6f76SAndroid Build Coastguard Worker     // Clean up temporary streams, preserve existing mStreams
265*e01b6f76SAndroid Build Coastguard Worker     destroyStreamsLocked(newStreams);
266*e01b6f76SAndroid Build Coastguard Worker     return -EINVAL;
267*e01b6f76SAndroid Build Coastguard Worker }
268*e01b6f76SAndroid Build Coastguard Worker 
destroyStreamsLocked(android::Vector<Stream * > & streams)269*e01b6f76SAndroid Build Coastguard Worker void Camera::destroyStreamsLocked(android::Vector<Stream *> &streams) {
270*e01b6f76SAndroid Build Coastguard Worker     for (size_t i = 0; i < streams.size(); i++) {
271*e01b6f76SAndroid Build Coastguard Worker         delete streams[i];
272*e01b6f76SAndroid Build Coastguard Worker     }
273*e01b6f76SAndroid Build Coastguard Worker     streams.clear();
274*e01b6f76SAndroid Build Coastguard Worker }
275*e01b6f76SAndroid Build Coastguard Worker 
reuseStreamLocked(camera3_stream_t * astream)276*e01b6f76SAndroid Build Coastguard Worker Stream *Camera::reuseStreamLocked(camera3_stream_t *astream) {
277*e01b6f76SAndroid Build Coastguard Worker     Stream *priv = reinterpret_cast<Stream*>(astream->priv);
278*e01b6f76SAndroid Build Coastguard Worker     // Verify the re-used stream's parameters match
279*e01b6f76SAndroid Build Coastguard Worker     if (!priv->isValidReuseStream(mId, astream)) {
280*e01b6f76SAndroid Build Coastguard Worker         ALOGE("%s:%d: Mismatched parameter in reused stream", __func__, mId);
281*e01b6f76SAndroid Build Coastguard Worker         return NULL;
282*e01b6f76SAndroid Build Coastguard Worker     }
283*e01b6f76SAndroid Build Coastguard Worker     // Mark stream to be reused
284*e01b6f76SAndroid Build Coastguard Worker     priv->mReuse = true;
285*e01b6f76SAndroid Build Coastguard Worker     return priv;
286*e01b6f76SAndroid Build Coastguard Worker }
287*e01b6f76SAndroid Build Coastguard Worker 
isValidStreamSetLocked(const android::Vector<Stream * > & streams)288*e01b6f76SAndroid Build Coastguard Worker bool Camera::isValidStreamSetLocked(const android::Vector<Stream *> &streams) {
289*e01b6f76SAndroid Build Coastguard Worker     int inputs = 0;
290*e01b6f76SAndroid Build Coastguard Worker     int outputs = 0;
291*e01b6f76SAndroid Build Coastguard Worker 
292*e01b6f76SAndroid Build Coastguard Worker     if (streams.isEmpty()) {
293*e01b6f76SAndroid Build Coastguard Worker         ALOGE("%s:%d: Zero count stream configuration streams", __func__, mId);
294*e01b6f76SAndroid Build Coastguard Worker         return false;
295*e01b6f76SAndroid Build Coastguard Worker     }
296*e01b6f76SAndroid Build Coastguard Worker     // Validate there is at most one input stream and at least one output stream
297*e01b6f76SAndroid Build Coastguard Worker     for (size_t i = 0; i < streams.size(); i++) {
298*e01b6f76SAndroid Build Coastguard Worker         // A stream may be both input and output (bidirectional)
299*e01b6f76SAndroid Build Coastguard Worker         if (streams[i]->isInputType())
300*e01b6f76SAndroid Build Coastguard Worker             inputs++;
301*e01b6f76SAndroid Build Coastguard Worker         if (streams[i]->isOutputType())
302*e01b6f76SAndroid Build Coastguard Worker             outputs++;
303*e01b6f76SAndroid Build Coastguard Worker     }
304*e01b6f76SAndroid Build Coastguard Worker     ALOGV("%s:%d: Configuring %d output streams and %d input streams",
305*e01b6f76SAndroid Build Coastguard Worker             __func__, mId, outputs, inputs);
306*e01b6f76SAndroid Build Coastguard Worker     if (outputs < 1) {
307*e01b6f76SAndroid Build Coastguard Worker         ALOGE("%s:%d: Stream config must have >= 1 output", __func__, mId);
308*e01b6f76SAndroid Build Coastguard Worker         return false;
309*e01b6f76SAndroid Build Coastguard Worker     }
310*e01b6f76SAndroid Build Coastguard Worker     if (inputs > 1) {
311*e01b6f76SAndroid Build Coastguard Worker         ALOGE("%s:%d: Stream config must have <= 1 input", __func__, mId);
312*e01b6f76SAndroid Build Coastguard Worker         return false;
313*e01b6f76SAndroid Build Coastguard Worker     }
314*e01b6f76SAndroid Build Coastguard Worker     // TODO: check for correct number of Bayer/YUV/JPEG/Encoder streams
315*e01b6f76SAndroid Build Coastguard Worker     return true;
316*e01b6f76SAndroid Build Coastguard Worker }
317*e01b6f76SAndroid Build Coastguard Worker 
setupStreamsLocked(android::Vector<Stream * > & streams)318*e01b6f76SAndroid Build Coastguard Worker void Camera::setupStreamsLocked(android::Vector<Stream *> &streams) {
319*e01b6f76SAndroid Build Coastguard Worker     /*
320*e01b6f76SAndroid Build Coastguard Worker      * This is where the HAL has to decide internally how to handle all of the
321*e01b6f76SAndroid Build Coastguard Worker      * streams, and then produce usage and max_buffer values for each stream.
322*e01b6f76SAndroid Build Coastguard Worker      * Note, the stream vector has been checked before this point for ALL invalid
323*e01b6f76SAndroid Build Coastguard Worker      * conditions, so it must find a successful configuration for this stream
324*e01b6f76SAndroid Build Coastguard Worker      * array.  The HAL may not return an error from this point.
325*e01b6f76SAndroid Build Coastguard Worker      *
326*e01b6f76SAndroid Build Coastguard Worker      * TODO: we just set all streams to be the same dummy values;
327*e01b6f76SAndroid Build Coastguard Worker      * real implementations will want to avoid USAGE_SW_{READ|WRITE}_OFTEN.
328*e01b6f76SAndroid Build Coastguard Worker      */
329*e01b6f76SAndroid Build Coastguard Worker     for (size_t i = 0; i < streams.size(); i++) {
330*e01b6f76SAndroid Build Coastguard Worker         uint32_t usage = 0;
331*e01b6f76SAndroid Build Coastguard Worker 
332*e01b6f76SAndroid Build Coastguard Worker         if (streams[i]->isOutputType())
333*e01b6f76SAndroid Build Coastguard Worker             usage |= GRALLOC_USAGE_SW_WRITE_OFTEN |
334*e01b6f76SAndroid Build Coastguard Worker                      GRALLOC_USAGE_HW_CAMERA_WRITE;
335*e01b6f76SAndroid Build Coastguard Worker         if (streams[i]->isInputType())
336*e01b6f76SAndroid Build Coastguard Worker             usage |= GRALLOC_USAGE_SW_READ_OFTEN |
337*e01b6f76SAndroid Build Coastguard Worker                      GRALLOC_USAGE_HW_CAMERA_READ;
338*e01b6f76SAndroid Build Coastguard Worker 
339*e01b6f76SAndroid Build Coastguard Worker         streams[i]->setUsage(usage);
340*e01b6f76SAndroid Build Coastguard Worker         streams[i]->setMaxBuffers(1);
341*e01b6f76SAndroid Build Coastguard Worker     }
342*e01b6f76SAndroid Build Coastguard Worker }
343*e01b6f76SAndroid Build Coastguard Worker 
isValidTemplateType(int type)344*e01b6f76SAndroid Build Coastguard Worker bool Camera::isValidTemplateType(int type) {
345*e01b6f76SAndroid Build Coastguard Worker     return type >= 1 && type < CAMERA3_TEMPLATE_COUNT;
346*e01b6f76SAndroid Build Coastguard Worker }
347*e01b6f76SAndroid Build Coastguard Worker 
constructDefaultRequestSettings(int type)348*e01b6f76SAndroid Build Coastguard Worker const camera_metadata_t* Camera::constructDefaultRequestSettings(int type) {
349*e01b6f76SAndroid Build Coastguard Worker     ALOGV("%s:%d: type=%d", __func__, mId, type);
350*e01b6f76SAndroid Build Coastguard Worker     android::Mutex::Autolock al(mDeviceLock);
351*e01b6f76SAndroid Build Coastguard Worker 
352*e01b6f76SAndroid Build Coastguard Worker     if (!isValidTemplateType(type)) {
353*e01b6f76SAndroid Build Coastguard Worker         ALOGE("%s:%d: Invalid template request type: %d", __func__, mId, type);
354*e01b6f76SAndroid Build Coastguard Worker         return NULL;
355*e01b6f76SAndroid Build Coastguard Worker     }
356*e01b6f76SAndroid Build Coastguard Worker 
357*e01b6f76SAndroid Build Coastguard Worker     // DO NOT try to initialize the device here, it will be guaranteed deadlock.
358*e01b6f76SAndroid Build Coastguard Worker     if (!mIsInitialized) {
359*e01b6f76SAndroid Build Coastguard Worker         ALOGE("Device is not initialized yet");
360*e01b6f76SAndroid Build Coastguard Worker         return NULL;
361*e01b6f76SAndroid Build Coastguard Worker     }
362*e01b6f76SAndroid Build Coastguard Worker 
363*e01b6f76SAndroid Build Coastguard Worker     return mTemplates[type];
364*e01b6f76SAndroid Build Coastguard Worker }
365*e01b6f76SAndroid Build Coastguard Worker 
366*e01b6f76SAndroid Build Coastguard Worker // This implementation is a copy-paste, probably we should override (or move) this to
367*e01b6f76SAndroid Build Coastguard Worker // device specific class.
processCaptureRequest(camera3_capture_request_t * request)368*e01b6f76SAndroid Build Coastguard Worker int Camera::processCaptureRequest(camera3_capture_request_t *request) {
369*e01b6f76SAndroid Build Coastguard Worker     camera3_capture_result result;
370*e01b6f76SAndroid Build Coastguard Worker     ALOGV("%s:%d: request=%p", __func__, mId, request);
371*e01b6f76SAndroid Build Coastguard Worker     ATRACE_CALL();
372*e01b6f76SAndroid Build Coastguard Worker     android::Mutex::Autolock al(mDeviceLock);
373*e01b6f76SAndroid Build Coastguard Worker 
374*e01b6f76SAndroid Build Coastguard Worker     if (request == NULL) {
375*e01b6f76SAndroid Build Coastguard Worker         ALOGE("%s:%d: NULL request recieved", __func__, mId);
376*e01b6f76SAndroid Build Coastguard Worker         return -EINVAL;
377*e01b6f76SAndroid Build Coastguard Worker     }
378*e01b6f76SAndroid Build Coastguard Worker 
379*e01b6f76SAndroid Build Coastguard Worker     ALOGV("%s:%d: Request Frame:%d Settings:%p", __func__, mId,
380*e01b6f76SAndroid Build Coastguard Worker             request->frame_number, request->settings);
381*e01b6f76SAndroid Build Coastguard Worker 
382*e01b6f76SAndroid Build Coastguard Worker     // NULL indicates use last settings
383*e01b6f76SAndroid Build Coastguard Worker     if (request->settings == NULL) {
384*e01b6f76SAndroid Build Coastguard Worker         if (mSettings == NULL) {
385*e01b6f76SAndroid Build Coastguard Worker             ALOGE("%s:%d: NULL settings without previous set Frame:%d Req:%p",
386*e01b6f76SAndroid Build Coastguard Worker                     __func__, mId, request->frame_number, request);
387*e01b6f76SAndroid Build Coastguard Worker             return -EINVAL;
388*e01b6f76SAndroid Build Coastguard Worker         }
389*e01b6f76SAndroid Build Coastguard Worker     } else {
390*e01b6f76SAndroid Build Coastguard Worker         updateSettingsLocked(request->settings);
391*e01b6f76SAndroid Build Coastguard Worker     }
392*e01b6f76SAndroid Build Coastguard Worker 
393*e01b6f76SAndroid Build Coastguard Worker     if (request->input_buffer != NULL) {
394*e01b6f76SAndroid Build Coastguard Worker         ALOGV("%s:%d: Reprocessing input buffer is not supported yet", __func__, mId);
395*e01b6f76SAndroid Build Coastguard Worker         return -EINVAL;
396*e01b6f76SAndroid Build Coastguard Worker     } else {
397*e01b6f76SAndroid Build Coastguard Worker         ALOGV("%s:%d: Capturing new frame.", __func__, mId);
398*e01b6f76SAndroid Build Coastguard Worker 
399*e01b6f76SAndroid Build Coastguard Worker         if (!isValidCaptureSettings(request->settings)) {
400*e01b6f76SAndroid Build Coastguard Worker             ALOGE("%s:%d: Invalid settings for capture request: %p",
401*e01b6f76SAndroid Build Coastguard Worker                     __func__, mId, request->settings);
402*e01b6f76SAndroid Build Coastguard Worker             return -EINVAL;
403*e01b6f76SAndroid Build Coastguard Worker         }
404*e01b6f76SAndroid Build Coastguard Worker     }
405*e01b6f76SAndroid Build Coastguard Worker 
406*e01b6f76SAndroid Build Coastguard Worker     if (request->num_output_buffers <= 0) {
407*e01b6f76SAndroid Build Coastguard Worker         ALOGE("%s:%d: Invalid number of output buffers: %d", __func__, mId,
408*e01b6f76SAndroid Build Coastguard Worker                 request->num_output_buffers);
409*e01b6f76SAndroid Build Coastguard Worker         return -EINVAL;
410*e01b6f76SAndroid Build Coastguard Worker     }
411*e01b6f76SAndroid Build Coastguard Worker     result.num_output_buffers = request->num_output_buffers;
412*e01b6f76SAndroid Build Coastguard Worker     result.output_buffers = new camera3_stream_buffer_t[result.num_output_buffers];
413*e01b6f76SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < request->num_output_buffers; i++) {
414*e01b6f76SAndroid Build Coastguard Worker         int res = processCaptureBuffer(&request->output_buffers[i],
415*e01b6f76SAndroid Build Coastguard Worker                 const_cast<camera3_stream_buffer_t*>(&result.output_buffers[i]));
416*e01b6f76SAndroid Build Coastguard Worker         if (res) {
417*e01b6f76SAndroid Build Coastguard Worker             delete [] result.output_buffers;
418*e01b6f76SAndroid Build Coastguard Worker             // TODO: this should probably be a total device failure; transient for now
419*e01b6f76SAndroid Build Coastguard Worker             return -EINVAL;
420*e01b6f76SAndroid Build Coastguard Worker         }
421*e01b6f76SAndroid Build Coastguard Worker     }
422*e01b6f76SAndroid Build Coastguard Worker 
423*e01b6f76SAndroid Build Coastguard Worker     result.frame_number = request->frame_number;
424*e01b6f76SAndroid Build Coastguard Worker     // TODO: return actual captured/reprocessed settings
425*e01b6f76SAndroid Build Coastguard Worker     result.result = request->settings;
426*e01b6f76SAndroid Build Coastguard Worker     // TODO: asynchronously return results
427*e01b6f76SAndroid Build Coastguard Worker     notifyShutter(request->frame_number, 0);
428*e01b6f76SAndroid Build Coastguard Worker     mCallbackOps->process_capture_result(mCallbackOps, &result);
429*e01b6f76SAndroid Build Coastguard Worker 
430*e01b6f76SAndroid Build Coastguard Worker     // Free up capture result related resources, HAL owns the capture result, and it
431*e01b6f76SAndroid Build Coastguard Worker     // is only valid during the process_capture_result call.
432*e01b6f76SAndroid Build Coastguard Worker     delete[] result.output_buffers;
433*e01b6f76SAndroid Build Coastguard Worker 
434*e01b6f76SAndroid Build Coastguard Worker     return 0;
435*e01b6f76SAndroid Build Coastguard Worker }
436*e01b6f76SAndroid Build Coastguard Worker 
flush()437*e01b6f76SAndroid Build Coastguard Worker int Camera::flush() {
438*e01b6f76SAndroid Build Coastguard Worker     int res;
439*e01b6f76SAndroid Build Coastguard Worker 
440*e01b6f76SAndroid Build Coastguard Worker     ALOGV("%s:%d: flush device", __func__, mId);
441*e01b6f76SAndroid Build Coastguard Worker     // per-device specific flush
442*e01b6f76SAndroid Build Coastguard Worker     res = flushDevice();
443*e01b6f76SAndroid Build Coastguard Worker     if (res != 0) {
444*e01b6f76SAndroid Build Coastguard Worker         ALOGE("%s:%d: Failed to flush device!", __func__, mId);
445*e01b6f76SAndroid Build Coastguard Worker         return res;
446*e01b6f76SAndroid Build Coastguard Worker     }
447*e01b6f76SAndroid Build Coastguard Worker     return 0;
448*e01b6f76SAndroid Build Coastguard Worker }
449*e01b6f76SAndroid Build Coastguard Worker 
updateSettingsLocked(const camera_metadata_t * new_settings)450*e01b6f76SAndroid Build Coastguard Worker void Camera::updateSettingsLocked(const camera_metadata_t *new_settings) {
451*e01b6f76SAndroid Build Coastguard Worker     if (mSettings != NULL) {
452*e01b6f76SAndroid Build Coastguard Worker         free_camera_metadata(mSettings);
453*e01b6f76SAndroid Build Coastguard Worker         mSettings = NULL;
454*e01b6f76SAndroid Build Coastguard Worker     }
455*e01b6f76SAndroid Build Coastguard Worker 
456*e01b6f76SAndroid Build Coastguard Worker     if (new_settings != NULL)
457*e01b6f76SAndroid Build Coastguard Worker         mSettings = clone_camera_metadata(new_settings);
458*e01b6f76SAndroid Build Coastguard Worker }
459*e01b6f76SAndroid Build Coastguard Worker 
notifyShutter(uint32_t frame_number,uint64_t timestamp)460*e01b6f76SAndroid Build Coastguard Worker void Camera::notifyShutter(uint32_t frame_number, uint64_t timestamp) {
461*e01b6f76SAndroid Build Coastguard Worker     int res;
462*e01b6f76SAndroid Build Coastguard Worker     struct timespec ts;
463*e01b6f76SAndroid Build Coastguard Worker 
464*e01b6f76SAndroid Build Coastguard Worker     // If timestamp is 0, get timestamp from right now instead
465*e01b6f76SAndroid Build Coastguard Worker     if (timestamp == 0) {
466*e01b6f76SAndroid Build Coastguard Worker         ALOGW("%s:%d: No timestamp provided, using CLOCK_BOOTTIME",
467*e01b6f76SAndroid Build Coastguard Worker                 __func__, mId);
468*e01b6f76SAndroid Build Coastguard Worker         res = clock_gettime(CLOCK_BOOTTIME, &ts);
469*e01b6f76SAndroid Build Coastguard Worker         if (res == 0) {
470*e01b6f76SAndroid Build Coastguard Worker             timestamp = ts.tv_sec * 1000000000ULL + ts.tv_nsec;
471*e01b6f76SAndroid Build Coastguard Worker         } else {
472*e01b6f76SAndroid Build Coastguard Worker             ALOGE("%s:%d: No timestamp and failed to get CLOCK_BOOTTIME %s(%d)",
473*e01b6f76SAndroid Build Coastguard Worker                     __func__, mId, strerror(errno), errno);
474*e01b6f76SAndroid Build Coastguard Worker         }
475*e01b6f76SAndroid Build Coastguard Worker     }
476*e01b6f76SAndroid Build Coastguard Worker     camera3_notify_msg_t m;
477*e01b6f76SAndroid Build Coastguard Worker     memset(&m, 0, sizeof(m));
478*e01b6f76SAndroid Build Coastguard Worker     m.type = CAMERA3_MSG_SHUTTER;
479*e01b6f76SAndroid Build Coastguard Worker     m.message.shutter.frame_number = frame_number;
480*e01b6f76SAndroid Build Coastguard Worker     m.message.shutter.timestamp = timestamp;
481*e01b6f76SAndroid Build Coastguard Worker     mCallbackOps->notify(mCallbackOps, &m);
482*e01b6f76SAndroid Build Coastguard Worker }
483*e01b6f76SAndroid Build Coastguard Worker 
dump(int fd)484*e01b6f76SAndroid Build Coastguard Worker void Camera::dump(int fd) {
485*e01b6f76SAndroid Build Coastguard Worker     ALOGV("%s:%d: Dumping to fd %d", __func__, mId, fd);
486*e01b6f76SAndroid Build Coastguard Worker     ATRACE_CALL();
487*e01b6f76SAndroid Build Coastguard Worker     android::Mutex::Autolock al(mDeviceLock);
488*e01b6f76SAndroid Build Coastguard Worker 
489*e01b6f76SAndroid Build Coastguard Worker     dprintf(fd, "Camera ID: %d (Busy: %d)\n", mId, mBusy);
490*e01b6f76SAndroid Build Coastguard Worker 
491*e01b6f76SAndroid Build Coastguard Worker     // TODO: dump all settings
492*e01b6f76SAndroid Build Coastguard Worker     dprintf(fd, "Most Recent Settings: (%p)\n", mSettings);
493*e01b6f76SAndroid Build Coastguard Worker 
494*e01b6f76SAndroid Build Coastguard Worker     dprintf(fd, "Number of streams: %zu\n", mStreams.size());
495*e01b6f76SAndroid Build Coastguard Worker     for (size_t i = 0; i < mStreams.size(); i++) {
496*e01b6f76SAndroid Build Coastguard Worker         dprintf(fd, "Stream %zu/%zu:\n", i, mStreams.size());
497*e01b6f76SAndroid Build Coastguard Worker         mStreams[i]->dump(fd);
498*e01b6f76SAndroid Build Coastguard Worker     }
499*e01b6f76SAndroid Build Coastguard Worker }
500*e01b6f76SAndroid Build Coastguard Worker 
templateToString(int type)501*e01b6f76SAndroid Build Coastguard Worker const char* Camera::templateToString(int type) {
502*e01b6f76SAndroid Build Coastguard Worker     switch (type) {
503*e01b6f76SAndroid Build Coastguard Worker     case CAMERA3_TEMPLATE_PREVIEW:
504*e01b6f76SAndroid Build Coastguard Worker         return "CAMERA3_TEMPLATE_PREVIEW";
505*e01b6f76SAndroid Build Coastguard Worker     case CAMERA3_TEMPLATE_STILL_CAPTURE:
506*e01b6f76SAndroid Build Coastguard Worker         return "CAMERA3_TEMPLATE_STILL_CAPTURE";
507*e01b6f76SAndroid Build Coastguard Worker     case CAMERA3_TEMPLATE_VIDEO_RECORD:
508*e01b6f76SAndroid Build Coastguard Worker         return "CAMERA3_TEMPLATE_VIDEO_RECORD";
509*e01b6f76SAndroid Build Coastguard Worker     case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
510*e01b6f76SAndroid Build Coastguard Worker         return "CAMERA3_TEMPLATE_VIDEO_SNAPSHOT";
511*e01b6f76SAndroid Build Coastguard Worker     case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
512*e01b6f76SAndroid Build Coastguard Worker         return "CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG";
513*e01b6f76SAndroid Build Coastguard Worker     case CAMERA3_TEMPLATE_MANUAL:
514*e01b6f76SAndroid Build Coastguard Worker         return "CAMERA3_TEMPLATE_MANUAL";
515*e01b6f76SAndroid Build Coastguard Worker     }
516*e01b6f76SAndroid Build Coastguard Worker 
517*e01b6f76SAndroid Build Coastguard Worker     return "Invalid template type!";
518*e01b6f76SAndroid Build Coastguard Worker }
519*e01b6f76SAndroid Build Coastguard Worker 
setTemplate(int type,camera_metadata_t * settings)520*e01b6f76SAndroid Build Coastguard Worker int Camera::setTemplate(int type, camera_metadata_t *settings) {
521*e01b6f76SAndroid Build Coastguard Worker     android::Mutex::Autolock al(mDeviceLock);
522*e01b6f76SAndroid Build Coastguard Worker 
523*e01b6f76SAndroid Build Coastguard Worker     if (!isValidTemplateType(type)) {
524*e01b6f76SAndroid Build Coastguard Worker         ALOGE("%s:%d: Invalid template request type: %d", __func__, mId, type);
525*e01b6f76SAndroid Build Coastguard Worker         return -EINVAL;
526*e01b6f76SAndroid Build Coastguard Worker     }
527*e01b6f76SAndroid Build Coastguard Worker 
528*e01b6f76SAndroid Build Coastguard Worker     if (mTemplates[type] != NULL) {
529*e01b6f76SAndroid Build Coastguard Worker         ALOGE("%s:%d: Setting already constructed template type %s(%d)",
530*e01b6f76SAndroid Build Coastguard Worker                 __func__, mId, templateToString(type), type);
531*e01b6f76SAndroid Build Coastguard Worker         return -EINVAL;
532*e01b6f76SAndroid Build Coastguard Worker     }
533*e01b6f76SAndroid Build Coastguard Worker 
534*e01b6f76SAndroid Build Coastguard Worker     // Make a durable copy of the underlying metadata
535*e01b6f76SAndroid Build Coastguard Worker     mTemplates[type] = clone_camera_metadata(settings);
536*e01b6f76SAndroid Build Coastguard Worker     if (mTemplates[type] == NULL) {
537*e01b6f76SAndroid Build Coastguard Worker         ALOGE("%s:%d: Failed to clone metadata %p for template type %s(%d)",
538*e01b6f76SAndroid Build Coastguard Worker                 __func__, mId, settings, templateToString(type), type);
539*e01b6f76SAndroid Build Coastguard Worker         return -EINVAL;
540*e01b6f76SAndroid Build Coastguard Worker     }
541*e01b6f76SAndroid Build Coastguard Worker     return 0;
542*e01b6f76SAndroid Build Coastguard Worker }
543*e01b6f76SAndroid Build Coastguard Worker 
544*e01b6f76SAndroid Build Coastguard Worker } // namespace usb_camera_hal
545