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