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 
17 package com.android.camera.processing.imagebackend;
18 
19 import com.google.common.base.Optional;
20 
21 import android.content.Context;
22 import android.location.Location;
23 
24 import com.android.camera.app.CameraServices;
25 import com.android.camera.debug.Log;
26 import com.android.camera.processing.ProcessingTask;
27 import com.android.camera.session.CaptureSession;
28 
29 import java.util.concurrent.locks.Condition;
30 
31 import javax.annotation.Nullable;
32 import 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
47 class 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      */
ImageShadowTask(ImageBackend.BlockSignalProtocol protocol, CaptureSession captureSession, Optional<Runnable> runnableWhenDone)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 
getProtocol()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      */
getRunnableWhenDone()91     public Runnable getRunnableWhenDone() {
92         return mRunnableWhenDone;
93     }
94 
95     @Override
process(Context context, CameraServices services, CaptureSession session)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
suspend()113     public void suspend() {
114         // Do nothing. We are unsuspendable.
115     }
116 
117     @Override
resume()118     public void resume() {
119         // Do nothing. We are unresumable.
120     }
121 
122     @Override
getName()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
getLocation()130     public Location getLocation() {
131         return null;
132     }
133 
134     @Override
getSession()135     public CaptureSession getSession() {
136         return mCaptureSession;
137     }
138 
139     @Override
setDoneListener(ProcessingTaskDoneListener listener)140     public void setDoneListener(ProcessingTaskDoneListener listener) {
141         mDoneListener = listener;
142     }
143 
144 }
145