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