1abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin/*
2abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin * Copyright (C) 2014 The Android Open Source Project
3abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin *
4abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin * Licensed under the Apache License, Version 2.0 (the "License");
5abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin * you may not use this file except in compliance with the License.
6abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin * You may obtain a copy of the License at
7abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin *
8abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin *      http://www.apache.org/licenses/LICENSE-2.0
9abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin *
10abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin * Unless required by applicable law or agreed to in writing, software
11abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin * distributed under the License is distributed on an "AS IS" BASIS,
12abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin * See the License for the specific language governing permissions and
14abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin * limitations under the License.
15abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin */
16abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin
17abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Linpackage com.android.camera.processing.imagebackend;
18abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin
190f0329889f69182648fe8f535335e48978d63cc0I-Jong Linimport com.google.common.base.Optional;
200f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin
21abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Linimport android.content.Context;
22abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Linimport android.location.Location;
230f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin
24abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Linimport com.android.camera.app.CameraServices;
25abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Linimport com.android.camera.debug.Log;
26abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Linimport com.android.camera.processing.ProcessingTask;
27abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Linimport com.android.camera.session.CaptureSession;
28abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin
29abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Linimport java.util.concurrent.locks.Condition;
300f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin
310f0329889f69182648fe8f535335e48978d63cc0I-Jong Linimport javax.annotation.Nullable;
320f0329889f69182648fe8f535335e48978d63cc0I-Jong Linimport javax.annotation.ParametersAreNonnullByDefault;
33abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin
34abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin/**
350f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * Implements a placeholder task so that ImageBackend can communicate to the
360f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * ProcessingServiceManager, when it is running a set of task created by the
370f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * receiveImage call. The ImageShadow tasks also contains a Runnable which can
380f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * be executed when the set of TaskImageContainers associated with the
390f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * ImageShadow tasks completes. This implementation of the ProcessingTask will
400f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * block the ProcessingServiceManager from running any other jobs. However,
410f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * ProcessingServiceManager has no thread control over the ImageBackend. So
420f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * while ProcessingServiceManager may queue up this ImageShadowTask for later
430f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * execution, the ImageBackend will process the TaskImageContainer jobs without
440f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin * regard to this ImageShadowTask being queued.
45abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin */
460f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin@ParametersAreNonnullByDefault
47abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Linclass ImageShadowTask implements ProcessingTask {
48abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    static final private Log.Tag TAG = new Log.Tag("ImageShadowTask");
49abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin
50abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    private final CaptureSession mCaptureSession;
51abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    private final ImageBackend.BlockSignalProtocol mProtocol;
520f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin    private final Runnable mRunnableWhenDone;
53abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    private ProcessingTaskDoneListener mDoneListener;
54abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    private Condition mSignal;
55abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin
560f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin    /**
570f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     * Constructor
580f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     *
590f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     * @param protocol the blocking implementation that will keep this shadow
600f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     *            task from completing before all of its associated subtasks are
610f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     *            done
620f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     * @param captureSession the capture session associated with this shadow
630f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     *            task
640f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     * @param runnableWhenDone optional runnable to be executed when all the
650f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     *            associated sub-tasks of the ImageShadowTask are completed.
660f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     *            This runnable will be executed on the Executor of the last
670f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     *            subtask that completes (as specified in TaskImageContainer).
680f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     *            This underlying runnable is a part of the ImageBackend
690f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     *            infrastructure, and should NOT be associated with the
700f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     *            ProcessingTask implementation.
710f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     */
72abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    ImageShadowTask(ImageBackend.BlockSignalProtocol protocol,
730f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin            CaptureSession captureSession, Optional<Runnable> runnableWhenDone) {
74abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        mProtocol = protocol;
75abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        mCaptureSession = captureSession;
760f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin        if(runnableWhenDone.isPresent()) {
770f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin            mRunnableWhenDone = runnableWhenDone.get();
780f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin        } else {
790f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin            mRunnableWhenDone = null;
800f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin        }
81abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    }
82abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin
83abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    ImageBackend.BlockSignalProtocol getProtocol() {
84abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        return mProtocol;
85abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    }
86abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin
870f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin    /**
880f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     * Returns the Runnable to be executed when all the associated
890f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     * TaskImageContainer of ImageShadowTask have been completed.
900f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin     */
910f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin    public Runnable getRunnableWhenDone() {
920f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin        return mRunnableWhenDone;
930f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin    }
940f0329889f69182648fe8f535335e48978d63cc0I-Jong Lin
95abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    @Override
96abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    public ProcessingResult process(Context context, CameraServices services, CaptureSession session) {
97abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        try {
98abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin            mProtocol.block();
99abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        } catch (InterruptedException e) {
100abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin            // Exit cleanly on Interrupt.
101abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin            Log.w(TAG, "Image Shadow task Interrupted.");
102abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        }
103abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin
104abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        ProcessingResult finalResult = new ProcessingResult(true, mCaptureSession);
105abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        // Always finishes alright.
106abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        if (mDoneListener != null) {
107abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin            mDoneListener.onDone(finalResult);
108abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        }
109abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        return finalResult;
110abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    }
111abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin
112abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    @Override
113abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    public void suspend() {
114abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        // Do nothing. We are unsuspendable.
115abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    }
116abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin
117abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    @Override
118abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    public void resume() {
119abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        // Do nothing. We are unresumable.
120abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    }
121abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin
122abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    @Override
123abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    public String getName() {
124abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        // Name is only required when Session is NULL. Session should never be
125abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        // set to NULL.
126abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        return null;
127abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    }
128abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin
129abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    @Override
130abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    public Location getLocation() {
131abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        return null;
132abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    }
133abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin
134abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    @Override
135abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    public CaptureSession getSession() {
136abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        return mCaptureSession;
137abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    }
138abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin
139abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    @Override
140abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    public void setDoneListener(ProcessingTaskDoneListener listener) {
141abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin        mDoneListener = listener;
142abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin    }
143abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin
144abac2a23443f13b58951d88bf4b972f31a562e3dI-Jong Lin}
145