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