OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.base; | 5 package org.chromium.base; |
6 | 6 |
7 import android.app.Activity; | 7 import android.app.Activity; |
8 import android.app.Application; | 8 import android.app.Application; |
9 import android.app.Application.ActivityLifecycleCallbacks; | 9 import android.app.Application.ActivityLifecycleCallbacks; |
10 import android.content.Context; | 10 import android.content.Context; |
11 import android.os.Bundle; | 11 import android.os.Bundle; |
12 | 12 |
13 import java.lang.ref.WeakReference; | 13 import java.lang.ref.WeakReference; |
14 import java.util.ArrayList; | 14 import java.util.ArrayList; |
15 import java.util.HashMap; | |
16 import java.util.List; | 15 import java.util.List; |
17 import java.util.Map; | 16 import java.util.Map; |
| 17 import java.util.concurrent.ConcurrentHashMap; |
18 | 18 |
19 /** | 19 /** |
20 * Provides information about the current activity's status, and a way | 20 * Provides information about the current activity's status, and a way |
21 * to register / unregister listeners for state changes. | 21 * to register / unregister listeners for state changes. |
22 */ | 22 */ |
23 @JNINamespace("base::android") | 23 @JNINamespace("base::android") |
24 public class ApplicationStatus { | 24 public class ApplicationStatus { |
25 private static class ActivityInfo { | 25 private static class ActivityInfo { |
26 private int mStatus = ActivityState.DESTROYED; | 26 private int mStatus = ActivityState.DESTROYED; |
27 private ObserverList<ActivityStateListener> mListeners = | 27 private ObserverList<ActivityStateListener> mListeners = |
(...skipping 16 matching lines...) Expand all Loading... |
44 /** | 44 /** |
45 * @return A list of {@link ActivityStateListener}s listening to this ac
tivity. | 45 * @return A list of {@link ActivityStateListener}s listening to this ac
tivity. |
46 */ | 46 */ |
47 public ObserverList<ActivityStateListener> getListeners() { | 47 public ObserverList<ActivityStateListener> getListeners() { |
48 return mListeners; | 48 return mListeners; |
49 } | 49 } |
50 } | 50 } |
51 | 51 |
52 private static Application sApplication; | 52 private static Application sApplication; |
53 | 53 |
| 54 private static Object sCachedApplicationStateLock = new Object(); |
54 private static Integer sCachedApplicationState; | 55 private static Integer sCachedApplicationState; |
55 | 56 |
56 /** Last activity that was shown (or null if none or it was destroyed). */ | 57 /** Last activity that was shown (or null if none or it was destroyed). */ |
57 private static Activity sActivity; | 58 private static Activity sActivity; |
58 | 59 |
59 /** A lazily initialized listener that forwards application state changes to
native. */ | 60 /** A lazily initialized listener that forwards application state changes to
native. */ |
60 private static ApplicationStateListener sNativeApplicationStateListener; | 61 private static ApplicationStateListener sNativeApplicationStateListener; |
61 | 62 |
62 /** | 63 /** |
63 * A map of which observers listen to state changes from which {@link Activi
ty}. | 64 * A map of which observers listen to state changes from which {@link Activi
ty}. |
64 */ | 65 */ |
65 private static final Map<Activity, ActivityInfo> sActivityInfo = | 66 private static final Map<Activity, ActivityInfo> sActivityInfo = |
66 new HashMap<Activity, ActivityInfo>(); | 67 new ConcurrentHashMap<Activity, ActivityInfo>(); |
67 | 68 |
68 /** | 69 /** |
69 * A list of observers to be notified when any {@link Activity} has a state
change. | 70 * A list of observers to be notified when any {@link Activity} has a state
change. |
70 */ | 71 */ |
71 private static final ObserverList<ActivityStateListener> sGeneralActivitySta
teListeners = | 72 private static final ObserverList<ActivityStateListener> sGeneralActivitySta
teListeners = |
72 new ObserverList<ActivityStateListener>(); | 73 new ObserverList<ActivityStateListener>(); |
73 | 74 |
74 /** | 75 /** |
75 * A list of observers to be notified when the visibility state of this {@li
nk Application} | 76 * A list of observers to be notified when the visibility state of this {@li
nk Application} |
76 * changes. See {@link #getStateForApplication()}. | 77 * changes. See {@link #getStateForApplication()}. |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 } | 181 } |
181 | 182 |
182 int oldApplicationState = getStateForApplication(); | 183 int oldApplicationState = getStateForApplication(); |
183 | 184 |
184 if (newState == ActivityState.CREATED) { | 185 if (newState == ActivityState.CREATED) { |
185 assert !sActivityInfo.containsKey(activity); | 186 assert !sActivityInfo.containsKey(activity); |
186 sActivityInfo.put(activity, new ActivityInfo()); | 187 sActivityInfo.put(activity, new ActivityInfo()); |
187 } | 188 } |
188 | 189 |
189 // Invalidate the cached application state. | 190 // Invalidate the cached application state. |
190 sCachedApplicationState = null; | 191 synchronized (sCachedApplicationStateLock) { |
| 192 sCachedApplicationState = null; |
| 193 } |
191 | 194 |
192 ActivityInfo info = sActivityInfo.get(activity); | 195 ActivityInfo info = sActivityInfo.get(activity); |
193 info.setStatus(newState); | 196 info.setStatus(newState); |
194 | 197 |
195 // Notify all state observers that are specifically listening to this ac
tivity. | 198 // Notify all state observers that are specifically listening to this ac
tivity. |
196 for (ActivityStateListener listener : info.getListeners()) { | 199 for (ActivityStateListener listener : info.getListeners()) { |
197 listener.onActivityStateChange(activity, newState); | 200 listener.onActivityStateChange(activity, newState); |
198 } | 201 } |
199 | 202 |
200 // Notify all state observers that are listening globally for all activi
ty state | 203 // Notify all state observers that are listening globally for all activi
ty state |
(...skipping 27 matching lines...) Expand all Loading... |
228 * out of all the activities tracked here, it has most recently gain
ed window focus. | 231 * out of all the activities tracked here, it has most recently gain
ed window focus. |
229 */ | 232 */ |
230 public static Activity getLastTrackedFocusedActivity() { | 233 public static Activity getLastTrackedFocusedActivity() { |
231 return sActivity; | 234 return sActivity; |
232 } | 235 } |
233 | 236 |
234 /** | 237 /** |
235 * @return A {@link List} of all non-destroyed {@link Activity}s. | 238 * @return A {@link List} of all non-destroyed {@link Activity}s. |
236 */ | 239 */ |
237 public static List<WeakReference<Activity>> getRunningActivities() { | 240 public static List<WeakReference<Activity>> getRunningActivities() { |
238 ThreadUtils.assertOnUiThread(); | |
239 List<WeakReference<Activity>> activities = new ArrayList<WeakReference<A
ctivity>>(); | 241 List<WeakReference<Activity>> activities = new ArrayList<WeakReference<A
ctivity>>(); |
240 for (Activity activity : sActivityInfo.keySet()) { | 242 for (Activity activity : sActivityInfo.keySet()) { |
241 activities.add(new WeakReference<Activity>(activity)); | 243 activities.add(new WeakReference<Activity>(activity)); |
242 } | 244 } |
243 return activities; | 245 return activities; |
244 } | 246 } |
245 | 247 |
246 /** | 248 /** |
247 * @return The {@link Context} for the {@link Application}. | 249 * @return The {@link Context} for the {@link Application}. |
248 */ | 250 */ |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 */ | 297 */ |
296 public static int getStateForActivity(Activity activity) { | 298 public static int getStateForActivity(Activity activity) { |
297 ActivityInfo info = sActivityInfo.get(activity); | 299 ActivityInfo info = sActivityInfo.get(activity); |
298 return info != null ? info.getStatus() : ActivityState.DESTROYED; | 300 return info != null ? info.getStatus() : ActivityState.DESTROYED; |
299 } | 301 } |
300 | 302 |
301 /** | 303 /** |
302 * @return The state of the application (see {@link ApplicationState}). | 304 * @return The state of the application (see {@link ApplicationState}). |
303 */ | 305 */ |
304 public static int getStateForApplication() { | 306 public static int getStateForApplication() { |
305 if (sCachedApplicationState == null) sCachedApplicationState = determine
ApplicationState(); | 307 synchronized (sCachedApplicationStateLock) { |
| 308 if (sCachedApplicationState == null) { |
| 309 sCachedApplicationState = determineApplicationState(); |
| 310 } |
| 311 } |
306 | 312 |
307 return sCachedApplicationState.intValue(); | 313 return sCachedApplicationState.intValue(); |
308 } | 314 } |
309 | 315 |
310 /** | 316 /** |
311 * Checks whether or not any Activity in this Application is visible to the
user. Note that | 317 * Checks whether or not any Activity in this Application is visible to the
user. Note that |
312 * this includes the PAUSED state, which can happen when the Activity is tem
porarily covered | 318 * this includes the PAUSED state, which can happen when the Activity is tem
porarily covered |
313 * by another Activity's Fragment (e.g.). | 319 * by another Activity's Fragment (e.g.). |
314 * @return Whether any Activity under this Application is visible. | 320 * @return Whether any Activity under this Application is visible. |
315 */ | 321 */ |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 | 439 |
434 if (hasPausedActivity) return ApplicationState.HAS_PAUSED_ACTIVITIES; | 440 if (hasPausedActivity) return ApplicationState.HAS_PAUSED_ACTIVITIES; |
435 if (hasStoppedActivity) return ApplicationState.HAS_STOPPED_ACTIVITIES; | 441 if (hasStoppedActivity) return ApplicationState.HAS_STOPPED_ACTIVITIES; |
436 return ApplicationState.HAS_DESTROYED_ACTIVITIES; | 442 return ApplicationState.HAS_DESTROYED_ACTIVITIES; |
437 } | 443 } |
438 | 444 |
439 // Called to notify the native side of state changes. | 445 // Called to notify the native side of state changes. |
440 // IMPORTANT: This is always called on the main thread! | 446 // IMPORTANT: This is always called on the main thread! |
441 private static native void nativeOnApplicationStateChange(int newState); | 447 private static native void nativeOnApplicationStateChange(int newState); |
442 } | 448 } |
OLD | NEW |