blob: b8611f8c16e0dd39b47af0fa1c3d350cc20b9dc9 [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) :
45 BasicClient(cameraService, remoteCallback->asBinder(), clientPackageName,
46 cameraId, cameraFacing, clientPid, clientUid, servicePid),
47 mRemoteCallback(remoteCallback) {
48}
Igor Murashkine7ee7632013-06-11 18:10:18 -070049
50// Interface used by CameraService
51
52CameraDeviceClient::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
68status_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;
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070079 mFrameProcessor = new FrameProcessorBase(mDevice);
Igor Murashkine7ee7632013-06-11 18:10:18 -070080 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,
Eino-Ville Talvala184dfe42013-11-07 15:13:16 -080085 /*listener*/this,
Zhijun He25a0aef2014-06-25 11:40:02 -070086 /*sendPartials*/true);
Igor Murashkine7ee7632013-06-11 18:10:18 -070087
88 return OK;
89}
90
91CameraDeviceClient::~CameraDeviceClient() {
92}
93
94status_t CameraDeviceClient::submitRequest(sp<CaptureRequest> request,
Jianing Weicb0652e2014-03-12 18:29:36 -070095 bool streaming,
96 /*out*/
97 int64_t* lastFrameNumber) {
98 List<sp<CaptureRequest> > requestList;
99 requestList.push_back(request);
100 return submitRequestList(requestList, streaming, lastFrameNumber);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700101}
102
Jianing Wei90e59c92014-03-12 18:29:36 -0700103status_t CameraDeviceClient::submitRequestList(List<sp<CaptureRequest> > requests,
Jianing Weicb0652e2014-03-12 18:29:36 -0700104 bool streaming, int64_t* lastFrameNumber) {
Jianing Wei90e59c92014-03-12 18:29:36 -0700105 ATRACE_CALL();
Mark Salyzyn50468412014-06-18 16:33:43 -0700106 ALOGV("%s-start of function. Request list size %zu", __FUNCTION__, requests.size());
Jianing Wei90e59c92014-03-12 18:29:36 -0700107
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());
Jianing Weicb0652e2014-03-12 18:29:36 -0700155 for (size_t i = 0; i < request->mSurfaceList.size(); ++i) {
156 sp<Surface> surface = request->mSurfaceList[i];
Jianing Wei90e59c92014-03-12 18:29:36 -0700157 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
Mark Salyzyn50468412014-06-18 16:33:43 -0700181 ALOGV("%s: Camera %d: Creating request with ID %d (%d of %zu)",
Jianing Wei90e59c92014-03-12 18:29:36 -0700182 __FUNCTION__, mCameraId, requestId, loopCounter, requests.size());
183
184 metadataRequestList.push_back(metadata);
185 }
186 mRequestIdCounter++;
187
188 if (streaming) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700189 res = mDevice->setStreamingRequestList(metadataRequestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -0700190 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 {
Jianing Weicb0652e2014-03-12 18:29:36 -0700197 res = mDevice->captureList(metadataRequestList, lastFrameNumber);
Jianing Wei90e59c92014-03-12 18:29:36 -0700198 if (res != OK) {
199 ALOGE("%s: Camera %d: Got error %d after trying to set capture",
200 __FUNCTION__, mCameraId, res);
201 }
Jianing Weicb0652e2014-03-12 18:29:36 -0700202 ALOGV("%s: requestId = %d ", __FUNCTION__, requestId);
Jianing Wei90e59c92014-03-12 18:29:36 -0700203 }
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
Jianing Weicb0652e2014-03-12 18:29:36 -0700213status_t CameraDeviceClient::cancelRequest(int requestId, int64_t* lastFrameNumber) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700214 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
Jianing Weicb0652e2014-03-12 18:29:36 -0700239 res = mDevice->clearStreamingRequest(lastFrameNumber);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700240
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
Ruben Brunkb2119af2014-05-09 19:57:56 -0700250status_t CameraDeviceClient::beginConfigure() {
251 // TODO: Implement this.
252 ALOGE("%s: Not implemented yet.", __FUNCTION__);
253 return OK;
254}
255
256status_t CameraDeviceClient::endConfigure() {
257 // TODO: Implement this.
258 ALOGE("%s: Not implemented yet.", __FUNCTION__);
259 return OK;
260}
261
Igor Murashkine7ee7632013-06-11 18:10:18 -0700262status_t CameraDeviceClient::deleteStream(int streamId) {
263 ATRACE_CALL();
264 ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);
265
266 status_t res;
267 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
268
269 Mutex::Autolock icl(mBinderSerializationLock);
270
271 if (!mDevice.get()) return DEAD_OBJECT;
272
273 // Guard against trying to delete non-created streams
274 ssize_t index = NAME_NOT_FOUND;
275 for (size_t i = 0; i < mStreamMap.size(); ++i) {
276 if (streamId == mStreamMap.valueAt(i)) {
277 index = i;
278 break;
279 }
280 }
281
282 if (index == NAME_NOT_FOUND) {
283 ALOGW("%s: Camera %d: Invalid stream ID (%d) specified, no stream "
284 "created yet", __FUNCTION__, mCameraId, streamId);
285 return BAD_VALUE;
286 }
287
288 // Also returns BAD_VALUE if stream ID was not valid
289 res = mDevice->deleteStream(streamId);
290
291 if (res == BAD_VALUE) {
292 ALOGE("%s: Camera %d: Unexpected BAD_VALUE when deleting stream, but we"
293 " already checked and the stream ID (%d) should be valid.",
294 __FUNCTION__, mCameraId, streamId);
295 } else if (res == OK) {
296 mStreamMap.removeItemsAt(index);
297
Igor Murashkine7ee7632013-06-11 18:10:18 -0700298 }
299
300 return res;
301}
302
303status_t CameraDeviceClient::createStream(int width, int height, int format,
304 const sp<IGraphicBufferProducer>& bufferProducer)
305{
306 ATRACE_CALL();
307 ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
308
309 status_t res;
310 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
311
312 Mutex::Autolock icl(mBinderSerializationLock);
313
Yin-Chia Yeh89f14da2014-06-10 16:05:44 -0700314 if (bufferProducer == NULL) {
315 ALOGE("%s: bufferProducer must not be null", __FUNCTION__);
316 return BAD_VALUE;
317 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700318 if (!mDevice.get()) return DEAD_OBJECT;
319
320 // Don't create multiple streams for the same target surface
321 {
322 ssize_t index = mStreamMap.indexOfKey(bufferProducer->asBinder());
323 if (index != NAME_NOT_FOUND) {
324 ALOGW("%s: Camera %d: Buffer producer already has a stream for it "
Colin Crosse5729fa2014-03-21 15:04:25 -0700325 "(ID %zd)",
Igor Murashkine7ee7632013-06-11 18:10:18 -0700326 __FUNCTION__, mCameraId, index);
327 return ALREADY_EXISTS;
328 }
329 }
330
Eino-Ville Talvala1da3b602013-09-26 15:28:55 -0700331 // HACK b/10949105
332 // Query consumer usage bits to set async operation mode for
333 // GLConsumer using controlledByApp parameter.
334 bool useAsync = false;
335 int32_t consumerUsage;
336 if ((res = bufferProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS,
337 &consumerUsage)) != OK) {
338 ALOGE("%s: Camera %d: Failed to query consumer usage", __FUNCTION__,
339 mCameraId);
340 return res;
341 }
342 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
343 ALOGW("%s: Camera %d: Forcing asynchronous mode for stream",
344 __FUNCTION__, mCameraId);
345 useAsync = true;
346 }
347
Igor Murashkine7ee7632013-06-11 18:10:18 -0700348 sp<IBinder> binder;
349 sp<ANativeWindow> anw;
350 if (bufferProducer != 0) {
351 binder = bufferProducer->asBinder();
Eino-Ville Talvala1da3b602013-09-26 15:28:55 -0700352 anw = new Surface(bufferProducer, useAsync);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700353 }
354
355 // TODO: remove w,h,f since we are ignoring them
356
357 if ((res = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, &width)) != OK) {
358 ALOGE("%s: Camera %d: Failed to query Surface width", __FUNCTION__,
359 mCameraId);
360 return res;
361 }
362 if ((res = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, &height)) != OK) {
363 ALOGE("%s: Camera %d: Failed to query Surface height", __FUNCTION__,
364 mCameraId);
365 return res;
366 }
367 if ((res = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &format)) != OK) {
368 ALOGE("%s: Camera %d: Failed to query Surface format", __FUNCTION__,
369 mCameraId);
370 return res;
371 }
372
373 // FIXME: remove this override since the default format should be
374 // IMPLEMENTATION_DEFINED. b/9487482
Igor Murashkin15811012013-07-29 12:25:59 -0700375 if (format >= HAL_PIXEL_FORMAT_RGBA_8888 &&
376 format <= HAL_PIXEL_FORMAT_BGRA_8888) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700377 ALOGW("%s: Camera %d: Overriding format 0x%x to IMPLEMENTATION_DEFINED",
378 __FUNCTION__, mCameraId, format);
379 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
380 }
381
382 // TODO: add startConfigure/stopConfigure call to CameraDeviceBase
383 // this will make it so Camera3Device doesn't call configure_streams
384 // after each call, but only once we are done with all.
385
386 int streamId = -1;
Eino-Ville Talvalac7ba4a52013-07-01 09:23:55 -0700387 if (format == HAL_PIXEL_FORMAT_BLOB) {
388 // JPEG buffers need to be sized for maximum possible compressed size
389 CameraMetadata staticInfo = mDevice->info();
390 camera_metadata_entry_t entry = staticInfo.find(ANDROID_JPEG_MAX_SIZE);
391 if (entry.count == 0) {
392 ALOGE("%s: Camera %d: Can't find maximum JPEG size in "
393 "static metadata!", __FUNCTION__, mCameraId);
394 return INVALID_OPERATION;
395 }
396 int32_t maxJpegSize = entry.data.i32[0];
397 res = mDevice->createStream(anw, width, height, format, maxJpegSize,
398 &streamId);
399 } else {
400 // All other streams are a known size
401 res = mDevice->createStream(anw, width, height, format, /*size*/0,
402 &streamId);
403 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700404
405 if (res == OK) {
406 mStreamMap.add(bufferProducer->asBinder(), streamId);
407
408 ALOGV("%s: Camera %d: Successfully created a new stream ID %d",
409 __FUNCTION__, mCameraId, streamId);
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700410
411 /**
412 * Set the stream transform flags to automatically
413 * rotate the camera stream for preview use cases.
414 */
415 int32_t transform = 0;
416 res = getRotationTransformLocked(&transform);
417
418 if (res != OK) {
419 // Error logged by getRotationTransformLocked.
420 return res;
421 }
422
423 res = mDevice->setStreamTransform(streamId, transform);
424 if (res != OK) {
425 ALOGE("%s: Failed to set stream transform (stream id %d)",
426 __FUNCTION__, streamId);
427 return res;
428 }
429
Igor Murashkine7ee7632013-06-11 18:10:18 -0700430 return streamId;
431 }
432
433 return res;
434}
435
436// Create a request object from a template.
437status_t CameraDeviceClient::createDefaultRequest(int templateId,
438 /*out*/
439 CameraMetadata* request)
440{
441 ATRACE_CALL();
442 ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);
443
444 status_t res;
445 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
446
447 Mutex::Autolock icl(mBinderSerializationLock);
448
449 if (!mDevice.get()) return DEAD_OBJECT;
450
451 CameraMetadata metadata;
452 if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK &&
453 request != NULL) {
454
455 request->swap(metadata);
456 }
457
458 return res;
459}
460
Igor Murashkin099b4572013-07-12 17:52:16 -0700461status_t CameraDeviceClient::getCameraInfo(/*out*/CameraMetadata* info)
Igor Murashkine7ee7632013-06-11 18:10:18 -0700462{
463 ATRACE_CALL();
464 ALOGV("%s", __FUNCTION__);
465
466 status_t res = OK;
467
Igor Murashkine7ee7632013-06-11 18:10:18 -0700468 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
469
470 Mutex::Autolock icl(mBinderSerializationLock);
471
472 if (!mDevice.get()) return DEAD_OBJECT;
473
Igor Murashkin099b4572013-07-12 17:52:16 -0700474 if (info != NULL) {
475 *info = mDevice->info(); // static camera metadata
476 // TODO: merge with device-specific camera metadata
477 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700478
479 return res;
480}
481
Zhijun He2ab500c2013-07-23 08:02:53 -0700482status_t CameraDeviceClient::waitUntilIdle()
483{
484 ATRACE_CALL();
485 ALOGV("%s", __FUNCTION__);
486
487 status_t res = OK;
488 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
489
490 Mutex::Autolock icl(mBinderSerializationLock);
491
492 if (!mDevice.get()) return DEAD_OBJECT;
493
494 // FIXME: Also need check repeating burst.
495 if (!mStreamingRequestList.isEmpty()) {
496 ALOGE("%s: Camera %d: Try to waitUntilIdle when there are active streaming requests",
497 __FUNCTION__, mCameraId);
498 return INVALID_OPERATION;
499 }
500 res = mDevice->waitUntilDrained();
501 ALOGV("%s Done", __FUNCTION__);
502
503 return res;
504}
505
Jianing Weicb0652e2014-03-12 18:29:36 -0700506status_t CameraDeviceClient::flush(int64_t* lastFrameNumber) {
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -0700507 ATRACE_CALL();
508 ALOGV("%s", __FUNCTION__);
509
510 status_t res = OK;
511 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
512
513 Mutex::Autolock icl(mBinderSerializationLock);
514
515 if (!mDevice.get()) return DEAD_OBJECT;
516
Jianing Wei3c76fa32014-04-21 11:34:34 -0700517 mStreamingRequestList.clear();
Jianing Weicb0652e2014-03-12 18:29:36 -0700518 return mDevice->flush(lastFrameNumber);
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -0700519}
520
Igor Murashkine7ee7632013-06-11 18:10:18 -0700521status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {
522 String8 result;
523 result.appendFormat("CameraDeviceClient[%d] (%p) PID: %d, dump:\n",
524 mCameraId,
525 getRemoteCallback()->asBinder().get(),
526 mClientPid);
527 result.append(" State: ");
528
529 // TODO: print dynamic/request section from most recent requests
530 mFrameProcessor->dump(fd, args);
531
532 return dumpDevice(fd, args);
533}
534
Jianing Weicb0652e2014-03-12 18:29:36 -0700535void CameraDeviceClient::notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
536 const CaptureResultExtras& resultExtras) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700537 // Thread safe. Don't bother locking.
538 sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
539
540 if (remoteCb != 0) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700541 remoteCb->onDeviceError(errorCode, resultExtras);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700542 }
543}
544
545void CameraDeviceClient::notifyIdle() {
546 // Thread safe. Don't bother locking.
547 sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
548
549 if (remoteCb != 0) {
550 remoteCb->onDeviceIdle();
551 }
552}
553
Jianing Weicb0652e2014-03-12 18:29:36 -0700554void CameraDeviceClient::notifyShutter(const CaptureResultExtras& resultExtras,
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700555 nsecs_t timestamp) {
556 // Thread safe. Don't bother locking.
557 sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
558 if (remoteCb != 0) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700559 remoteCb->onCaptureStarted(resultExtras, timestamp);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700560 }
561}
562
Igor Murashkine7ee7632013-06-11 18:10:18 -0700563// TODO: refactor the code below this with IProCameraUser.
564// it's 100% copy-pasted, so lets not change it right now to make it easier.
565
566void CameraDeviceClient::detachDevice() {
567 if (mDevice == 0) return;
568
569 ALOGV("Camera %d: Stopping processors", mCameraId);
570
571 mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
572 FRAME_PROCESSOR_LISTENER_MAX_ID,
573 /*listener*/this);
574 mFrameProcessor->requestExit();
575 ALOGV("Camera %d: Waiting for threads", mCameraId);
576 mFrameProcessor->join();
577 ALOGV("Camera %d: Disconnecting device", mCameraId);
578
579 // WORKAROUND: HAL refuses to disconnect while there's streams in flight
580 {
581 mDevice->clearStreamingRequest();
582
583 status_t code;
584 if ((code = mDevice->waitUntilDrained()) != OK) {
585 ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
586 code);
587 }
588 }
589
590 Camera2ClientBase::detachDevice();
591}
592
593/** Device-related methods */
Jianing Weicb0652e2014-03-12 18:29:36 -0700594void CameraDeviceClient::onResultAvailable(const CaptureResult& result) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700595 ATRACE_CALL();
596 ALOGV("%s", __FUNCTION__);
597
Igor Murashkin4fb55c12013-08-29 17:43:01 -0700598 // Thread-safe. No lock necessary.
599 sp<ICameraDeviceCallbacks> remoteCb = mRemoteCallback;
600 if (remoteCb != NULL) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700601 remoteCb->onResultReceived(result.mMetadata, result.mResultExtras);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700602 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700603}
604
605// TODO: move to Camera2ClientBase
606bool CameraDeviceClient::enforceRequestPermissions(CameraMetadata& metadata) {
607
608 const int pid = IPCThreadState::self()->getCallingPid();
609 const int selfPid = getpid();
610 camera_metadata_entry_t entry;
611
612 /**
613 * Mixin default important security values
614 * - android.led.transmit = defaulted ON
615 */
616 CameraMetadata staticInfo = mDevice->info();
617 entry = staticInfo.find(ANDROID_LED_AVAILABLE_LEDS);
618 for(size_t i = 0; i < entry.count; ++i) {
619 uint8_t led = entry.data.u8[i];
620
621 switch(led) {
622 case ANDROID_LED_AVAILABLE_LEDS_TRANSMIT: {
623 uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON;
624 if (!metadata.exists(ANDROID_LED_TRANSMIT)) {
625 metadata.update(ANDROID_LED_TRANSMIT,
626 &transmitDefault, 1);
627 }
628 break;
629 }
630 }
631 }
632
633 // We can do anything!
634 if (pid == selfPid) {
635 return true;
636 }
637
638 /**
639 * Permission check special fields in the request
640 * - android.led.transmit = android.permission.CAMERA_DISABLE_TRANSMIT
641 */
642 entry = metadata.find(ANDROID_LED_TRANSMIT);
643 if (entry.count > 0 && entry.data.u8[0] != ANDROID_LED_TRANSMIT_ON) {
644 String16 permissionString =
645 String16("android.permission.CAMERA_DISABLE_TRANSMIT_LED");
646 if (!checkCallingPermission(permissionString)) {
647 const int uid = IPCThreadState::self()->getCallingUid();
648 ALOGE("Permission Denial: "
649 "can't disable transmit LED pid=%d, uid=%d", pid, uid);
650 return false;
651 }
652 }
653
654 return true;
655}
656
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700657status_t CameraDeviceClient::getRotationTransformLocked(int32_t* transform) {
658 ALOGV("%s: begin", __FUNCTION__);
659
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700660 const CameraMetadata& staticInfo = mDevice->info();
Ruben Brunk5698d442014-06-18 10:39:40 -0700661 return CameraUtils::getRotationTransform(staticInfo, transform);
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700662}
663
Igor Murashkine7ee7632013-06-11 18:10:18 -0700664} // namespace android