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