1a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling/* 2a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * Copyright (C) 2013 The Android Open Source Project 3a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * 4a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * Licensed under the Apache License, Version 2.0 (the "License"); 5a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * you may not use this file except in compliance with the License. 6a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * You may obtain a copy of the License at 7a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * 8a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * http://www.apache.org/licenses/LICENSE-2.0 9a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * 10a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * Unless required by applicable law or agreed to in writing, software 11a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * distributed under the License is distributed on an "AS IS" BASIS, 12a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * See the License for the specific language governing permissions and 14a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * limitations under the License. 15a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling */ 16a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 17a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberlingpackage com.android.camera.session; 18a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 196dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberlingimport android.graphics.Bitmap; 20a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberlingimport android.location.Location; 21a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberlingimport android.net.Uri; 22a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 23abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberlingimport com.android.camera.async.MainThread; 245596b4c902dcb685928b43678f428746ca5ffd08Angus Kongimport com.android.camera.debug.Log; 25a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 26a86b048709342fc53cee92aa047a15a22462c71cSascha Haeberlingimport java.io.File; 27a86b048709342fc53cee92aa047a15a22462c71cSascha Haeberlingimport java.io.IOException; 28a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberlingimport java.util.HashMap; 29a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberlingimport java.util.LinkedList; 30a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberlingimport java.util.Map; 31a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 32a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling/** 33a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * Implementation for the {@link CaptureSessionManager}. 34abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * <p> 35abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * Basic usage: 36abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * <ul> 37abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * <li>Create a new capture session.</li> 38abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * <li>Pass it around to anywhere where the status of a session needs to be 39abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * updated.</li> 40abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * <li>If this is a longer operation, use one of the start* methods to indicate 41abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * that processing of this session has started. The Camera app right now will 42abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * use this to add a new item to the filmstrip and indicate the current 43abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * progress.</li> 44abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * <li>If the final result is already available and no processing is required, 45abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * store the final image using saveAndFinish</li> 46abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * <li>For longer operations, update the thumbnail and status message using the 47abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * provided methods.</li> 48abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * <li>For longer operations, update the thumbnail and status message using the 49abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * provided methods.</li> 50abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * <li>Once processing is done, the final image can be saved using saveAndFinish 51abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * </li> 52abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * </ul> 53abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * </p> 54abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * It's OK to call saveAndFinish either before or after the session has been 55abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * started. 56abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * <p> 57abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * If startSession is called after the session has been finished, it will be 58abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * treated as a no-op. 59abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling * </p> 60a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling */ 61a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberlingpublic class CaptureSessionManagerImpl implements CaptureSessionManager { 62f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling 63f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling private final class SessionNotifierImpl implements SessionNotifier { 64f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling /** 65f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * Notifies all task listeners that the task with the given URI has been 66f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * queued. 67f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling */ 68f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling @Override 69f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling public void notifyTaskQueued(final Uri uri) { 70f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling mMainHandler.execute(new Runnable() { 71f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling @Override 72f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling public void run() { 73f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling synchronized (mTaskListeners) { 74f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling for (SessionListener listener : mTaskListeners) { 75f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling listener.onSessionQueued(uri); 76f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 77f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 78f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 79f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling }); 80f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 81f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling 82f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling /** 83f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * Notifies all task listeners that the task with the given URI has been 84f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * finished. 85f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling */ 86f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling @Override 87f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling public void notifyTaskDone(final Uri uri) { 88f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling mMainHandler.execute(new Runnable() { 89f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling @Override 90f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling public void run() { 91f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling synchronized (mTaskListeners) { 92f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling for (SessionListener listener : mTaskListeners) { 93f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling listener.onSessionDone(uri); 94f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 95f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 96995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger finalizeSession(uri); 97f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 98f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling }); 99f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 100f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling 101f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling /** 102f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * Notifies all task listeners that the task with the given URI has been 103f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * failed to process. 104f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling */ 105f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling @Override 1060460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling public void notifyTaskFailed(final Uri uri, final int failureMessageId, 107698e271d2b263778bfa73d1e67d6e2cd2783c89ezafir final boolean removeFromFilmstrip) { 108f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling mMainHandler.execute(new Runnable() { 109f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling @Override 110f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling public void run() { 111f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling synchronized (mTaskListeners) { 112f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling for (SessionListener listener : mTaskListeners) { 1130460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling listener.onSessionFailed(uri, failureMessageId, removeFromFilmstrip); 114f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 115f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 116995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger finalizeSession(uri); 117f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 118f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling }); 119f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 120f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling 1219c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling @Override 1229c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling public void notifyTaskCanceled(final Uri uri) { 1239c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling mMainHandler.execute(new Runnable() { 1249c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling @Override 1259c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling public void run() { 1269c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling synchronized (mTaskListeners) { 1279c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling for (SessionListener listener : mTaskListeners) { 1289c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling listener.onSessionCanceled(uri); 1299c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling } 1309c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling } 1319c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling finalizeSession(uri); 1329c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling } 1339c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling }); 1349c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling } 1359c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling 136f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling /** 137f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * Notifies all task listeners that the task with the given URI has 138f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * progressed to the given state. 139f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling */ 140f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling @Override 141f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling public void notifyTaskProgress(final Uri uri, final int progressPercent) { 142f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling mMainHandler.execute(new Runnable() { 143f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling @Override 144f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling public void run() { 145f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling synchronized (mTaskListeners) { 146f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling for (SessionListener listener : mTaskListeners) { 147f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling listener.onSessionProgress(uri, progressPercent); 148f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 149f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 150f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 151f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling }); 152f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 153f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling 154f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling /** 155f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * Notifies all task listeners that the task with the given URI has 156f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * changed its progress message. 157f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling */ 158f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling @Override 1590460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling public void notifyTaskProgressText(final Uri uri, final int messageId) { 160f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling mMainHandler.execute(new Runnable() { 161f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling @Override 162f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling public void run() { 163f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling synchronized (mTaskListeners) { 164f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling for (SessionListener listener : mTaskListeners) { 1650460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling listener.onSessionProgressText(uri, messageId); 166f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 167f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 168f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 169f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling }); 170f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 171f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling 172f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling /** 173f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * Notifies all task listeners that the media associated with the task 174f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * has been updated. 175f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling */ 176f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling @Override 177f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling public void notifySessionUpdated(final Uri uri) { 178f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling mMainHandler.execute(new Runnable() { 179f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling @Override 180f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling public void run() { 181f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling synchronized (mTaskListeners) { 182f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling for (SessionListener listener : mTaskListeners) { 183f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling listener.onSessionUpdated(uri); 184f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 185f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 186f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 187f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling }); 188f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 189f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling 190f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling /** 191f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * Notifies all task listeners that the task with the given URI has 192f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * updated its media. 193f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * 194f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * @param indicator the bitmap that should be used for the capture 195f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * indicator 196f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling * @param rotationDegrees the rotation of the updated preview 197f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling */ 198f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling @Override 199f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling public void notifySessionCaptureIndicatorAvailable(final Bitmap indicator, final int 200f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling rotationDegrees) { 201f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling mMainHandler.execute(new Runnable() { 202f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling @Override 203f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling public void run() { 204f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling synchronized (mTaskListeners) { 205f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling for (SessionListener listener : mTaskListeners) { 206f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling listener.onSessionCaptureIndicatorUpdate(indicator, rotationDegrees); 207f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 208f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 209f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 210f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling }); 211f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 212f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu 213f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu @Override 214f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu public void notifySessionThumbnailAvailable(final Bitmap thumbnail) { 215f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu mMainHandler.execute(new Runnable() { 216f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu @Override 217f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu public void run() { 218f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu synchronized (mTaskListeners) { 219f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu for (SessionListener listener : mTaskListeners) { 220f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu listener.onSessionThumbnailUpdate(thumbnail); 221f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu } 222f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu } 223f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu } 224f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu }); 225f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu } 226f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu 227f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu @Override 228f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu public void notifySessionPictureDataAvailable( 229f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu final byte[] pictureData, final int orientation) { 230f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu mMainHandler.execute(new Runnable() { 231f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu @Override 232f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu public void run() { 233f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu synchronized (mTaskListeners) { 234f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu for (SessionListener listener : mTaskListeners) { 235f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu listener.onSessionPictureDataUpdate(pictureData, orientation); 236f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu } 237f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu } 238f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu } 239f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu }); 240f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu } 241f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling } 242f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling 243abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling private static final Log.Tag TAG = new Log.Tag("CaptureSessMgrImpl"); 244b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling 245f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling /** Sessions in progress, keyed by URI. */ 246f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling private final Map<String, CaptureSession> mSessions; 247f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling private final SessionNotifier mSessionNotifier; 2485fb629902527b7c688358ece3ef1f181322fc2abSenpo Hu private final CaptureSessionFactory mSessionFactory; 249a86b048709342fc53cee92aa047a15a22462c71cSascha Haeberling private final SessionStorageManager mSessionStorageManager; 250f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling /** Used to fire events to the session listeners from the main thread. */ 251f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling private final MainThread mMainHandler; 252a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 2530460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling /** Failed session messages. Uri -> message ID. */ 2540460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling private final HashMap<Uri, Integer> mFailedSessionMessages = new HashMap<>(); 255597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling 256a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling /** Listeners interested in task update events. */ 257a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling private final LinkedList<SessionListener> mTaskListeners = new LinkedList<SessionListener>(); 258a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 259a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling /** 260a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * Initializes a new {@link CaptureSessionManager} implementation. 261a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling * 2625fb629902527b7c688358ece3ef1f181322fc2abSenpo Hu * @param sessionFactory used to create new capture session objects. 263a86b048709342fc53cee92aa047a15a22462c71cSascha Haeberling * @param sessionStorageManager used to tell modules where to store 264a86b048709342fc53cee92aa047a15a22462c71cSascha Haeberling * temporary session data 2655fb629902527b7c688358ece3ef1f181322fc2abSenpo Hu * @param mainHandler the main handler which listener callback is executed on. 266a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling */ 2675fb629902527b7c688358ece3ef1f181322fc2abSenpo Hu public CaptureSessionManagerImpl( 2685fb629902527b7c688358ece3ef1f181322fc2abSenpo Hu CaptureSessionFactory sessionFactory, 2695fb629902527b7c688358ece3ef1f181322fc2abSenpo Hu SessionStorageManager sessionStorageManager, 270b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling MainThread mainHandler) { 2715fb629902527b7c688358ece3ef1f181322fc2abSenpo Hu mSessionFactory = sessionFactory; 272b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling mSessions = new HashMap<>(); 273f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling mSessionNotifier = new SessionNotifierImpl(); 274a86b048709342fc53cee92aa047a15a22462c71cSascha Haeberling mSessionStorageManager = sessionStorageManager; 275abf1e994d236a65180eecfcb6997003ab12795dfSascha Haeberling mMainHandler = mainHandler; 276a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 277a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 278995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger @Override 2795fb629902527b7c688358ece3ef1f181322fc2abSenpo Hu public CaptureSession createNewSession(String title, long sessionStartMillis, Location location) { 280f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling return mSessionFactory.createNewSession(this, mSessionNotifier, title, sessionStartMillis, 281f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling location); 282a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 283a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 284a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling @Override 285adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling public void putSession(Uri sessionUri, CaptureSession session) { 2868111aa0a298688da560dcac6bc4c3f92b878dbc7Sascha Haeberling synchronized (mSessions) { 287adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling mSessions.put(sessionUri.toString(), session); 288adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling } 289adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling } 290adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling 291adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling @Override 292cc79da28315aa4cb346e06346df5e379272d5c92Seth Raphael public CaptureSession getSession(Uri sessionUri) { 2938111aa0a298688da560dcac6bc4c3f92b878dbc7Sascha Haeberling synchronized (mSessions) { 294adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling return mSessions.get(sessionUri.toString()); 295adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling } 296cc79da28315aa4cb346e06346df5e379272d5c92Seth Raphael } 297cc79da28315aa4cb346e06346df5e379272d5c92Seth Raphael 298cc79da28315aa4cb346e06346df5e379272d5c92Seth Raphael @Override 299995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger public CaptureSession removeSession(Uri sessionUri) { 300995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger synchronized (mSessions) { 301995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger return mSessions.remove(sessionUri.toString()); 302995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger } 303995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger } 304995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger 305995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger @Override 306a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling public void addSessionListener(SessionListener listener) { 307a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling synchronized (mTaskListeners) { 308a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling mTaskListeners.add(listener); 309a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 310a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 311a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 312a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling @Override 313a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling public void removeSessionListener(SessionListener listener) { 314a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling synchronized (mTaskListeners) { 315a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling mTaskListeners.remove(listener); 316a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 317a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling } 318a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling 319a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling @Override 320a86b048709342fc53cee92aa047a15a22462c71cSascha Haeberling public File getSessionDirectory(String subDirectory) throws IOException { 3218111aa0a298688da560dcac6bc4c3f92b878dbc7Sascha Haeberling return mSessionStorageManager.getSessionDirectory(subDirectory); 322a86b048709342fc53cee92aa047a15a22462c71cSascha Haeberling } 323a86b048709342fc53cee92aa047a15a22462c71cSascha Haeberling 324b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling @Override 325b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling public boolean hasErrorMessage(Uri uri) { 326b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling return mFailedSessionMessages.containsKey(uri); 327b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling } 328b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling 329b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling @Override 3300460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling public int getErrorMessageId(Uri uri) { 3310460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling Integer messageId = mFailedSessionMessages.get(uri); 3320460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling if (messageId != null) { 3330460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling return messageId; 3340460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling } 3350460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling return -1; 336b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling } 337b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling 338b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling @Override 339b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling public void removeErrorMessage(Uri uri) { 340b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling mFailedSessionMessages.remove(uri); 341b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling } 342b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling 343f0ff1a9aa44d04f680af7cec8b97c3b01d3e76bdSascha Haeberling @Override 3440460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling public void putErrorMessage(Uri uri, int failureMessageId) { 3450460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling mFailedSessionMessages.put(uri, failureMessageId); 346b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling } 347b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling 348b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling @Override 349b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling public void fillTemporarySession(final SessionListener listener) { 350b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling mMainHandler.execute(new Runnable() { 351b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling @Override 352b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling public void run() { 353b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling synchronized (mSessions) { 354b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling for (String sessionUri : mSessions.keySet()) { 355b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling CaptureSession session = mSessions.get(sessionUri); 356b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling listener.onSessionQueued(session.getUri()); 357b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling listener.onSessionProgress(session.getUri(), session.getProgress()); 358b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling listener.onSessionProgressText(session.getUri(), 3590460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling session.getProgressMessageId()); 360b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling } 361b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling } 362b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling } 363b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling }); 364b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling } 365995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger 366995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger /** 367995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger * When done with a session, remove it from internal map and finalize it. 368995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger * 369995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger * @param uri Uri of the session to remove and finalize 370995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger */ 371995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger private void finalizeSession(Uri uri) { 372995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger CaptureSession session; 373995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger synchronized (mSessions) { 374995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger session = removeSession(uri); 375995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger } 376995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger if (session != null) { 377976bba4cfffb0089d4b7c61e16b90f506dbf1a2bSascha Haeberling session.finalizeSession(); 378995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger } 379995083b53be47e1e27133e403da0b63a03d07ea7Alan Newberger } 380a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling} 381