Deny SCHEDULE_EXACT_ALARM by default to newer apps

Apps targeting T will not get SCHEDULE_EXACT_ALARM permission by
default, except in a few privileged special cases.

Test: atest FrameworksMockingServicesTests:AlarmManagerServiceTest
atest CtsAlarmManagerTestCases:ExactAlarmsTest

Bug: 226439802
Change-Id: Ie81a9c3bd8b863c3fd64aaf413209ff8862de74b
This commit is contained in:
Suprabh Shukla
2022-04-05 15:06:24 -07:00
parent ee9ba8ff1b
commit a1adc26c84
5 changed files with 229 additions and 33 deletions

View File

@@ -27,6 +27,7 @@ import android.annotation.SystemApi;
import android.annotation.SystemService; import android.annotation.SystemService;
import android.annotation.TestApi; import android.annotation.TestApi;
import android.compat.annotation.ChangeId; import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.compat.annotation.EnabledSince; import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage; import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context; import android.content.Context;
@@ -280,6 +281,18 @@ public class AlarmManager {
@EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
public static final long ENABLE_USE_EXACT_ALARM = 218533173L; public static final long ENABLE_USE_EXACT_ALARM = 218533173L;
/**
* For apps targeting {@link Build.VERSION_CODES#TIRAMISU} or above, the permission
* {@link Manifest.permission#SCHEDULE_EXACT_ALARM} will be denied, unless the user explicitly
* allows it from Settings.
*
* TODO (b/226439802): change to EnabledSince(T) after SDK finalization.
* @hide
*/
@ChangeId
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2)
public static final long SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT = 226439802L;
@UnsupportedAppUsage @UnsupportedAppUsage
private final IAlarmManager mService; private final IAlarmManager mService;
private final Context mContext; private final Context mContext;

View File

@@ -66,6 +66,7 @@ import android.app.IAlarmListener;
import android.app.IAlarmManager; import android.app.IAlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.compat.CompatChanges; import android.app.compat.CompatChanges;
import android.app.role.RoleManager;
import android.app.usage.UsageStatsManager; import android.app.usage.UsageStatsManager;
import android.app.usage.UsageStatsManagerInternal; import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
@@ -164,6 +165,7 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.TimeZone; import java.util.TimeZone;
@@ -224,6 +226,7 @@ public class AlarmManagerService extends SystemService {
private ActivityManagerInternal mActivityManagerInternal; private ActivityManagerInternal mActivityManagerInternal;
private final EconomyManagerInternal mEconomyManagerInternal; private final EconomyManagerInternal mEconomyManagerInternal;
private PackageManagerInternal mPackageManagerInternal; private PackageManagerInternal mPackageManagerInternal;
private RoleManager mRoleManager;
private volatile PermissionManagerServiceInternal mLocalPermissionManager; private volatile PermissionManagerServiceInternal mLocalPermissionManager;
final Object mLock = new Object(); final Object mLock = new Object();
@@ -562,6 +565,9 @@ public class AlarmManagerService extends SystemService {
@VisibleForTesting @VisibleForTesting
static final String KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED = static final String KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED =
"kill_on_schedule_exact_alarm_revoked"; "kill_on_schedule_exact_alarm_revoked";
@VisibleForTesting
static final String KEY_SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT =
"schedule_exact_alarm_denied_by_default";
private static final long DEFAULT_MIN_FUTURITY = 5 * 1000; private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
private static final long DEFAULT_MIN_INTERVAL = 60 * 1000; private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
@@ -606,6 +612,9 @@ public class AlarmManagerService extends SystemService {
private static final boolean DEFAULT_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED = true; private static final boolean DEFAULT_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED = true;
// TODO(b/226439802): Flip to true.
private static final boolean DEFAULT_SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT = false;
// Minimum futurity of a new alarm // Minimum futurity of a new alarm
public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY; public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
@@ -693,6 +702,14 @@ public class AlarmManagerService extends SystemService {
public boolean KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED = public boolean KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED =
DEFAULT_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED; DEFAULT_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED;
/**
* When this is {@code true}, apps with the change
* {@link AlarmManager#SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT} enabled will not get
* {@link Manifest.permission#SCHEDULE_EXACT_ALARM} unless the user grants it to them.
*/
public volatile boolean SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT =
DEFAULT_SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT;
public boolean USE_TARE_POLICY = Settings.Global.DEFAULT_ENABLE_TARE == 1; public boolean USE_TARE_POLICY = Settings.Global.DEFAULT_ENABLE_TARE == 1;
private long mLastAllowWhileIdleWhitelistDuration = -1; private long mLastAllowWhileIdleWhitelistDuration = -1;
@@ -876,6 +893,15 @@ public class AlarmManagerService extends SystemService {
KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED, KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED,
DEFAULT_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED); DEFAULT_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED);
break; break;
case KEY_SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT:
final boolean oldValue = SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT;
SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT = properties.getBoolean(
KEY_SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT,
DEFAULT_SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT);
handleScheduleExactAlarmDeniedByDefaultChange(oldValue,
SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT);
break;
default: default:
if (name.startsWith(KEY_PREFIX_STANDBY_QUOTA) && !standbyQuotaUpdated) { if (name.startsWith(KEY_PREFIX_STANDBY_QUOTA) && !standbyQuotaUpdated) {
// The quotas need to be updated in order, so we can't just rely // The quotas need to be updated in order, so we can't just rely
@@ -946,6 +972,15 @@ public class AlarmManagerService extends SystemService {
} }
} }
private void handleScheduleExactAlarmDeniedByDefaultChange(boolean oldValue,
boolean newValue) {
if (oldValue == newValue) {
return;
}
mHandler.obtainMessage(AlarmHandler.CHECK_EXACT_ALARM_PERMISSION_ON_FEATURE_TOGGLE,
newValue).sendToTarget();
}
private void migrateAlarmsToNewStoreLocked() { private void migrateAlarmsToNewStoreLocked() {
final AlarmStore newStore = LAZY_BATCHING ? new LazyAlarmStore() final AlarmStore newStore = LAZY_BATCHING ? new LazyAlarmStore()
: new BatchingAlarmStore(); : new BatchingAlarmStore();
@@ -1122,6 +1157,9 @@ public class AlarmManagerService extends SystemService {
pw.print(KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED, pw.print(KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED,
KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED); KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED);
pw.println(); pw.println();
pw.print(KEY_SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT,
SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT);
pw.println();
pw.print(Settings.Global.ENABLE_TARE, USE_TARE_POLICY); pw.print(Settings.Global.ENABLE_TARE, USE_TARE_POLICY);
pw.println(); pw.println();
@@ -1892,11 +1930,10 @@ public class AlarmManagerService extends SystemService {
if (hasUseExactAlarmInternal(packageName, uid)) { if (hasUseExactAlarmInternal(packageName, uid)) {
return; return;
} }
if (!mExactAlarmCandidates.contains(UserHandle.getAppId(uid))) {
final boolean requested = mExactAlarmCandidates.contains( // Permission not requested, app op doesn't matter.
UserHandle.getAppId(uid)); return;
final boolean denyListed = }
mConstants.EXACT_ALARM_DENY_LIST.contains(packageName);
final int newMode = mAppOps.checkOpNoThrow( final int newMode = mAppOps.checkOpNoThrow(
AppOpsManager.OP_SCHEDULE_EXACT_ALARM, uid, packageName); AppOpsManager.OP_SCHEDULE_EXACT_ALARM, uid, packageName);
@@ -1913,11 +1950,24 @@ public class AlarmManagerService extends SystemService {
mLastOpScheduleExactAlarm.setValueAt(index, newMode); mLastOpScheduleExactAlarm.setValueAt(index, newMode);
} }
} }
if (oldMode == newMode) {
return;
}
final boolean allowedByDefault =
isScheduleExactAlarmAllowedByDefault(packageName, uid);
final boolean hadPermission = getScheduleExactAlarmState(requested, final boolean hadPermission;
denyListed, oldMode); if (oldMode != AppOpsManager.MODE_DEFAULT) {
final boolean hasPermission = getScheduleExactAlarmState(requested, hadPermission = (oldMode == AppOpsManager.MODE_ALLOWED);
denyListed, newMode); } else {
hadPermission = allowedByDefault;
}
final boolean hasPermission;
if (newMode != AppOpsManager.MODE_DEFAULT) {
hasPermission = (newMode == AppOpsManager.MODE_ALLOWED);
} else {
hasPermission = allowedByDefault;
}
if (hadPermission && !hasPermission) { if (hadPermission && !hasPermission) {
mHandler.obtainMessage(AlarmHandler.REMOVE_EXACT_ALARMS, mHandler.obtainMessage(AlarmHandler.REMOVE_EXACT_ALARMS,
@@ -1939,6 +1989,8 @@ public class AlarmManagerService extends SystemService {
LocalServices.getService(AppStandbyInternal.class); LocalServices.getService(AppStandbyInternal.class);
appStandbyInternal.addListener(new AppStandbyTracker()); appStandbyInternal.addListener(new AppStandbyTracker());
mRoleManager = getContext().getSystemService(RoleManager.class);
mMetricsHelper.registerPuller(() -> mAlarmStore); mMetricsHelper.registerPuller(() -> mAlarmStore);
} }
} }
@@ -2525,19 +2577,6 @@ public class AlarmManagerService extends SystemService {
} }
} }
private static boolean getScheduleExactAlarmState(boolean requested, boolean denyListed,
int appOpMode) {
// This does not account for the state of the USE_EXACT_ALARM permission.
// The caller should do that separately.
if (!requested) {
return false;
}
if (appOpMode == AppOpsManager.MODE_DEFAULT) {
return !denyListed;
}
return appOpMode == AppOpsManager.MODE_ALLOWED;
}
boolean hasUseExactAlarmInternal(String packageName, int uid) { boolean hasUseExactAlarmInternal(String packageName, int uid) {
return isUseExactAlarmEnabled(packageName, UserHandle.getUserId(uid)) return isUseExactAlarmEnabled(packageName, UserHandle.getUserId(uid))
&& (PermissionChecker.checkPermissionForPreflight(getContext(), && (PermissionChecker.checkPermissionForPreflight(getContext(),
@@ -2545,6 +2584,32 @@ public class AlarmManagerService extends SystemService {
packageName) == PermissionChecker.PERMISSION_GRANTED); packageName) == PermissionChecker.PERMISSION_GRANTED);
} }
/**
* Returns whether SCHEDULE_EXACT_ALARM is allowed by default.
*/
boolean isScheduleExactAlarmAllowedByDefault(String packageName, int uid) {
if (isScheduleExactAlarmDeniedByDefault(packageName, UserHandle.getUserId(uid))) {
// This is essentially like changing the protection level of the permission to
// (privileged|signature|role|appop), but have to implement this logic to maintain
// compatibility for older apps.
if (mPackageManagerInternal.isPlatformSigned(packageName)
|| mPackageManagerInternal.isUidPrivileged(uid)) {
return true;
}
final long token = Binder.clearCallingIdentity();
try {
final List<String> wellbeingHolders = (mRoleManager != null)
? mRoleManager.getRoleHolders(RoleManager.ROLE_SYSTEM_WELLBEING)
: Collections.emptyList();
return wellbeingHolders.contains(packageName);
} finally {
Binder.restoreCallingIdentity(token);
}
}
return !mConstants.EXACT_ALARM_DENY_LIST.contains(packageName);
}
boolean hasScheduleExactAlarmInternal(String packageName, int uid) { boolean hasScheduleExactAlarmInternal(String packageName, int uid) {
final long start = mStatLogger.getTime(); final long start = mStatLogger.getTime();
@@ -2560,7 +2625,7 @@ public class AlarmManagerService extends SystemService {
final int mode = mAppOps.checkOpNoThrow(AppOpsManager.OP_SCHEDULE_EXACT_ALARM, uid, final int mode = mAppOps.checkOpNoThrow(AppOpsManager.OP_SCHEDULE_EXACT_ALARM, uid,
packageName); packageName);
if (mode == AppOpsManager.MODE_DEFAULT) { if (mode == AppOpsManager.MODE_DEFAULT) {
hasPermission = !mConstants.EXACT_ALARM_DENY_LIST.contains(packageName); hasPermission = isScheduleExactAlarmAllowedByDefault(packageName, uid);
} else { } else {
hasPermission = (mode == AppOpsManager.MODE_ALLOWED); hasPermission = (mode == AppOpsManager.MODE_ALLOWED);
} }
@@ -2860,6 +2925,13 @@ public class AlarmManagerService extends SystemService {
packageName, UserHandle.of(userId)); packageName, UserHandle.of(userId));
} }
private boolean isScheduleExactAlarmDeniedByDefault(String packageName, int userId) {
return mConstants.SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT
&& CompatChanges.isChangeEnabled(
AlarmManager.SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT, packageName,
UserHandle.of(userId));
}
@NeverCompile // Avoid size overhead of debugging code. @NeverCompile // Avoid size overhead of debugging code.
void dumpImpl(IndentingPrintWriter pw) { void dumpImpl(IndentingPrintWriter pw) {
synchronized (mLock) { synchronized (mLock) {
@@ -3769,26 +3841,27 @@ public class AlarmManagerService extends SystemService {
if (!isExactAlarmChangeEnabled(changedPackage, userId)) { if (!isExactAlarmChangeEnabled(changedPackage, userId)) {
continue; continue;
} }
if (isScheduleExactAlarmDeniedByDefault(changedPackage, userId)) {
continue;
}
if (hasUseExactAlarmInternal(changedPackage, uid)) { if (hasUseExactAlarmInternal(changedPackage, uid)) {
continue; continue;
} }
if (!mExactAlarmCandidates.contains(UserHandle.getAppId(uid))) {
// Permission isn't requested, deny list doesn't matter.
continue;
}
final int appOpMode; final int appOpMode;
synchronized (mLock) { synchronized (mLock) {
appOpMode = mLastOpScheduleExactAlarm.get(uid, appOpMode = mLastOpScheduleExactAlarm.get(uid,
AppOpsManager.opToDefaultMode(AppOpsManager.OP_SCHEDULE_EXACT_ALARM)); AppOpsManager.opToDefaultMode(AppOpsManager.OP_SCHEDULE_EXACT_ALARM));
} }
final boolean requested = mExactAlarmCandidates.contains(UserHandle.getAppId(uid)); if (appOpMode != AppOpsManager.MODE_DEFAULT) {
// Deny list doesn't matter.
// added: true => package was added to the deny list
// added: false => package was removed from the deny list
final boolean hadPermission = getScheduleExactAlarmState(requested, !added,
appOpMode);
final boolean hasPermission = getScheduleExactAlarmState(requested, added,
appOpMode);
if (hadPermission == hasPermission) {
continue; continue;
} }
// added: true => package was added to the deny list
// added: false => package was removed from the deny list
if (added) { if (added) {
synchronized (mLock) { synchronized (mLock) {
removeExactAlarmsOnPermissionRevokedLocked(uid, removeExactAlarmsOnPermissionRevokedLocked(uid,
@@ -4634,6 +4707,7 @@ public class AlarmManagerService extends SystemService {
public static final int REFRESH_EXACT_ALARM_CANDIDATES = 11; public static final int REFRESH_EXACT_ALARM_CANDIDATES = 11;
public static final int TARE_AFFORDABILITY_CHANGED = 12; public static final int TARE_AFFORDABILITY_CHANGED = 12;
public static final int CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE = 13; public static final int CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE = 13;
public static final int CHECK_EXACT_ALARM_PERMISSION_ON_FEATURE_TOGGLE = 14;
AlarmHandler() { AlarmHandler() {
super(Looper.myLooper()); super(Looper.myLooper());
@@ -4759,6 +4833,35 @@ public class AlarmManagerService extends SystemService {
} }
} }
break; break;
case CHECK_EXACT_ALARM_PERMISSION_ON_FEATURE_TOGGLE:
final boolean defaultDenied = (Boolean) msg.obj;
final int[] startedUserIds = mActivityManagerInternal.getStartedUserIds();
for (int appId : mExactAlarmCandidates) {
for (int userId : startedUserIds) {
uid = UserHandle.getUid(userId, appId);
final AndroidPackage packageForUid =
mPackageManagerInternal.getPackage(uid);
if (packageForUid == null) {
continue;
}
final String pkg = packageForUid.getPackageName();
if (defaultDenied) {
if (!hasScheduleExactAlarmInternal(pkg, uid)
&& !hasUseExactAlarmInternal(pkg, uid)) {
synchronized (mLock) {
removeExactAlarmsOnPermissionRevokedLocked(uid, pkg,
true);
}
}
} else if (hasScheduleExactAlarmInternal(pkg, uid)) {
sendScheduleExactAlarmPermissionStateChangedBroadcast(pkg,
UserHandle.getUserId(uid));
}
}
}
break;
default: default:
// nope, just ignore it // nope, just ignore it
break; break;

View File

@@ -1207,6 +1207,11 @@ public abstract class PackageManagerInternal {
@Nullable @Nullable
public abstract SharedUserApi getSharedUserApi(int sharedUserAppId); public abstract SharedUserApi getSharedUserApi(int sharedUserAppId);
/**
* Returns if the given uid is privileged or not.
*/
public abstract boolean isUidPrivileged(int uid);
/** /**
* Initiates a package state mutation request, returning the current state as known by * Initiates a package state mutation request, returning the current state as known by
* PackageManager. This allows the later commit request to compare the initial values and * PackageManager. This allows the later commit request to compare the initial values and

View File

@@ -722,6 +722,11 @@ abstract class PackageManagerInternalBase extends PackageManagerInternal {
return snapshot().getSharedUser(sharedUserAppId); return snapshot().getSharedUser(sharedUserAppId);
} }
@Override
public boolean isUidPrivileged(int uid) {
return snapshot().isUidPrivileged(uid);
}
@NonNull @NonNull
@Override @Override
@Deprecated @Deprecated

View File

@@ -27,6 +27,7 @@ import static android.app.AlarmManager.FLAG_STANDALONE;
import static android.app.AlarmManager.FLAG_WAKE_FROM_IDLE; import static android.app.AlarmManager.FLAG_WAKE_FROM_IDLE;
import static android.app.AlarmManager.RTC; import static android.app.AlarmManager.RTC;
import static android.app.AlarmManager.RTC_WAKEUP; import static android.app.AlarmManager.RTC_WAKEUP;
import static android.app.AlarmManager.SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT;
import static android.app.AlarmManager.WINDOW_EXACT; import static android.app.AlarmManager.WINDOW_EXACT;
import static android.app.AlarmManager.WINDOW_HEURISTIC; import static android.app.AlarmManager.WINDOW_HEURISTIC;
import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.MODE_ALLOWED;
@@ -122,6 +123,7 @@ import android.app.IAlarmListener;
import android.app.IAlarmManager; import android.app.IAlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.compat.CompatChanges; import android.app.compat.CompatChanges;
import android.app.role.RoleManager;
import android.app.usage.UsageStatsManagerInternal; import android.app.usage.UsageStatsManagerInternal;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
@@ -184,6 +186,7 @@ import org.mockito.quality.Strictness;
import org.mockito.stubbing.Answer; import org.mockito.stubbing.Answer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@@ -232,6 +235,8 @@ public class AlarmManagerServiceTest {
@Mock @Mock
private PackageManagerInternal mPackageManagerInternal; private PackageManagerInternal mPackageManagerInternal;
@Mock @Mock
private RoleManager mRoleManager;
@Mock
private AppStateTrackerImpl mAppStateTracker; private AppStateTrackerImpl mAppStateTracker;
@Mock @Mock
private AlarmManagerService.ClockReceiver mClockReceiver; private AlarmManagerService.ClockReceiver mClockReceiver;
@@ -457,6 +462,7 @@ public class AlarmManagerServiceTest {
when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager); when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
when(mMockContext.getSystemService(BatteryManager.class)).thenReturn(mBatteryManager); when(mMockContext.getSystemService(BatteryManager.class)).thenReturn(mBatteryManager);
when(mMockContext.getSystemService(RoleManager.class)).thenReturn(mRoleManager);
registerAppIds(new String[]{TEST_CALLING_PACKAGE}, registerAppIds(new String[]{TEST_CALLING_PACKAGE},
new Integer[]{UserHandle.getAppId(TEST_CALLING_UID)}); new Integer[]{UserHandle.getAppId(TEST_CALLING_UID)});
@@ -3190,6 +3196,70 @@ public class AlarmManagerServiceTest {
assertEquals(0, remaining.size()); assertEquals(0, remaining.size());
} }
@Test
public void isScheduleExactAlarmAllowedByDefault() {
final String package1 = "priv";
final String package2 = "signed";
final String package3 = "normal";
final String package4 = "wellbeing";
final int uid1 = 1294;
final int uid2 = 8321;
final int uid3 = 3412;
final int uid4 = 4591;
when(mPackageManagerInternal.isUidPrivileged(uid1)).thenReturn(true);
when(mPackageManagerInternal.isUidPrivileged(uid2)).thenReturn(false);
when(mPackageManagerInternal.isUidPrivileged(uid3)).thenReturn(false);
when(mPackageManagerInternal.isUidPrivileged(uid4)).thenReturn(false);
when(mPackageManagerInternal.isPlatformSigned(package1)).thenReturn(false);
when(mPackageManagerInternal.isPlatformSigned(package2)).thenReturn(true);
when(mPackageManagerInternal.isPlatformSigned(package3)).thenReturn(false);
when(mPackageManagerInternal.isPlatformSigned(package4)).thenReturn(false);
when(mRoleManager.getRoleHolders(RoleManager.ROLE_SYSTEM_WELLBEING)).thenReturn(
Arrays.asList(package4));
mockChangeEnabled(SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT, true);
mService.mConstants.SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT = false;
mService.mConstants.EXACT_ALARM_DENY_LIST = new ArraySet<>(new String[] {
package1,
package3,
});
// Deny listed packages will be false.
assertFalse(mService.isScheduleExactAlarmAllowedByDefault(package1, uid1));
assertTrue(mService.isScheduleExactAlarmAllowedByDefault(package2, uid2));
assertFalse(mService.isScheduleExactAlarmAllowedByDefault(package3, uid3));
assertTrue(mService.isScheduleExactAlarmAllowedByDefault(package4, uid4));
mockChangeEnabled(SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT, false);
mService.mConstants.SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT = true;
mService.mConstants.EXACT_ALARM_DENY_LIST = new ArraySet<>(new String[] {
package1,
package3,
});
// Same as above, deny listed packages will be false.
assertFalse(mService.isScheduleExactAlarmAllowedByDefault(package1, uid1));
assertTrue(mService.isScheduleExactAlarmAllowedByDefault(package2, uid2));
assertFalse(mService.isScheduleExactAlarmAllowedByDefault(package3, uid3));
assertTrue(mService.isScheduleExactAlarmAllowedByDefault(package4, uid4));
mockChangeEnabled(SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT, true);
mService.mConstants.SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT = true;
mService.mConstants.EXACT_ALARM_DENY_LIST = new ArraySet<>(new String[] {
package1,
package3,
});
// Deny list doesn't matter now, only exemptions should be true.
assertTrue(mService.isScheduleExactAlarmAllowedByDefault(package1, uid1));
assertTrue(mService.isScheduleExactAlarmAllowedByDefault(package2, uid2));
assertFalse(mService.isScheduleExactAlarmAllowedByDefault(package3, uid3));
assertTrue(mService.isScheduleExactAlarmAllowedByDefault(package4, uid4));
}
@Test @Test
public void alarmScheduledAtomPushed() { public void alarmScheduledAtomPushed() {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {