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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/precache/PrecacheServiceLauncher.java

Issue 1036363002: Reland of "precache: Move the java files into //components/precache/android" (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 5 years, 8 months 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
OLDNEW
(Empty)
1 // Copyright 2015 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.chrome.browser.precache;
6
7 import android.app.AlarmManager;
8 import android.app.PendingIntent;
9 import android.content.BroadcastReceiver;
10 import android.content.Context;
11 import android.content.Intent;
12 import android.content.SharedPreferences;
13 import android.content.SharedPreferences.Editor;
14 import android.os.PowerManager;
15 import android.os.PowerManager.WakeLock;
16 import android.os.SystemClock;
17 import android.preference.PreferenceManager;
18
19 import org.chromium.base.ThreadUtils;
20 import org.chromium.base.VisibleForTesting;
21 import org.chromium.components.precache.DeviceState;
22
23 /**
24 * BroadcastReceiver that determines when conditions are right for precaching, a nd starts the
25 * {@link PrecacheService} if they are. Conditions are right for precaching when the device is
26 * connected to power, Wi-Fi, interactivity (e.g., the screen) is off, and at le ast
27 * |WAIT_UNTIL_NEXT_PRECACHE_MS| have passed since the last time precaching was done.
28 */
29 public class PrecacheServiceLauncher extends BroadcastReceiver {
30 private static final String TAG = "PrecacheServiceLauncher";
31
32 @VisibleForTesting
33 static final String PREF_IS_PRECACHING_ENABLED = "precache.is_precaching_ena bled";
34
35 @VisibleForTesting
36 static final String PREF_PRECACHE_LAST_TIME = "precache.last_time";
37
38 @VisibleForTesting
39 static final String ACTION_ALARM =
40 "org.chromium.chrome.browser.precache.PrecacheServiceLauncher.ALARM" ;
41
42 private static final int INTERACTIVE_STATE_POLLING_PERIOD_MS = 15 * 60 * 100 0; // 15 minutes.
43 static final int WAIT_UNTIL_NEXT_PRECACHE_MS = 4 * 60 * 60 * 1000; // 4 hou rs.
44
45 private static WakeLock sWakeLock = null;
46
47 private DeviceState mDeviceState = DeviceState.getInstance();
48
49 @VisibleForTesting
50 void setDeviceState(DeviceState deviceState) {
51 mDeviceState = deviceState;
52 }
53
54 /**
55 * Set whether or not precaching is enabled. If precaching is enabled, this receiver will start
56 * the PrecacheService when it receives an intent. If precaching is disabled , any running
57 * PrecacheService will be stopped, and this receiver will do nothing when i t receives an
58 * intent.
59 *
60 * @param context The Context to use.
61 * @param enabled Whether or not precaching is enabled.
62 */
63 public static void setIsPrecachingEnabled(Context context, boolean enabled) {
64 Editor editor = PreferenceManager.getDefaultSharedPreferences(context).e dit();
65 editor.putBoolean(PREF_IS_PRECACHING_ENABLED, enabled);
66 editor.apply();
67
68 if (!enabled) {
69 // Stop any running PrecacheService. If PrecacheService is not runni ng, then this does
70 // nothing.
71 Intent serviceIntent = new Intent(null, null, context, PrecacheServi ce.class);
72 context.stopService(serviceIntent);
73 }
74 }
75
76
77 @Override
78 public void onReceive(Context context, Intent intent) {
79 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences( context);
80 boolean isPrecachingEnabled = prefs.getBoolean(PREF_IS_PRECACHING_ENABLE D, false);
81 long lastPrecacheTimeMs = prefs.getLong(PREF_PRECACHE_LAST_TIME, 0L);
82 if (lastPrecacheTimeMs > getElapsedRealtimeOnSystem()) {
83 // System.elapsedRealtime() counts milliseconds since boot, so if th e device has been
84 // rebooted since the last time precaching was performed, reset last PrecacheTimeMs to 0.
85 lastPrecacheTimeMs = 0L;
86 }
87
88 // Do nothing if precaching is disabled.
89 if (!isPrecachingEnabled) return;
90
91 boolean isPowerConnected = mDeviceState.isPowerConnected(context);
92 boolean isWifiAvailable = mDeviceState.isWifiAvailable(context);
93 boolean isInteractive = mDeviceState.isInteractive(context);
94 boolean areConditionsGoodForPrecaching =
95 isPowerConnected && isWifiAvailable && !isInteractive;
96 long timeSinceLastPrecacheMs = getElapsedRealtimeOnSystem() - lastPrecac heTimeMs;
97 boolean hasEnoughTimePassedSinceLastPrecache =
98 timeSinceLastPrecacheMs >= WAIT_UNTIL_NEXT_PRECACHE_MS;
99
100 // Only start precaching when an alarm action is received. This is to pr event situations
101 // such as power being connected, precaching starting, then precaching b eing immediately
102 // canceled because the screen turns on in response to power being conne cted.
103 if (ACTION_ALARM.equals(intent.getAction())
104 && areConditionsGoodForPrecaching
105 && hasEnoughTimePassedSinceLastPrecache) {
106 // Store a pref indicating that precaching is starting now.
107 Editor editor = prefs.edit();
108 editor.putLong(PREF_PRECACHE_LAST_TIME, getElapsedRealtimeOnSystem() );
109 editor.apply();
110
111 setAlarm(context, Math.max(
112 INTERACTIVE_STATE_POLLING_PERIOD_MS, WAIT_UNTIL_NEXT_PRECACH E_MS));
113
114 acquireWakeLockAndStartService(context);
115 } else {
116 if (isPowerConnected && isWifiAvailable) {
117 // If we're just waiting for non-interactivity (e.g., the screen to be off), or for
118 // enough time to pass after Wi-Fi or power has been connected, then set an alarm
119 // for the next time to check the device state. We can't receive SCREEN_ON/OFF
120 // intents as is done for detecting changes in power and connect ivity, because
121 // SCREEN_ON/OFF intents are only delivered to BroadcastReceiver s that are
122 // registered dynamically in code, but the PrecacheServiceLaunch er is registered in
123 // the Android manifest.
124 setAlarm(context, Math.max(INTERACTIVE_STATE_POLLING_PERIOD_MS,
125 WAIT_UNTIL_NEXT_PRECACHE_MS - timeSinceLastPrecacheMs));
126 } else {
127 // If the device doesn't have connected power or doesn't have Wi -Fi, then there's no
128 // point in setting an alarm.
129 cancelAlarm(context);
130 }
131 }
132 }
133
134 /** Release the wakelock if it is held. */
135 @VisibleForTesting
136 protected static void releaseWakeLock() {
137 ThreadUtils.assertOnUiThread();
138 if (sWakeLock != null && sWakeLock.isHeld()) sWakeLock.release();
139 }
140
141 /**
142 * Acquire the wakelock and start the PrecacheService.
143 *
144 * @param context The Context to use to start the service.
145 */
146 private void acquireWakeLockAndStartService(Context context) {
147 acquireWakeLock(context);
148 startPrecacheService(context);
149 }
150
151 @VisibleForTesting
152 protected void startPrecacheService(Context context) {
153 Intent serviceIntent = new Intent(
154 PrecacheService.ACTION_START_PRECACHE, null, context, PrecacheSe rvice.class);
155 context.startService(serviceIntent);
156 }
157
158 @VisibleForTesting
159 protected void acquireWakeLock(Context context) {
160 ThreadUtils.assertOnUiThread();
161 if (sWakeLock == null) {
162 PowerManager pm = (PowerManager) context.getSystemService(Context.PO WER_SERVICE);
163 sWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
164 }
165 sWakeLock.acquire();
166 }
167
168 /**
169 * Get a PendingIntent for setting an alarm to notify the PrecacheServiceLau ncher.
170 *
171 * @param context The Context to use for the PendingIntent.
172 * @return The PendingIntent.
173 */
174 private static PendingIntent getPendingAlarmIntent(Context context) {
175 return PendingIntent.getBroadcast(context, 0,
176 new Intent(ACTION_ALARM, null, context, PrecacheServiceLauncher. class),
177 PendingIntent.FLAG_UPDATE_CURRENT);
178 }
179
180 /**
181 * Set an alarm to notify the PrecacheServiceLauncher in the future.
182 *
183 * @param context The Context to use.
184 * @param delayMs Delay in milliseconds before the alarm goes off.
185 */
186 private void setAlarm(Context context, long delayMs) {
187 setAlarmOnSystem(context, AlarmManager.ELAPSED_REALTIME_WAKEUP,
188 getElapsedRealtimeOnSystem() + delayMs, getPendingAlarmIntent(co ntext));
189 }
190
191 /**
192 * Set the alarm on the system using the given parameters. This method can b e overridden in
193 * tests.
194 */
195 @VisibleForTesting
196 protected void setAlarmOnSystem(Context context, int type, long triggerAtMil lis,
197 PendingIntent operation) {
198 AlarmManager alarmManager = (AlarmManager) context.getSystemService(Cont ext.ALARM_SERVICE);
199 alarmManager.set(type, triggerAtMillis, operation);
200 }
201
202 /**
203 * Cancel a previously set alarm, if there is one. This method can be overri dden in tests.
204 *
205 * @param context The Context to use.
206 */
207 private void cancelAlarm(Context context) {
208 cancelAlarmOnSystem(context, getPendingAlarmIntent(context));
209 }
210
211 /** Cancel a previously set alarm on the system. This method can be overridd en in tests. */
212 @VisibleForTesting
213 protected void cancelAlarmOnSystem(Context context, PendingIntent operation) {
214 AlarmManager alarmManager = (AlarmManager) context.getSystemService(Cont ext.ALARM_SERVICE);
215 alarmManager.cancel(operation);
216 }
217
218 @VisibleForTesting
219 protected long getElapsedRealtimeOnSystem() {
220 return SystemClock.elapsedRealtime();
221 }
222 }
223
OLDNEW
« no previous file with comments | « chrome/android/java/src/org/chromium/chrome/browser/precache/PrecacheService.java ('k') | chrome/android/javatests/DEPS » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698