Cancel data loading when hourly job happens in the first 40 minutes
after booting in AOSP.
Test: make RunSettingsRoboTests + manual
Bug: 257384343
Change-Id: I437b68719ff5ece73fa33b74cb144f4262528e8c
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
index 959820a..e51db08 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
@@ -136,6 +136,11 @@
boolean isExtraDefend();
/**
+ * Returns {@code true} if delay the hourly job when device is booting.
+ */
+ boolean delayHourlyJobWhenBooting();
+
+ /**
* Gets a intent for one time bypass charge limited to resume charging.
*/
Intent getResumeChargeIntent(boolean isDockDefender);
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
index 94e4872..ba8587c 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -157,6 +157,11 @@
}
@Override
+ public boolean delayHourlyJobWhenBooting() {
+ return true;
+ }
+
+ @Override
public Set<CharSequence> getHideBackgroundUsageTimeSet(Context context) {
return new ArraySet<>();
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java b/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java
index c9d73cd..8c9285e 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java
@@ -24,13 +24,17 @@
import android.util.Log;
import com.android.settings.core.instrumentation.ElapsedTimeUtils;
+import com.android.settings.overlay.FeatureFactory;
import java.time.Duration;
/** Receives broadcasts to start or stop the periodic fetching job. */
public final class BootBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "BootBroadcastReceiver";
- private static final long RESCHEDULE_FOR_BOOT_ACTION = Duration.ofSeconds(6).toMillis();
+ private static final long RESCHEDULE_FOR_BOOT_ACTION_WITH_DELAY =
+ Duration.ofMinutes(40).toMillis();
+ private static final long RESCHEDULE_FOR_BOOT_ACTION_WITHOUT_DELAY =
+ Duration.ofSeconds(6).toMillis();
private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -67,7 +71,7 @@
case Intent.ACTION_TIME_CHANGED:
Log.d(TAG, "refresh job and clear all data from action=" + action);
DatabaseUtils.clearAll(context);
- PeriodicJobManager.getInstance(context).refreshJob();
+ PeriodicJobManager.getInstance(context).refreshJob(/*fromBoot=*/ false);
break;
default:
Log.w(TAG, "receive unsupported action=" + action);
@@ -78,15 +82,23 @@
final Intent recheckIntent = new Intent(ACTION_PERIODIC_JOB_RECHECK);
recheckIntent.setClass(context, BootBroadcastReceiver.class);
mHandler.postDelayed(() -> context.sendBroadcast(recheckIntent),
- RESCHEDULE_FOR_BOOT_ACTION);
+ getRescheduleTimeForBootAction(context));
} else if (ACTION_SETUP_WIZARD_FINISHED.equals(action)) {
ElapsedTimeUtils.storeSuwFinishedTimestamp(context, System.currentTimeMillis());
}
}
+ private long getRescheduleTimeForBootAction(Context context) {
+ final boolean delayHourlyJobWhenBooting =
+ FeatureFactory.getFactory(context)
+ .getPowerUsageFeatureProvider(context)
+ .delayHourlyJobWhenBooting();
+ return delayHourlyJobWhenBooting
+ ? RESCHEDULE_FOR_BOOT_ACTION_WITH_DELAY
+ : RESCHEDULE_FOR_BOOT_ACTION_WITHOUT_DELAY;
+ }
+
private static void refreshJobs(Context context) {
- // Clears useless data from battery usage database if needed.
- DatabaseUtils.clearExpiredDataIfNeeded(context);
- PeriodicJobManager.getInstance(context).refreshJob();
+ PeriodicJobManager.getInstance(context).refreshJob(/*fromBoot=*/ true);
}
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobManager.java b/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobManager.java
index 39293dc..2b18e92 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobManager.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobManager.java
@@ -24,6 +24,8 @@
import androidx.annotation.VisibleForTesting;
+import com.android.settings.overlay.FeatureFactory;
+
import java.text.SimpleDateFormat;
import java.time.Clock;
import java.time.Duration;
@@ -45,6 +47,9 @@
@VisibleForTesting
static final int DATA_FETCH_INTERVAL_MINUTE = 60;
+ @VisibleForTesting
+ static long sBroadcastDelayFromBoot = Duration.ofMinutes(40).toMillis();
+
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
void reset() {
sSingleton = null; // for testing only
@@ -65,7 +70,7 @@
/** Schedules the next alarm job if it is available. */
@SuppressWarnings("JavaUtilDate")
- public void refreshJob() {
+ public void refreshJob(final boolean fromBoot) {
if (mAlarmManager == null) {
Log.e(TAG, "cannot schedule next alarm job");
return;
@@ -74,7 +79,7 @@
final PendingIntent pendingIntent = getPendingIntent();
cancelJob(pendingIntent);
// Uses UTC time to avoid scheduler is impacted by different timezone.
- final long triggerAtMillis = getTriggerAtMillis(Clock.systemUTC());
+ final long triggerAtMillis = getTriggerAtMillis(mContext, Clock.systemUTC(), fromBoot);
mAlarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
Log.d(TAG, "schedule next alarm job at "
@@ -90,11 +95,21 @@
}
/** Gets the next alarm trigger UTC time in milliseconds. */
- static long getTriggerAtMillis(Clock clock) {
+ static long getTriggerAtMillis(Context context, Clock clock, final boolean fromBoot) {
long currentTimeMillis = clock.millis();
+ final boolean delayHourlyJobWhenBooting =
+ FeatureFactory.getFactory(context)
+ .getPowerUsageFeatureProvider(context)
+ .delayHourlyJobWhenBooting();
// Rounds to the previous nearest time slot and shifts to the next one.
long timeSlotUnit = Duration.ofMinutes(DATA_FETCH_INTERVAL_MINUTE).toMillis();
- return (currentTimeMillis / timeSlotUnit) * timeSlotUnit + timeSlotUnit;
+ long targetTime = (currentTimeMillis / timeSlotUnit) * timeSlotUnit + timeSlotUnit;
+ if (delayHourlyJobWhenBooting
+ && fromBoot
+ && (targetTime - currentTimeMillis) <= sBroadcastDelayFromBoot) {
+ targetTime += timeSlotUnit;
+ }
+ return targetTime;
}
private PendingIntent getPendingIntent() {
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobReceiver.java b/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobReceiver.java
index d6a2f62..3ca4532 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobReceiver.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobReceiver.java
@@ -42,7 +42,7 @@
BatteryUsageDataLoader.enqueueWork(context, /*isFullChargeStart=*/ false);
AppUsageDataLoader.enqueueWork(context);
Log.d(TAG, "refresh periodic job from action=" + action);
- PeriodicJobManager.getInstance(context).refreshJob();
+ PeriodicJobManager.getInstance(context).refreshJob(/*fromBoot=*/ false);
DatabaseUtils.clearExpiredDataIfNeeded(context);
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiverTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiverTest.java
index 514ac63..ba51e29 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiverTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiverTest.java
@@ -125,28 +125,6 @@
}
@Test
- public void onReceive_containsExpiredData_clearsExpiredDataFromDatabase()
- throws InterruptedException {
- insertExpiredData(/*shiftDay=*/ DatabaseUtils.DATA_RETENTION_INTERVAL_DAY);
-
- mReceiver.onReceive(mContext, new Intent(Intent.ACTION_BOOT_COMPLETED));
-
- TimeUnit.MILLISECONDS.sleep(100);
- assertThat(mDao.getAllAfter(0)).hasSize(1);
- }
-
- @Test
- public void onReceive_withoutExpiredData_notClearsExpiredDataFromDatabase()
- throws InterruptedException {
- insertExpiredData(/*shiftDay=*/ DatabaseUtils.DATA_RETENTION_INTERVAL_DAY - 1);
-
- mReceiver.onReceive(mContext, new Intent(Intent.ACTION_BOOT_COMPLETED));
-
- TimeUnit.MILLISECONDS.sleep(100);
- assertThat(mDao.getAllAfter(0)).hasSize(3);
- }
-
- @Test
public void onReceive_withTimeChangedIntent_clearsAllDataAndRefreshesJob()
throws InterruptedException {
mReceiver.onReceive(mContext, new Intent(Intent.ACTION_TIME_CHANGED));
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobManagerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobManagerTest.java
index 9e27bb0..efbce12 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobManagerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PeriodicJobManagerTest.java
@@ -57,7 +57,7 @@
@Test
public void refreshJob_refreshesAlarmJob() {
- mPeriodicJobManager.refreshJob();
+ mPeriodicJobManager.refreshJob(/*fromBoot=*/ false);
final ShadowAlarmManager.ScheduledAlarm alarm =
mShadowAlarmManager.peekNextScheduledAlarm();
@@ -76,7 +76,7 @@
FakeClock fakeClock = new FakeClock();
fakeClock.setCurrentTime(currentTimeDuration);
- assertThat(PeriodicJobManager.getTriggerAtMillis(fakeClock))
+ assertThat(PeriodicJobManager.getTriggerAtMillis(mContext, fakeClock, /*fromBoot=*/ false))
.isEqualTo(currentTimeDuration.plusMinutes(timeSlotUnit).toMillis());
}
@@ -89,7 +89,7 @@
fakeClock.setCurrentTime(
currentTimeDuration.plusMinutes(1L).plusMillis(51L));
- assertThat(PeriodicJobManager.getTriggerAtMillis(fakeClock))
+ assertThat(PeriodicJobManager.getTriggerAtMillis(mContext, fakeClock, /*fromBoot=*/ true))
.isEqualTo(currentTimeDuration.plusMinutes(timeSlotUnit).toMillis());
}
}