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