1 /*
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
19 //#define LOG_NDEBUG 0
20
21 #include <cutils/properties.h>
22 #include <utils/Log.h>
23 #include <utils/Trace.h>
24 #include <gui/Surface.h>
25 #include <camera/camera2/CaptureRequest.h>
26 #include <camera/CameraUtils.h>
27
28 #include "common/CameraDeviceBase.h"
29 #include "api2/CameraDeviceClient.h"
30
31
32
33 namespace android {
34 using namespace camera2;
35
CameraDeviceClientBase(const sp<CameraService> & cameraService,const sp<ICameraDeviceCallbacks> & remoteCallback,const String16 & clientPackageName,int cameraId,int cameraFacing,int clientPid,uid_t clientUid,int servicePid)36 CameraDeviceClientBase::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) :
45 BasicClient(cameraService, remoteCallback->asBinder(), clientPackageName,
46 cameraId, cameraFacing, clientPid, clientUid, servicePid),
47 mRemoteCallback(remoteCallback) {
48 }
49
50 // Interface used by CameraService
51
CameraDeviceClient(const sp<CameraService> & cameraService,const sp<ICameraDeviceCallbacks> & remoteCallback,const String16 & clientPackageName,int cameraId,int cameraFacing,int clientPid,uid_t clientUid,int servicePid)52 CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
53 const sp<ICameraDeviceCallbacks>& remoteCallback,
54 const String16& clientPackageName,
55 int cameraId,
56 int cameraFacing,
57 int clientPid,
58 uid_t clientUid,
59 int servicePid) :
60 Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
61 cameraId, cameraFacing, clientPid, clientUid, servicePid),
62 mRequestIdCounter(0) {
63
64 ATRACE_CALL();
65 ALOGI("CameraDeviceClient %d: Opened", cameraId);
66 }
67
initialize(camera_module_t * module)68 status_t CameraDeviceClient::initialize(camera_module_t *module)
69 {
70 ATRACE_CALL();
71 status_t res;
72
73 res = Camera2ClientBase::initialize(module);
74 if (res != OK) {
75 return res;
76 }
77
78 String8 threadName;
79 mFrameProcessor = new FrameProcessorBase(mDevice);
80 threadName = String8::format("CDU-%d-FrameProc", mCameraId);
81 mFrameProcessor->run(threadName.string());
82
83 mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
84 FRAME_PROCESSOR_LISTENER_MAX_ID,
85 /*listener*/this,
86 /*sendPartials*/true);
87
88 return OK;
89 }
90
~CameraDeviceClient()91 CameraDeviceClient::~CameraDeviceClient() {
92 }
93
submitRequest(sp<CaptureRequest> request,bool streaming,int64_t * lastFrameNumber)94 status_t CameraDeviceClient::submitRequest(sp<CaptureRequest> request,
95 bool streaming,
96 /*out*/
97 int64_t* lastFrameNumber) {
98 List<sp<CaptureRequest> > requestList;
99 requestList.push_back(request);
100 return submitRequestList(requestList, streaming, lastFrameNumber);
101 }
102
submitRequestList(List<sp<CaptureRequest>> requests,bool streaming,int64_t * lastFrameNumber)103 status_t CameraDeviceClient::submitRequestList(List<sp<CaptureRequest> > requests,
104 bool streaming, int64_t* lastFrameNumber) {
105 ATRACE_CALL();
106 ALOGV("%s-start of function. Request list size %zu", __FUNCTION__, requests.size());
107
108 status_t res;
109 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
110
111 Mutex::Autolock icl(mBinderSerializationLock);
112
113 if (!mDevice.get()) return DEAD_OBJECT;
114
115 if (requests.empty()) {
116 ALOGE("%s: Camera %d: Sent null request. Rejecting request.",
117 __FUNCTION__, mCameraId);
118 return BAD_VALUE;
119 }
120
121 List<const CameraMetadata> metadataRequestList;
122 int32_t requestId = mRequestIdCounter;
123 uint32_t loopCounter = 0;
124
125 for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end(); ++it) {
126 sp<CaptureRequest> request = *it;
127 if (request == 0) {
128 ALOGE("%s: Camera %d: Sent null request.",
129 __FUNCTION__, mCameraId);
130 return BAD_VALUE;
131 }
132
133 CameraMetadata metadata(request->mMetadata);
134 if (metadata.isEmpty()) {
135 ALOGE("%s: Camera %d: Sent empty metadata packet. Rejecting request.",
136 __FUNCTION__, mCameraId);
137 return BAD_VALUE;
138 } else if (request->mSurfaceList.isEmpty()) {
139 ALOGE("%s: Camera %d: Requests must have at least one surface target. "
140 "Rejecting request.", __FUNCTION__, mCameraId);
141 return BAD_VALUE;
142 }
143
144 if (!enforceRequestPermissions(metadata)) {
145 // Callee logs
146 return PERMISSION_DENIED;
147 }
148
149 /**
150 * Write in the output stream IDs which we calculate from
151 * the capture request's list of surface targets
152 */
153 Vector<int32_t> outputStreamIds;
154 outputStreamIds.setCapacity(request->mSurfaceList.size());
155 for (size_t i = 0; i < request->mSurfaceList.size(); ++i) {
156 sp<Surface> surface = request->mSurfaceList[i];
157 if (surface == 0) continue;
158
159 sp<IGraphicBufferProducer> gbp = surface->getIGraphicBufferProducer();
160 int idx = mStreamMap.indexOfKey(gbp->asBinder());
161
162 // Trying to submit request with surface that wasn't created
163 if (idx == NAME_NOT_FOUND) {
164 ALOGE("%s: Camera %d: Tried to submit a request with a surface that"
165 " we have not called createStream on",
166 __FUNCTION__, mCameraId);
167 return BAD_VALUE;
168 }
169
170 int streamId = mStreamMap.valueAt(idx);
171 outputStreamIds.push_back(streamId);
172 ALOGV("%s: Camera %d: Appending output stream %d to request",
173 __FUNCTION__, mCameraId, streamId);
174 }
175
176 metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS, &outputStreamIds[0],
177 outputStreamIds.size());
178
179 metadata.update(ANDROID_REQUEST_ID, &requestId, /*size*/1);
180 loopCounter++; // loopCounter starts from 1
181 ALOGV("%s: Camera %d: Creating request with ID %d (%d of %zu)",
182 __FUNCTION__, mCameraId, requestId, loopCounter, requests.size());
183
184 metadataRequestList.push_back(metadata);
185 }
186 mRequestIdCounter++;
187
188 if (streaming) {
189 res = mDevice->setStreamingRequestList(metadataRequestList, lastFrameNumber);
190 if (res != OK) {
191 ALOGE("%s: Camera %d: Got error %d after trying to set streaming "
192 "request", __FUNCTION__, mCameraId, res);
193 } else {
194 mStreamingRequestList.push_back(requestId);
195 }
196 } else {
197 res = mDevice->captureList(metadataRequestList, lastFrameNumber);
198 if (res != OK) {
199 ALOGE("%s: Camera %d: Got error %d after trying to set capture",
200 __FUNCTION__, mCameraId, res);
201 }
202 ALOGV("%s: requestId = %d ", __FUNCTION__, requestId);
203 }
204
205 ALOGV("%s: Camera %d: End of function", __FUNCTION__, mCameraId);
206 if (res == OK) {
207 return requestId;
208 }
209
210 return res;
211 }
212
cancelRequest(int requestId,int64_t * lastFrameNumber)213 status_t CameraDeviceClient::cancelRequest(int requestId, int64_t* lastFrameNumber) {
214 ATRACE_CALL();
215 ALOGV("%s, requestId = %d", __FUNCTION__, requestId);
216
217 status_t res;
218
219 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
220
221 Mutex::Autolock icl(mBinderSerializationLock);
222
223 if (!mDevice.get()) return DEAD_OBJECT;
224
225 Vector<int>::iterator it, end;
226 for (it = mStreamingRequestList.begin(), end = mStreamingRequestList.end();
227 it != end; ++it) {
228 if (*it == requestId) {
229 break;
230 }
231 }
232
233 if (it == end) {
234 ALOGE("%s: Camera%d: Did not find request id %d in list of streaming "
235 "requests", __FUNCTION__, mCameraId, requestId);
236 return BAD_VALUE;
237 }
238
239 res = mDevice->clearStreamingRequest(lastFrameNumber);
240
241 if (res == OK) {
242 ALOGV("%s: Camera %d: Successfully cleared streaming request",
243 __FUNCTION__, mCameraId);
244 mStreamingRequestList.erase(it);
245 }
246
247 return res;
248 }
249
beginConfigure()250 status_t CameraDeviceClient::beginConfigure() {
251 // TODO: Implement this.
252 ALOGE("%s: Not implemented yet.", __FUNCTION__);
253 return OK;
254 }
255
endConfigure()256 status_t CameraDeviceClient::endConfigure() {
257 ALOGV("%s: ending configure (%zu streams)",
258 __FUNCTION__, mStreamMap.size());
259
260 status_t res;
261 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
262
263 Mutex::Autolock icl(mBinderSerializationLock);
264
265 if (!mDevice.get()) return DEAD_OBJECT;
266
267 return mDevice->configureStreams();
268 }
269
deleteStream(int streamId)270 status_t CameraDeviceClient::deleteStream(int streamId) {
271 ATRACE_CALL();
272 ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);
273
274 status_t res;
275 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
276
277 Mutex::Autolock icl(mBinderSerializationLock);
278
279 if (!mDevice.get()) return DEAD_OBJECT;
280
281 // Guard against trying to delete non-created streams
282 ssize_t index = NAME_NOT_FOUND;
283 for (size_t i = 0; i < mStreamMap.size(); ++i) {
284 if (streamId == mStreamMap.valueAt(i)) {
285 index = i;
286 break;
287 }
288 }
289
290 if (index == NAME_NOT_FOUND) {
291 ALOGW("%s: Camera %d: Invalid stream ID (%d) specified, no stream "
292 "created yet", __FUNCTION__, mCameraId, streamId);
293 return BAD_VALUE;
294 }
295
296 // Also returns BAD_VALUE if stream ID was not valid
297 res = mDevice->deleteStream(streamId);
298
299 if (res == BAD_VALUE) {
300 ALOGE("%s: Camera %d: Unexpected BAD_VALUE when deleting stream, but we"
301 " already checked and the stream ID (%d) should be valid.",
302 __FUNCTION__, mCameraId, streamId);
303 } else if (res == OK) {
304 mStreamMap.removeItemsAt(index);
305
306 }
307
308 return res;
309 }
310
createStream(int width,int height,int format,const sp<IGraphicBufferProducer> & bufferProducer)311 status_t CameraDeviceClient::createStream(int width, int height, int format,
312 const sp<IGraphicBufferProducer>& bufferProducer)
313 {
314 ATRACE_CALL();
315 ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
316
317 status_t res;
318 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
319
320 Mutex::Autolock icl(mBinderSerializationLock);
321
322 if (bufferProducer == NULL) {
323 ALOGE("%s: bufferProducer must not be null", __FUNCTION__);
324 return BAD_VALUE;
325 }
326 if (!mDevice.get()) return DEAD_OBJECT;
327
328 // Don't create multiple streams for the same target surface
329 {
330 ssize_t index = mStreamMap.indexOfKey(bufferProducer->asBinder());
331 if (index != NAME_NOT_FOUND) {
332 ALOGW("%s: Camera %d: Buffer producer already has a stream for it "
333 "(ID %zd)",
334 __FUNCTION__, mCameraId, index);
335 return ALREADY_EXISTS;
336 }
337 }
338
339 // HACK b/10949105
340 // Query consumer usage bits to set async operation mode for
341 // GLConsumer using controlledByApp parameter.
342 bool useAsync = false;
343 int32_t consumerUsage;
344 if ((res = bufferProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS,
345 &consumerUsage)) != OK) {
346 ALOGE("%s: Camera %d: Failed to query consumer usage", __FUNCTION__,
347 mCameraId);
348 return res;
349 }
350 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
351 ALOGW("%s: Camera %d: Forcing asynchronous mode for stream",
352 __FUNCTION__, mCameraId);
353 useAsync = true;
354 }
355
356 int32_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
357 GRALLOC_USAGE_RENDERSCRIPT;
358 int32_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
359 GraphicBuffer::USAGE_HW_TEXTURE |
360 GraphicBuffer::USAGE_HW_COMPOSER;
361 bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
362 (consumerUsage & allowedFlags) != 0;
363
364 sp<IBinder> binder;
365 sp<ANativeWindow> anw;
366 if (bufferProducer != 0) {
367 binder = bufferProducer->asBinder();
368 anw = new Surface(bufferProducer, useAsync);
369 }
370
371 // TODO: remove w,h,f since we are ignoring them
372
373 if ((res = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, &width)) != OK) {
374 ALOGE("%s: Camera %d: Failed to query Surface width", __FUNCTION__,
375 mCameraId);
376 return res;
377 }
378 if ((res = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, &height)) != OK) {
379 ALOGE("%s: Camera %d: Failed to query Surface height", __FUNCTION__,
380 mCameraId);
381 return res;
382 }
383 if ((res = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &format)) != OK) {
384 ALOGE("%s: Camera %d: Failed to query Surface format", __FUNCTION__,
385 mCameraId);
386 return res;
387 }
388
389 // FIXME: remove this override since the default format should be
390 // IMPLEMENTATION_DEFINED. b/9487482
391 if (format >= HAL_PIXEL_FORMAT_RGBA_8888 &&
392 format <= HAL_PIXEL_FORMAT_BGRA_8888) {
393 ALOGW("%s: Camera %d: Overriding format %#x to IMPLEMENTATION_DEFINED",
394 __FUNCTION__, mCameraId, format);
395 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
396 }
397
398 // Round dimensions to the nearest dimensions available for this format
399 if (flexibleConsumer && !CameraDeviceClient::roundBufferDimensionNearest(width, height,
400 format, mDevice->info(), /*out*/&width, /*out*/&height)) {
401 ALOGE("%s: No stream configurations with the format %#x defined, failed to create stream.",
402 __FUNCTION__, format);
403 return BAD_VALUE;
404 }
405
406 int streamId = -1;
407 res = mDevice->createStream(anw, width, height, format, &streamId);
408
409 if (res == OK) {
410 mStreamMap.add(bufferProducer->asBinder(), streamId);
411
412 ALOGV("%s: Camera %d: Successfully created a new stream ID %d",
413 __FUNCTION__, mCameraId, streamId);
414
415 /**
416 * Set the stream transform flags to automatically
417 * rotate the camera stream for preview use cases.
418 */
419 int32_t transform = 0;
420 res = getRotationTransformLocked(&transform);
421
422 if (res != OK) {
423 // Error logged by getRotationTransformLocked.
424 return res;
425 }
426
427 res = mDevice->setStreamTransform(streamId, transform);
428 if (res != OK) {
429 ALOGE("%s: Failed to set stream transform (stream id %d)",
430 __FUNCTION__, streamId);
431 return res;
432 }
433
434 return streamId;
435 }
436
437 return res;
438 }
439
440
roundBufferDimensionNearest(int32_t width,int32_t height,int32_t format,const CameraMetadata & info,int32_t * outWidth,int32_t * outHeight)441 bool CameraDeviceClient::roundBufferDimensionNearest(int32_t width, int32_t height,
442 int32_t format, const CameraMetadata& info,
443 /*out*/int32_t* outWidth, /*out*/int32_t* outHeight) {
444
445 camera_metadata_ro_entry streamConfigs =
446 info.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
447
448 int32_t bestWidth = -1;
449 int32_t bestHeight = -1;
450
451 // Iterate through listed stream configurations and find the one with the smallest euclidean
452 // distance from the given dimensions for the given format.
453 for (size_t i = 0; i < streamConfigs.count; i += 4) {
454 int32_t fmt = streamConfigs.data.i32[i];
455 int32_t w = streamConfigs.data.i32[i + 1];
456 int32_t h = streamConfigs.data.i32[i + 2];
457
458 // Ignore input/output type for now
459 if (fmt == format) {
460 if (w == width && h == height) {
461 bestWidth = width;
462 bestHeight = height;
463 break;
464 } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 ||
465 CameraDeviceClient::euclidDistSquare(w, h, width, height) <
466 CameraDeviceClient::euclidDistSquare(bestWidth, bestHeight, width, height))) {
467 bestWidth = w;
468 bestHeight = h;
469 }
470 }
471 }
472
473 if (bestWidth == -1) {
474 // Return false if no configurations for this format were listed
475 return false;
476 }
477
478 // Set the outputs to the closet width/height
479 if (outWidth != NULL) {
480 *outWidth = bestWidth;
481 }
482 if (outHeight != NULL) {
483 *outHeight = bestHeight;
484 }
485
486 // Return true if at least one configuration for this format was listed
487 return true;
488 }
489
euclidDistSquare(int32_t x0,int32_t y0,int32_t x1,int32_t y1)490 int64_t CameraDeviceClient::euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
491 int64_t d0 = x0 - x1;
492 int64_t d1 = y0 - y1;
493 return d0 * d0 + d1 * d1;
494 }
495
496 // Create a request object from a template.
createDefaultRequest(int templateId,CameraMetadata * request)497 status_t CameraDeviceClient::createDefaultRequest(int templateId,
498 /*out*/
499 CameraMetadata* request)
500 {
501 ATRACE_CALL();
502 ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);
503
504 status_t res;
505 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
506
507 Mutex::Autolock icl(mBinderSerializationLock);
508
509 if (!mDevice.get()) return DEAD_OBJECT;
510
511 CameraMetadata metadata;
512 if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK &&
513 request != NULL) {
514
515 request->swap(metadata);
516 }
517
518 return res;
519 }
520
getCameraInfo(CameraMetadata * info)521 status_t CameraDeviceClient::getCameraInfo(/*out*/CameraMetadata* info)
522 {
523 ATRACE_CALL();
524 ALOGV("%s", __FUNCTION__);
525
526 status_t res = OK;
527
528 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
529
530 Mutex::Autolock icl(mBinderSerializationLock);
531
532 if (!mDevice.get()) return DEAD_OBJECT;
533
534 if (info != NULL) {
535 *info = mDevice->info(); // static camera metadata
536 // TODO: merge with device-specific camera metadata
537 }
538
539 return res;
540 }
541
waitUntilIdle()542 status_t CameraDeviceClient::waitUntilIdle()
543 {
544 ATRACE_CALL();
545 ALOGV("%s", __FUNCTION__);
546
547 status_t res = OK;
548 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
549
550 Mutex::Autolock icl(mBinderSerializationLock);
551
552 if (!mDevice.get()) return DEAD_OBJECT;
553
554 // FIXME: Also need check repeating burst.
555 if (!mStreamingRequestList.isEmpty()) {
556 ALOGE("%s: Camera %d: Try to waitUntilIdle when there are active streaming requests",
557 __FUNCTION__, mCameraId);
558 return INVALID_OPERATION;
559 }
560 res = mDevice->waitUntilDrained();
561 ALOGV("%s Done", __FUNCTION__);
562
563 return res;
564 }
565
flush(int64_t * lastFrameNumber)566 status_t CameraDeviceClient::flush(int64_t* lastFrameNumber) {
567 ATRACE_CALL();
568 ALOGV("%s", __FUNCTION__);
569
570 status_t res = OK;
571 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
572
573 Mutex::Autolock icl(mBinderSerializationLock);
574
575 if (!mDevice.get()) return DEAD_OBJECT;
576
577 mStreamingRequestList.clear();
578 return mDevice->flush(lastFrameNumber);
579 }
580
dump(int fd,const Vector<String16> & args)581 status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {
582 String8 result;
583 result.appendFormat("CameraDeviceClient[%d] (%p) dump:\n",
584 mCameraId,
585 getRemoteCallback()->asBinder().get());
586 result.appendFormat(" Current client: %s (PID %d, UID %u)\n",
587 String8(mClientPackageName).string(),
588 mClientPid, mClientUid);
589
590 result.append(" State:\n");
591 result.appendFormat(" Request ID counter: %d\n", mRequestIdCounter);
592 if (!mStreamMap.isEmpty()) {
593 result.append(" Current stream IDs:\n");
594 for (size_t i = 0; i < mStreamMap.size(); i++) {
595 result.appendFormat(" Stream %d\n", mStreamMap.valueAt(i));
596 }
597 } else {
598 result.append(" No streams configured.\n");
599 }
600 write(fd, result.string(), result.size());
601 // TODO: print dynamic/request section from most recent requests
602 mFrameProcessor->dump(fd, args);
603
604 return dumpDevice(fd, args);
605 }
606
notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,const CaptureResultExtras & resultExtras)607 void CameraDeviceClient::notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
608 const CaptureResultExtras& resultExtras) {
609 // Thread safe. Don't bother locking.
610 sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
611
612 if (remoteCb != 0) {
613 remoteCb->onDeviceError(errorCode, resultExtras);
614 }
615 }
616
notifyIdle()617 void CameraDeviceClient::notifyIdle() {
618 // Thread safe. Don't bother locking.
619 sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
620
621 if (remoteCb != 0) {
622 remoteCb->onDeviceIdle();
623 }
624 }
625
notifyShutter(const CaptureResultExtras & resultExtras,nsecs_t timestamp)626 void CameraDeviceClient::notifyShutter(const CaptureResultExtras& resultExtras,
627 nsecs_t timestamp) {
628 // Thread safe. Don't bother locking.
629 sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
630 if (remoteCb != 0) {
631 remoteCb->onCaptureStarted(resultExtras, timestamp);
632 }
633 }
634
635 // TODO: refactor the code below this with IProCameraUser.
636 // it's 100% copy-pasted, so lets not change it right now to make it easier.
637
detachDevice()638 void CameraDeviceClient::detachDevice() {
639 if (mDevice == 0) return;
640
641 ALOGV("Camera %d: Stopping processors", mCameraId);
642
643 mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
644 FRAME_PROCESSOR_LISTENER_MAX_ID,
645 /*listener*/this);
646 mFrameProcessor->requestExit();
647 ALOGV("Camera %d: Waiting for threads", mCameraId);
648 mFrameProcessor->join();
649 ALOGV("Camera %d: Disconnecting device", mCameraId);
650
651 // WORKAROUND: HAL refuses to disconnect while there's streams in flight
652 {
653 mDevice->clearStreamingRequest();
654
655 status_t code;
656 if ((code = mDevice->waitUntilDrained()) != OK) {
657 ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
658 code);
659 }
660 }
661
662 Camera2ClientBase::detachDevice();
663 }
664
665 /** Device-related methods */
onResultAvailable(const CaptureResult & result)666 void CameraDeviceClient::onResultAvailable(const CaptureResult& result) {
667 ATRACE_CALL();
668 ALOGV("%s", __FUNCTION__);
669
670 // Thread-safe. No lock necessary.
671 sp<ICameraDeviceCallbacks> remoteCb = mRemoteCallback;
672 if (remoteCb != NULL) {
673 remoteCb->onResultReceived(result.mMetadata, result.mResultExtras);
674 }
675 }
676
677 // TODO: move to Camera2ClientBase
enforceRequestPermissions(CameraMetadata & metadata)678 bool CameraDeviceClient::enforceRequestPermissions(CameraMetadata& metadata) {
679
680 const int pid = IPCThreadState::self()->getCallingPid();
681 const int selfPid = getpid();
682 camera_metadata_entry_t entry;
683
684 /**
685 * Mixin default important security values
686 * - android.led.transmit = defaulted ON
687 */
688 CameraMetadata staticInfo = mDevice->info();
689 entry = staticInfo.find(ANDROID_LED_AVAILABLE_LEDS);
690 for(size_t i = 0; i < entry.count; ++i) {
691 uint8_t led = entry.data.u8[i];
692
693 switch(led) {
694 case ANDROID_LED_AVAILABLE_LEDS_TRANSMIT: {
695 uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON;
696 if (!metadata.exists(ANDROID_LED_TRANSMIT)) {
697 metadata.update(ANDROID_LED_TRANSMIT,
698 &transmitDefault, 1);
699 }
700 break;
701 }
702 }
703 }
704
705 // We can do anything!
706 if (pid == selfPid) {
707 return true;
708 }
709
710 /**
711 * Permission check special fields in the request
712 * - android.led.transmit = android.permission.CAMERA_DISABLE_TRANSMIT
713 */
714 entry = metadata.find(ANDROID_LED_TRANSMIT);
715 if (entry.count > 0 && entry.data.u8[0] != ANDROID_LED_TRANSMIT_ON) {
716 String16 permissionString =
717 String16("android.permission.CAMERA_DISABLE_TRANSMIT_LED");
718 if (!checkCallingPermission(permissionString)) {
719 const int uid = IPCThreadState::self()->getCallingUid();
720 ALOGE("Permission Denial: "
721 "can't disable transmit LED pid=%d, uid=%d", pid, uid);
722 return false;
723 }
724 }
725
726 return true;
727 }
728
getRotationTransformLocked(int32_t * transform)729 status_t CameraDeviceClient::getRotationTransformLocked(int32_t* transform) {
730 ALOGV("%s: begin", __FUNCTION__);
731
732 const CameraMetadata& staticInfo = mDevice->info();
733 return CameraUtils::getRotationTransform(staticInfo, transform);
734 }
735
736 } // namespace android
737