Home | History | Annotate | Download | only in api2
      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 
     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 
     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 
     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 
     91 CameraDeviceClient::~CameraDeviceClient() {
     92 }
     93 
     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 
    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 
    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 
    250 status_t CameraDeviceClient::beginConfigure() {
    251     // TODO: Implement this.
    252     ALOGE("%s: Not implemented yet.", __FUNCTION__);
    253     return OK;
    254 }
    255 
    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 
    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 
    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 
    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 
    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.
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 */
    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
    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 
    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