diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index ed717c4914676..699808156033d 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -195,10 +195,35 @@ public class Bmgr {
return;
}
+ if ("scheduling".equals(op)) {
+ setSchedulingEnabled(userId);
+ return;
+ }
+
System.err.println("Unknown command");
showUsage();
}
+ private void setSchedulingEnabled(int userId) {
+ String arg = nextArg();
+ if (arg == null) {
+ showUsage();
+ return;
+ }
+
+ try {
+ boolean enable = Boolean.parseBoolean(arg);
+ mBmgr.setFrameworkSchedulingEnabledForUser(userId, enable);
+ System.out.println(
+ "Backup scheduling is now "
+ + (enable ? "enabled" : "disabled")
+ + " for user "
+ + userId);
+ } catch (RemoteException e) {
+ handleRemoteException(e);
+ }
+ }
+
private void handleRemoteException(RemoteException e) {
System.err.println(e.toString());
System.err.println(BMGR_NOT_RUNNING_ERR);
@@ -944,6 +969,7 @@ public class Bmgr {
System.err.println(" bmgr activate BOOL");
System.err.println(" bmgr activated");
System.err.println(" bmgr autorestore BOOL");
+ System.err.println(" bmgr scheduling BOOL");
System.err.println("");
System.err.println("The '--user' option specifies the user on which the operation is run.");
System.err.println("It must be the first argument before the operation.");
@@ -1021,6 +1047,9 @@ public class Bmgr {
System.err.println("");
System.err.println("The 'autorestore' command enables or disables automatic restore when");
System.err.println("a new package is installed.");
+ System.err.println("");
+ System.err.println("The 'scheduling' command enables or disables backup scheduling in the");
+ System.err.println("framework.");
}
private static class BackupMonitor extends IBackupManagerMonitor.Stub {
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index bad282ead3d3a..ddeb2f936c7af 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -16,7 +16,6 @@
package android.app.backup;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -38,8 +37,6 @@ import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.List;
/**
@@ -409,6 +406,33 @@ public class BackupManager {
}
}
+ /**
+ * Enable/disable the framework backup scheduling entirely for the current user. When disabled,
+ * no Key/Value or Full backup jobs will be scheduled by the Android framework.
+ *
+ *
Note: This does not disable backups: only their scheduling is affected and backups can
+ * still be triggered manually.
+ *
+ *
Callers must hold the android.permission.BACKUP permission to use this method.
+ *
+ * @hide
+ */
+ @RequiresPermission(allOf = {android.Manifest.permission.BACKUP,
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional = true)
+ public void setFrameworkSchedulingEnabled(boolean isEnabled) {
+ checkServiceBinder();
+ if (sService == null) {
+ Log.e(TAG, "setFrameworkSchedulingEnabled() couldn't connect");
+ return;
+ }
+
+ try {
+ sService.setFrameworkSchedulingEnabledForUser(mContext.getUserId(), isEnabled);
+ } catch (RemoteException e) {
+ Log.e(TAG, "setFrameworkSchedulingEnabled() couldn't connect");
+ }
+ }
+
/**
* Report whether the backup mechanism is currently enabled.
*
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index aeb498721fb69..041c2a7c09f42 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -155,6 +155,22 @@ interface IBackupManager {
*/
void setBackupEnabledForUser(int userId, boolean isEnabled);
+
+ /**
+ * Enable/disable the framework backup scheduling entirely. When disabled, no Key/Value or Full
+ * backup jobs will be scheduled by the Android framework.
+ *
+ *
Note: This does not disable backups: only their scheduling is affected and backups can
+ * still be triggered manually.
+ *
+ *
Callers must hold the android.permission.BACKUP permission to use this method. If
+ * {@code userId} is different from the calling user id, then the caller must additionally hold
+ * the android.permission.INTERACT_ACROSS_USERS_FULL permission.
+ *
+ * @param userId The user for which backup scheduling should be enabled/disabled.
+ */
+ void setFrameworkSchedulingEnabledForUser(int userId, boolean isEnabled);
+
/**
* {@link android.app.backup.IBackupManager.setBackupEnabledForUser} for the calling user id.
*/
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 76ca20cb47187..388670844f490 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8659,6 +8659,12 @@ public final class Settings {
@Readable
public static final String BACKUP_AUTO_RESTORE = "backup_auto_restore";
+ /**
+ * Controls whether framework backup scheduling is enabled.
+ * @hide
+ */
+ public static final String BACKUP_SCHEDULING_ENABLED = "backup_scheduling_enabled";
+
/**
* Indicates whether settings backup has been fully provisioned.
* Type: int ( 0 = unprovisioned, 1 = fully provisioned )
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 4365a9b441b13..5ee36f373783b 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -695,6 +695,7 @@ public class SettingsBackupTest {
Settings.Secure.BACKUP_AUTO_RESTORE,
Settings.Secure.BACKUP_ENABLED,
Settings.Secure.BACKUP_PROVISIONED,
+ Settings.Secure.BACKUP_SCHEDULING_ENABLED,
Settings.Secure.BACKUP_TRANSPORT,
Settings.Secure.CALL_SCREENING_DEFAULT_COMPONENT,
Settings.Secure.CAMERA_LIFT_TRIGGER_ENABLED, // Candidate for backup?
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 8c09dcde58d0c..dc475f696a96c 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -25,7 +25,6 @@ import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.backup.BackupManager;
-import android.app.backup.BackupRestoreEventLogger;
import android.app.backup.BackupRestoreEventLogger.DataTypeResult;
import android.app.backup.IBackupManager;
import android.app.backup.IBackupManagerMonitor;
@@ -722,6 +721,17 @@ public class BackupManagerService extends IBackupManager.Stub {
}
}
+ @Override
+ public void setFrameworkSchedulingEnabledForUser(int userId, boolean isEnabled) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId,
+ "setFrameworkSchedulingEnabledForUser()");
+
+ if (userBackupManagerService != null) {
+ userBackupManagerService.setFrameworkSchedulingEnabled(isEnabled);
+ }
+ }
+
@Override
public void setBackupEnabledForUser(@UserIdInt int userId, boolean isEnabled)
throws RemoteException {
diff --git a/services/backup/java/com/android/server/backup/FullBackupJob.java b/services/backup/java/com/android/server/backup/FullBackupJob.java
index 0bb25e360f152..fe0e1c6b6fcb4 100644
--- a/services/backup/java/com/android/server/backup/FullBackupJob.java
+++ b/services/backup/java/com/android/server/backup/FullBackupJob.java
@@ -45,9 +45,12 @@ public class FullBackupJob extends JobService {
private final SparseArray mParamsForUser = new SparseArray<>();
public static void schedule(int userId, Context ctx, long minDelay,
- BackupManagerConstants constants) {
+ UserBackupManagerService userBackupManagerService) {
+ if (!userBackupManagerService.isFrameworkSchedulingEnabled()) return;
+
JobScheduler js = (JobScheduler) ctx.getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo.Builder builder = new JobInfo.Builder(getJobIdForUserId(userId), sIdleService);
+ final BackupManagerConstants constants = userBackupManagerService.getConstants();
synchronized (constants) {
builder.setRequiresDeviceIdle(true)
.setRequiredNetworkType(constants.getFullBackupRequiredNetworkType())
diff --git a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
index 058dcae3102f8..164bbeaff6bc7 100644
--- a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
+++ b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
@@ -64,14 +64,16 @@ public class KeyValueBackupJob extends JobService {
@VisibleForTesting
public static final int MAX_JOB_ID = 52418896;
- public static void schedule(int userId, Context ctx, BackupManagerConstants constants) {
- schedule(userId, ctx, 0, constants);
+ public static void schedule(int userId, Context ctx,
+ UserBackupManagerService userBackupManagerService) {
+ schedule(userId, ctx, 0, userBackupManagerService);
}
public static void schedule(int userId, Context ctx, long delay,
- BackupManagerConstants constants) {
+ UserBackupManagerService userBackupManagerService) {
synchronized (KeyValueBackupJob.class) {
- if (sScheduledForUserId.get(userId)) {
+ if (sScheduledForUserId.get(userId)
+ || !userBackupManagerService.isFrameworkSchedulingEnabled()) {
return;
}
@@ -80,6 +82,7 @@ public class KeyValueBackupJob extends JobService {
final int networkType;
final boolean needsCharging;
+ final BackupManagerConstants constants = userBackupManagerService.getConstants();
synchronized (constants) {
interval = constants.getKeyValueBackupIntervalMilliseconds();
fuzz = constants.getKeyValueBackupFuzzMilliseconds();
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 6ba01d712e92d..40a4af95413a4 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -1958,8 +1958,8 @@ public class UserBackupManagerService {
}
// We don't want the backup jobs to kick in any time soon.
// Reschedules them to run in the distant future.
- KeyValueBackupJob.schedule(mUserId, mContext, BUSY_BACKOFF_MIN_MILLIS, mConstants);
- FullBackupJob.schedule(mUserId, mContext, 2 * BUSY_BACKOFF_MIN_MILLIS, mConstants);
+ KeyValueBackupJob.schedule(mUserId, mContext, BUSY_BACKOFF_MIN_MILLIS, this);
+ FullBackupJob.schedule(mUserId, mContext, 2 * BUSY_BACKOFF_MIN_MILLIS, this);
} finally {
Binder.restoreCallingIdentity(oldToken);
}
@@ -2088,7 +2088,7 @@ public class UserBackupManagerService {
final long interval = mConstants.getFullBackupIntervalMilliseconds();
final long appLatency = (timeSinceLast < interval) ? (interval - timeSinceLast) : 0;
final long latency = Math.max(transportMinLatency, appLatency);
- FullBackupJob.schedule(mUserId, mContext, latency, mConstants);
+ FullBackupJob.schedule(mUserId, mContext, latency, this);
} else {
if (DEBUG_SCHEDULING) {
Slog.i(
@@ -2226,7 +2226,7 @@ public class UserBackupManagerService {
addUserIdToLogMessage(
mUserId, "Deferring scheduled full backups in battery saver mode"));
}
- FullBackupJob.schedule(mUserId, mContext, keyValueBackupInterval, mConstants);
+ FullBackupJob.schedule(mUserId, mContext, keyValueBackupInterval, this);
return false;
}
@@ -2392,7 +2392,7 @@ public class UserBackupManagerService {
+ "operation; rescheduling +" + latency));
}
final long deferTime = latency; // pin for the closure
- FullBackupJob.schedule(mUserId, mContext, deferTime, mConstants);
+ FullBackupJob.schedule(mUserId, mContext, deferTime, this);
return false;
}
@@ -2495,7 +2495,7 @@ public class UserBackupManagerService {
}
// ...and schedule a backup pass if necessary
- KeyValueBackupJob.schedule(mUserId, mContext, mConstants);
+ KeyValueBackupJob.schedule(mUserId, mContext, this);
}
// Note: packageName is currently unused, but may be in the future
@@ -2730,7 +2730,7 @@ public class UserBackupManagerService {
mUserId, "Not running backup while in battery save mode"));
}
// Try again in several hours.
- KeyValueBackupJob.schedule(mUserId, mContext, mConstants);
+ KeyValueBackupJob.schedule(mUserId, mContext, this);
} else {
if (DEBUG) {
Slog.v(TAG, addUserIdToLogMessage(mUserId, "Scheduling immediate backup pass"));
@@ -3208,12 +3208,49 @@ public class UserBackupManagerService {
}
}
+ synchronized void setFrameworkSchedulingEnabled(boolean isEnabled) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
+ "setFrameworkSchedulingEnabled");
+
+ boolean wasEnabled = isFrameworkSchedulingEnabled();
+ if (wasEnabled == isEnabled) return;
+
+ Slog.i(TAG, addUserIdToLogMessage(mUserId,
+ (isEnabled ? "Enabling" : "Disabling") + " backup scheduling"));
+
+ final long oldId = Binder.clearCallingIdentity();
+ try {
+ // TODO(b/264889098): Consider at a later point if we should us a sentinel file as
+ // setBackupEnabled.
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.BACKUP_SCHEDULING_ENABLED, isEnabled ? 1 : 0, mUserId);
+
+ if (!isEnabled) {
+ KeyValueBackupJob.cancel(mUserId, mContext);
+ FullBackupJob.cancel(mUserId, mContext);
+ } else {
+ KeyValueBackupJob.schedule(mUserId, mContext, this);
+ scheduleNextFullBackupJob(/* transportMinLatency */ 0);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(oldId);
+ }
+ }
+
+ synchronized boolean isFrameworkSchedulingEnabled() {
+ // By default scheduling is enabled
+ final int defaultSetting = 1;
+ int isEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.BACKUP_SCHEDULING_ENABLED, defaultSetting, mUserId);
+ return isEnabled == 1;
+ }
+
@VisibleForTesting
void updateStateOnBackupEnabled(boolean wasEnabled, boolean enable) {
synchronized (mQueueLock) {
if (enable && !wasEnabled && mSetupComplete) {
// if we've just been enabled, start scheduling backup passes
- KeyValueBackupJob.schedule(mUserId, mContext, mConstants);
+ KeyValueBackupJob.schedule(mUserId, mContext, this);
scheduleNextFullBackupJob(0);
} else if (!enable) {
// No longer enabled, so stop running backups
@@ -4127,6 +4164,8 @@ public class UserBackupManagerService {
pw.println("Auto-restore is " + (mAutoRestore ? "enabled" : "disabled"));
if (mBackupRunning) pw.println("Backup currently running");
pw.println(isBackupOperationInProgress() ? "Backup in progress" : "No backups running");
+ pw.println("Framework scheduling is "
+ + (isFrameworkSchedulingEnabled() ? "enabled" : "disabled"));
pw.println("Last backup pass started: " + mLastBackupPass
+ " (now = " + System.currentTimeMillis() + ')');
pw.println(" next scheduled: " + KeyValueBackupJob.nextScheduled(mUserId));
diff --git a/services/backup/java/com/android/server/backup/internal/SetupObserver.java b/services/backup/java/com/android/server/backup/internal/SetupObserver.java
index c5e912e6d18b9..f399fe9e7ab9f 100644
--- a/services/backup/java/com/android/server/backup/internal/SetupObserver.java
+++ b/services/backup/java/com/android/server/backup/internal/SetupObserver.java
@@ -23,7 +23,6 @@ import static com.android.server.backup.UserBackupManagerService.getSetupComplet
import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
-import android.provider.Settings;
import android.util.Slog;
import com.android.server.backup.KeyValueBackupJob;
@@ -78,7 +77,7 @@ public class SetupObserver extends ContentObserver {
Slog.d(TAG, "Setup complete so starting backups");
}
KeyValueBackupJob.schedule(mUserBackupManagerService.getUserId(), mContext,
- mUserBackupManagerService.getConstants());
+ mUserBackupManagerService);
mUserBackupManagerService.scheduleNextFullBackupJob(0);
}
}
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
index ca92b6986731f..41e8092436b54 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -1246,7 +1246,7 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable {
delay = 0;
}
KeyValueBackupJob.schedule(mBackupManagerService.getUserId(),
- mBackupManagerService.getContext(), delay, mBackupManagerService.getConstants());
+ mBackupManagerService.getContext(), delay, mBackupManagerService);
for (String packageName : mOriginalQueue) {
mBackupManagerService.dataChangedImpl(packageName);
diff --git a/services/robotests/backup/src/com/android/server/backup/FullBackupJobTest.java b/services/robotests/backup/src/com/android/server/backup/FullBackupJobTest.java
index dbc0da7074777..c8797e25b7407 100644
--- a/services/robotests/backup/src/com/android/server/backup/FullBackupJobTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/FullBackupJobTest.java
@@ -18,6 +18,8 @@ package com.android.server.backup;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
+
import android.annotation.UserIdInt;
import android.app.job.JobScheduler;
import android.content.Context;
@@ -31,6 +33,8 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
@@ -45,14 +49,20 @@ public class FullBackupJobTest {
private BackupManagerConstants mConstants;
private ShadowJobScheduler mShadowJobScheduler;
+ @Mock
+ private UserBackupManagerService mUserBackupManagerService;
+
@UserIdInt private int mUserOneId;
@UserIdInt private int mUserTwoId;
@Before
public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mConstants = new BackupManagerConstants(Handler.getMain(), mContext.getContentResolver());
mConstants.start();
+ when(mUserBackupManagerService.getConstants()).thenReturn(mConstants);
+ when(mUserBackupManagerService.isFrameworkSchedulingEnabled()).thenReturn(true);
mShadowJobScheduler = Shadows.shadowOf(mContext.getSystemService(JobScheduler.class));
@@ -69,8 +79,8 @@ public class FullBackupJobTest {
@Test
public void testSchedule_afterScheduling_jobExists() {
- FullBackupJob.schedule(mUserOneId, mContext, 0, mConstants);
- FullBackupJob.schedule(mUserTwoId, mContext, 0, mConstants);
+ FullBackupJob.schedule(mUserOneId, mContext, 0, mUserBackupManagerService);
+ FullBackupJob.schedule(mUserTwoId, mContext, 0, mUserBackupManagerService);
assertThat(mShadowJobScheduler.getPendingJob(getJobIdForUserId(mUserOneId))).isNotNull();
assertThat(mShadowJobScheduler.getPendingJob(getJobIdForUserId(mUserTwoId))).isNotNull();
@@ -78,18 +88,34 @@ public class FullBackupJobTest {
@Test
public void testCancel_afterCancelling_jobDoesntExist() {
- FullBackupJob.schedule(mUserOneId, mContext, 0, mConstants);
- FullBackupJob.schedule(mUserTwoId, mContext, 0, mConstants);
+ FullBackupJob.schedule(mUserOneId, mContext, 0, mUserBackupManagerService);
+ FullBackupJob.schedule(mUserTwoId, mContext, 0, mUserBackupManagerService);
FullBackupJob.cancel(mUserOneId, mContext);
FullBackupJob.cancel(mUserTwoId, mContext);
assertThat(mShadowJobScheduler.getPendingJob(getJobIdForUserId(mUserOneId))).isNull();
assertThat(mShadowJobScheduler.getPendingJob(getJobIdForUserId(mUserTwoId))).isNull();
}
+
+ @Test
+ public void testSchedule_isNoopIfDisabled() {
+ when(mUserBackupManagerService.isFrameworkSchedulingEnabled()).thenReturn(false);
+ FullBackupJob.schedule(mUserOneId, mContext, 0, mUserBackupManagerService);
+
+ assertThat(mShadowJobScheduler.getPendingJob(getJobIdForUserId(mUserOneId))).isNull();
+ }
+
+ @Test
+ public void testSchedule_schedulesJobIfEnabled() {
+ when(mUserBackupManagerService.isFrameworkSchedulingEnabled()).thenReturn(true);
+ FullBackupJob.schedule(mUserOneId, mContext, 0, mUserBackupManagerService);
+
+ assertThat(mShadowJobScheduler.getPendingJob(getJobIdForUserId(mUserOneId))).isNotNull();
+ }
//
@Test
public void testSchedule_onlySchedulesForRequestedUser() {
- FullBackupJob.schedule(mUserOneId, mContext, 0, mConstants);
+ FullBackupJob.schedule(mUserOneId, mContext, 0, mUserBackupManagerService);
assertThat(mShadowJobScheduler.getPendingJob(getJobIdForUserId(mUserOneId))).isNotNull();
assertThat(mShadowJobScheduler.getPendingJob(getJobIdForUserId(mUserTwoId))).isNull();
@@ -97,8 +123,8 @@ public class FullBackupJobTest {
//
@Test
public void testCancel_onlyCancelsForRequestedUser() {
- FullBackupJob.schedule(mUserOneId, mContext, 0, mConstants);
- FullBackupJob.schedule(mUserTwoId, mContext, 0, mConstants);
+ FullBackupJob.schedule(mUserOneId, mContext, 0, mUserBackupManagerService);
+ FullBackupJob.schedule(mUserTwoId, mContext, 0, mUserBackupManagerService);
FullBackupJob.cancel(mUserOneId, mContext);
assertThat(mShadowJobScheduler.getPendingJob(getJobIdForUserId(mUserOneId))).isNull();
diff --git a/services/robotests/backup/src/com/android/server/backup/KeyValueBackupJobTest.java b/services/robotests/backup/src/com/android/server/backup/KeyValueBackupJobTest.java
index 1c5fac28de3c5..712ac55d2ff5f 100644
--- a/services/robotests/backup/src/com/android/server/backup/KeyValueBackupJobTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/KeyValueBackupJobTest.java
@@ -18,6 +18,8 @@ package com.android.server.backup;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
+
import android.annotation.UserIdInt;
import android.content.Context;
import android.os.Handler;
@@ -30,6 +32,8 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@@ -41,14 +45,20 @@ public class KeyValueBackupJobTest {
private Context mContext;
private BackupManagerConstants mConstants;
+ @Mock
+ private UserBackupManagerService mUserBackupManagerService;
+
@UserIdInt private int mUserOneId;
@UserIdInt private int mUserTwoId;
@Before
public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mConstants = new BackupManagerConstants(Handler.getMain(), mContext.getContentResolver());
mConstants.start();
+ when(mUserBackupManagerService.getConstants()).thenReturn(mConstants);
+ when(mUserBackupManagerService.isFrameworkSchedulingEnabled()).thenReturn(true);
mUserOneId = UserHandle.USER_SYSTEM;
mUserTwoId = mUserOneId + 1;
@@ -61,6 +71,22 @@ public class KeyValueBackupJobTest {
KeyValueBackupJob.cancel(mUserTwoId, mContext);
}
+ @Test
+ public void testSchedule_isNoopIfDisabled() {
+ when(mUserBackupManagerService.isFrameworkSchedulingEnabled()).thenReturn(false);
+ KeyValueBackupJob.schedule(mUserOneId, mContext, mUserBackupManagerService);
+
+ assertThat(KeyValueBackupJob.isScheduled(mUserOneId)).isFalse();
+ }
+
+ @Test
+ public void testSchedule_schedulesJobIfEnabled() {
+ when(mUserBackupManagerService.isFrameworkSchedulingEnabled()).thenReturn(true);
+ KeyValueBackupJob.schedule(mUserOneId, mContext, mUserBackupManagerService);
+
+ assertThat(KeyValueBackupJob.isScheduled(mUserOneId)).isTrue();
+ }
+
@Test
public void testIsScheduled_beforeScheduling_returnsFalse() {
assertThat(KeyValueBackupJob.isScheduled(mUserOneId)).isFalse();
@@ -69,8 +95,8 @@ public class KeyValueBackupJobTest {
@Test
public void testIsScheduled_afterScheduling_returnsTrue() {
- KeyValueBackupJob.schedule(mUserOneId, mContext, mConstants);
- KeyValueBackupJob.schedule(mUserTwoId, mContext, mConstants);
+ KeyValueBackupJob.schedule(mUserOneId, mContext, mUserBackupManagerService);
+ KeyValueBackupJob.schedule(mUserTwoId, mContext, mUserBackupManagerService);
assertThat(KeyValueBackupJob.isScheduled(mUserOneId)).isTrue();
assertThat(KeyValueBackupJob.isScheduled(mUserTwoId)).isTrue();
@@ -78,8 +104,8 @@ public class KeyValueBackupJobTest {
@Test
public void testIsScheduled_afterCancelling_returnsFalse() {
- KeyValueBackupJob.schedule(mUserOneId, mContext, mConstants);
- KeyValueBackupJob.schedule(mUserTwoId, mContext, mConstants);
+ KeyValueBackupJob.schedule(mUserOneId, mContext, mUserBackupManagerService);
+ KeyValueBackupJob.schedule(mUserTwoId, mContext, mUserBackupManagerService);
KeyValueBackupJob.cancel(mUserOneId, mContext);
KeyValueBackupJob.cancel(mUserTwoId, mContext);
@@ -89,7 +115,7 @@ public class KeyValueBackupJobTest {
@Test
public void testIsScheduled_afterScheduling_returnsTrueOnlyForScheduledUser() {
- KeyValueBackupJob.schedule(mUserOneId, mContext, mConstants);
+ KeyValueBackupJob.schedule(mUserOneId, mContext, mUserBackupManagerService);
assertThat(KeyValueBackupJob.isScheduled(mUserOneId)).isTrue();
assertThat(KeyValueBackupJob.isScheduled(mUserTwoId)).isFalse();
@@ -97,8 +123,8 @@ public class KeyValueBackupJobTest {
@Test
public void testIsScheduled_afterCancelling_returnsFalseOnlyForCancelledUser() {
- KeyValueBackupJob.schedule(mUserOneId, mContext, mConstants);
- KeyValueBackupJob.schedule(mUserTwoId, mContext, mConstants);
+ KeyValueBackupJob.schedule(mUserOneId, mContext, mUserBackupManagerService);
+ KeyValueBackupJob.schedule(mUserTwoId, mContext, mUserBackupManagerService);
KeyValueBackupJob.cancel(mUserOneId, mContext);
assertThat(KeyValueBackupJob.isScheduled(mUserOneId)).isFalse();