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