ProcessingServiceManager.java revision dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2
1dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling/* 2dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * Copyright (C) 2014 The Android Open Source Project 3dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * 4dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * Licensed under the Apache License, Version 2.0 (the "License"); 5dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * you may not use this file except in compliance with the License. 6dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * You may obtain a copy of the License at 7dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * 8dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * http://www.apache.org/licenses/LICENSE-2.0 9dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * 10dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * Unless required by applicable law or agreed to in writing, software 11dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * distributed under the License is distributed on an "AS IS" BASIS, 12dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * See the License for the specific language governing permissions and 14dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * limitations under the License. 15dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling */ 16dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 17dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberlingpackage com.android.camera.processing; 18dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 19dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberlingimport android.content.Context; 20dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberlingimport android.content.Intent; 21dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberlingimport android.util.Log; 22dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 23dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberlingimport java.util.LinkedList; 24dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberlingimport java.util.NoSuchElementException; 25dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 26dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling/** 27dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * Manages a queue of processing tasks as well as the processing service 28dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * lifecycle. 29dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * <p> 30dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * Clients should only use this class and not the {@link ProcessingService} 31dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * directly. 32dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling */ 33dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberlingpublic class ProcessingServiceManager { 34dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling private static final String TAG = "ProcessingServiceManager"; 35dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 36dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling /** The singleton instance of this manager. */ 37dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling private static ProcessingServiceManager sInstance; 38dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 39dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling /** The application context. */ 40dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling private final Context mAppContext; 41dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 42dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling /** Queue of tasks to be processed. */ 43dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling private final LinkedList<ProcessingTask> mQueue = new LinkedList<ProcessingTask>(); 44dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 45dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling /** Whether a processing service is currently running. */ 46dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling private volatile boolean mServiceRunning = false; 47dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 48dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling /** 49dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * Initializes the singleton instance. 50dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * 51dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * @param context the application context. 52dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling */ 53dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling public static void initSingleton(Context appContext) { 54dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling sInstance = new ProcessingServiceManager(appContext); 55dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 56dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 57dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling /** 58dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * Note: Make sure to call {@link #initSingleton(Context)} first. 59dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * 60dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * @return the singleton instance of the processing service manager. 61dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling */ 62dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling public static ProcessingServiceManager getInstance() { 63dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling if (sInstance == null) { 64dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling throw new IllegalStateException("initSingleton() not yet called."); 65dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 66dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling return sInstance; 67dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 68dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 69dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling private ProcessingServiceManager(Context context) { 70dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling mAppContext = context; 71dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 72dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 73dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling /** 74dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * Enqueues a new task. If the service is not already running, it will be 75dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * started. 76dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * 77dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * @param task The task to be enqueued. 78dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling */ 79dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling public synchronized void enqueueTask(ProcessingTask task) { 80dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling mQueue.add(task); 81dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling Log.d(TAG, "Task added. Queue size now: " + mQueue.size()); 82dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 83dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling if (!mServiceRunning) { 84dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling // Starts the service which will then work through the queue. Once 85dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling // the queue is empty (#popNextSession() returns null), the task 86dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling // will kill itself automatically and call #stitchingFinished(). 87dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling mAppContext.startService(new Intent(mAppContext, ProcessingService.class)); 88dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 89dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling mServiceRunning = true; 90dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 91dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 92dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling /** 93dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * Remove the next task from the queue and return it. 94dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * 95dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * @return The next Task or <code>null</code>, of no more tasks are in the 96dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * queue. 97dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling */ 98dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling public synchronized ProcessingTask popNextSession() { 99dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling try { 100dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling return mQueue.remove(); 101dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } catch (NoSuchElementException e) { 102dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling return null; 103dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 104dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 105dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 106dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling /** 107dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * Called by the processing service, notifying us that it has finished. 108dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling */ 109dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling public synchronized void notifyStitchingFinished() { 110dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling this.mServiceRunning = false; 111dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 112dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling} 113