165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/*
265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Copyright (C) 2011 The Android Open Source Project
365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Licensed under the Apache License, Version 2.0 (the "License");
565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * you may not use this file except in compliance with the License.
665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * You may obtain a copy of the License at
765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *      http://www.apache.org/licenses/LICENSE-2.0
965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
1065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Unless required by applicable law or agreed to in writing, software
1165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * distributed under the License is distributed on an "AS IS" BASIS,
1265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * See the License for the specific language governing permissions and
1465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * limitations under the License.
1565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */
1665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
1765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
1865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpackage android.filterfw.core;
1965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.os.AsyncTask;
2165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.os.Handler;
2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.util.Log;
2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.lang.InterruptedException;
2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.lang.Runnable;
2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.concurrent.CancellationException;
2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.concurrent.ExecutionException;
2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.concurrent.TimeoutException;
3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.concurrent.TimeUnit;
3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/**
3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * @hide
3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */
3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpublic class AsyncRunner extends GraphRunner{
3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private Class mSchedulerClass;
3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private SyncRunner mRunner;
3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private AsyncRunnerTask mRunTask;
4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private OnRunnerDoneListener mDoneListener;
4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private boolean isProcessing;
4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private Exception mException;
4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private class RunnerResult {
4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public int status = RESULT_UNKNOWN;
4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public Exception exception;
4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private class AsyncRunnerTask extends AsyncTask<SyncRunner, Void, RunnerResult> {
5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        private static final String TAG = "AsyncRunnerTask";
5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        @Override
5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        protected RunnerResult doInBackground(SyncRunner... runner) {
5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            RunnerResult result = new RunnerResult();
5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            try {
5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                if (runner.length > 1) {
6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                    throw new RuntimeException("More than one runner received!");
6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                }
6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                runner[0].assertReadyToStep();
6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                // Preparation
6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                if (mLogVerbose) Log.v(TAG, "Starting background graph processing.");
6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                activateGlContext();
6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                if (mLogVerbose) Log.v(TAG, "Preparing filter graph for processing.");
7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                runner[0].beginProcessing();
7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                if (mLogVerbose) Log.v(TAG, "Running graph.");
7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                // Run loop
7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                result.status = RESULT_RUNNING;
7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                while (!isCancelled() && result.status == RESULT_RUNNING) {
7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                    if (!runner[0].performStep()) {
7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                        result.status = runner[0].determinePostRunState();
7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                        if (result.status == GraphRunner.RESULT_SLEEPING) {
8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                            runner[0].waitUntilWake();
8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                            result.status = RESULT_RUNNING;
8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                        }
8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                    }
8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                }
8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                // Cleanup
8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                if (isCancelled()) {
8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                    result.status = RESULT_STOPPED;
8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                }
9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            } catch (Exception exception) {
9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                result.exception = exception;
9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                result.status = RESULT_ERROR;
9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            // Deactivate context.
9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            try {
9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                deactivateGlContext();
9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            } catch (Exception exception) {
9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                result.exception = exception;
10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                result.status = RESULT_ERROR;
10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (mLogVerbose) Log.v(TAG, "Done with background graph processing.");
10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            return result;
10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        @Override
10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        protected void onCancelled(RunnerResult result) {
10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            onPostExecute(result);
11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        @Override
11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        protected void onPostExecute(RunnerResult result) {
11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (mLogVerbose) Log.v(TAG, "Starting post-execute.");
11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            setRunning(false);
11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (result == null) {
11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                // Cancelled before got to doInBackground
11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                result = new RunnerResult();
11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                result.status = RESULT_STOPPED;
12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            setException(result.exception);
12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (result.status == RESULT_STOPPED || result.status == RESULT_ERROR) {
12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                if (mLogVerbose) Log.v(TAG, "Closing filters.");
12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                try {
12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                    mRunner.close();
12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                } catch (Exception exception) {
12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                    result.status = RESULT_ERROR;
12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                    setException(exception);
12965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                }
13065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
13165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (mDoneListener != null) {
13265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                if (mLogVerbose) Log.v(TAG, "Calling graph done callback.");
13365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                mDoneListener.onRunnerDone(result.status);
13465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
13565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (mLogVerbose) Log.v(TAG, "Completed post-execute.");
13665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
13765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
13865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
13965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private boolean mLogVerbose;
14065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private static final String TAG = "AsyncRunner";
14165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
14265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /** Create a new asynchronous graph runner with the given filter
14365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * context, and the given scheduler class.
14465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     *
14565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * Must be created on the UI thread.
14665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     */
14765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public AsyncRunner(FilterContext context, Class schedulerClass) {
14865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        super(context);
14965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
15065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mSchedulerClass = schedulerClass;
15165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE);
15265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
15365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
15465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /** Create a new asynchronous graph runner with the given filter
15565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * context. Uses a default scheduler.
15665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     *
15765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * Must be created on the UI thread.
15865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     */
15965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public AsyncRunner(FilterContext context) {
16065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        super(context);
16165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
16265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mSchedulerClass = SimpleScheduler.class;
16365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE);
16465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
16565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
16665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /** Set a callback to be called in the UI thread once the AsyncRunner
16765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * completes running a graph, whether the completion is due to a stop() call
16865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * or the filters running out of data to process.
16965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     */
17065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
17165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setDoneCallback(OnRunnerDoneListener listener) {
17265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mDoneListener = listener;
17365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
17465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
17565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /** Sets the graph to be run. Will call prepare() on graph. Cannot be called
17665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * when a graph is already running.
17765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     */
17865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    synchronized public void setGraph(FilterGraph graph) {
17965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (isRunning()) {
18065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Graph is already running!");
18165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
18265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mRunner = new SyncRunner(mFilterContext, graph, mSchedulerClass);
18365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
18465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
18565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
18665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public FilterGraph getGraph() {
18765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return mRunner != null ? mRunner.getGraph() : null;
18865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
18965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
19065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /** Execute the graph in a background thread. */
19165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
19265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    synchronized public void run() {
19365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mLogVerbose) Log.v(TAG, "Running graph.");
19465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        setException(null);
19565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
19665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (isRunning()) {
19765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Graph is already running!");
19865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
19965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mRunner == null) {
20065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Cannot run before a graph is set!");
20165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
20265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mRunTask = this.new AsyncRunnerTask();
20365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
20465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        setRunning(true);
20565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mRunTask.execute(mRunner);
20665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
20765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
20865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /** Stop graph execution. This is an asynchronous call; register a callback
20965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * with setDoneCallback to be notified of when the background processing has
21065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * been completed. Calling stop will close the filter graph. */
21165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
21265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    synchronized public void stop() {
21365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mRunTask != null && !mRunTask.isCancelled() ) {
21465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (mLogVerbose) Log.v(TAG, "Stopping graph.");
21565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mRunTask.cancel(false);
21665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
21765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
21865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
21965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
22065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    synchronized public void close() {
22165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (isRunning()) {
22265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Cannot close graph while it is running!");
22365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
22465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mLogVerbose) Log.v(TAG, "Closing filters.");
22565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mRunner.close();
22665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
22765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
22865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /** Check if background processing is happening */
22965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
23065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    synchronized public boolean isRunning() {
23165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return isProcessing;
23265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
23365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
23565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    synchronized public Exception getError() {
23665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return mException;
23765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
23865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    synchronized private void setRunning(boolean running) {
24065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        isProcessing = running;
24165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
24265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
24365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    synchronized private void setException(Exception exception) {
24465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mException = exception;
24565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
24665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
24765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
248