| 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 | } |