blob: b6f667722c498f65e5a185e921a210b409cc789f [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.
272 ALOGE("%s: Not implemented yet.", __FUNCTION__);
273 return OK;
274}
275
276status_t CameraDeviceClient::endConfigure() {
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
280 status_t res;
281 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
282
283 Mutex::Autolock icl(mBinderSerializationLock);
284
285 if (!mDevice.get()) return DEAD_OBJECT;
286
287 return mDevice->configureStreams();
Ruben Brunkb2119af2014-05-09 19:57:56 -0700288}
289
Igor Murashkine7ee7632013-06-11 18:10:18 -0700290status_t CameraDeviceClient::deleteStream(int streamId) {
291 ATRACE_CALL();
292 ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);
293
294 status_t res;
295 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
296
297 Mutex::Autolock icl(mBinderSerializationLock);
298
299 if (!mDevice.get()) return DEAD_OBJECT;
300
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700301 bool isInput = false;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700302 ssize_t index = NAME_NOT_FOUND;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700303
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700304 if (mInputStream.configured && mInputStream.id == streamId) {
305 isInput = true;
306 } else {
307 // Guard against trying to delete non-created streams
308 for (size_t i = 0; i < mStreamMap.size(); ++i) {
309 if (streamId == mStreamMap.valueAt(i)) {
310 index = i;
311 break;
312 }
313 }
314
315 if (index == NAME_NOT_FOUND) {
316 ALOGW("%s: Camera %d: Invalid stream ID (%d) specified, no stream "
317 "created yet", __FUNCTION__, mCameraId, streamId);
318 return BAD_VALUE;
319 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700320 }
321
322 // Also returns BAD_VALUE if stream ID was not valid
323 res = mDevice->deleteStream(streamId);
324
325 if (res == BAD_VALUE) {
326 ALOGE("%s: Camera %d: Unexpected BAD_VALUE when deleting stream, but we"
327 " already checked and the stream ID (%d) should be valid.",
328 __FUNCTION__, mCameraId, streamId);
329 } else if (res == OK) {
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700330 if (isInput) {
331 mInputStream.configured = false;
332 } else {
333 mStreamMap.removeItemsAt(index);
334 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700335 }
336
337 return res;
338}
339
Yin-Chia Yehb97babb2015-03-12 13:42:44 -0700340status_t CameraDeviceClient::createStream(const OutputConfiguration &outputConfiguration)
Igor Murashkine7ee7632013-06-11 18:10:18 -0700341{
342 ATRACE_CALL();
Igor Murashkine7ee7632013-06-11 18:10:18 -0700343
344 status_t res;
345 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
346
347 Mutex::Autolock icl(mBinderSerializationLock);
348
Yin-Chia Yehb97babb2015-03-12 13:42:44 -0700349
350 sp<IGraphicBufferProducer> bufferProducer = outputConfiguration.getGraphicBufferProducer();
Yin-Chia Yeh89f14da2014-06-10 16:05:44 -0700351 if (bufferProducer == NULL) {
352 ALOGE("%s: bufferProducer must not be null", __FUNCTION__);
353 return BAD_VALUE;
354 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700355 if (!mDevice.get()) return DEAD_OBJECT;
356
357 // Don't create multiple streams for the same target surface
358 {
Marco Nelissenf8880202014-11-14 07:58:25 -0800359 ssize_t index = mStreamMap.indexOfKey(IInterface::asBinder(bufferProducer));
Igor Murashkine7ee7632013-06-11 18:10:18 -0700360 if (index != NAME_NOT_FOUND) {
361 ALOGW("%s: Camera %d: Buffer producer already has a stream for it "
Colin Crosse5729fa2014-03-21 15:04:25 -0700362 "(ID %zd)",
Igor Murashkine7ee7632013-06-11 18:10:18 -0700363 __FUNCTION__, mCameraId, index);
364 return ALREADY_EXISTS;
365 }
366 }
367
Eino-Ville Talvala1da3b602013-09-26 15:28:55 -0700368 // HACK b/10949105
369 // Query consumer usage bits to set async operation mode for
370 // GLConsumer using controlledByApp parameter.
371 bool useAsync = false;
372 int32_t consumerUsage;
373 if ((res = bufferProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS,
374 &consumerUsage)) != OK) {
375 ALOGE("%s: Camera %d: Failed to query consumer usage", __FUNCTION__,
376 mCameraId);
377 return res;
378 }
379 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
380 ALOGW("%s: Camera %d: Forcing asynchronous mode for stream",
381 __FUNCTION__, mCameraId);
382 useAsync = true;
383 }
384
Ruben Brunkbba75572014-11-20 17:29:50 -0800385 int32_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
386 GRALLOC_USAGE_RENDERSCRIPT;
387 int32_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
388 GraphicBuffer::USAGE_HW_TEXTURE |
389 GraphicBuffer::USAGE_HW_COMPOSER;
390 bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
391 (consumerUsage & allowedFlags) != 0;
392
Marco Nelissenf8880202014-11-14 07:58:25 -0800393 sp<IBinder> binder = IInterface::asBinder(bufferProducer);
Eino-Ville Talvalae992e752014-11-07 16:17:48 -0800394 sp<ANativeWindow> anw = new Surface(bufferProducer, useAsync);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700395
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -0800396 int width, height, format;
397 android_dataspace dataSpace;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700398
399 if ((res = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, &width)) != OK) {
400 ALOGE("%s: Camera %d: Failed to query Surface width", __FUNCTION__,
401 mCameraId);
402 return res;
403 }
404 if ((res = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, &height)) != OK) {
405 ALOGE("%s: Camera %d: Failed to query Surface height", __FUNCTION__,
406 mCameraId);
407 return res;
408 }
409 if ((res = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &format)) != OK) {
410 ALOGE("%s: Camera %d: Failed to query Surface format", __FUNCTION__,
411 mCameraId);
412 return res;
413 }
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -0800414 if ((res = anw->query(anw.get(), NATIVE_WINDOW_DEFAULT_DATASPACE,
415 reinterpret_cast<int*>(&dataSpace))) != OK) {
416 ALOGE("%s: Camera %d: Failed to query Surface dataSpace", __FUNCTION__,
417 mCameraId);
418 return res;
419 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700420
421 // FIXME: remove this override since the default format should be
422 // IMPLEMENTATION_DEFINED. b/9487482
Igor Murashkin15811012013-07-29 12:25:59 -0700423 if (format >= HAL_PIXEL_FORMAT_RGBA_8888 &&
424 format <= HAL_PIXEL_FORMAT_BGRA_8888) {
Ruben Brunkbba75572014-11-20 17:29:50 -0800425 ALOGW("%s: Camera %d: Overriding format %#x to IMPLEMENTATION_DEFINED",
Igor Murashkine7ee7632013-06-11 18:10:18 -0700426 __FUNCTION__, mCameraId, format);
427 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
428 }
429
Ruben Brunkbba75572014-11-20 17:29:50 -0800430 // Round dimensions to the nearest dimensions available for this format
431 if (flexibleConsumer && !CameraDeviceClient::roundBufferDimensionNearest(width, height,
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -0800432 format, dataSpace, mDevice->info(), /*out*/&width, /*out*/&height)) {
Ruben Brunkbba75572014-11-20 17:29:50 -0800433 ALOGE("%s: No stream configurations with the format %#x defined, failed to create stream.",
434 __FUNCTION__, format);
435 return BAD_VALUE;
436 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700437
438 int streamId = -1;
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -0800439 res = mDevice->createStream(anw, width, height, format, dataSpace,
Yin-Chia Yehb97babb2015-03-12 13:42:44 -0700440 static_cast<camera3_stream_rotation_t>
441 (outputConfiguration.getRotation()),
442 &streamId);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700443
444 if (res == OK) {
Eino-Ville Talvalae992e752014-11-07 16:17:48 -0800445 mStreamMap.add(binder, streamId);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700446
447 ALOGV("%s: Camera %d: Successfully created a new stream ID %d",
448 __FUNCTION__, mCameraId, streamId);
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700449
450 /**
451 * Set the stream transform flags to automatically
452 * rotate the camera stream for preview use cases.
453 */
454 int32_t transform = 0;
455 res = getRotationTransformLocked(&transform);
456
457 if (res != OK) {
458 // Error logged by getRotationTransformLocked.
459 return res;
460 }
461
462 res = mDevice->setStreamTransform(streamId, transform);
463 if (res != OK) {
464 ALOGE("%s: Failed to set stream transform (stream id %d)",
465 __FUNCTION__, streamId);
466 return res;
467 }
468
Igor Murashkine7ee7632013-06-11 18:10:18 -0700469 return streamId;
470 }
471
472 return res;
473}
474
Ruben Brunkbba75572014-11-20 17:29:50 -0800475
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700476status_t CameraDeviceClient::createInputStream(int width, int height,
477 int format) {
478
479 ATRACE_CALL();
480 ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
481
482 status_t res;
483 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
484
485 Mutex::Autolock icl(mBinderSerializationLock);
486 if (!mDevice.get()) return DEAD_OBJECT;
487
488 if (mInputStream.configured) {
489 ALOGE("%s: Camera %d: Already has an input stream "
490 " configuration. (ID %zd)", __FUNCTION__, mCameraId,
491 mInputStream.id);
492 return ALREADY_EXISTS;
493 }
494
495 int streamId = -1;
496 res = mDevice->createInputStream(width, height, format, &streamId);
497 if (res == OK) {
498 mInputStream.configured = true;
499 mInputStream.width = width;
500 mInputStream.height = height;
501 mInputStream.format = format;
502 mInputStream.id = streamId;
503
504 ALOGV("%s: Camera %d: Successfully created a new input stream ID %d",
505 __FUNCTION__, mCameraId, streamId);
506
507 return streamId;
508 }
509
510 return res;
511}
512
513status_t CameraDeviceClient::getInputBufferProducer(
514 /*out*/sp<IGraphicBufferProducer> *producer) {
515 status_t res;
516 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
517
518 if (producer == NULL) {
519 return BAD_VALUE;
520 }
521
522 Mutex::Autolock icl(mBinderSerializationLock);
523 if (!mDevice.get()) return DEAD_OBJECT;
524
525 return mDevice->getInputBufferProducer(producer);
526}
527
Ruben Brunkbba75572014-11-20 17:29:50 -0800528bool CameraDeviceClient::roundBufferDimensionNearest(int32_t width, int32_t height,
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -0800529 int32_t format, android_dataspace dataSpace, const CameraMetadata& info,
Ruben Brunkbba75572014-11-20 17:29:50 -0800530 /*out*/int32_t* outWidth, /*out*/int32_t* outHeight) {
531
532 camera_metadata_ro_entry streamConfigs =
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -0800533 (dataSpace == HAL_DATASPACE_DEPTH) ?
534 info.find(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS) :
Ruben Brunkbba75572014-11-20 17:29:50 -0800535 info.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
536
537 int32_t bestWidth = -1;
538 int32_t bestHeight = -1;
539
540 // Iterate through listed stream configurations and find the one with the smallest euclidean
541 // distance from the given dimensions for the given format.
542 for (size_t i = 0; i < streamConfigs.count; i += 4) {
543 int32_t fmt = streamConfigs.data.i32[i];
544 int32_t w = streamConfigs.data.i32[i + 1];
545 int32_t h = streamConfigs.data.i32[i + 2];
546
547 // Ignore input/output type for now
548 if (fmt == format) {
549 if (w == width && h == height) {
550 bestWidth = width;
551 bestHeight = height;
552 break;
553 } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 ||
554 CameraDeviceClient::euclidDistSquare(w, h, width, height) <
555 CameraDeviceClient::euclidDistSquare(bestWidth, bestHeight, width, height))) {
556 bestWidth = w;
557 bestHeight = h;
558 }
559 }
560 }
561
562 if (bestWidth == -1) {
563 // Return false if no configurations for this format were listed
564 return false;
565 }
566
567 // Set the outputs to the closet width/height
568 if (outWidth != NULL) {
569 *outWidth = bestWidth;
570 }
571 if (outHeight != NULL) {
572 *outHeight = bestHeight;
573 }
574
575 // Return true if at least one configuration for this format was listed
576 return true;
577}
578
579int64_t CameraDeviceClient::euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
580 int64_t d0 = x0 - x1;
581 int64_t d1 = y0 - y1;
582 return d0 * d0 + d1 * d1;
583}
584
Igor Murashkine7ee7632013-06-11 18:10:18 -0700585// Create a request object from a template.
586status_t CameraDeviceClient::createDefaultRequest(int templateId,
587 /*out*/
588 CameraMetadata* request)
589{
590 ATRACE_CALL();
591 ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);
592
593 status_t res;
594 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
595
596 Mutex::Autolock icl(mBinderSerializationLock);
597
598 if (!mDevice.get()) return DEAD_OBJECT;
599
600 CameraMetadata metadata;
601 if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK &&
602 request != NULL) {
603
604 request->swap(metadata);
605 }
606
607 return res;
608}
609
Igor Murashkin099b4572013-07-12 17:52:16 -0700610status_t CameraDeviceClient::getCameraInfo(/*out*/CameraMetadata* info)
Igor Murashkine7ee7632013-06-11 18:10:18 -0700611{
612 ATRACE_CALL();
613 ALOGV("%s", __FUNCTION__);
614
615 status_t res = OK;
616
Igor Murashkine7ee7632013-06-11 18:10:18 -0700617 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
618
619 Mutex::Autolock icl(mBinderSerializationLock);
620
621 if (!mDevice.get()) return DEAD_OBJECT;
622
Igor Murashkin099b4572013-07-12 17:52:16 -0700623 if (info != NULL) {
624 *info = mDevice->info(); // static camera metadata
625 // TODO: merge with device-specific camera metadata
626 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700627
628 return res;
629}
630
Zhijun He2ab500c2013-07-23 08:02:53 -0700631status_t CameraDeviceClient::waitUntilIdle()
632{
633 ATRACE_CALL();
634 ALOGV("%s", __FUNCTION__);
635
636 status_t res = OK;
637 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
638
639 Mutex::Autolock icl(mBinderSerializationLock);
640
641 if (!mDevice.get()) return DEAD_OBJECT;
642
643 // FIXME: Also need check repeating burst.
644 if (!mStreamingRequestList.isEmpty()) {
645 ALOGE("%s: Camera %d: Try to waitUntilIdle when there are active streaming requests",
646 __FUNCTION__, mCameraId);
647 return INVALID_OPERATION;
648 }
649 res = mDevice->waitUntilDrained();
650 ALOGV("%s Done", __FUNCTION__);
651
652 return res;
653}
654
Jianing Weicb0652e2014-03-12 18:29:36 -0700655status_t CameraDeviceClient::flush(int64_t* lastFrameNumber) {
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -0700656 ATRACE_CALL();
657 ALOGV("%s", __FUNCTION__);
658
659 status_t res = OK;
660 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
661
662 Mutex::Autolock icl(mBinderSerializationLock);
663
664 if (!mDevice.get()) return DEAD_OBJECT;
665
Jianing Wei3c76fa32014-04-21 11:34:34 -0700666 mStreamingRequestList.clear();
Jianing Weicb0652e2014-03-12 18:29:36 -0700667 return mDevice->flush(lastFrameNumber);
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -0700668}
669
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -0700670status_t CameraDeviceClient::prepare(int streamId) {
671 ATRACE_CALL();
672 ALOGV("%s", __FUNCTION__);
673
674 status_t res = OK;
675 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
676
677 Mutex::Autolock icl(mBinderSerializationLock);
678
679 // Guard against trying to prepare non-created streams
680 ssize_t index = NAME_NOT_FOUND;
681 for (size_t i = 0; i < mStreamMap.size(); ++i) {
682 if (streamId == mStreamMap.valueAt(i)) {
683 index = i;
684 break;
685 }
686 }
687
688 if (index == NAME_NOT_FOUND) {
689 ALOGW("%s: Camera %d: Invalid stream ID (%d) specified, no stream "
690 "created yet", __FUNCTION__, mCameraId, streamId);
691 return BAD_VALUE;
692 }
693
Eino-Ville Talvala261394e2015-05-13 14:28:38 -0700694 // Also returns BAD_VALUE if stream ID was not valid, or stream already
695 // has been used
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -0700696 res = mDevice->prepare(streamId);
697
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -0700698 return res;
699}
700
Igor Murashkine7ee7632013-06-11 18:10:18 -0700701status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {
702 String8 result;
Eino-Ville Talvala67489d22014-09-18 15:52:02 -0700703 result.appendFormat("CameraDeviceClient[%d] (%p) dump:\n",
Igor Murashkine7ee7632013-06-11 18:10:18 -0700704 mCameraId,
Eino-Ville Talvalae992e752014-11-07 16:17:48 -0800705 (getRemoteCallback() != NULL ?
Marco Nelissenf8880202014-11-14 07:58:25 -0800706 IInterface::asBinder(getRemoteCallback()).get() : NULL) );
Ruben Brunkcc776712015-02-17 20:18:47 -0800707 result.appendFormat(" Current client UID %u\n", mClientUid);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700708
Eino-Ville Talvala67489d22014-09-18 15:52:02 -0700709 result.append(" State:\n");
710 result.appendFormat(" Request ID counter: %d\n", mRequestIdCounter);
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700711 if (mInputStream.configured) {
712 result.appendFormat(" Current input stream ID: %d\n",
713 mInputStream.id);
714 } else {
715 result.append(" No input stream configured.\n");
716 }
Eino-Ville Talvala67489d22014-09-18 15:52:02 -0700717 if (!mStreamMap.isEmpty()) {
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700718 result.append(" Current output stream IDs:\n");
Eino-Ville Talvala67489d22014-09-18 15:52:02 -0700719 for (size_t i = 0; i < mStreamMap.size(); i++) {
720 result.appendFormat(" Stream %d\n", mStreamMap.valueAt(i));
721 }
722 } else {
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700723 result.append(" No output streams configured.\n");
Eino-Ville Talvala67489d22014-09-18 15:52:02 -0700724 }
725 write(fd, result.string(), result.size());
Igor Murashkine7ee7632013-06-11 18:10:18 -0700726 // TODO: print dynamic/request section from most recent requests
727 mFrameProcessor->dump(fd, args);
728
729 return dumpDevice(fd, args);
730}
731
Jianing Weicb0652e2014-03-12 18:29:36 -0700732void CameraDeviceClient::notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
733 const CaptureResultExtras& resultExtras) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700734 // Thread safe. Don't bother locking.
735 sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
736
737 if (remoteCb != 0) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700738 remoteCb->onDeviceError(errorCode, resultExtras);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700739 }
740}
741
742void CameraDeviceClient::notifyIdle() {
743 // Thread safe. Don't bother locking.
744 sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
745
746 if (remoteCb != 0) {
747 remoteCb->onDeviceIdle();
748 }
749}
750
Jianing Weicb0652e2014-03-12 18:29:36 -0700751void CameraDeviceClient::notifyShutter(const CaptureResultExtras& resultExtras,
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700752 nsecs_t timestamp) {
753 // Thread safe. Don't bother locking.
754 sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
755 if (remoteCb != 0) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700756 remoteCb->onCaptureStarted(resultExtras, timestamp);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700757 }
758}
759
Eino-Ville Talvala4d44cad2015-04-11 13:15:45 -0700760void CameraDeviceClient::notifyPrepared(int streamId) {
761 // Thread safe. Don't bother locking.
762 sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
763 if (remoteCb != 0) {
764 remoteCb->onPrepared(streamId);
765 }
766}
767
Igor Murashkine7ee7632013-06-11 18:10:18 -0700768void CameraDeviceClient::detachDevice() {
769 if (mDevice == 0) return;
770
771 ALOGV("Camera %d: Stopping processors", mCameraId);
772
773 mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
774 FRAME_PROCESSOR_LISTENER_MAX_ID,
775 /*listener*/this);
776 mFrameProcessor->requestExit();
777 ALOGV("Camera %d: Waiting for threads", mCameraId);
778 mFrameProcessor->join();
779 ALOGV("Camera %d: Disconnecting device", mCameraId);
780
781 // WORKAROUND: HAL refuses to disconnect while there's streams in flight
782 {
783 mDevice->clearStreamingRequest();
784
785 status_t code;
786 if ((code = mDevice->waitUntilDrained()) != OK) {
787 ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
788 code);
789 }
790 }
791
792 Camera2ClientBase::detachDevice();
793}
794
795/** Device-related methods */
Jianing Weicb0652e2014-03-12 18:29:36 -0700796void CameraDeviceClient::onResultAvailable(const CaptureResult& result) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700797 ATRACE_CALL();
798 ALOGV("%s", __FUNCTION__);
799
Igor Murashkin4fb55c12013-08-29 17:43:01 -0700800 // Thread-safe. No lock necessary.
801 sp<ICameraDeviceCallbacks> remoteCb = mRemoteCallback;
802 if (remoteCb != NULL) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700803 remoteCb->onResultReceived(result.mMetadata, result.mResultExtras);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700804 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700805}
806
807// TODO: move to Camera2ClientBase
808bool CameraDeviceClient::enforceRequestPermissions(CameraMetadata& metadata) {
809
810 const int pid = IPCThreadState::self()->getCallingPid();
811 const int selfPid = getpid();
812 camera_metadata_entry_t entry;
813
814 /**
815 * Mixin default important security values
816 * - android.led.transmit = defaulted ON
817 */
818 CameraMetadata staticInfo = mDevice->info();
819 entry = staticInfo.find(ANDROID_LED_AVAILABLE_LEDS);
820 for(size_t i = 0; i < entry.count; ++i) {
821 uint8_t led = entry.data.u8[i];
822
823 switch(led) {
824 case ANDROID_LED_AVAILABLE_LEDS_TRANSMIT: {
825 uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON;
826 if (!metadata.exists(ANDROID_LED_TRANSMIT)) {
827 metadata.update(ANDROID_LED_TRANSMIT,
828 &transmitDefault, 1);
829 }
830 break;
831 }
832 }
833 }
834
835 // We can do anything!
836 if (pid == selfPid) {
837 return true;
838 }
839
840 /**
841 * Permission check special fields in the request
842 * - android.led.transmit = android.permission.CAMERA_DISABLE_TRANSMIT
843 */
844 entry = metadata.find(ANDROID_LED_TRANSMIT);
845 if (entry.count > 0 && entry.data.u8[0] != ANDROID_LED_TRANSMIT_ON) {
846 String16 permissionString =
847 String16("android.permission.CAMERA_DISABLE_TRANSMIT_LED");
848 if (!checkCallingPermission(permissionString)) {
849 const int uid = IPCThreadState::self()->getCallingUid();
850 ALOGE("Permission Denial: "
851 "can't disable transmit LED pid=%d, uid=%d", pid, uid);
852 return false;
853 }
854 }
855
856 return true;
857}
858
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700859status_t CameraDeviceClient::getRotationTransformLocked(int32_t* transform) {
860 ALOGV("%s: begin", __FUNCTION__);
861
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700862 const CameraMetadata& staticInfo = mDevice->info();
Ruben Brunk5698d442014-06-18 10:39:40 -0700863 return CameraUtils::getRotationTransform(staticInfo, transform);
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700864}
865
Igor Murashkine7ee7632013-06-11 18:10:18 -0700866} // namespace android