1/*
2 * Copyright (C) 2014 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
17package com.android.camera.processing.imagebackend;
18
19import com.google.common.base.Optional;
20
21import android.content.Context;
22import android.location.Location;
23
24import com.android.camera.app.CameraServices;
25import com.android.camera.debug.Log;
26import com.android.camera.processing.ProcessingTask;
27import com.android.camera.session.CaptureSession;
28
29import java.util.concurrent.locks.Condition;
30
31import javax.annotation.Nullable;
32import javax.annotation.ParametersAreNonnullByDefault;
33
34/**
35 * Implements a placeholder task so that ImageBackend can communicate to the
36 * ProcessingServiceManager, when it is running a set of task created by the
37 * receiveImage call. The ImageShadow tasks also contains a Runnable which can
38 * be executed when the set of TaskImageContainers associated with the
39 * ImageShadow tasks completes. This implementation of the ProcessingTask will
40 * block the ProcessingServiceManager from running any other jobs. However,
41 * ProcessingServiceManager has no thread control over the ImageBackend. So
42 * while ProcessingServiceManager may queue up this ImageShadowTask for later
43 * execution, the ImageBackend will process the TaskImageContainer jobs without
44 * regard to this ImageShadowTask being queued.
45 */
46@ParametersAreNonnullByDefault
47class ImageShadowTask implements ProcessingTask {
48    static final private Log.Tag TAG = new Log.Tag("ImageShadowTask");
49
50    private final CaptureSession mCaptureSession;
51    private final ImageBackend.BlockSignalProtocol mProtocol;
52    private final Runnable mRunnableWhenDone;
53    private ProcessingTaskDoneListener mDoneListener;
54    private Condition mSignal;
55
56    /**
57     * Constructor
58     *
59     * @param protocol the blocking implementation that will keep this shadow
60     *            task from completing before all of its associated subtasks are
61     *            done
62     * @param captureSession the capture session associated with this shadow
63     *            task
64     * @param runnableWhenDone optional runnable to be executed when all the
65     *            associated sub-tasks of the ImageShadowTask are completed.
66     *            This runnable will be executed on the Executor of the last
67     *            subtask that completes (as specified in TaskImageContainer).
68     *            This underlying runnable is a part of the ImageBackend
69     *            infrastructure, and should NOT be associated with the
70     *            ProcessingTask implementation.
71     */
72    ImageShadowTask(ImageBackend.BlockSignalProtocol protocol,
73            CaptureSession captureSession, Optional<Runnable> runnableWhenDone) {
74        mProtocol = protocol;
75        mCaptureSession = captureSession;
76        if(runnableWhenDone.isPresent()) {
77            mRunnableWhenDone = runnableWhenDone.get();
78        } else {
79            mRunnableWhenDone = null;
80        }
81    }
82
83    ImageBackend.BlockSignalProtocol getProtocol() {
84        return mProtocol;
85    }
86
87    /**
88     * Returns the Runnable to be executed when all the associated
89     * TaskImageContainer of ImageShadowTask have been completed.
90     */
91    public Runnable getRunnableWhenDone() {
92        return mRunnableWhenDone;
93    }
94
95    @Override
96    public ProcessingResult process(Context context, CameraServices services, CaptureSession session) {
97        try {
98            mProtocol.block();
99        } catch (InterruptedException e) {
100            // Exit cleanly on Interrupt.
101            Log.w(TAG, "Image Shadow task Interrupted.");
102        }
103
104        ProcessingResult finalResult = new ProcessingResult(true, mCaptureSession);
105        // Always finishes alright.
106        if (mDoneListener != null) {
107            mDoneListener.onDone(finalResult);
108        }
109        return finalResult;
110    }
111
112    @Override
113    public void suspend() {
114        // Do nothing. We are unsuspendable.
115    }
116
117    @Override
118    public void resume() {
119        // Do nothing. We are unresumable.
120    }
121
122    @Override
123    public String getName() {
124        // Name is only required when Session is NULL. Session should never be
125        // set to NULL.
126        return null;
127    }
128
129    @Override
130    public Location getLocation() {
131        return null;
132    }
133
134    @Override
135    public CaptureSession getSession() {
136        return mCaptureSession;
137    }
138
139    @Override
140    public void setDoneListener(ProcessingTaskDoneListener listener) {
141        mDoneListener = listener;
142    }
143
144}
145