CaptureSequencer.cpp revision 7b82efe7a376c882f8f938e1c41b8311a8cdda4a
1/*
2 * Copyright (C) 2012 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 "Camera2-CaptureSequencer"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20
21#include <utils/Log.h>
22#include <utils/Trace.h>
23#include <utils/Vector.h>
24
25#include "api1/Camera2Client.h"
26#include "api1/client2/CaptureSequencer.h"
27#include "api1/client2/BurstCapture.h"
28#include "api1/client2/Parameters.h"
29#include "api1/client2/ZslProcessorInterface.h"
30
31namespace android {
32namespace camera2 {
33
34/** Public members */
35
36CaptureSequencer::CaptureSequencer(wp<Camera2Client> client):
37        Thread(false),
38        mStartCapture(false),
39        mBusy(false),
40        mNewAEState(false),
41        mNewFrameReceived(false),
42        mNewCaptureReceived(false),
43        mShutterNotified(false),
44        mClient(client),
45        mCaptureState(IDLE),
46        mTriggerId(0),
47        mTimeoutCount(0),
48        mCaptureId(Camera2Client::kCaptureRequestIdStart),
49        mMsgType(0) {
50    ALOGV("%s", __FUNCTION__);
51}
52
53CaptureSequencer::~CaptureSequencer() {
54    ALOGV("%s: Exit", __FUNCTION__);
55}
56
57void CaptureSequencer::setZslProcessor(wp<ZslProcessorInterface> processor) {
58    Mutex::Autolock l(mInputMutex);
59    mZslProcessor = processor;
60}
61
62status_t CaptureSequencer::startCapture(int msgType) {
63    ALOGV("%s", __FUNCTION__);
64    ATRACE_CALL();
65    Mutex::Autolock l(mInputMutex);
66    if (mBusy) {
67        ALOGE("%s: Already busy capturing!", __FUNCTION__);
68        return INVALID_OPERATION;
69    }
70    if (!mStartCapture) {
71        mMsgType = msgType;
72        mStartCapture = true;
73        mStartCaptureSignal.signal();
74    }
75    return OK;
76}
77
78status_t CaptureSequencer::waitUntilIdle(nsecs_t timeout) {
79    ATRACE_CALL();
80    ALOGV("%s: Waiting for idle", __FUNCTION__);
81    Mutex::Autolock l(mStateMutex);
82    status_t res = -1;
83    while (mCaptureState != IDLE) {
84        nsecs_t startTime = systemTime();
85
86        res = mStateChanged.waitRelative(mStateMutex, timeout);
87        if (res != OK) return res;
88
89        timeout -= (systemTime() - startTime);
90    }
91    ALOGV("%s: Now idle", __FUNCTION__);
92    return OK;
93}
94
95void CaptureSequencer::notifyAutoExposure(uint8_t newState, int triggerId) {
96    ATRACE_CALL();
97    Mutex::Autolock l(mInputMutex);
98    mAEState = newState;
99    mAETriggerId = triggerId;
100    if (!mNewAEState) {
101        mNewAEState = true;
102        mNewNotifySignal.signal();
103    }
104}
105
106void CaptureSequencer::onFrameAvailable(int32_t frameId,
107        const CameraMetadata &frame) {
108    ALOGV("%s: Listener found new frame", __FUNCTION__);
109    ATRACE_CALL();
110    Mutex::Autolock l(mInputMutex);
111    mNewFrameId = frameId;
112    mNewFrame = frame;
113    if (!mNewFrameReceived) {
114        mNewFrameReceived = true;
115        mNewFrameSignal.signal();
116    }
117}
118
119void CaptureSequencer::onCaptureAvailable(nsecs_t timestamp,
120        sp<MemoryBase> captureBuffer) {
121    ATRACE_CALL();
122    ALOGV("%s", __FUNCTION__);
123    Mutex::Autolock l(mInputMutex);
124    mCaptureTimestamp = timestamp;
125    mCaptureBuffer = captureBuffer;
126    if (!mNewCaptureReceived) {
127        mNewCaptureReceived = true;
128        mNewCaptureSignal.signal();
129    }
130}
131
132
133void CaptureSequencer::dump(int fd, const Vector<String16>& /*args*/) {
134    String8 result;
135    if (mCaptureRequest.entryCount() != 0) {
136        result = "    Capture request:\n";
137        write(fd, result.string(), result.size());
138        mCaptureRequest.dump(fd, 2, 6);
139    } else {
140        result = "    Capture request: undefined\n";
141        write(fd, result.string(), result.size());
142    }
143    result = String8::format("    Current capture state: %s\n",
144            kStateNames[mCaptureState]);
145    result.append("    Latest captured frame:\n");
146    write(fd, result.string(), result.size());
147    mNewFrame.dump(fd, 2, 6);
148}
149
150/** Private members */
151
152const char* CaptureSequencer::kStateNames[CaptureSequencer::NUM_CAPTURE_STATES+1] =
153{
154    "IDLE",
155    "START",
156    "ZSL_START",
157    "ZSL_WAITING",
158    "ZSL_REPROCESSING",
159    "STANDARD_START",
160    "STANDARD_PRECAPTURE_WAIT",
161    "STANDARD_CAPTURE",
162    "STANDARD_CAPTURE_WAIT",
163    "BURST_CAPTURE_START",
164    "BURST_CAPTURE_WAIT",
165    "DONE",
166    "ERROR",
167    "UNKNOWN"
168};
169
170const CaptureSequencer::StateManager
171        CaptureSequencer::kStateManagers[CaptureSequencer::NUM_CAPTURE_STATES-1] = {
172    &CaptureSequencer::manageIdle,
173    &CaptureSequencer::manageStart,
174    &CaptureSequencer::manageZslStart,
175    &CaptureSequencer::manageZslWaiting,
176    &CaptureSequencer::manageZslReprocessing,
177    &CaptureSequencer::manageStandardStart,
178    &CaptureSequencer::manageStandardPrecaptureWait,
179    &CaptureSequencer::manageStandardCapture,
180    &CaptureSequencer::manageStandardCaptureWait,
181    &CaptureSequencer::manageBurstCaptureStart,
182    &CaptureSequencer::manageBurstCaptureWait,
183    &CaptureSequencer::manageDone,
184};
185
186bool CaptureSequencer::threadLoop() {
187
188    sp<Camera2Client> client = mClient.promote();
189    if (client == 0) return false;
190
191    CaptureState currentState;
192    {
193        Mutex::Autolock l(mStateMutex);
194        currentState = mCaptureState;
195    }
196
197    currentState = (this->*kStateManagers[currentState])(client);
198
199    Mutex::Autolock l(mStateMutex);
200    if (currentState != mCaptureState) {
201        mCaptureState = currentState;
202        ATRACE_INT("cam2_capt_state", mCaptureState);
203        ALOGV("Camera %d: New capture state %s",
204                client->getCameraId(), kStateNames[mCaptureState]);
205        mStateChanged.signal();
206    }
207
208    if (mCaptureState == ERROR) {
209        ALOGE("Camera %d: Stopping capture sequencer due to error",
210                client->getCameraId());
211        return false;
212    }
213
214    return true;
215}
216
217CaptureSequencer::CaptureState CaptureSequencer::manageIdle(
218        sp<Camera2Client> &/*client*/) {
219    status_t res;
220    Mutex::Autolock l(mInputMutex);
221    while (!mStartCapture) {
222        res = mStartCaptureSignal.waitRelative(mInputMutex,
223                kWaitDuration);
224        if (res == TIMED_OUT) break;
225    }
226    if (mStartCapture) {
227        mStartCapture = false;
228        mBusy = true;
229        return START;
230    }
231    return IDLE;
232}
233
234CaptureSequencer::CaptureState CaptureSequencer::manageDone(sp<Camera2Client> &client) {
235    status_t res = OK;
236    ATRACE_CALL();
237    mCaptureId++;
238    if (mCaptureId >= Camera2Client::kCaptureRequestIdEnd) {
239        mCaptureId = Camera2Client::kCaptureRequestIdStart;
240    }
241    {
242        Mutex::Autolock l(mInputMutex);
243        mBusy = false;
244    }
245
246    {
247        SharedParameters::Lock l(client->getParameters());
248        switch (l.mParameters.state) {
249            case Parameters::DISCONNECTED:
250                ALOGW("%s: Camera %d: Discarding image data during shutdown ",
251                        __FUNCTION__, client->getCameraId());
252                res = INVALID_OPERATION;
253                break;
254            case Parameters::STILL_CAPTURE:
255                res = client->getCameraDevice()->waitUntilDrained();
256                if (res != OK) {
257                    ALOGE("%s: Camera %d: Can't idle after still capture: "
258                            "%s (%d)", __FUNCTION__, client->getCameraId(),
259                            strerror(-res), res);
260                }
261                l.mParameters.state = Parameters::STOPPED;
262                break;
263            case Parameters::VIDEO_SNAPSHOT:
264                l.mParameters.state = Parameters::RECORD;
265                break;
266            default:
267                ALOGE("%s: Camera %d: Still image produced unexpectedly "
268                        "in state %s!",
269                        __FUNCTION__, client->getCameraId(),
270                        Parameters::getStateName(l.mParameters.state));
271                res = INVALID_OPERATION;
272        }
273    }
274    sp<ZslProcessorInterface> processor = mZslProcessor.promote();
275    if (processor != 0) {
276        ALOGV("%s: Memory optimization, clearing ZSL queue",
277              __FUNCTION__);
278        processor->clearZslQueue();
279    }
280
281    /**
282     * Fire the jpegCallback in Camera#takePicture(..., jpegCallback)
283     */
284    if (mCaptureBuffer != 0 && res == OK) {
285        Camera2Client::SharedCameraCallbacks::Lock
286            l(client->mSharedCameraCallbacks);
287        ALOGV("%s: Sending still image to client", __FUNCTION__);
288        if (l.mRemoteCallback != 0) {
289            l.mRemoteCallback->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE,
290                    mCaptureBuffer, NULL);
291        } else {
292            ALOGV("%s: No client!", __FUNCTION__);
293        }
294    }
295    mCaptureBuffer.clear();
296
297    return IDLE;
298}
299
300CaptureSequencer::CaptureState CaptureSequencer::manageStart(
301        sp<Camera2Client> &client) {
302    ALOGV("%s", __FUNCTION__);
303    status_t res;
304    ATRACE_CALL();
305    SharedParameters::Lock l(client->getParameters());
306    CaptureState nextState = DONE;
307
308    res = updateCaptureRequest(l.mParameters, client);
309    if (res != OK ) {
310        ALOGE("%s: Camera %d: Can't update still image capture request: %s (%d)",
311                __FUNCTION__, client->getCameraId(), strerror(-res), res);
312        return DONE;
313    }
314
315    if(l.mParameters.lightFx != Parameters::LIGHTFX_NONE &&
316            l.mParameters.state == Parameters::STILL_CAPTURE) {
317        nextState = BURST_CAPTURE_START;
318    }
319    else if (l.mParameters.zslMode &&
320            l.mParameters.state == Parameters::STILL_CAPTURE &&
321            l.mParameters.flashMode != Parameters::FLASH_MODE_ON) {
322        nextState = ZSL_START;
323    } else {
324        nextState = STANDARD_START;
325    }
326    mShutterNotified = false;
327
328    return nextState;
329}
330
331CaptureSequencer::CaptureState CaptureSequencer::manageZslStart(
332        sp<Camera2Client> &client) {
333    ALOGV("%s", __FUNCTION__);
334    status_t res;
335    sp<ZslProcessorInterface> processor = mZslProcessor.promote();
336    if (processor == 0) {
337        ALOGE("%s: No ZSL queue to use!", __FUNCTION__);
338        return DONE;
339    }
340
341    client->registerFrameListener(mCaptureId, mCaptureId + 1,
342            this);
343
344    // TODO: Actually select the right thing here.
345    res = processor->pushToReprocess(mCaptureId);
346    if (res != OK) {
347        if (res == NOT_ENOUGH_DATA) {
348            ALOGV("%s: Camera %d: ZSL queue doesn't have good frame, "
349                    "falling back to normal capture", __FUNCTION__,
350                    client->getCameraId());
351        } else {
352            ALOGE("%s: Camera %d: Error in ZSL queue: %s (%d)",
353                    __FUNCTION__, client->getCameraId(), strerror(-res), res);
354        }
355        return STANDARD_START;
356    }
357
358    SharedParameters::Lock l(client->getParameters());
359    /* warning: this also locks a SharedCameraCallbacks */
360    shutterNotifyLocked(l.mParameters, client, mMsgType);
361    mShutterNotified = true;
362    mTimeoutCount = kMaxTimeoutsForCaptureEnd;
363    return STANDARD_CAPTURE_WAIT;
364}
365
366CaptureSequencer::CaptureState CaptureSequencer::manageZslWaiting(
367        sp<Camera2Client> &/*client*/) {
368    ALOGV("%s", __FUNCTION__);
369    return DONE;
370}
371
372CaptureSequencer::CaptureState CaptureSequencer::manageZslReprocessing(
373        sp<Camera2Client> &/*client*/) {
374    ALOGV("%s", __FUNCTION__);
375    return START;
376}
377
378CaptureSequencer::CaptureState CaptureSequencer::manageStandardStart(
379        sp<Camera2Client> &client) {
380    ATRACE_CALL();
381
382    // Get the onFrameAvailable callback when the requestID == mCaptureId
383    client->registerFrameListener(mCaptureId, mCaptureId + 1,
384            this);
385    {
386        SharedParameters::Lock l(client->getParameters());
387        mTriggerId = l.mParameters.precaptureTriggerCounter++;
388    }
389    client->getCameraDevice()->triggerPrecaptureMetering(mTriggerId);
390
391    mAeInPrecapture = false;
392    mTimeoutCount = kMaxTimeoutsForPrecaptureStart;
393    return STANDARD_PRECAPTURE_WAIT;
394}
395
396CaptureSequencer::CaptureState CaptureSequencer::manageStandardPrecaptureWait(
397        sp<Camera2Client> &/*client*/) {
398    status_t res;
399    ATRACE_CALL();
400    Mutex::Autolock l(mInputMutex);
401    while (!mNewAEState) {
402        res = mNewNotifySignal.waitRelative(mInputMutex, kWaitDuration);
403        if (res == TIMED_OUT) {
404            mTimeoutCount--;
405            break;
406        }
407    }
408    if (mTimeoutCount <= 0) {
409        ALOGW("Timed out waiting for precapture %s",
410                mAeInPrecapture ? "end" : "start");
411        return STANDARD_CAPTURE;
412    }
413    if (mNewAEState) {
414        if (!mAeInPrecapture) {
415            // Waiting to see PRECAPTURE state
416            if (mAETriggerId == mTriggerId &&
417                    mAEState == ANDROID_CONTROL_AE_STATE_PRECAPTURE) {
418                ALOGV("%s: Got precapture start", __FUNCTION__);
419                mAeInPrecapture = true;
420                mTimeoutCount = kMaxTimeoutsForPrecaptureEnd;
421            }
422        } else {
423            // Waiting to see PRECAPTURE state end
424            if (mAETriggerId == mTriggerId &&
425                    mAEState != ANDROID_CONTROL_AE_STATE_PRECAPTURE) {
426                ALOGV("%s: Got precapture end", __FUNCTION__);
427                return STANDARD_CAPTURE;
428            }
429        }
430        mNewAEState = false;
431    }
432    return STANDARD_PRECAPTURE_WAIT;
433}
434
435CaptureSequencer::CaptureState CaptureSequencer::manageStandardCapture(
436        sp<Camera2Client> &client) {
437    status_t res;
438    ATRACE_CALL();
439    SharedParameters::Lock l(client->getParameters());
440    Vector<uint8_t> outputStreams;
441
442    /**
443     * Set up output streams in the request
444     *  - preview
445     *  - capture/jpeg
446     *  - callback (if preview callbacks enabled)
447     *  - recording (if recording enabled)
448     */
449    outputStreams.push(client->getPreviewStreamId());
450    outputStreams.push(client->getCaptureStreamId());
451
452    if (l.mParameters.previewCallbackFlags &
453            CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) {
454        outputStreams.push(client->getCallbackStreamId());
455    }
456
457    if (l.mParameters.state == Parameters::VIDEO_SNAPSHOT) {
458        outputStreams.push(client->getRecordingStreamId());
459    }
460
461    res = mCaptureRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,
462            outputStreams);
463    if (res == OK) {
464        res = mCaptureRequest.update(ANDROID_REQUEST_ID,
465                &mCaptureId, 1);
466    }
467    if (res == OK) {
468        res = mCaptureRequest.sort();
469    }
470
471    if (res != OK) {
472        ALOGE("%s: Camera %d: Unable to set up still capture request: %s (%d)",
473                __FUNCTION__, client->getCameraId(), strerror(-res), res);
474        return DONE;
475    }
476
477    // Create a capture copy since CameraDeviceBase#capture takes ownership
478    CameraMetadata captureCopy = mCaptureRequest;
479    if (captureCopy.entryCount() == 0) {
480        ALOGE("%s: Camera %d: Unable to copy capture request for HAL device",
481                __FUNCTION__, client->getCameraId());
482        return DONE;
483    }
484
485    /**
486     * Clear the streaming request for still-capture pictures
487     *   (as opposed to i.e. video snapshots)
488     */
489    if (l.mParameters.state == Parameters::STILL_CAPTURE) {
490        // API definition of takePicture() - stop preview before taking pic
491        res = client->stopStream();
492        if (res != OK) {
493            ALOGE("%s: Camera %d: Unable to stop preview for still capture: "
494                    "%s (%d)",
495                    __FUNCTION__, client->getCameraId(), strerror(-res), res);
496            return DONE;
497        }
498    }
499    // TODO: Capture should be atomic with setStreamingRequest here
500    res = client->getCameraDevice()->capture(captureCopy);
501    if (res != OK) {
502        ALOGE("%s: Camera %d: Unable to submit still image capture request: "
503                "%s (%d)",
504                __FUNCTION__, client->getCameraId(), strerror(-res), res);
505        return DONE;
506    }
507
508    mTimeoutCount = kMaxTimeoutsForCaptureEnd;
509    return STANDARD_CAPTURE_WAIT;
510}
511
512CaptureSequencer::CaptureState CaptureSequencer::manageStandardCaptureWait(
513        sp<Camera2Client> &client) {
514    status_t res;
515    ATRACE_CALL();
516    Mutex::Autolock l(mInputMutex);
517
518    // Wait for new metadata result (mNewFrame)
519    while (!mNewFrameReceived) {
520        res = mNewFrameSignal.waitRelative(mInputMutex, kWaitDuration);
521        if (res == TIMED_OUT) {
522            mTimeoutCount--;
523            break;
524        }
525    }
526
527    // Approximation of the shutter being closed
528    // - TODO: use the hal3 exposure callback in Camera3Device instead
529    if (mNewFrameReceived && !mShutterNotified) {
530        SharedParameters::Lock l(client->getParameters());
531        /* warning: this also locks a SharedCameraCallbacks */
532        shutterNotifyLocked(l.mParameters, client, mMsgType);
533        mShutterNotified = true;
534    }
535
536    // Wait until jpeg was captured by JpegProcessor
537    while (mNewFrameReceived && !mNewCaptureReceived) {
538        res = mNewCaptureSignal.waitRelative(mInputMutex, kWaitDuration);
539        if (res == TIMED_OUT) {
540            mTimeoutCount--;
541            break;
542        }
543    }
544    if (mTimeoutCount <= 0) {
545        ALOGW("Timed out waiting for capture to complete");
546        return DONE;
547    }
548    if (mNewFrameReceived && mNewCaptureReceived) {
549        if (mNewFrameId != mCaptureId) {
550            ALOGW("Mismatched capture frame IDs: Expected %d, got %d",
551                    mCaptureId, mNewFrameId);
552        }
553        camera_metadata_entry_t entry;
554        entry = mNewFrame.find(ANDROID_SENSOR_TIMESTAMP);
555        if (entry.count == 0) {
556            ALOGE("No timestamp field in capture frame!");
557        }
558        if (entry.data.i64[0] != mCaptureTimestamp) {
559            ALOGW("Mismatched capture timestamps: Metadata frame %lld,"
560                    " captured buffer %lld",
561                    entry.data.i64[0],
562                    mCaptureTimestamp);
563        }
564        client->removeFrameListener(mCaptureId, mCaptureId + 1, this);
565
566        mNewFrameReceived = false;
567        mNewCaptureReceived = false;
568        return DONE;
569    }
570    return STANDARD_CAPTURE_WAIT;
571}
572
573CaptureSequencer::CaptureState CaptureSequencer::manageBurstCaptureStart(
574        sp<Camera2Client> &client) {
575    ALOGV("%s", __FUNCTION__);
576    status_t res;
577    ATRACE_CALL();
578
579    // check which burst mode is set, create respective burst object
580    {
581        SharedParameters::Lock l(client->getParameters());
582
583        res = updateCaptureRequest(l.mParameters, client);
584        if(res != OK) {
585            return DONE;
586        }
587
588        //
589        // check for burst mode type in mParameters here
590        //
591        mBurstCapture = new BurstCapture(client, this);
592    }
593
594    res = mCaptureRequest.update(ANDROID_REQUEST_ID, &mCaptureId, 1);
595    if (res == OK) {
596        res = mCaptureRequest.sort();
597    }
598    if (res != OK) {
599        ALOGE("%s: Camera %d: Unable to set up still capture request: %s (%d)",
600                __FUNCTION__, client->getCameraId(), strerror(-res), res);
601        return DONE;
602    }
603
604    CameraMetadata captureCopy = mCaptureRequest;
605    if (captureCopy.entryCount() == 0) {
606        ALOGE("%s: Camera %d: Unable to copy capture request for HAL device",
607                __FUNCTION__, client->getCameraId());
608        return DONE;
609    }
610
611    Vector<CameraMetadata> requests;
612    requests.push(mCaptureRequest);
613    res = mBurstCapture->start(requests, mCaptureId);
614    mTimeoutCount = kMaxTimeoutsForCaptureEnd * 10;
615    return BURST_CAPTURE_WAIT;
616}
617
618CaptureSequencer::CaptureState CaptureSequencer::manageBurstCaptureWait(
619        sp<Camera2Client> &/*client*/) {
620    status_t res;
621    ATRACE_CALL();
622
623    while (!mNewCaptureReceived) {
624        res = mNewCaptureSignal.waitRelative(mInputMutex, kWaitDuration);
625        if (res == TIMED_OUT) {
626            mTimeoutCount--;
627            break;
628        }
629    }
630
631    if (mTimeoutCount <= 0) {
632        ALOGW("Timed out waiting for burst capture to complete");
633        return DONE;
634    }
635    if (mNewCaptureReceived) {
636        mNewCaptureReceived = false;
637        // TODO: update mCaptureId to last burst's capture ID + 1?
638        return DONE;
639    }
640
641    return BURST_CAPTURE_WAIT;
642}
643
644status_t CaptureSequencer::updateCaptureRequest(const Parameters &params,
645        sp<Camera2Client> &client) {
646    ATRACE_CALL();
647    status_t res;
648    if (mCaptureRequest.entryCount() == 0) {
649        res = client->getCameraDevice()->createDefaultRequest(
650                CAMERA2_TEMPLATE_STILL_CAPTURE,
651                &mCaptureRequest);
652        if (res != OK) {
653            ALOGE("%s: Camera %d: Unable to create default still image request:"
654                    " %s (%d)", __FUNCTION__, client->getCameraId(),
655                    strerror(-res), res);
656            return res;
657        }
658    }
659
660    res = params.updateRequest(&mCaptureRequest);
661    if (res != OK) {
662        ALOGE("%s: Camera %d: Unable to update common entries of capture "
663                "request: %s (%d)", __FUNCTION__, client->getCameraId(),
664                strerror(-res), res);
665        return res;
666    }
667
668    res = params.updateRequestJpeg(&mCaptureRequest);
669    if (res != OK) {
670        ALOGE("%s: Camera %d: Unable to update JPEG entries of capture "
671                "request: %s (%d)", __FUNCTION__, client->getCameraId(),
672                strerror(-res), res);
673        return res;
674    }
675
676    return OK;
677}
678
679/*static*/ void CaptureSequencer::shutterNotifyLocked(const Parameters &params,
680            sp<Camera2Client> client, int msgType) {
681    ATRACE_CALL();
682
683    if (params.state == Parameters::STILL_CAPTURE
684        && params.playShutterSound
685        && (msgType & CAMERA_MSG_SHUTTER)) {
686        client->getCameraService()->playSound(CameraService::SOUND_SHUTTER);
687    }
688
689    {
690        Camera2Client::SharedCameraCallbacks::Lock
691            l(client->mSharedCameraCallbacks);
692
693        ALOGV("%s: Notifying of shutter close to client", __FUNCTION__);
694        if (l.mRemoteCallback != 0) {
695            // ShutterCallback
696            l.mRemoteCallback->notifyCallback(CAMERA_MSG_SHUTTER,
697                                            /*ext1*/0, /*ext2*/0);
698
699            // RawCallback with null buffer
700            l.mRemoteCallback->notifyCallback(CAMERA_MSG_RAW_IMAGE_NOTIFY,
701                                            /*ext1*/0, /*ext2*/0);
702        } else {
703            ALOGV("%s: No client!", __FUNCTION__);
704        }
705    }
706}
707
708
709}; // namespace camera2
710}; // namespace android
711