blob: 4d276bee7268b3092503333c31057a11afabb512 [file] [log] [blame]
Igor Murashkine7ee7632013-06-11 18:10:18 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "CameraDeviceClient"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
Jianing Weicb0652e2014-03-12 18:29:36 -070019//#define LOG_NDEBUG 0
Igor Murashkine7ee7632013-06-11 18:10:18 -070020
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070021#include <cutils/properties.h>
Igor Murashkine7ee7632013-06-11 18:10:18 -070022#include <utils/Log.h>
23#include <utils/Trace.h>
Igor Murashkine7ee7632013-06-11 18:10:18 -070024#include <gui/Surface.h>
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070025#include <camera/camera2/CaptureRequest.h>
Ruben Brunk5698d442014-06-18 10:39:40 -070026#include <camera/CameraUtils.h>
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070027
28#include "common/CameraDeviceBase.h"
29#include "api2/CameraDeviceClient.h"
30
31
Igor Murashkine7ee7632013-06-11 18:10:18 -070032
33namespace android {
34using namespace camera2;
35
36CameraDeviceClientBase::CameraDeviceClientBase(
37 const sp<CameraService>& cameraService,
38 const sp<ICameraDeviceCallbacks>& remoteCallback,
39 const String16& clientPackageName,
40 int cameraId,
41 int cameraFacing,
42 int clientPid,
43 uid_t clientUid,
44 int servicePid) :
Eino-Ville Talvalae992e752014-11-07 16:17:48 -080045 BasicClient(cameraService,
Marco Nelissenf8880202014-11-14 07:58:25 -080046 IInterface::asBinder(remoteCallback),
Eino-Ville Talvalae992e752014-11-07 16:17:48 -080047 clientPackageName,
48 cameraId,
49 cameraFacing,
50 clientPid,
51 clientUid,
52 servicePid),
Igor Murashkine7ee7632013-06-11 18:10:18 -070053 mRemoteCallback(remoteCallback) {
54}
Igor Murashkine7ee7632013-06-11 18:10:18 -070055
56// Interface used by CameraService
57
58CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
59 const sp<ICameraDeviceCallbacks>& remoteCallback,
60 const String16& clientPackageName,
61 int cameraId,
62 int cameraFacing,
63 int clientPid,
64 uid_t clientUid,
65 int servicePid) :
66 Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
67 cameraId, cameraFacing, clientPid, clientUid, servicePid),
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -070068 mInputStream(),
Igor Murashkine7ee7632013-06-11 18:10:18 -070069 mRequestIdCounter(0) {
70
71 ATRACE_CALL();
72 ALOGI("CameraDeviceClient %d: Opened", cameraId);
73}
74
Yin-Chia Yehe074a932015-01-30 10:29:02 -080075status_t CameraDeviceClient::initialize(CameraModule *module)
Igor Murashkine7ee7632013-06-11 18:10:18 -070076{
77 ATRACE_CALL();
78 status_t res;
79
80 res = Camera2ClientBase::initialize(module);
81 if (res != OK) {
82 return res;
83 }
84
85 String8 threadName;
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070086 mFrameProcessor = new FrameProcessorBase(mDevice);
Igor Murashkine7ee7632013-06-11 18:10:18 -070087 threadName = String8::format("CDU-%d-FrameProc", mCameraId);
88 mFrameProcessor->run(threadName.string());
89
90 mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
91 FRAME_PROCESSOR_LISTENER_MAX_ID,
Eino-Ville Talvala184dfe42013-11-07 15:13:16 -080092 /*listener*/this,
Zhijun He25a0aef2014-06-25 11:40:02 -070093 /*sendPartials*/true);
Igor Murashkine7ee7632013-06-11 18:10:18 -070094
95 return OK;
96}
97
98CameraDeviceClient::~CameraDeviceClient() {
99}
100
101status_t CameraDeviceClient::submitRequest(sp<CaptureRequest> request,
Jianing Weicb0652e2014-03-12 18:29:36 -0700102 bool streaming,
103 /*out*/
104 int64_t* lastFrameNumber) {
105 List<sp<CaptureRequest> > requestList;
106 requestList.push_back(request);
107 return submitRequestList(requestList, streaming, lastFrameNumber);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700108}
109
Jianing Wei90e59c92014-03-12 18:29:36 -0700110status_t CameraDeviceClient::submitRequestList(List<sp<CaptureRequest> > requests,
Jianing Weicb0652e2014-03-12 18:29:36 -0700111 bool streaming, int64_t* lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700112 ATRACE_CALL();
Mark Salyzyn50468412014-06-18 16:33:43 -0700113 ALOGV("%s-start of function. Request list size %zu", __FUNCTION__, requests.size());
Jianing Wei90e59c92014-03-12 18:29:36 -0700114
115 status_t res;
116 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
117
118 Mutex::Autolock icl(mBinderSerializationLock);
119
120 if (!mDevice.get()) return DEAD_OBJECT;
121
122 if (requests.empty()) {
123 ALOGE("%s: Camera %d: Sent null request. Rejecting request.",
124 __FUNCTION__, mCameraId);
125 return BAD_VALUE;
126 }
127
128 List<const CameraMetadata> metadataRequestList;
129 int32_t requestId = mRequestIdCounter;
130 uint32_t loopCounter = 0;
131
132 for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end(); ++it) {
133 sp<CaptureRequest> request = *it;
134 if (request == 0) {
135 ALOGE("%s: Camera %d: Sent null request.",
136 __FUNCTION__, mCameraId);
137 return BAD_VALUE;
Chien-Yu Chened0412e2015-04-27 15:04:22 -0700138 } else if (request->mIsReprocess) {
139 if (!mInputStream.configured) {
140 ALOGE("%s: Camera %d: no input stream is configured.", __FUNCTION__, mCameraId);
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700141 return BAD_VALUE;
Chien-Yu Chened0412e2015-04-27 15:04:22 -0700142 } else if (streaming) {
143 ALOGE("%s: Camera %d: streaming reprocess requests not supported.", __FUNCTION__,
144 mCameraId);
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700145 return BAD_VALUE;
146 }
Jianing Wei90e59c92014-03-12 18:29:36 -0700147 }
148
149 CameraMetadata metadata(request->mMetadata);
150 if (metadata.isEmpty()) {
151 ALOGE("%s: Camera %d: Sent empty metadata packet. Rejecting request.",
152 __FUNCTION__, mCameraId);
153 return BAD_VALUE;
154 } else if (request->mSurfaceList.isEmpty()) {
155 ALOGE("%s: Camera %d: Requests must have at least one surface target. "
156 "Rejecting request.", __FUNCTION__, mCameraId);
157 return BAD_VALUE;
158 }
159
160 if (!enforceRequestPermissions(metadata)) {
161 // Callee logs
162 return PERMISSION_DENIED;
163 }
164
165 /**
166 * Write in the output stream IDs which we calculate from
167 * the capture request's list of surface targets
168 */
169 Vector<int32_t> outputStreamIds;
170 outputStreamIds.setCapacity(request->mSurfaceList.size());
Jianing Weicb0652e2014-03-12 18:29:36 -0700171 for (size_t i = 0; i < request->mSurfaceList.size(); ++i) {
172 sp<Surface> surface = request->mSurfaceList[i];
Jianing Wei90e59c92014-03-12 18:29:36 -0700173 if (surface == 0) continue;
174
175 sp<IGraphicBufferProducer> gbp = surface->getIGraphicBufferProducer();
Marco Nelissenf8880202014-11-14 07:58:25 -0800176 int idx = mStreamMap.indexOfKey(IInterface::asBinder(gbp));
Jianing Wei90e59c92014-03-12 18:29:36 -0700177
178 // Trying to submit request with surface that wasn't created
179 if (idx == NAME_NOT_FOUND) {
180 ALOGE("%s: Camera %d: Tried to submit a request with a surface that"
181 " we have not called createStream on",
182 __FUNCTION__, mCameraId);
183 return BAD_VALUE;
184 }
185
186 int streamId = mStreamMap.valueAt(idx);
187 outputStreamIds.push_back(streamId);
188 ALOGV("%s: Camera %d: Appending output stream %d to request",
189 __FUNCTION__, mCameraId, streamId);
190 }
191
192 metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS, &outputStreamIds[0],
193 outputStreamIds.size());
194
Chien-Yu Chened0412e2015-04-27 15:04:22 -0700195 if (request->mIsReprocess) {
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700196 metadata.update(ANDROID_REQUEST_INPUT_STREAMS, &mInputStream.id, 1);
197 }
198
Jianing Wei90e59c92014-03-12 18:29:36 -0700199 metadata.update(ANDROID_REQUEST_ID, &requestId, /*size*/1);
200 loopCounter++; // loopCounter starts from 1
Mark Salyzyn50468412014-06-18 16:33:43 -0700201 ALOGV("%s: Camera %d: Creating request with ID %d (%d of %zu)",
Jianing Wei90e59c92014-03-12 18:29:36 -0700202 __FUNCTION__, mCameraId, requestId, loopCounter, requests.size());
203
204 metadataRequestList.push_back(metadata);
205 }
206 mRequestIdCounter++;
207
208 if (streaming) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700209 res = mDevice->setStreamingRequestList(metadataRequestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -0700210 if (res != OK) {
211 ALOGE("%s: Camera %d: Got error %d after trying to set streaming "
212 "request", __FUNCTION__, mCameraId, res);
213 } else {
214 mStreamingRequestList.push_back(requestId);
215 }
216 } else {
Jianing Weicb0652e2014-03-12 18:29:36 -0700217 res = mDevice->captureList(metadataRequestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -0700218 if (res != OK) {
219 ALOGE("%s: Camera %d: Got error %d after trying to set capture",
220 __FUNCTION__, mCameraId, res);
221 }
Jianing Weicb0652e2014-03-12 18:29:36 -0700222 ALOGV("%s: requestId = %d ", __FUNCTION__, requestId);
Jianing Wei90e59c92014-03-12 18:29:36 -0700223 }
224
225 ALOGV("%s: Camera %d: End of function", __FUNCTION__, mCameraId);
226 if (res == OK) {
227 return requestId;
228 }
229
230 return res;
231}
232
Jianing Weicb0652e2014-03-12 18:29:36 -0700233status_t CameraDeviceClient::cancelRequest(int requestId, int64_t* lastFrameNumber) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700234 ATRACE_CALL();
235 ALOGV("%s, requestId = %d", __FUNCTION__, requestId);
236
237 status_t res;
238
239 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
240
241 Mutex::Autolock icl(mBinderSerializationLock);
242
243 if (!mDevice.get()) return DEAD_OBJECT;
244
245 Vector<int>::iterator it, end;
246 for (it = mStreamingRequestList.begin(), end = mStreamingRequestList.end();
247 it != end; ++it) {
248 if (*it == requestId) {
249 break;
250 }
251 }
252
253 if (it == end) {
254 ALOGE("%s: Camera%d: Did not find request id %d in list of streaming "
255 "requests", __FUNCTION__, mCameraId, requestId);
256 return BAD_VALUE;
257 }
258
Jianing Weicb0652e2014-03-12 18:29:36 -0700259 res = mDevice->clearStreamingRequest(lastFrameNumber);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700260
261 if (res == OK) {
262 ALOGV("%s: Camera %d: Successfully cleared streaming request",
263 __FUNCTION__, mCameraId);
264 mStreamingRequestList.erase(it);
265 }
266
267 return res;
268}
269
Ruben Brunkb2119af2014-05-09 19:57:56 -0700270status_t CameraDeviceClient::beginConfigure() {
271 // TODO: Implement this.
Zhijun He1fa89992015-06-01 15:44:31 -0700272 ALOGV("%s: Not implemented yet.", __FUNCTION__);
Ruben Brunkb2119af2014-05-09 19:57:56 -0700273 return OK;
274}
275
Zhijun He1fa89992015-06-01 15:44:31 -0700276status_t CameraDeviceClient::endConfigure(bool isConstrainedHighSpeed) {
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700277 ALOGV("%s: ending configure (%d input stream, %zu output streams)",
278 __FUNCTION__, mInputStream.configured ? 1 : 0, mStreamMap.size());
Igor Murashkine2d167e2014-08-19 16:19:59 -0700279
Zhijun He1fa89992015-06-01 15:44:31 -0700280 // Sanitize the high speed session against necessary capability bit.
281 if (isConstrainedHighSpeed) {
282 CameraMetadata staticInfo = mDevice->info();
283 camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
284 bool isConstrainedHighSpeedSupported = false;
285 for(size_t i = 0; i < entry.count; ++i) {
286 uint8_t capability = entry.data.u8[i];
287 if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO) {
288 isConstrainedHighSpeedSupported = true;
289 break;
290 }
291 }
292 if (!isConstrainedHighSpeedSupported) {
293 ALOGE("%s: Camera %d: Try to create a constrained high speed configuration on a device"
294 " that doesn't support it.",
295 __FUNCTION__, mCameraId);
296 return INVALID_OPERATION;
297 }
298 }
299
Igor Murashkine2d167e2014-08-19 16:19:59 -0700300 status_t res;
301 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
302
303 Mutex::Autolock icl(mBinderSerializationLock);
304
305 if (!mDevice.get()) return DEAD_OBJECT;
306
Zhijun He1fa89992015-06-01 15:44:31 -0700307 return mDevice->configureStreams(isConstrainedHighSpeed);
Ruben Brunkb2119af2014-05-09 19:57:56 -0700308}
309
Igor Murashkine7ee7632013-06-11 18:10:18 -0700310status_t CameraDeviceClient::deleteStream(int streamId) {
311 ATRACE_CALL();
312 ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);
313
314 status_t res;
315 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
316
317 Mutex::Autolock icl(mBinderSerializationLock);
318
319 if (!mDevice.get()) return DEAD_OBJECT;
320
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700321 bool isInput = false;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700322 ssize_t index = NAME_NOT_FOUND;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700323
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700324 if (mInputStream.configured && mInputStream.id == streamId) {
325 isInput = true;
326 } else {
327 // Guard against trying to delete non-created streams
328 for (size_t i = 0; i < mStreamMap.size(); ++i) {
329 if (streamId == mStreamMap.valueAt(i)) {
330 index = i;
331 break;
332 }
333 }
334
335 if (index == NAME_NOT_FOUND) {
336 ALOGW("%s: Camera %d: Invalid stream ID (%d) specified, no stream "
337 "created yet", __FUNCTION__, mCameraId, streamId);
338 return BAD_VALUE;
339 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700340 }
341
342 // Also returns BAD_VALUE if stream ID was not valid
343 res = mDevice->deleteStream(streamId);
344
345 if (res == BAD_VALUE) {
346 ALOGE("%s: Camera %d: Unexpected BAD_VALUE when deleting stream, but we"
347 " already checked and the stream ID (%d) should be valid.",
348 __FUNCTION__, mCameraId, streamId);
349 } else if (res == OK) {
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700350 if (isInput) {
351 mInputStream.configured = false;
352 } else {
353 mStreamMap.removeItemsAt(index);
354 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700355 }
356
357 return res;
358}
359
Yin-Chia Yehb97babb2015-03-12 13:42:44 -0700360status_t CameraDeviceClient::createStream(const OutputConfiguration &outputConfiguration)
Igor Murashkine7ee7632013-06-11 18:10:18 -0700361{
362 ATRACE_CALL();
Igor Murashkine7ee7632013-06-11 18:10:18 -0700363
364 status_t res;
365 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
366
367 Mutex::Autolock icl(mBinderSerializationLock);
368
Yin-Chia Yehb97babb2015-03-12 13:42:44 -0700369
370 sp<IGraphicBufferProducer> bufferProducer = outputConfiguration.getGraphicBufferProducer();
Yin-Chia Yeh89f14da2014-06-10 16:05:44 -0700371 if (bufferProducer == NULL) {
372 ALOGE("%s: bufferProducer must not be null", __FUNCTION__);
373 return BAD_VALUE;
374 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700375 if (!mDevice.get()) return DEAD_OBJECT;
376
377 // Don't create multiple streams for the same target surface
378 {
Marco Nelissenf8880202014-11-14 07:58:25 -0800379 ssize_t index = mStreamMap.indexOfKey(IInterface::asBinder(bufferProducer));
Igor Murashkine7ee7632013-06-11 18:10:18 -0700380 if (index != NAME_NOT_FOUND) {
381 ALOGW("%s: Camera %d: Buffer producer already has a stream for it "
Colin Crosse5729fa2014-03-21 15:04:25 -0700382 "(ID %zd)",
Igor Murashkine7ee7632013-06-11 18:10:18 -0700383 __FUNCTION__, mCameraId, index);
384 return ALREADY_EXISTS;
385 }
386 }
387
Eino-Ville Talvala1da3b602013-09-26 15:28:55 -0700388 // HACK b/10949105
389 // Query consumer usage bits to set async operation mode for
390 // GLConsumer using controlledByApp parameter.
391 bool useAsync = false;
392 int32_t consumerUsage;
393 if ((res = bufferProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS,
394 &consumerUsage)) != OK) {
395 ALOGE("%s: Camera %d: Failed to query consumer usage", __FUNCTION__,
396 mCameraId);
397 return res;
398 }
399 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
400 ALOGW("%s: Camera %d: Forcing asynchronous mode for stream",
401 __FUNCTION__, mCameraId);
402 useAsync = true;
403 }
404
Ruben Brunkbba75572014-11-20 17:29:50 -0800405 int32_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
406 GRALLOC_USAGE_RENDERSCRIPT;
407 int32_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
408 GraphicBuffer::USAGE_HW_TEXTURE |
409 GraphicBuffer::USAGE_HW_COMPOSER;
410 bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
411 (consumerUsage & allowedFlags) != 0;
412
Marco Nelissenf8880202014-11-14 07:58:25 -0800413 sp<IBinder> binder = IInterface::asBinder(bufferProducer);
Eino-Ville Talvalae992e752014-11-07 16:17:48 -0800414 sp<ANativeWindow> anw = new Surface(bufferProducer, useAsync);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700415
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -0800416 int width, height, format;
417 android_dataspace dataSpace;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700418
419 if ((res = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, &width)) != OK) {
420 ALOGE("%s: Camera %d: Failed to query Surface width", __FUNCTION__,
421 mCameraId);
422 return res;
423 }
424 if ((res = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, &height)) != OK) {
425 ALOGE("%s: Camera %d: Failed to query Surface height", __FUNCTION__,
426 mCameraId);
427 return res;
428 }
429 if ((res = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &format)) != OK) {
430 ALOGE("%s: Camera %d: Failed to query Surface format", __FUNCTION__,
431 mCameraId);
432 return res;
433 }
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -0800434 if ((res = anw->query(anw.get(), NATIVE_WINDOW_DEFAULT_DATASPACE,
435 reinterpret_cast<int*>(&dataSpace))) != OK) {
436 ALOGE("%s: Camera %d: Failed to query Surface dataSpace", __FUNCTION__,
437 mCameraId);
438 return res;
439 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700440
441 // FIXME: remove this override since the default format should be
442 // IMPLEMENTATION_DEFINED. b/9487482
Igor Murashkin15811012013-07-29 12:25:59 -0700443 if (format >= HAL_PIXEL_FORMAT_RGBA_8888 &&
444 format <= HAL_PIXEL_FORMAT_BGRA_8888) {
Ruben Brunkbba75572014-11-20 17:29:50 -0800445 ALOGW("%s: Camera %d: Overriding format %#x to IMPLEMENTATION_DEFINED",
Igor Murashkine7ee7632013-06-11 18:10:18 -0700446 __FUNCTION__, mCameraId, format);
447 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
448 }
449
Ruben Brunkbba75572014-11-20 17:29:50 -0800450 // Round dimensions to the nearest dimensions available for this format
451 if (flexibleConsumer && !CameraDeviceClient::roundBufferDimensionNearest(width, height,
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -0800452 format, dataSpace, mDevice->info(), /*out*/&width, /*out*/&height)) {
Ruben Brunkbba75572014-11-20 17:29:50 -0800453 ALOGE("%s: No stream configurations with the format %#x defined, failed to create stream.",
454 __FUNCTION__, format);
455 return BAD_VALUE;
456 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700457
458 int streamId = -1;
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -0800459 res = mDevice->createStream(anw, width, height, format, dataSpace,
Yin-Chia Yehb97babb2015-03-12 13:42:44 -0700460 static_cast<camera3_stream_rotation_t>
461 (outputConfiguration.getRotation()),
462 &streamId);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700463
464 if (res == OK) {
Eino-Ville Talvalae992e752014-11-07 16:17:48 -0800465 mStreamMap.add(binder, streamId);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700466
467 ALOGV("%s: Camera %d: Successfully created a new stream ID %d",
468 __FUNCTION__, mCameraId, streamId);
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700469
470 /**
471 * Set the stream transform flags to automatically
472 * rotate the camera stream for preview use cases.
473 */
474 int32_t transform = 0;
475 res = getRotationTransformLocked(&transform);
476
477 if (res != OK) {
478 // Error logged by getRotationTransformLocked.
479 return res;
480 }
481
482 res = mDevice->setStreamTransform(streamId, transform);
483 if (res != OK) {
484 ALOGE("%s: Failed to set stream transform (stream id %d)",
485 __FUNCTION__, streamId);
486 return res;
487 }
488
Igor Murashkine7ee7632013-06-11 18:10:18 -0700489 return streamId;
490 }
491
492 return res;
493}
494
Ruben Brunkbba75572014-11-20 17:29:50 -0800495
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700496status_t CameraDeviceClient::createInputStream(int width, int height,
497 int format) {
498
499 ATRACE_CALL();
500 ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
501
502 status_t res;
503 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
504
505 Mutex::Autolock icl(mBinderSerializationLock);
506 if (!mDevice.get()) return DEAD_OBJECT;
507
508 if (mInputStream.configured) {
509 ALOGE("%s: Camera %d: Already has an input stream "
510 " configuration. (ID %zd)", __FUNCTION__, mCameraId,
511 mInputStream.id);
512 return ALREADY_EXISTS;
513 }
514
515 int streamId = -1;
516 res = mDevice->createInputStream(width, height, format, &streamId);
517 if (res == OK) {
518 mInputStream.configured = true;
519 mInputStream.width = width;
520 mInputStream.height = height;
521 mInputStream.format = format;
522 mInputStream.id = streamId;
523
524 ALOGV("%s: Camera %d: Successfully created a new input stream ID %d",
525 __FUNCTION__, mCameraId, streamId);
526
527 return streamId;
528 }
529
530 return res;
531}
532
533status_t CameraDeviceClient::getInputBufferProducer(
534 /*out*/sp<IGraphicBufferProducer> *producer) {
535 status_t res;
536 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
537
538 if (producer == NULL) {
539 return BAD_VALUE;
540 }
541
542 Mutex::Autolock icl(mBinderSerializationLock);
543 if (!mDevice.get()) return DEAD_OBJECT;
544
545 return mDevice->getInputBufferProducer(producer);
546}
547
Ruben Brunkbba75572014-11-20 17:29:50 -0800548bool CameraDeviceClient::roundBufferDimensionNearest(int32_t width, int32_t height,
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -0800549 int32_t format, android_dataspace dataSpace, const CameraMetadata& info,
Ruben Brunkbba75572014-11-20 17:29:50 -0800550 /*out*/int32_t* outWidth, /*out*/int32_t* outHeight) {
551
552 camera_metadata_ro_entry streamConfigs =
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -0800553 (dataSpace == HAL_DATASPACE_DEPTH) ?
554 info.find(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS) :
Ruben Brunkbba75572014-11-20 17:29:50 -0800555 info.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
556
557 int32_t bestWidth = -1;
558 int32_t bestHeight = -1;
559
560 // Iterate through listed stream configurations and find the one with the smallest euclidean
561 // distance from the given dimensions for the given format.
562 for (size_t i = 0; i < streamConfigs.count; i += 4) {
563 int32_t fmt = streamConfigs.data.i32[i];
564 int32_t w = streamConfigs.data.i32[i + 1];
565 int32_t h = streamConfigs.data.i32[i + 2];
566
567 // Ignore input/output type for now
568 if (fmt == format) {
569 if (w == width && h == height) {
570 bestWidth = width;
571 bestHeight = height;
572 break;
573 } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 ||
574 CameraDeviceClient::euclidDistSquare(w, h, width, height) <
575 CameraDeviceClient::euclidDistSquare(bestWidth, bestHeight, width, height))) {
576 bestWidth = w;
577 bestHeight = h;
578 }
579 }
580 }
581
582 if (bestWidth == -1) {
583 // Return false if no configurations for this format were listed
584 return false;
585 }
586
587 // Set the outputs to the closet width/height
588 if (outWidth != NULL) {
589 *outWidth = bestWidth;
590 }
591 if (outHeight != NULL) {
592 *outHeight = bestHeight;
593 }
594
595 // Return true if at least one configuration for this format was listed
596 return true;
597}
598
599int64_t CameraDeviceClient::euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
600 int64_t d0 = x0 - x1;
601 int64_t d1 = y0 - y1;
602 return d0 * d0 + d1 * d1;
603}
604
Igor Murashkine7ee7632013-06-11 18:10:18 -0700605// Create a request object from a template.
606status_t CameraDeviceClient::createDefaultRequest(int templateId,
607 /*out*/
608 CameraMetadata* request)
609{
610 ATRACE_CALL();
611 ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);
612
613 status_t res;
614 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
615
616 Mutex::Autolock icl(mBinderSerializationLock);
617
618 if (!mDevice.get()) return DEAD_OBJECT;
619
620 CameraMetadata metadata;
621 if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK &&
622 request != NULL) {
623
624 request->swap(metadata);
625 }
626
627 return res;
628}
629
Igor Murashkin099b4572013-07-12 17:52:16 -0700630status_t CameraDeviceClient::getCameraInfo(/*out*/CameraMetadata* info)
Igor Murashkine7ee7632013-06-11 18:10:18 -0700631{
632 ATRACE_CALL();
633 ALOGV("%s", __FUNCTION__);
634
635 status_t res = OK;
636
Igor Murashkine7ee7632013-06-11 18:10:18 -0700637 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
638
639 Mutex::Autolock icl(mBinderSerializationLock);
640
641 if (!mDevice.get()) return DEAD_OBJECT;
642
Igor Murashkin099b4572013-07-12 17:52:16 -0700643 if (info != NULL) {
644 *info = mDevice->info(); // static camera metadata
645 // TODO: merge with device-specific camera metadata
646 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700647
648 return res;
649}
650
Zhijun He2ab500c2013-07-23 08:02:53 -0700651status_t CameraDeviceClient::waitUntilIdle()
652{
653 ATRACE_CALL();
654 ALOGV("%s", __FUNCTION__);
655
656 status_t res = OK;
657 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
658
659 Mutex::Autolock icl(mBinderSerializationLock);
660
661 if (!mDevice.get()) return DEAD_OBJECT;
662
663 // FIXME: Also need check repeating burst.
664 if (!mStreamingRequestList.isEmpty()) {
665 ALOGE("%s: Camera %d: Try to waitUntilIdle when there are active streaming requests",
666 __FUNCTION__, mCameraId);
667 return INVALID_OPERATION;
668 }
669 res = mDevice->waitUntilDrained();
670 ALOGV("%s Done", __FUNCTION__);
671
672 return res;
673}
674
Jianing Weicb0652e2014-03-12 18:29:36 -0700675status_t CameraDeviceClient::flush(int64_t* lastFrameNumber) {
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -0700676 ATRACE_CALL();
677 ALOGV("%s", __FUNCTION__);
678
679 status_t res = OK;
680 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
681
682 Mutex::Autolock icl(mBinderSerializationLock);
683
684 if (!mDevice.get()) return DEAD_OBJECT;
685
Jianing Wei3c76fa32014-04-21 11:34:34 -0700686 mStreamingRequestList.clear();
Jianing Weicb0652e2014-03-12 18:29:36 -0700687 return mDevice->flush(lastFrameNumber);
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -0700688}
689
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -0700690status_t CameraDeviceClient::prepare(int streamId) {
691 ATRACE_CALL();
692 ALOGV("%s", __FUNCTION__);
693
694 status_t res = OK;
695 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
696
697 Mutex::Autolock icl(mBinderSerializationLock);
698
699 // Guard against trying to prepare non-created streams
700 ssize_t index = NAME_NOT_FOUND;
701 for (size_t i = 0; i < mStreamMap.size(); ++i) {
702 if (streamId == mStreamMap.valueAt(i)) {
703 index = i;
704 break;
705 }
706 }
707
708 if (index == NAME_NOT_FOUND) {
709 ALOGW("%s: Camera %d: Invalid stream ID (%d) specified, no stream "
710 "created yet", __FUNCTION__, mCameraId, streamId);
711 return BAD_VALUE;
712 }
713
Eino-Ville Talvala261394e2015-05-13 14:28:38 -0700714 // Also returns BAD_VALUE if stream ID was not valid, or stream already
715 // has been used
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -0700716 res = mDevice->prepare(streamId);
717
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -0700718 return res;
719}
720
Igor Murashkine7ee7632013-06-11 18:10:18 -0700721status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {
722 String8 result;
Eino-Ville Talvala67489d22014-09-18 15:52:02 -0700723 result.appendFormat("CameraDeviceClient[%d] (%p) dump:\n",
Igor Murashkine7ee7632013-06-11 18:10:18 -0700724 mCameraId,
Eino-Ville Talvalae992e752014-11-07 16:17:48 -0800725 (getRemoteCallback() != NULL ?
Marco Nelissenf8880202014-11-14 07:58:25 -0800726 IInterface::asBinder(getRemoteCallback()).get() : NULL) );
Ruben Brunkcc776712015-02-17 20:18:47 -0800727 result.appendFormat(" Current client UID %u\n", mClientUid);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700728
Eino-Ville Talvala67489d22014-09-18 15:52:02 -0700729 result.append(" State:\n");
730 result.appendFormat(" Request ID counter: %d\n", mRequestIdCounter);
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700731 if (mInputStream.configured) {
732 result.appendFormat(" Current input stream ID: %d\n",
733 mInputStream.id);
734 } else {
735 result.append(" No input stream configured.\n");
736 }
Eino-Ville Talvala67489d22014-09-18 15:52:02 -0700737 if (!mStreamMap.isEmpty()) {
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700738 result.append(" Current output stream IDs:\n");
Eino-Ville Talvala67489d22014-09-18 15:52:02 -0700739 for (size_t i = 0; i < mStreamMap.size(); i++) {
740 result.appendFormat(" Stream %d\n", mStreamMap.valueAt(i));
741 }
742 } else {
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700743 result.append(" No output streams configured.\n");
Eino-Ville Talvala67489d22014-09-18 15:52:02 -0700744 }
745 write(fd, result.string(), result.size());
Igor Murashkine7ee7632013-06-11 18:10:18 -0700746 // TODO: print dynamic/request section from most recent requests
747 mFrameProcessor->dump(fd, args);
748
749 return dumpDevice(fd, args);
750}
751
Jianing Weicb0652e2014-03-12 18:29:36 -0700752void CameraDeviceClient::notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
753 const CaptureResultExtras& resultExtras) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700754 // Thread safe. Don't bother locking.
755 sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
756
757 if (remoteCb != 0) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700758 remoteCb->onDeviceError(errorCode, resultExtras);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700759 }
760}
761
762void CameraDeviceClient::notifyIdle() {
763 // Thread safe. Don't bother locking.
764 sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
765
766 if (remoteCb != 0) {
767 remoteCb->onDeviceIdle();
768 }
769}
770
Jianing Weicb0652e2014-03-12 18:29:36 -0700771void CameraDeviceClient::notifyShutter(const CaptureResultExtras& resultExtras,
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700772 nsecs_t timestamp) {
773 // Thread safe. Don't bother locking.
774 sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
775 if (remoteCb != 0) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700776 remoteCb->onCaptureStarted(resultExtras, timestamp);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700777 }
778}
779
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -0700780void CameraDeviceClient::notifyPrepared(int streamId) {
781 // Thread safe. Don't bother locking.
782 sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
783 if (remoteCb != 0) {
784 remoteCb->onPrepared(streamId);
785 }
786}
787
Igor Murashkine7ee7632013-06-11 18:10:18 -0700788void CameraDeviceClient::detachDevice() {
789 if (mDevice == 0) return;
790
791 ALOGV("Camera %d: Stopping processors", mCameraId);
792
793 mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
794 FRAME_PROCESSOR_LISTENER_MAX_ID,
795 /*listener*/this);
796 mFrameProcessor->requestExit();
797 ALOGV("Camera %d: Waiting for threads", mCameraId);
798 mFrameProcessor->join();
799 ALOGV("Camera %d: Disconnecting device", mCameraId);
800
801 // WORKAROUND: HAL refuses to disconnect while there's streams in flight
802 {
803 mDevice->clearStreamingRequest();
804
805 status_t code;
806 if ((code = mDevice->waitUntilDrained()) != OK) {
807 ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
808 code);
809 }
810 }
811
812 Camera2ClientBase::detachDevice();
813}
814
815/** Device-related methods */
Jianing Weicb0652e2014-03-12 18:29:36 -0700816void CameraDeviceClient::onResultAvailable(const CaptureResult& result) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700817 ATRACE_CALL();
818 ALOGV("%s", __FUNCTION__);
819
Igor Murashkin4fb55c12013-08-29 17:43:01 -0700820 // Thread-safe. No lock necessary.
821 sp<ICameraDeviceCallbacks> remoteCb = mRemoteCallback;
822 if (remoteCb != NULL) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700823 remoteCb->onResultReceived(result.mMetadata, result.mResultExtras);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700824 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700825}
826
827// TODO: move to Camera2ClientBase
828bool CameraDeviceClient::enforceRequestPermissions(CameraMetadata& metadata) {
829
830 const int pid = IPCThreadState::self()->getCallingPid();
831 const int selfPid = getpid();
832 camera_metadata_entry_t entry;
833
834 /**
835 * Mixin default important security values
836 * - android.led.transmit = defaulted ON
837 */
838 CameraMetadata staticInfo = mDevice->info();
839 entry = staticInfo.find(ANDROID_LED_AVAILABLE_LEDS);
840 for(size_t i = 0; i < entry.count; ++i) {
841 uint8_t led = entry.data.u8[i];
842
843 switch(led) {
844 case ANDROID_LED_AVAILABLE_LEDS_TRANSMIT: {
845 uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON;
846 if (!metadata.exists(ANDROID_LED_TRANSMIT)) {
847 metadata.update(ANDROID_LED_TRANSMIT,
848 &transmitDefault, 1);
849 }
850 break;
851 }
852 }
853 }
854
855 // We can do anything!
856 if (pid == selfPid) {
857 return true;
858 }
859
860 /**
861 * Permission check special fields in the request
862 * - android.led.transmit = android.permission.CAMERA_DISABLE_TRANSMIT
863 */
864 entry = metadata.find(ANDROID_LED_TRANSMIT);
865 if (entry.count > 0 && entry.data.u8[0] != ANDROID_LED_TRANSMIT_ON) {
866 String16 permissionString =
867 String16("android.permission.CAMERA_DISABLE_TRANSMIT_LED");
868 if (!checkCallingPermission(permissionString)) {
869 const int uid = IPCThreadState::self()->getCallingUid();
870 ALOGE("Permission Denial: "
871 "can't disable transmit LED pid=%d, uid=%d", pid, uid);
872 return false;
873 }
874 }
875
876 return true;
877}
878
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700879status_t CameraDeviceClient::getRotationTransformLocked(int32_t* transform) {
880 ALOGV("%s: begin", __FUNCTION__);
881
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700882 const CameraMetadata& staticInfo = mDevice->info();
Ruben Brunk5698d442014-06-18 10:39:40 -0700883 return CameraUtils::getRotationTransform(staticInfo, transform);
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700884}
885
Igor Murashkine7ee7632013-06-11 18:10:18 -0700886} // namespace android