Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(124)

Side by Side Diff: base/android/java/src/org/chromium/base/ApplicationStatus.java

Issue 1378653002: [Android] Enable ApplicationStatus for WebView. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: add intial sCachedApplicationState Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 private static Object sCachedApplicationStateLock = new Object(); 57 private static Object sCachedApplicationStateLock = new Object();
58 private static Integer sCachedApplicationState; 58 private static Integer sCachedApplicationState;
59 59
60 /** Last activity that was shown (or null if none or it was destroyed). */ 60 /** Last activity that was shown (or null if none or it was destroyed). */
61 private static Activity sActivity; 61 private static Activity sActivity;
62 62
63 /** A lazily initialized listener that forwards application state changes to native. */ 63 /** A lazily initialized listener that forwards application state changes to native. */
64 private static ApplicationStateListener sNativeApplicationStateListener; 64 private static ApplicationStateListener sNativeApplicationStateListener;
65 65
66 /** 66 /**
67 * If true means we are running in an activity lifecycle independent mode,
68 * see {@link #initializeActivityIndependent(Application, Context)} for more details.
69 */
70 private static boolean sActivityLifecycleIndependentMode = false;
71
72 /**
73 * Context corresponding to sApplication. Note this context can be different from sApplication
74 * iself so use sApplicationContext instead of casting sApplication.
75 */
76 private static Context sApplicationContext;
77
78 /**
67 * A map of which observers listen to state changes from which {@link Activi ty}. 79 * A map of which observers listen to state changes from which {@link Activi ty}.
68 */ 80 */
69 private static final Map<Activity, ActivityInfo> sActivityInfo = 81 private static final Map<Activity, ActivityInfo> sActivityInfo =
70 new ConcurrentHashMap<Activity, ActivityInfo>(); 82 new ConcurrentHashMap<Activity, ActivityInfo>();
71 83
72 /** 84 /**
73 * A list of observers to be notified when any {@link Activity} has a state change. 85 * A list of observers to be notified when any {@link Activity} has a state change.
74 */ 86 */
75 private static final ObserverList<ActivityStateListener> sGeneralActivitySta teListeners = 87 private static final ObserverList<ActivityStateListener> sGeneralActivitySta teListeners =
76 new ObserverList<ActivityStateListener>(); 88 new ObserverList<ActivityStateListener>();
(...skipping 25 matching lines...) Expand all
102 * @param activity The activity that had a state change. 114 * @param activity The activity that had a state change.
103 * @param newState New activity state. 115 * @param newState New activity state.
104 */ 116 */
105 public void onActivityStateChange(Activity activity, int newState); 117 public void onActivityStateChange(Activity activity, int newState);
106 } 118 }
107 119
108 private ApplicationStatus() {} 120 private ApplicationStatus() {}
109 121
110 /** 122 /**
111 * Initializes the activity status for a specified application. 123 * Initializes the activity status for a specified application.
124 * This method only registers for ActivityLifecycle changes.
112 * 125 *
113 * @param application The application whose status you wish to monitor. 126 * @param application The application whose status you wish to monitor.
114 */ 127 */
115 public static void initialize(BaseChromiumApplication application) { 128 private static void initializeLifecycleCallbacks(Application application) {
116 sApplication = application; 129 sApplication = application;
117 130
118 application.registerWindowFocusChangedListener(
119 new BaseChromiumApplication.WindowFocusChangedListener() {
120 @Override
121 public void onWindowFocusChanged(Activity activity, boolean hasFocus) {
122 if (!hasFocus || activity == sActivity) return;
123
124 int state = getStateForActivity(activity);
125
126 if (state != ActivityState.DESTROYED && state != Activit yState.STOPPED) {
127 sActivity = activity;
128 }
129
130 // TODO(dtrainor): Notify of active activity change?
131 }
132 });
133
134 application.registerActivityLifecycleCallbacks(new ActivityLifecycleCall backs() { 131 application.registerActivityLifecycleCallbacks(new ActivityLifecycleCall backs() {
135 @Override 132 @Override
136 public void onActivityCreated(final Activity activity, Bundle savedI nstanceState) { 133 public void onActivityCreated(final Activity activity, Bundle savedI nstanceState) {
137 onStateChange(activity, ActivityState.CREATED); 134 onStateChange(activity, ActivityState.CREATED);
138 } 135 }
139 136
140 @Override 137 @Override
141 public void onActivityDestroyed(Activity activity) { 138 public void onActivityDestroyed(Activity activity) {
142 onStateChange(activity, ActivityState.DESTROYED); 139 onStateChange(activity, ActivityState.DESTROYED);
143 } 140 }
(...skipping 17 matching lines...) Expand all
161 } 158 }
162 159
163 @Override 160 @Override
164 public void onActivityStopped(Activity activity) { 161 public void onActivityStopped(Activity activity) {
165 onStateChange(activity, ActivityState.STOPPED); 162 onStateChange(activity, ActivityState.STOPPED);
166 } 163 }
167 }); 164 });
168 } 165 }
169 166
170 /** 167 /**
168 * Initializes the activity status for a specified application.
169 * The initialization should happen before any activity is created.
170 *
171 * @param application The application whose status you wish to monitor.
172 */
173 public static void initialize(BaseChromiumApplication application) {
174 sApplicationContext = application.getApplicationContext();
175 initializeLifecycleCallbacks(application);
176
177 application.registerWindowFocusChangedListener(
178 new BaseChromiumApplication.WindowFocusChangedListener() {
179 @Override
180 public void onWindowFocusChanged(Activity activity, boolean hasFocus) {
181 if (!hasFocus || activity == sActivity) return;
182
183 int state = getStateForActivity(activity);
184
185 if (state != ActivityState.DESTROYED && state != Activit yState.STOPPED) {
186 sActivity = activity;
187 }
188
189 // TODO(dtrainor): Notify of active activity change?
190 }
191 });
192 }
193
194
195 /**
196 * Initializes ApplicationStatus in "ActivityLifecycleIndependentMode". This mode is
197 * different from the regular initialization (@see initialize) in the follow ing ways:
198 * 1. Currently doesn't listen to focus changes (hence sActivity is always null).
199 * 2. Allows to specify a custom applicationContext and an android applica tion object.
200 * 3. Allows to call this method at any time during lifetime of the applic ation.
201 */
202 public static void initializeActivityIndependent(Application application,
203 Context applicationContext) {
204 sActivityLifecycleIndependentMode = true;
205 sApplicationContext = applicationContext;
206
207 // Assume we have running activity (or activity that will be running ver y soon).
208 // This is to handle the case when "initializeActivityIndependent" is ex ecuted
209 // after the ActivityState.CREATED, ActivityState.STARTED and ActivitySt ate.RESUMED
210 // have been dispatched.
211 synchronized (sCachedApplicationStateLock) {
212 sCachedApplicationState = ApplicationState.HAS_RUNNING_ACTIVITIES;
213 }
214
215 initializeLifecycleCallbacks(application);
216 }
217
218 /**
171 * Must be called by the main activity when it changes state. 219 * Must be called by the main activity when it changes state.
172 * 220 *
173 * @param activity Current activity. 221 * @param activity Current activity.
174 * @param newState New state value. 222 * @param newState New state value.
175 */ 223 */
176 private static void onStateChange(Activity activity, int newState) { 224 private static void onStateChange(Activity activity, int newState) {
177 if (activity == null) throw new IllegalArgumentException("null activity is not supported"); 225 if (activity == null) throw new IllegalArgumentException("null activity is not supported");
178 226
179 if (sActivity == null
180 || newState == ActivityState.CREATED
181 || newState == ActivityState.RESUMED
182 || newState == ActivityState.STARTED) {
183 sActivity = activity;
184 }
185
186 int oldApplicationState = getStateForApplication(); 227 int oldApplicationState = getStateForApplication();
187 228
188 if (newState == ActivityState.CREATED) { 229 if (sActivityLifecycleIndependentMode) {
189 assert !sActivityInfo.containsKey(activity); 230 assert sActivity == null;
190 sActivityInfo.put(activity, new ActivityInfo()); 231 if (!sActivityInfo.containsKey(activity)) {
232 sActivityInfo.put(activity, new ActivityInfo());
233 }
234 } else {
235 if (sActivity == null
236 || newState == ActivityState.CREATED
237 || newState == ActivityState.RESUMED
238 || newState == ActivityState.STARTED) {
239 sActivity = activity;
240 }
241
242 if (newState == ActivityState.CREATED) {
243 assert !sActivityInfo.containsKey(activity);
244 sActivityInfo.put(activity, new ActivityInfo());
245 }
191 } 246 }
192 247
193 // Invalidate the cached application state. 248 // Invalidate the cached application state.
194 synchronized (sCachedApplicationStateLock) { 249 synchronized (sCachedApplicationStateLock) {
195 sCachedApplicationState = null; 250 sCachedApplicationState = null;
196 } 251 }
197 252
198 ActivityInfo info = sActivityInfo.get(activity); 253 ActivityInfo info = sActivityInfo.get(activity);
199 info.setStatus(newState); 254 info.setStatus(newState);
200 255
(...skipping 25 matching lines...) Expand all
226 * Testing method to update the state of the specified activity. 281 * Testing method to update the state of the specified activity.
227 */ 282 */
228 @VisibleForTesting 283 @VisibleForTesting
229 public static void onStateChangeForTesting(Activity activity, int newState) { 284 public static void onStateChangeForTesting(Activity activity, int newState) {
230 onStateChange(activity, newState); 285 onStateChange(activity, newState);
231 } 286 }
232 287
233 /** 288 /**
234 * @return The most recent focused {@link Activity} tracked by this class. Being focused means 289 * @return The most recent focused {@link Activity} tracked by this class. Being focused means
235 * out of all the activities tracked here, it has most recently gain ed window focus. 290 * out of all the activities tracked here, it has most recently gain ed window focus.
291 * Note that in 'sActivityLifecycleIndependentMode' the returned Act ivity is currently
292 * always null (see crbug.com/538175).
236 */ 293 */
237 public static Activity getLastTrackedFocusedActivity() { 294 public static Activity getLastTrackedFocusedActivity() {
295 // sActivityLifecycleIndependentMode implies sActivity == null
296 assert !sActivityLifecycleIndependentMode || sActivity == null;
238 return sActivity; 297 return sActivity;
239 } 298 }
240 299
241 /** 300 /**
242 * @return A {@link List} of all non-destroyed {@link Activity}s. 301 * @return A {@link List} of all non-destroyed {@link Activity}s.
243 */ 302 */
244 public static List<WeakReference<Activity>> getRunningActivities() { 303 public static List<WeakReference<Activity>> getRunningActivities() {
245 List<WeakReference<Activity>> activities = new ArrayList<WeakReference<A ctivity>>(); 304 List<WeakReference<Activity>> activities = new ArrayList<WeakReference<A ctivity>>();
246 for (Activity activity : sActivityInfo.keySet()) { 305 for (Activity activity : sActivityInfo.keySet()) {
247 activities.add(new WeakReference<Activity>(activity)); 306 activities.add(new WeakReference<Activity>(activity));
248 } 307 }
249 return activities; 308 return activities;
250 } 309 }
251 310
252 /** 311 /**
253 * @return The {@link Context} for the {@link Application}. 312 * @return The {@link Context} for the {@link Application}.
254 */ 313 */
255 public static Context getApplicationContext() { 314 public static Context getApplicationContext() {
256 return sApplication != null ? sApplication.getApplicationContext() : nul l; 315 return sApplicationContext;
257 } 316 }
258 317
259 /** 318 /**
260 * Query the state for a given activity. If the activity is not being track ed, this will 319 * Query the state for a given activity. If the activity is not being track ed, this will
261 * return {@link ActivityState#DESTROYED}. 320 * return {@link ActivityState#DESTROYED}.
262 * 321 *
263 * <p> 322 * <p>
264 * Please note that Chrome can have multiple activities running simultaneous ly. Please also 323 * Please note that Chrome can have multiple activities running simultaneous ly. Please also
265 * look at {@link #getStateForApplication()} for more details. 324 * look at {@link #getStateForApplication()} for more details.
266 * 325 *
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 501
443 if (hasPausedActivity) return ApplicationState.HAS_PAUSED_ACTIVITIES; 502 if (hasPausedActivity) return ApplicationState.HAS_PAUSED_ACTIVITIES;
444 if (hasStoppedActivity) return ApplicationState.HAS_STOPPED_ACTIVITIES; 503 if (hasStoppedActivity) return ApplicationState.HAS_STOPPED_ACTIVITIES;
445 return ApplicationState.HAS_DESTROYED_ACTIVITIES; 504 return ApplicationState.HAS_DESTROYED_ACTIVITIES;
446 } 505 }
447 506
448 // Called to notify the native side of state changes. 507 // Called to notify the native side of state changes.
449 // IMPORTANT: This is always called on the main thread! 508 // IMPORTANT: This is always called on the main thread!
450 private static native void nativeOnApplicationStateChange(int newState); 509 private static native void nativeOnApplicationStateChange(int newState);
451 } 510 }
OLDNEW
« no previous file with comments | « android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698