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 Renn
2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.util.Log;
2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/**
2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * @hide
2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */
2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpublic class AsyncRunner extends GraphRunner{
2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private Class mSchedulerClass;
3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private SyncRunner mRunner;
3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private AsyncRunnerTask mRunTask;
3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private OnRunnerDoneListener mDoneListener;
3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private boolean isProcessing;
3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private Exception mException;
3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private class RunnerResult {
3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public int status = RESULT_UNKNOWN;
4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public Exception exception;
4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private class AsyncRunnerTask extends AsyncTask<SyncRunner, Void, RunnerResult> {
4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        private static final String TAG = "AsyncRunnerTask";
4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        @Override
4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        protected RunnerResult doInBackground(SyncRunner... runner) {
4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            RunnerResult result = new RunnerResult();
5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            try {
5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                if (runner.length > 1) {
5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                    throw new RuntimeException("More than one runner received!");
5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                }
5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                runner[0].assertReadyToStep();
5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                // Preparation
5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                if (mLogVerbose) Log.v(TAG, "Starting background graph processing.");
5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                activateGlContext();
6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                if (mLogVerbose) Log.v(TAG, "Preparing filter graph for processing.");
6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                runner[0].beginProcessing();
6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                if (mLogVerbose) Log.v(TAG, "Running graph.");
6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                // Run loop
6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                result.status = RESULT_RUNNING;
6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                while (!isCancelled() && result.status == RESULT_RUNNING) {
6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                    if (!runner[0].performStep()) {
7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                        result.status = runner[0].determinePostRunState();
7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                        if (result.status == GraphRunner.RESULT_SLEEPING) {
7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                            runner[0].waitUntilWake();
7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                            result.status = RESULT_RUNNING;
7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                        }
7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                    }
7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                }
7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                // Cleanup
7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                if (isCancelled()) {
8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                    result.status = RESULT_STOPPED;
8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                }
8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            } catch (Exception exception) {
8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                result.exception = exception;
8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                result.status = RESULT_ERROR;
8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            // Deactivate context.
8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            try {
8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                deactivateGlContext();
9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            } catch (Exception exception) {
9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                result.exception = exception;
9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                result.status = RESULT_ERROR;
9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (mLogVerbose) Log.v(TAG, "Done with background graph processing.");
9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            return result;
9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        @Override
10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        protected void onCancelled(RunnerResult result) {
10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            onPostExecute(result);
10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        @Override
10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        protected void onPostExecute(RunnerResult result) {
10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (mLogVerbose) Log.v(TAG, "Starting post-execute.");
10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            setRunning(false);
10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (result == null) {
10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                // Cancelled before got to doInBackground
11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                result = new RunnerResult();
11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                result.status = RESULT_STOPPED;
11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            setException(result.exception);
11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (result.status == RESULT_STOPPED || result.status == RESULT_ERROR) {
11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                if (mLogVerbose) Log.v(TAG, "Closing filters.");
11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                try {
11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                    mRunner.close();
11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                } catch (Exception exception) {
11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                    result.status = RESULT_ERROR;
12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                    setException(exception);
12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                }
12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (mDoneListener != null) {
12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                if (mLogVerbose) Log.v(TAG, "Calling graph done callback.");
12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                mDoneListener.onRunnerDone(result.status);
12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (mLogVerbose) Log.v(TAG, "Completed post-execute.");
12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
12965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
13065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
13165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private boolean mLogVerbose;
13265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private static final String TAG = "AsyncRunner";
13365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
13465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /** Create a new asynchronous graph runner with the given filter
13565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * context, and the given scheduler class.
13665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     *
13765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * Must be created on the UI thread.
13865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     */
13965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public AsyncRunner(FilterContext context, Class schedulerClass) {
14065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        super(context);
14165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
14265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mSchedulerClass = schedulerClass;
14365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE);
14465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
14565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
14665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /** Create a new asynchronous graph runner with the given filter
14765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * context. Uses a default scheduler.
14865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     *
14965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * Must be created on the UI thread.
15065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     */
15165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public AsyncRunner(FilterContext context) {
15265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        super(context);
15365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
15465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mSchedulerClass = SimpleScheduler.class;
15565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE);
15665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
15765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
15865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /** Set a callback to be called in the UI thread once the AsyncRunner
15965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * completes running a graph, whether the completion is due to a stop() call
16065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * or the filters running out of data to process.
16165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     */
16265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
16365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setDoneCallback(OnRunnerDoneListener listener) {
16465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mDoneListener = listener;
16565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
16665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
16765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /** Sets the graph to be run. Will call prepare() on graph. Cannot be called
16865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * when a graph is already running.
16965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     */
17065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    synchronized public void setGraph(FilterGraph graph) {
17165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (isRunning()) {
17265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Graph is already running!");
17365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
17465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mRunner = new SyncRunner(mFilterContext, graph, mSchedulerClass);
17565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
17665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
17765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
17865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public FilterGraph getGraph() {
17965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return mRunner != null ? mRunner.getGraph() : null;
18065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
18165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
18265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /** Execute the graph in a background thread. */
18365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
18465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    synchronized public void run() {
18565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mLogVerbose) Log.v(TAG, "Running graph.");
18665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        setException(null);
18765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
18865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (isRunning()) {
18965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Graph is already running!");
19065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
19165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mRunner == null) {
19265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Cannot run before a graph is set!");
19365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
19465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mRunTask = this.new AsyncRunnerTask();
19565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
19665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        setRunning(true);
19765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mRunTask.execute(mRunner);
19865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
19965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
20065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /** Stop graph execution. This is an asynchronous call; register a callback
20165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * with setDoneCallback to be notified of when the background processing has
20265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * been completed. Calling stop will close the filter graph. */
20365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
20465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    synchronized public void stop() {
20565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mRunTask != null && !mRunTask.isCancelled() ) {
20665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (mLogVerbose) Log.v(TAG, "Stopping graph.");
20765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mRunTask.cancel(false);
20865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
20965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
21065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
21165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
21265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    synchronized public void close() {
21365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (isRunning()) {
21465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Cannot close graph while it is running!");
21565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
21665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mLogVerbose) Log.v(TAG, "Closing filters.");
21765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mRunner.close();
21865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
21965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
22065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /** Check if background processing is happening */
22165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
22265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    synchronized public boolean isRunning() {
22365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return isProcessing;
22465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
22565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
22665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
22765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    synchronized public Exception getError() {
22865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return mException;
22965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
23065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    synchronized private void setRunning(boolean running) {
23265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        isProcessing = running;
23365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
23465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    synchronized private void setException(Exception exception) {
23665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mException = exception;
23765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
23865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
240