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