1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | package org.chromium.base; |
6 | |
7 | import android.app.Activity; |
8 | import android.os.Handler; |
9 | import android.os.Looper; |
10 | |
11 | /** |
12 | * Provides information about the current activity's status, and a way |
13 | * to register / unregister listeners for state changes. |
14 | */ |
15 | @JNINamespace("base::android") |
16 | public class ActivityStatus { |
17 | |
18 | // Constants matching activity states reported to StateListener.onStateChange |
19 | // As an implementation detail, these are now defined in the auto-generated |
20 | // ActivityState interface, to be shared with C++. |
21 | public static final int CREATED = ActivityState.CREATED; |
22 | public static final int STARTED = ActivityState.STARTED; |
23 | public static final int RESUMED = ActivityState.RESUMED; |
24 | public static final int PAUSED = ActivityState.PAUSED; |
25 | public static final int STOPPED = ActivityState.STOPPED; |
26 | public static final int DESTROYED = ActivityState.DESTROYED; |
27 | |
28 | // Current main activity, or null if none. |
29 | private static Activity sActivity; |
30 | |
31 | // Current main activity's state. This can be set even if sActivity is null, to simplify unit |
32 | // testing. |
33 | private static int sActivityState; |
34 | |
35 | private static final ObserverList<StateListener> sStateListeners = |
36 | new ObserverList<StateListener>(); |
37 | |
38 | /** |
39 | * Interface to be implemented by listeners. |
40 | */ |
41 | public interface StateListener { |
42 | /** |
43 | * Called when the activity's state changes. |
44 | * @param newState New activity state. |
45 | */ |
46 | public void onActivityStateChange(int newState); |
47 | } |
48 | |
49 | private ActivityStatus() {} |
50 | |
51 | /** |
52 | * Must be called by the main activity when it changes state. |
53 | * @param activity Current activity. |
54 | * @param newState New state value. |
55 | */ |
56 | public static void onStateChange(Activity activity, int newState) { |
57 | if (sActivity != activity) { |
58 | // ActivityStatus is notified with the CREATED event very late during the main activity |
59 | // creation to avoid making startup performance worse than it is by notifying observers |
60 | // that could do some expensive work. This can lead to non-CREATED events being fired |
61 | // before the CREATED event which is problematic. |
62 | // TODO(pliard): fix http://crbug.com/176837. |
63 | sActivity = activity; |
64 | } |
65 | sActivityState = newState; |
66 | for (StateListener listener : sStateListeners) { |
67 | listener.onActivityStateChange(newState); |
68 | } |
69 | if (newState == DESTROYED) { |
70 | sActivity = null; |
71 | } |
72 | } |
73 | |
74 | /** |
75 | * Indicates that the parent activity is currently paused. |
76 | */ |
77 | public static boolean isPaused() { |
78 | return sActivityState == PAUSED; |
79 | } |
80 | |
81 | /** |
82 | * Returns the current main application activity. |
83 | */ |
84 | public static Activity getActivity() { |
85 | return sActivity; |
86 | } |
87 | |
88 | /** |
89 | * Returns the current main application activity's state. |
90 | */ |
91 | public static int getState() { |
92 | return sActivityState; |
93 | } |
94 | |
95 | /** |
96 | * Registers the given listener to receive activity state changes. |
97 | * @param listener Listener to receive state changes. |
98 | */ |
99 | public static void registerStateListener(StateListener listener) { |
100 | sStateListeners.addObserver(listener); |
101 | } |
102 | |
103 | /** |
104 | * Unregisters the given listener from receiving activity state changes. |
105 | * @param listener Listener that doesn't want to receive state changes. |
106 | */ |
107 | public static void unregisterStateListener(StateListener listener) { |
108 | sStateListeners.removeObserver(listener); |
109 | } |
110 | |
111 | /** |
112 | * Registers the single thread-safe native activity status listener. |
113 | * This handles the case where the caller is not on the main thread. |
114 | * Note that this is used by a leaky singleton object from the native |
115 | * side, hence lifecycle management is greatly simplified. |
116 | */ |
117 | @CalledByNative |
118 | private static void registerThreadSafeNativeStateListener() { |
119 | ThreadUtils.runOnUiThread(new Runnable () { |
120 | @Override |
121 | public void run() { |
122 | // Register a new listener that calls nativeOnActivityStateChange. |
123 | sStateListeners.addObserver(new StateListener() { |
124 | @Override |
125 | public void onActivityStateChange(int newState) { |
126 | nativeOnActivityStateChange(newState); |
127 | } |
128 | }); |
129 | } |
130 | }); |
131 | } |
132 | |
133 | // Called to notify the native side of state changes. |
134 | // IMPORTANT: This is always called on the main thread! |
135 | private static native void nativeOnActivityStateChange(int newState); |
136 | } |