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 194a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberlingimport android.app.Notification; 204a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberlingimport android.app.NotificationManager; 21dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberlingimport android.app.Service; 2258acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberlingimport android.content.BroadcastReceiver; 23dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberlingimport android.content.Context; 24dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberlingimport android.content.Intent; 2558acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberlingimport android.content.IntentFilter; 26dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberlingimport android.os.IBinder; 27dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberlingimport android.os.PowerManager; 28dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberlingimport android.os.PowerManager.WakeLock; 29dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberlingimport android.os.Process; 3058acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberlingimport android.support.v4.content.LocalBroadcastManager; 31dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 32dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberlingimport com.android.camera.app.CameraApp; 33dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberlingimport com.android.camera.app.CameraServices; 345596b4c902dcb685928b43678f428746ca5ffd08Angus Kongimport com.android.camera.debug.Log; 352a978f2b7b07ce4e5f6163910912e79fed38aff8Seth Raphaelimport com.android.camera.session.CaptureSession; 364a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberlingimport com.android.camera.session.CaptureSession.ProgressListener; 37dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberlingimport com.android.camera.session.CaptureSessionManager; 384a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberlingimport com.android.camera2.R; 39dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 4058acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberlingimport java.util.concurrent.locks.Lock; 4158acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberlingimport java.util.concurrent.locks.ReentrantLock; 4258acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling 43dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling/** 44dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * A service that processes a {@code ProcessingTask}. The service uses a fifo 45dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * queue so that only one {@code ProcessingTask} is processed at a time. 46dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * <p> 47dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * The service is meant to be called via {@code ProcessingService.addTask}, 48dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * which takes care of starting the service and enqueueing the 49dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * {@code ProcessingTask} task: 50dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * 51dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * <pre> 52dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * {@code 53dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * ProcessingTask task = new MyProcessingTask(...); 54dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * ProcessingService.addTask(task); 55dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * } 56dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * </pre> 57dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling */ 584a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberlingpublic class ProcessingService extends Service implements ProgressListener { 5958acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling /** 6058acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling * Class used to receive broadcast and control the service accordingly. 6158acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling */ 6258acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling public class ServiceController extends BroadcastReceiver { 6358acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling @Override 6458acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling public void onReceive(Context context, Intent intent) { 6558acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling if (intent.getAction() == ACTION_PAUSE_PROCESSING_SERVICE) { 6658acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling ProcessingService.this.pause(); 6758acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling } else if (intent.getAction() == ACTION_RESUME_PROCESSING_SERVICE) { 6858acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling ProcessingService.this.resume(); 6958acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling } 7058acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling } 7158acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling } 7258acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling 735596b4c902dcb685928b43678f428746ca5ffd08Angus Kong private static final Log.Tag TAG = new Log.Tag("ProcessingService"); 74dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling private static final int THREAD_PRIORITY = Process.THREAD_PRIORITY_DISPLAY; 754a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling private static final int CAMERA_NOTIFICATION_ID = 2; 764a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling private Notification.Builder mNotificationBuilder; 774a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling private NotificationManager mNotificationManager; 7858acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling 7958acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling /** Sending this broadcast intent will cause the processing to pause. */ 8058acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling public static final String ACTION_PAUSE_PROCESSING_SERVICE = 8158acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling "com.android.camera.processing.PAUSE"; 8258acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling /** 8358acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling * Sending this broadcast intent will cause the processing to resume after 8458acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling * it has been paused. 8558acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling */ 8658acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling public static final String ACTION_RESUME_PROCESSING_SERVICE = 8758acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling "com.android.camera.processing.RESUME"; 8858acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling 89dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling private WakeLock mWakeLock; 9058acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling private final ServiceController mServiceController = new ServiceController(); 91dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 92dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling /** Manages the capture session. */ 93dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling private CaptureSessionManager mSessionManager; 94dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 95dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling private ProcessingServiceManager mProcessingServiceManager; 96dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling private Thread mProcessingThread; 9758acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling private volatile boolean mPaused = false; 9858acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling private ProcessingTask mCurrentTask; 9958acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling private final Lock mSuspendStatusLock = new ReentrantLock(); 100dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 101dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling @Override 102dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling public void onCreate() { 103dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling mProcessingServiceManager = ProcessingServiceManager.getInstance(); 104dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling mSessionManager = getServices().getCaptureSessionManager(); 105dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 106dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling // Keep CPU awake while allowing screen and keyboard to switch off. 107dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling PowerManager powerManager = (PowerManager) getSystemService( 108dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling Context.POWER_SERVICE); 1095596b4c902dcb685928b43678f428746ca5ffd08Angus Kong mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG.toString()); 110dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling mWakeLock.acquire(); 11158acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling 11258acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling IntentFilter intentFilter = new IntentFilter(); 11358acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling intentFilter.addAction(ACTION_PAUSE_PROCESSING_SERVICE); 11458acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling intentFilter.addAction(ACTION_RESUME_PROCESSING_SERVICE); 11558acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling LocalBroadcastManager.getInstance(this).registerReceiver(mServiceController, intentFilter); 1164a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling mNotificationBuilder = createInProgressNotificationBuilder(); 1174a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 118dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 119dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 120dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling @Override 121dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling public void onDestroy() { 122dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling Log.d(TAG, "Shutting down"); 123dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling // TODO: Cancel session in progress... 124dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 125dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling // Unlock the power manager, i.e. let power management kick in if 126dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling // needed. 127dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling if (mWakeLock.isHeld()) { 128dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling mWakeLock.release(); 129dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 13058acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling LocalBroadcastManager.getInstance(this).unregisterReceiver(mServiceController); 1314a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling stopForeground(true); 132dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 133dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 134dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling @Override 135dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling public int onStartCommand(Intent intent, int flags, int startId) { 1364a5b9e0b9f4eab654f30588941749a25aeba97feSascha Haeberling Log.d(TAG, "Starting in foreground."); 1374a5b9e0b9f4eab654f30588941749a25aeba97feSascha Haeberling 1384a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling // We need to start this service in foreground so that it's not getting 1394a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling // killed easily when memory pressure is building up. 1404a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling startForeground(CAMERA_NOTIFICATION_ID, mNotificationBuilder.build()); 14158acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling 142dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling asyncProcessAllTasksAndShutdown(); 143dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 144dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling // We want this service to continue running until it is explicitly 145dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling // stopped, so return sticky. 146dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling return START_STICKY; 147dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 148dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 149dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling @Override 150dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling public IBinder onBind(Intent intent) { 151dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling // We don't provide binding, so return null. 152dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling return null; 153dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 154dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 15558acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling private void pause() { 1564a5b9e0b9f4eab654f30588941749a25aeba97feSascha Haeberling Log.d(TAG, "Pausing"); 15758acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling try { 15858acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling mSuspendStatusLock.lock(); 15958acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling mPaused = true; 16058acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling if (mCurrentTask != null) { 16158acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling mCurrentTask.suspend(); 16258acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling } 16358acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling } finally { 16458acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling mSuspendStatusLock.unlock(); 16558acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling } 16658acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling } 16758acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling 16858acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling private void resume() { 1694a5b9e0b9f4eab654f30588941749a25aeba97feSascha Haeberling Log.d(TAG, "Resuming"); 17058acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling try { 17158acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling mSuspendStatusLock.lock(); 17258acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling mPaused = false; 17358acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling if (mCurrentTask != null) { 17458acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling mCurrentTask.resume(); 17558acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling } 17658acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling } finally { 17758acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling mSuspendStatusLock.unlock(); 17858acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling } 17958acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling } 18058acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling 181dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling /** 182dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * Starts a thread to process all tasks. When no more tasks are in the 183dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * queue, it exits the thread and shuts down the service. 184dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling */ 185dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling private void asyncProcessAllTasksAndShutdown() { 186dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling if (mProcessingThread != null) { 187dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling return; 188dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 18958acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling mProcessingThread = new Thread("CameraProcessingThread") { 190dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling @Override 191dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling public void run() { 192dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling // Set the thread priority 193dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling android.os.Process.setThreadPriority(THREAD_PRIORITY); 194dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 195dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling ProcessingTask task; 196dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling while ((task = mProcessingServiceManager.popNextSession()) != null) { 19758acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling mCurrentTask = task; 19858acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling try { 19958acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling mSuspendStatusLock.lock(); 20058acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling if (mPaused) { 20158acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling mCurrentTask.suspend(); 20258acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling } 20358acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling } finally { 20458acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling mSuspendStatusLock.unlock(); 20558acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling } 206dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling processAndNotify(task); 207dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 208dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling stopSelf(); 209dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 210dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling }; 211dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling mProcessingThread.start(); 212dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 213dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 214dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling /** 215dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * Processes a {@code ProcessingTask} and updates the notification bar. 216dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling */ 217dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling void processAndNotify(ProcessingTask task) { 218dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling if (task == null) { 219dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling Log.e(TAG, "Reference to ProcessingTask is null"); 220dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling return; 221dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 2222a978f2b7b07ce4e5f6163910912e79fed38aff8Seth Raphael CaptureSession session = task.getSession(); 2232a978f2b7b07ce4e5f6163910912e79fed38aff8Seth Raphael if (session == null) { 22457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling // TODO: Timestamp is not required right now, refactor this to make it clearer. 22557bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling session = mSessionManager.createNewSession(task.getName(), 0, task.getLocation()); 2262a978f2b7b07ce4e5f6163910912e79fed38aff8Seth Raphael } 2274a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling resetNotification(); 2284a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling 2294a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling // Adding the listener also causes it to get called for the session's 2304a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling // current status message and percent completed. 2314a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling session.addProgressListener(this); 2324a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling 23358acf0df808ea67e8ad9ab6ffccff4548566580aSascha Haeberling System.gc(); 2344a5b9e0b9f4eab654f30588941749a25aeba97feSascha Haeberling Log.d(TAG, "Processing start"); 2352a978f2b7b07ce4e5f6163910912e79fed38aff8Seth Raphael task.process(this, getServices(), session); 2364a5b9e0b9f4eab654f30588941749a25aeba97feSascha Haeberling Log.d(TAG, "Processing done"); 237dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 238dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling 2394a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling private void resetNotification() { 2404a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling mNotificationBuilder.setContentText("…").setProgress(100, 0, false); 2414a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling postNotification(); 2424a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling } 2434a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling 244dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling /** 245dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling * Returns the common camera services. 246dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling */ 247dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling private CameraServices getServices() { 248dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling return (CameraApp) this.getApplication(); 249dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling } 2504a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling 2514a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling private void postNotification() { 2524a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling mNotificationManager.notify(CAMERA_NOTIFICATION_ID, mNotificationBuilder.build()); 2534a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling } 2544a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling 2554a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling /** 2564a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling * Creates a notification to indicate that a computation is in progress. 2574a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling */ 2584a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling private Notification.Builder createInProgressNotificationBuilder() { 2594a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling return new Notification.Builder(this) 2604a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling .setSmallIcon(R.drawable.ic_notification) 2614a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling .setWhen(System.currentTimeMillis()) 2624a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling .setOngoing(true) 2634a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling .setContentTitle(this.getText(R.string.app_name)); 2644a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling } 2654a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling 2664a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling @Override 2674a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling public void onProgressChanged(int progress) { 2684a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling mNotificationBuilder.setProgress(100, progress, false); 2694a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling postNotification(); 2704a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling } 2714a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling 2724a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling @Override 2734a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling public void onStatusMessageChanged(CharSequence message) { 2744a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling mNotificationBuilder.setContentText(message); 2754a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling postNotification(); 2764a400d7f09ea0655d4730e904892e3a9d96993ebSascha Haeberling } 277dd2d9e610aa9dc71fe0938f38de43bb0e26f3bb2Sascha Haeberling} 278