blob: 72126c16a38a6976c82e787afd361b47a58358f1 [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
19// #define LOG_NDEBUG 0
20
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>
26
27#include "common/CameraDeviceBase.h"
28#include "api2/CameraDeviceClient.h"
29
30
Igor Murashkine7ee7632013-06-11 18:10:18 -070031
32namespace android {
33using namespace camera2;
34
35CameraDeviceClientBase::CameraDeviceClientBase(
36 const sp<CameraService>& cameraService,
37 const sp<ICameraDeviceCallbacks>& remoteCallback,
38 const String16& clientPackageName,
39 int cameraId,
40 int cameraFacing,
41 int clientPid,
42 uid_t clientUid,
43 int servicePid) :
44 BasicClient(cameraService, remoteCallback->asBinder(), clientPackageName,
45 cameraId, cameraFacing, clientPid, clientUid, servicePid),
46 mRemoteCallback(remoteCallback) {
47}
Igor Murashkine7ee7632013-06-11 18:10:18 -070048
49// Interface used by CameraService
50
51CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
52 const sp<ICameraDeviceCallbacks>& remoteCallback,
53 const String16& clientPackageName,
54 int cameraId,
55 int cameraFacing,
56 int clientPid,
57 uid_t clientUid,
58 int servicePid) :
59 Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
60 cameraId, cameraFacing, clientPid, clientUid, servicePid),
61 mRequestIdCounter(0) {
62
63 ATRACE_CALL();
64 ALOGI("CameraDeviceClient %d: Opened", cameraId);
65}
66
67status_t CameraDeviceClient::initialize(camera_module_t *module)
68{
69 ATRACE_CALL();
70 status_t res;
71
72 res = Camera2ClientBase::initialize(module);
73 if (res != OK) {
74 return res;
75 }
76
77 String8 threadName;
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070078 mFrameProcessor = new FrameProcessorBase(mDevice);
Igor Murashkine7ee7632013-06-11 18:10:18 -070079 threadName = String8::format("CDU-%d-FrameProc", mCameraId);
80 mFrameProcessor->run(threadName.string());
81
82 mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
83 FRAME_PROCESSOR_LISTENER_MAX_ID,
84 /*listener*/this);
85
86 return OK;
87}
88
89CameraDeviceClient::~CameraDeviceClient() {
90}
91
92status_t CameraDeviceClient::submitRequest(sp<CaptureRequest> request,
93 bool streaming) {
94 ATRACE_CALL();
95 ALOGV("%s", __FUNCTION__);
96
97 status_t res;
98
99 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
100
101 Mutex::Autolock icl(mBinderSerializationLock);
102
103 if (!mDevice.get()) return DEAD_OBJECT;
104
105 if (request == 0) {
106 ALOGE("%s: Camera %d: Sent null request. Rejecting request.",
107 __FUNCTION__, mCameraId);
108 return BAD_VALUE;
109 }
110
111 CameraMetadata metadata(request->mMetadata);
112
113 if (metadata.isEmpty()) {
114 ALOGE("%s: Camera %d: Sent empty metadata packet. Rejecting request.",
115 __FUNCTION__, mCameraId);
116 return BAD_VALUE;
117 } else if (request->mSurfaceList.size() == 0) {
118 ALOGE("%s: Camera %d: Requests must have at least one surface target. "
119 "Rejecting request.", __FUNCTION__, mCameraId);
120 return BAD_VALUE;
121 }
122
123 if (!enforceRequestPermissions(metadata)) {
124 // Callee logs
125 return PERMISSION_DENIED;
126 }
127
128 /**
129 * Write in the output stream IDs which we calculate from
130 * the capture request's list of surface targets
131 */
Zhijun Hed1d64672013-09-06 15:00:01 -0700132 Vector<int32_t> outputStreamIds;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700133 outputStreamIds.setCapacity(request->mSurfaceList.size());
134 for (size_t i = 0; i < request->mSurfaceList.size(); ++i) {
135 sp<Surface> surface = request->mSurfaceList[i];
136
137 if (surface == 0) continue;
138
139 sp<IGraphicBufferProducer> gbp = surface->getIGraphicBufferProducer();
140 int idx = mStreamMap.indexOfKey(gbp->asBinder());
141
142 // Trying to submit request with surface that wasn't created
143 if (idx == NAME_NOT_FOUND) {
144 ALOGE("%s: Camera %d: Tried to submit a request with a surface that"
145 " we have not called createStream on",
146 __FUNCTION__, mCameraId);
147 return BAD_VALUE;
148 }
149
150 int streamId = mStreamMap.valueAt(idx);
151 outputStreamIds.push_back(streamId);
152 ALOGV("%s: Camera %d: Appending output stream %d to request",
153 __FUNCTION__, mCameraId, streamId);
154 }
155
156 metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS, &outputStreamIds[0],
157 outputStreamIds.size());
158
Igor Murashkine7ee7632013-06-11 18:10:18 -0700159 int32_t requestId = mRequestIdCounter++;
160 metadata.update(ANDROID_REQUEST_ID, &requestId, /*size*/1);
161 ALOGV("%s: Camera %d: Submitting request with ID %d",
162 __FUNCTION__, mCameraId, requestId);
163
164 if (streaming) {
165 res = mDevice->setStreamingRequest(metadata);
166 if (res != OK) {
167 ALOGE("%s: Camera %d: Got error %d after trying to set streaming "
168 "request", __FUNCTION__, mCameraId, res);
169 } else {
Zhijun Hefe0799e2013-07-19 13:18:43 -0700170 mStreamingRequestList.push_back(requestId);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700171 }
172 } else {
173 res = mDevice->capture(metadata);
174 if (res != OK) {
175 ALOGE("%s: Camera %d: Got error %d after trying to set capture",
176 __FUNCTION__, mCameraId, res);
177 }
178 }
179
180 ALOGV("%s: Camera %d: End of function", __FUNCTION__, mCameraId);
181 if (res == OK) {
182 return requestId;
183 }
184
185 return res;
186}
187
188status_t CameraDeviceClient::cancelRequest(int requestId) {
189 ATRACE_CALL();
190 ALOGV("%s, requestId = %d", __FUNCTION__, requestId);
191
192 status_t res;
193
194 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
195
196 Mutex::Autolock icl(mBinderSerializationLock);
197
198 if (!mDevice.get()) return DEAD_OBJECT;
199
200 Vector<int>::iterator it, end;
201 for (it = mStreamingRequestList.begin(), end = mStreamingRequestList.end();
202 it != end; ++it) {
203 if (*it == requestId) {
204 break;
205 }
206 }
207
208 if (it == end) {
209 ALOGE("%s: Camera%d: Did not find request id %d in list of streaming "
210 "requests", __FUNCTION__, mCameraId, requestId);
211 return BAD_VALUE;
212 }
213
214 res = mDevice->clearStreamingRequest();
215
216 if (res == OK) {
217 ALOGV("%s: Camera %d: Successfully cleared streaming request",
218 __FUNCTION__, mCameraId);
219 mStreamingRequestList.erase(it);
220 }
221
222 return res;
223}
224
225status_t CameraDeviceClient::deleteStream(int streamId) {
226 ATRACE_CALL();
227 ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId);
228
229 status_t res;
230 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
231
232 Mutex::Autolock icl(mBinderSerializationLock);
233
234 if (!mDevice.get()) return DEAD_OBJECT;
235
236 // Guard against trying to delete non-created streams
237 ssize_t index = NAME_NOT_FOUND;
238 for (size_t i = 0; i < mStreamMap.size(); ++i) {
239 if (streamId == mStreamMap.valueAt(i)) {
240 index = i;
241 break;
242 }
243 }
244
245 if (index == NAME_NOT_FOUND) {
246 ALOGW("%s: Camera %d: Invalid stream ID (%d) specified, no stream "
247 "created yet", __FUNCTION__, mCameraId, streamId);
248 return BAD_VALUE;
249 }
250
251 // Also returns BAD_VALUE if stream ID was not valid
252 res = mDevice->deleteStream(streamId);
253
254 if (res == BAD_VALUE) {
255 ALOGE("%s: Camera %d: Unexpected BAD_VALUE when deleting stream, but we"
256 " already checked and the stream ID (%d) should be valid.",
257 __FUNCTION__, mCameraId, streamId);
258 } else if (res == OK) {
259 mStreamMap.removeItemsAt(index);
260
261 ALOGV("%s: Camera %d: Successfully deleted stream ID (%d)",
262 __FUNCTION__, mCameraId, streamId);
263 }
264
265 return res;
266}
267
268status_t CameraDeviceClient::createStream(int width, int height, int format,
269 const sp<IGraphicBufferProducer>& bufferProducer)
270{
271 ATRACE_CALL();
272 ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
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 // Don't create multiple streams for the same target surface
282 {
283 ssize_t index = mStreamMap.indexOfKey(bufferProducer->asBinder());
284 if (index != NAME_NOT_FOUND) {
285 ALOGW("%s: Camera %d: Buffer producer already has a stream for it "
286 "(ID %d)",
287 __FUNCTION__, mCameraId, index);
288 return ALREADY_EXISTS;
289 }
290 }
291
Eino-Ville Talvala1da3b602013-09-26 15:28:55 -0700292 // HACK b/10949105
293 // Query consumer usage bits to set async operation mode for
294 // GLConsumer using controlledByApp parameter.
295 bool useAsync = false;
296 int32_t consumerUsage;
297 if ((res = bufferProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS,
298 &consumerUsage)) != OK) {
299 ALOGE("%s: Camera %d: Failed to query consumer usage", __FUNCTION__,
300 mCameraId);
301 return res;
302 }
303 if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
304 ALOGW("%s: Camera %d: Forcing asynchronous mode for stream",
305 __FUNCTION__, mCameraId);
306 useAsync = true;
307 }
308
Igor Murashkine7ee7632013-06-11 18:10:18 -0700309 sp<IBinder> binder;
310 sp<ANativeWindow> anw;
311 if (bufferProducer != 0) {
312 binder = bufferProducer->asBinder();
Eino-Ville Talvala1da3b602013-09-26 15:28:55 -0700313 anw = new Surface(bufferProducer, useAsync);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700314 }
315
316 // TODO: remove w,h,f since we are ignoring them
317
318 if ((res = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, &width)) != OK) {
319 ALOGE("%s: Camera %d: Failed to query Surface width", __FUNCTION__,
320 mCameraId);
321 return res;
322 }
323 if ((res = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, &height)) != OK) {
324 ALOGE("%s: Camera %d: Failed to query Surface height", __FUNCTION__,
325 mCameraId);
326 return res;
327 }
328 if ((res = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &format)) != OK) {
329 ALOGE("%s: Camera %d: Failed to query Surface format", __FUNCTION__,
330 mCameraId);
331 return res;
332 }
333
334 // FIXME: remove this override since the default format should be
335 // IMPLEMENTATION_DEFINED. b/9487482
Igor Murashkin15811012013-07-29 12:25:59 -0700336 if (format >= HAL_PIXEL_FORMAT_RGBA_8888 &&
337 format <= HAL_PIXEL_FORMAT_BGRA_8888) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700338 ALOGW("%s: Camera %d: Overriding format 0x%x to IMPLEMENTATION_DEFINED",
339 __FUNCTION__, mCameraId, format);
340 format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
341 }
342
343 // TODO: add startConfigure/stopConfigure call to CameraDeviceBase
344 // this will make it so Camera3Device doesn't call configure_streams
345 // after each call, but only once we are done with all.
346
347 int streamId = -1;
Eino-Ville Talvalac7ba4a52013-07-01 09:23:55 -0700348 if (format == HAL_PIXEL_FORMAT_BLOB) {
349 // JPEG buffers need to be sized for maximum possible compressed size
350 CameraMetadata staticInfo = mDevice->info();
351 camera_metadata_entry_t entry = staticInfo.find(ANDROID_JPEG_MAX_SIZE);
352 if (entry.count == 0) {
353 ALOGE("%s: Camera %d: Can't find maximum JPEG size in "
354 "static metadata!", __FUNCTION__, mCameraId);
355 return INVALID_OPERATION;
356 }
357 int32_t maxJpegSize = entry.data.i32[0];
358 res = mDevice->createStream(anw, width, height, format, maxJpegSize,
359 &streamId);
360 } else {
361 // All other streams are a known size
362 res = mDevice->createStream(anw, width, height, format, /*size*/0,
363 &streamId);
364 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700365
366 if (res == OK) {
367 mStreamMap.add(bufferProducer->asBinder(), streamId);
368
369 ALOGV("%s: Camera %d: Successfully created a new stream ID %d",
370 __FUNCTION__, mCameraId, streamId);
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700371
372 /**
373 * Set the stream transform flags to automatically
374 * rotate the camera stream for preview use cases.
375 */
376 int32_t transform = 0;
377 res = getRotationTransformLocked(&transform);
378
379 if (res != OK) {
380 // Error logged by getRotationTransformLocked.
381 return res;
382 }
383
384 res = mDevice->setStreamTransform(streamId, transform);
385 if (res != OK) {
386 ALOGE("%s: Failed to set stream transform (stream id %d)",
387 __FUNCTION__, streamId);
388 return res;
389 }
390
Igor Murashkine7ee7632013-06-11 18:10:18 -0700391 return streamId;
392 }
393
394 return res;
395}
396
397// Create a request object from a template.
398status_t CameraDeviceClient::createDefaultRequest(int templateId,
399 /*out*/
400 CameraMetadata* request)
401{
402 ATRACE_CALL();
403 ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);
404
405 status_t res;
406 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
407
408 Mutex::Autolock icl(mBinderSerializationLock);
409
410 if (!mDevice.get()) return DEAD_OBJECT;
411
412 CameraMetadata metadata;
413 if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK &&
414 request != NULL) {
415
416 request->swap(metadata);
417 }
418
419 return res;
420}
421
Igor Murashkin099b4572013-07-12 17:52:16 -0700422status_t CameraDeviceClient::getCameraInfo(/*out*/CameraMetadata* info)
Igor Murashkine7ee7632013-06-11 18:10:18 -0700423{
424 ATRACE_CALL();
425 ALOGV("%s", __FUNCTION__);
426
427 status_t res = OK;
428
Igor Murashkine7ee7632013-06-11 18:10:18 -0700429 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
430
431 Mutex::Autolock icl(mBinderSerializationLock);
432
433 if (!mDevice.get()) return DEAD_OBJECT;
434
Igor Murashkin099b4572013-07-12 17:52:16 -0700435 if (info != NULL) {
436 *info = mDevice->info(); // static camera metadata
437 // TODO: merge with device-specific camera metadata
438 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700439
440 return res;
441}
442
Zhijun He2ab500c2013-07-23 08:02:53 -0700443status_t CameraDeviceClient::waitUntilIdle()
444{
445 ATRACE_CALL();
446 ALOGV("%s", __FUNCTION__);
447
448 status_t res = OK;
449 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
450
451 Mutex::Autolock icl(mBinderSerializationLock);
452
453 if (!mDevice.get()) return DEAD_OBJECT;
454
455 // FIXME: Also need check repeating burst.
456 if (!mStreamingRequestList.isEmpty()) {
457 ALOGE("%s: Camera %d: Try to waitUntilIdle when there are active streaming requests",
458 __FUNCTION__, mCameraId);
459 return INVALID_OPERATION;
460 }
461 res = mDevice->waitUntilDrained();
462 ALOGV("%s Done", __FUNCTION__);
463
464 return res;
465}
466
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -0700467status_t CameraDeviceClient::flush() {
468 ATRACE_CALL();
469 ALOGV("%s", __FUNCTION__);
470
471 status_t res = OK;
472 if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
473
474 Mutex::Autolock icl(mBinderSerializationLock);
475
476 if (!mDevice.get()) return DEAD_OBJECT;
477
478 return mDevice->flush();
479}
480
Igor Murashkine7ee7632013-06-11 18:10:18 -0700481status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {
482 String8 result;
483 result.appendFormat("CameraDeviceClient[%d] (%p) PID: %d, dump:\n",
484 mCameraId,
485 getRemoteCallback()->asBinder().get(),
486 mClientPid);
487 result.append(" State: ");
488
489 // TODO: print dynamic/request section from most recent requests
490 mFrameProcessor->dump(fd, args);
491
492 return dumpDevice(fd, args);
493}
494
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700495
496void CameraDeviceClient::notifyError() {
497 // Thread safe. Don't bother locking.
498 sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
499
500 if (remoteCb != 0) {
501 remoteCb->onDeviceError(ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE);
502 }
503}
504
505void CameraDeviceClient::notifyIdle() {
506 // Thread safe. Don't bother locking.
507 sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
508
509 if (remoteCb != 0) {
510 remoteCb->onDeviceIdle();
511 }
512}
513
514void CameraDeviceClient::notifyShutter(int requestId,
515 nsecs_t timestamp) {
516 // Thread safe. Don't bother locking.
517 sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
518 if (remoteCb != 0) {
519 remoteCb->onCaptureStarted(requestId, timestamp);
520 }
521}
522
Igor Murashkine7ee7632013-06-11 18:10:18 -0700523// TODO: refactor the code below this with IProCameraUser.
524// it's 100% copy-pasted, so lets not change it right now to make it easier.
525
526void CameraDeviceClient::detachDevice() {
527 if (mDevice == 0) return;
528
529 ALOGV("Camera %d: Stopping processors", mCameraId);
530
531 mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
532 FRAME_PROCESSOR_LISTENER_MAX_ID,
533 /*listener*/this);
534 mFrameProcessor->requestExit();
535 ALOGV("Camera %d: Waiting for threads", mCameraId);
536 mFrameProcessor->join();
537 ALOGV("Camera %d: Disconnecting device", mCameraId);
538
539 // WORKAROUND: HAL refuses to disconnect while there's streams in flight
540 {
541 mDevice->clearStreamingRequest();
542
543 status_t code;
544 if ((code = mDevice->waitUntilDrained()) != OK) {
545 ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
546 code);
547 }
548 }
549
550 Camera2ClientBase::detachDevice();
551}
552
553/** Device-related methods */
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700554void CameraDeviceClient::onFrameAvailable(int32_t requestId,
555 const CameraMetadata& frame) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700556 ATRACE_CALL();
557 ALOGV("%s", __FUNCTION__);
558
Igor Murashkin4fb55c12013-08-29 17:43:01 -0700559 // Thread-safe. No lock necessary.
560 sp<ICameraDeviceCallbacks> remoteCb = mRemoteCallback;
561 if (remoteCb != NULL) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700562 ALOGV("%s: frame = %p ", __FUNCTION__, &frame);
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700563 remoteCb->onResultReceived(requestId, frame);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700564 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700565}
566
567// TODO: move to Camera2ClientBase
568bool CameraDeviceClient::enforceRequestPermissions(CameraMetadata& metadata) {
569
570 const int pid = IPCThreadState::self()->getCallingPid();
571 const int selfPid = getpid();
572 camera_metadata_entry_t entry;
573
574 /**
575 * Mixin default important security values
576 * - android.led.transmit = defaulted ON
577 */
578 CameraMetadata staticInfo = mDevice->info();
579 entry = staticInfo.find(ANDROID_LED_AVAILABLE_LEDS);
580 for(size_t i = 0; i < entry.count; ++i) {
581 uint8_t led = entry.data.u8[i];
582
583 switch(led) {
584 case ANDROID_LED_AVAILABLE_LEDS_TRANSMIT: {
585 uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON;
586 if (!metadata.exists(ANDROID_LED_TRANSMIT)) {
587 metadata.update(ANDROID_LED_TRANSMIT,
588 &transmitDefault, 1);
589 }
590 break;
591 }
592 }
593 }
594
595 // We can do anything!
596 if (pid == selfPid) {
597 return true;
598 }
599
600 /**
601 * Permission check special fields in the request
602 * - android.led.transmit = android.permission.CAMERA_DISABLE_TRANSMIT
603 */
604 entry = metadata.find(ANDROID_LED_TRANSMIT);
605 if (entry.count > 0 && entry.data.u8[0] != ANDROID_LED_TRANSMIT_ON) {
606 String16 permissionString =
607 String16("android.permission.CAMERA_DISABLE_TRANSMIT_LED");
608 if (!checkCallingPermission(permissionString)) {
609 const int uid = IPCThreadState::self()->getCallingUid();
610 ALOGE("Permission Denial: "
611 "can't disable transmit LED pid=%d, uid=%d", pid, uid);
612 return false;
613 }
614 }
615
616 return true;
617}
618
Igor Murashkinf8b2a6f2013-09-17 17:03:28 -0700619status_t CameraDeviceClient::getRotationTransformLocked(int32_t* transform) {
620 ALOGV("%s: begin", __FUNCTION__);
621
622 if (transform == NULL) {
623 ALOGW("%s: null transform", __FUNCTION__);
624 return BAD_VALUE;
625 }
626
627 *transform = 0;
628
629 const CameraMetadata& staticInfo = mDevice->info();
630 camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_SENSOR_ORIENTATION);
631 if (entry.count == 0) {
632 ALOGE("%s: Camera %d: Can't find android.sensor.orientation in "
633 "static metadata!", __FUNCTION__, mCameraId);
634 return INVALID_OPERATION;
635 }
636
637 int32_t& flags = *transform;
638
639 int orientation = entry.data.i32[0];
640 switch (orientation) {
641 case 0:
642 flags = 0;
643 break;
644 case 90:
645 flags = NATIVE_WINDOW_TRANSFORM_ROT_90;
646 break;
647 case 180:
648 flags = NATIVE_WINDOW_TRANSFORM_ROT_180;
649 break;
650 case 270:
651 flags = NATIVE_WINDOW_TRANSFORM_ROT_270;
652 break;
653 default:
654 ALOGE("%s: Invalid HAL android.sensor.orientation value: %d",
655 __FUNCTION__, orientation);
656 return INVALID_OPERATION;
657 }
658
659 /**
660 * This magic flag makes surfaceflinger un-rotate the buffers
661 * to counter the extra global device UI rotation whenever the user
662 * physically rotates the device.
663 *
664 * By doing this, the camera buffer always ends up aligned
665 * with the physical camera for a "see through" effect.
666 *
667 * In essence, the buffer only gets rotated during preview use-cases.
668 * The user is still responsible to re-create streams of the proper
669 * aspect ratio, or the preview will end up looking non-uniformly
670 * stretched.
671 */
672 flags |= NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
673
674 ALOGV("%s: final transform = 0x%x", __FUNCTION__, flags);
675
676 return OK;
677}
678
Igor Murashkine7ee7632013-06-11 18:10:18 -0700679} // namespace android