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
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}
49
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;
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
91CameraDeviceClient::~CameraDeviceClient() {
92}
93
94status_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
103status_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
213status_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
250status_t CameraDeviceClient::beginConfigure() {
251    // TODO: Implement this.
252    ALOGE("%s: Not implemented yet.", __FUNCTION__);
253    return OK;
254}
255
256status_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
270status_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
311status_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
441bool 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
490int64_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.
497status_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
521status_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
542status_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
566status_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
581status_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
607void 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
617void 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
626void 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
638void 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 */
666void 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
678bool 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
729status_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