10b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin/* 20b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * Copyright (C) 2014 The Android Open Source Project 30b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * 40b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * Licensed under the Apache License, Version 2.0 (the "License"); 50b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * you may not use this file except in compliance with the License. 60b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * You may obtain a copy of the License at 70b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * 80b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * http://www.apache.org/licenses/LICENSE-2.0 90b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * 100b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * Unless required by applicable law or agreed to in writing, software 110b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * distributed under the License is distributed on an "AS IS" BASIS, 120b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * See the License for the specific language governing permissions and 140b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * limitations under the License. 150b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin */ 160b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkinpackage android.hardware.camera2.utils; 170b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin 180b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkinimport android.hardware.camera2.utils.TaskDrainer.DrainListener; 190b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkinimport android.os.Handler; 200b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin 210b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin/** 220b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * Keep track of a single concurrent task starting and finishing; 230b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * allow draining the existing task and figuring out when the task has finished 240b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * (and won't restart). 250b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * 260b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * <p>The initial state is to allow all tasks to be started and finished. A task may only be started 270b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * once, after which it must be finished before starting again. Likewise, finishing a task 280b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * that hasn't been started is also not allowed.</p> 290b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * 300b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * <p>When draining begins, the task cannot be started again. This guarantees that at some 310b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * point the task will be finished forever, at which point the {@link DrainListener#onDrained} 320b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * callback will be invoked.</p> 330b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin */ 340b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkinpublic class TaskSingleDrainer { 350b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin 360b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin private final TaskDrainer<Object> mTaskDrainer; 370b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin private final Object mSingleTask = new Object(); 380b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin 390b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin /** 400b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * Create a new task drainer; {@code onDrained} callbacks will be posted to the listener 410b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * via the {@code handler}. 420b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * 430b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * @param handler a non-{@code null} handler to use to post runnables to 440b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * @param listener a non-{@code null} listener where {@code onDrained} will be called 450b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin */ 460b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin public TaskSingleDrainer(Handler handler, DrainListener listener) { 470b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin mTaskDrainer = new TaskDrainer<>(handler, listener); 480b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin } 490b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin 500b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin /** 510b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * Create a new task drainer; {@code onDrained} callbacks will be posted to the listener 520b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * via the {@code handler}. 530b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * 540b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * @param handler a non-{@code null} handler to use to post runnables to 550b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * @param listener a non-{@code null} listener where {@code onDrained} will be called 560b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * @param name an optional name used for debug logging 570b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin */ 580b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin public TaskSingleDrainer(Handler handler, DrainListener listener, String name) { 590b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin mTaskDrainer = new TaskDrainer<>(handler, listener, name); 600b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin } 610b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin 620b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin /** 630b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * Mark this asynchronous task as having started. 640b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * 650b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * <p>The task cannot be started more than once without first having finished. Once 660b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * draining begins with {@link #beginDrain}, no new tasks can be started.</p> 670b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * 680b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * @see #taskFinished 690b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * @see #beginDrain 700b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * 710b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * @throws IllegalStateException 720b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * If attempting to start a task which is already started (and not finished), 730b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * or if attempting to start a task after draining has begun. 740b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin */ 750b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin public void taskStarted() { 760b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin mTaskDrainer.taskStarted(mSingleTask); 770b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin } 780b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin 790b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin /** 800b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * Do not allow any more task re-starts; once the existing task is finished, 810b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * fire the {@link DrainListener#onDrained} callback asynchronously. 820b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * 830b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * <p>This operation is idempotent; calling it more than once has no effect.</p> 840b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin */ 850b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin public void beginDrain() { 860b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin mTaskDrainer.beginDrain(); 870b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin } 880b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin 890b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin /** 900b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * Mark this asynchronous task as having finished. 910b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * 920b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * <p>The task cannot be finished if it hasn't started. Once finished, a task 930b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * cannot be finished again (unless it's started again).</p> 940b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * 950b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * @see #taskStarted 960b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * @see #beginDrain 970b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * 980b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * @throws IllegalStateException 990b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin * If attempting to start a task which is already finished (and not re-started), 1000b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin */ 1010b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin public void taskFinished() { 1020b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin mTaskDrainer.taskFinished(mSingleTask); 1030b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin } 1040b27d3453d5e257594792e9177c5fedb1bc6f9e9Igor Murashkin} 105