OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 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.chrome.browser.precache; | 5 package org.chromium.chrome.browser.precache; |
6 | 6 |
7 import android.app.AlarmManager; | 7 import android.app.AlarmManager; |
8 import android.app.PendingIntent; | 8 import android.app.PendingIntent; |
9 import android.content.BroadcastReceiver; | 9 import android.content.BroadcastReceiver; |
10 import android.content.Context; | 10 import android.content.Context; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 void setDeviceState(DeviceState deviceState) { | 51 void setDeviceState(DeviceState deviceState) { |
52 mDeviceState = deviceState; | 52 mDeviceState = deviceState; |
53 } | 53 } |
54 | 54 |
55 /** | 55 /** |
56 * Set whether or not precaching is enabled. If precaching is enabled, this
receiver will start | 56 * Set whether or not precaching is enabled. If precaching is enabled, this
receiver will start |
57 * the PrecacheService when it receives an intent. If precaching is disabled
, any running | 57 * the PrecacheService when it receives an intent. If precaching is disabled
, any running |
58 * PrecacheService will be stopped, and this receiver will do nothing when i
t receives an | 58 * PrecacheService will be stopped, and this receiver will do nothing when i
t receives an |
59 * intent. | 59 * intent. |
60 * | 60 * |
61 * @param context The Context to use. | 61 * @param context The application context. |
62 * @param enabled Whether or not precaching is enabled. | 62 * @param enabled Whether or not precaching is enabled. |
63 */ | 63 */ |
64 public static void setIsPrecachingEnabled(Context context, boolean enabled)
{ | 64 public static void setIsPrecachingEnabled(Context context, boolean enabled)
{ |
65 Log.v(TAG, "setIsPrecachingEnabled(%s)", enabled); | 65 Log.v(TAG, "setIsPrecachingEnabled(%s)", enabled); |
66 Editor editor = PreferenceManager.getDefaultSharedPreferences(context).e
dit(); | 66 Editor editor = PreferenceManager.getDefaultSharedPreferences(context).e
dit(); |
67 editor.putBoolean(PREF_IS_PRECACHING_ENABLED, enabled); | 67 editor.putBoolean(PREF_IS_PRECACHING_ENABLED, enabled); |
68 editor.apply(); | 68 editor.apply(); |
69 | 69 |
70 if (!enabled) { | 70 if (!enabled) { |
71 // Stop any running PrecacheService. If PrecacheService is not runni
ng, then this does | 71 // Stop any running PrecacheService. If PrecacheService is not runni
ng, then this does |
72 // nothing. | 72 // nothing. |
73 Intent serviceIntent = new Intent(null, null, context, PrecacheServi
ce.class); | 73 Intent serviceIntent = new Intent(null, null, context, PrecacheServi
ce.class); |
74 context.stopService(serviceIntent); | 74 context.stopService(serviceIntent); |
75 } | 75 } |
76 } | 76 } |
77 | 77 |
| 78 /** |
| 79 * Handler for when precaching has finished. If precaching had successfully
started, sets an |
| 80 * alarm for a subsequent run, and updates the last precache time. If not (i
.e. the precache |
| 81 * attempt aborted), sets an alarm for another attempt. |
| 82 * |
| 83 * @param context The application context. |
| 84 * @param precacheStarted Whether precaching successfully started. |
| 85 */ |
| 86 public static void precachingFinished(Context context, boolean precacheStart
ed) { |
| 87 new PrecacheServiceLauncher().precachingFinishedInternal(context, precac
heStarted); |
| 88 } |
| 89 |
| 90 private void precachingFinishedInternal(Context context, boolean precacheSta
rted) { |
| 91 Log.v(TAG, "precachingFinished(%s)", precacheStarted); |
| 92 if (precacheStarted) { |
| 93 // Store a pref indicating that precaching is starting now. |
| 94 setAlarm(context, |
| 95 Math.max(INTERACTIVE_STATE_POLLING_PERIOD_MS, WAIT_UNTIL_NEX
T_PRECACHE_MS)); |
| 96 |
| 97 Editor editor = PreferenceManager.getDefaultSharedPreferences(contex
t).edit(); |
| 98 editor.putLong(PREF_PRECACHE_LAST_TIME, getElapsedRealtimeOnSystem()
); |
| 99 editor.apply(); |
| 100 } else { |
| 101 setAlarm(context, |
| 102 Math.max(INTERACTIVE_STATE_POLLING_PERIOD_MS, |
| 103 WAIT_UNTIL_NEXT_PRECACHE_MS - timeSinceLastPrecacheM
s(context))); |
| 104 } |
| 105 } |
| 106 |
78 @VisibleForTesting | 107 @VisibleForTesting |
79 static boolean isPrecachingEnabled(Context context) { | 108 static boolean isPrecachingEnabled(Context context) { |
80 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(
context); | 109 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(
context); |
81 return prefs.getBoolean(PREF_IS_PRECACHING_ENABLED, false); | 110 return prefs.getBoolean(PREF_IS_PRECACHING_ENABLED, false); |
82 } | 111 } |
83 | 112 |
84 @Override | 113 @Override |
85 public void onReceive(Context context, Intent intent) { | 114 public void onReceive(Context context, Intent intent) { |
86 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(
context); | |
87 long lastPrecacheTimeMs = prefs.getLong(PREF_PRECACHE_LAST_TIME, 0L); | |
88 if (lastPrecacheTimeMs > getElapsedRealtimeOnSystem()) { | |
89 // System.elapsedRealtime() counts milliseconds since boot, so if th
e device has been | |
90 // rebooted since the last time precaching was performed, reset last
PrecacheTimeMs to 0. | |
91 lastPrecacheTimeMs = 0L; | |
92 } | |
93 | |
94 // Do nothing if precaching is disabled. | 115 // Do nothing if precaching is disabled. |
95 if (!isPrecachingEnabled(context)) return; | 116 if (!isPrecachingEnabled(context)) return; |
96 | 117 |
97 boolean isPowerConnected = mDeviceState.isPowerConnected(context); | 118 boolean isPowerConnected = mDeviceState.isPowerConnected(context); |
98 boolean isWifiAvailable = mDeviceState.isWifiAvailable(context); | 119 boolean isWifiAvailable = mDeviceState.isWifiAvailable(context); |
99 boolean isInteractive = mDeviceState.isInteractive(context); | 120 boolean isInteractive = mDeviceState.isInteractive(context); |
100 boolean areConditionsGoodForPrecaching = | 121 boolean areConditionsGoodForPrecaching = |
101 isPowerConnected && isWifiAvailable && !isInteractive; | 122 isPowerConnected && isWifiAvailable && !isInteractive; |
102 long timeSinceLastPrecacheMs = getElapsedRealtimeOnSystem() - lastPrecac
heTimeMs; | |
103 boolean hasEnoughTimePassedSinceLastPrecache = | 123 boolean hasEnoughTimePassedSinceLastPrecache = |
104 timeSinceLastPrecacheMs >= WAIT_UNTIL_NEXT_PRECACHE_MS; | 124 timeSinceLastPrecacheMs(context) >= WAIT_UNTIL_NEXT_PRECACHE_MS; |
105 | 125 |
106 // Only start precaching when an alarm action is received. This is to pr
event situations | 126 // Only start precaching when an alarm action is received. This is to pr
event situations |
107 // such as power being connected, precaching starting, then precaching b
eing immediately | 127 // such as power being connected, precaching starting, then precaching b
eing immediately |
108 // canceled because the screen turns on in response to power being conne
cted. | 128 // canceled because the screen turns on in response to power being conne
cted. |
109 if (ACTION_ALARM.equals(intent.getAction()) | 129 if (ACTION_ALARM.equals(intent.getAction()) |
110 && areConditionsGoodForPrecaching | 130 && areConditionsGoodForPrecaching |
111 && hasEnoughTimePassedSinceLastPrecache) { | 131 && hasEnoughTimePassedSinceLastPrecache) { |
112 // Store a pref indicating that precaching is starting now. | |
113 Editor editor = prefs.edit(); | |
114 editor.putLong(PREF_PRECACHE_LAST_TIME, getElapsedRealtimeOnSystem()
); | |
115 editor.apply(); | |
116 | |
117 setAlarm(context, Math.max( | |
118 INTERACTIVE_STATE_POLLING_PERIOD_MS, WAIT_UNTIL_NEXT_PRECACH
E_MS)); | |
119 | |
120 acquireWakeLockAndStartService(context); | 132 acquireWakeLockAndStartService(context); |
121 } else { | 133 } else { |
122 if (isPowerConnected && isWifiAvailable) { | 134 if (isPowerConnected && isWifiAvailable) { |
123 // If we're just waiting for non-interactivity (e.g., the screen
to be off), or for | 135 // If we're just waiting for non-interactivity (e.g., the screen
to be off), or for |
124 // enough time to pass after Wi-Fi or power has been connected,
then set an alarm | 136 // enough time to pass after Wi-Fi or power has been connected,
then set an alarm |
125 // for the next time to check the device state. We can't receive
SCREEN_ON/OFF | 137 // for the next time to check the device state. We can't receive
SCREEN_ON/OFF |
126 // intents as is done for detecting changes in power and connect
ivity, because | 138 // intents as is done for detecting changes in power and connect
ivity, because |
127 // SCREEN_ON/OFF intents are only delivered to BroadcastReceiver
s that are | 139 // SCREEN_ON/OFF intents are only delivered to BroadcastReceiver
s that are |
128 // registered dynamically in code, but the PrecacheServiceLaunch
er is registered in | 140 // registered dynamically in code, but the PrecacheServiceLaunch
er is registered in |
129 // the Android manifest. | 141 // the Android manifest. |
130 setAlarm(context, Math.max(INTERACTIVE_STATE_POLLING_PERIOD_MS, | 142 setAlarm(context, |
131 WAIT_UNTIL_NEXT_PRECACHE_MS - timeSinceLastPrecacheMs)); | 143 Math.max(INTERACTIVE_STATE_POLLING_PERIOD_MS, |
| 144 WAIT_UNTIL_NEXT_PRECACHE_MS - timeSinceLastPreca
cheMs(context))); |
132 } else { | 145 } else { |
133 // If the device doesn't have connected power or doesn't have Wi
-Fi, then there's no | 146 // If the device doesn't have connected power or doesn't have Wi
-Fi, then there's no |
134 // point in setting an alarm. | 147 // point in setting an alarm. |
135 cancelAlarm(context); | 148 cancelAlarm(context); |
136 } | 149 } |
137 } | 150 } |
138 } | 151 } |
139 | 152 |
140 /** Release the wakelock if it is held. */ | 153 /** Release the wakelock if it is held. */ |
141 @VisibleForTesting | 154 @VisibleForTesting |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 @VisibleForTesting | 231 @VisibleForTesting |
219 protected void cancelAlarmOnSystem(Context context, PendingIntent operation)
{ | 232 protected void cancelAlarmOnSystem(Context context, PendingIntent operation)
{ |
220 AlarmManager alarmManager = (AlarmManager) context.getSystemService(Cont
ext.ALARM_SERVICE); | 233 AlarmManager alarmManager = (AlarmManager) context.getSystemService(Cont
ext.ALARM_SERVICE); |
221 alarmManager.cancel(operation); | 234 alarmManager.cancel(operation); |
222 } | 235 } |
223 | 236 |
224 @VisibleForTesting | 237 @VisibleForTesting |
225 protected long getElapsedRealtimeOnSystem() { | 238 protected long getElapsedRealtimeOnSystem() { |
226 return SystemClock.elapsedRealtime(); | 239 return SystemClock.elapsedRealtime(); |
227 } | 240 } |
| 241 |
| 242 /** Returns the number of milliseconds since the last precache run completed
. */ |
| 243 private long timeSinceLastPrecacheMs(Context context) { |
| 244 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(
context); |
| 245 long lastPrecacheTimeMs = prefs.getLong(PREF_PRECACHE_LAST_TIME, 0L); |
| 246 if (lastPrecacheTimeMs > getElapsedRealtimeOnSystem()) { |
| 247 // System.elapsedRealtime() counts milliseconds since boot, so if th
e device has been |
| 248 // rebooted since the last time precaching was performed, reset last
PrecacheTimeMs to 0. |
| 249 lastPrecacheTimeMs = 0L; |
| 250 } |
| 251 return getElapsedRealtimeOnSystem() - lastPrecacheTimeMs; |
| 252 } |
228 } | 253 } |
229 | 254 |
OLD | NEW |