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