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