Merge "Fixes SelectLongPressTimeoutPreferenceControllerTest summary check." into udc-dev
diff --git a/src/com/android/settings/applications/AppStateAlarmsAndRemindersBridge.java b/src/com/android/settings/applications/AppStateAlarmsAndRemindersBridge.java
index ffe8767..c96e8fb 100644
--- a/src/com/android/settings/applications/AppStateAlarmsAndRemindersBridge.java
+++ b/src/com/android/settings/applications/AppStateAlarmsAndRemindersBridge.java
@@ -18,11 +18,11 @@
import android.Manifest;
import android.app.AlarmManager;
-import android.app.AppGlobals;
import android.app.compat.CompatChanges;
import android.content.Context;
-import android.content.pm.IPackageManager;
-import android.os.RemoteException;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.PowerExemptionManager;
import android.os.UserHandle;
import android.util.Log;
@@ -32,8 +32,6 @@
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.AppFilter;
-import libcore.util.EmptyArray;
-
import java.util.List;
/**
@@ -42,26 +40,24 @@
* Also provides app filters that can use the info.
*/
public class AppStateAlarmsAndRemindersBridge extends AppStateBaseBridge {
- private static final String PERMISSION = Manifest.permission.SCHEDULE_EXACT_ALARM;
+ private static final String SEA_PERMISSION = Manifest.permission.SCHEDULE_EXACT_ALARM;
+ private static final String UEA_PERMISSION = Manifest.permission.USE_EXACT_ALARM;
private static final String TAG = "AlarmsAndRemindersBridge";
@VisibleForTesting
AlarmManager mAlarmManager;
@VisibleForTesting
- String[] mRequesterPackages;
+ PowerExemptionManager mPowerExemptionManager;
+ @VisibleForTesting
+ PackageManager mPackageManager;
public AppStateAlarmsAndRemindersBridge(Context context, ApplicationsState appState,
Callback callback) {
super(appState, callback);
+ mPowerExemptionManager = context.getSystemService(PowerExemptionManager.class);
mAlarmManager = context.getSystemService(AlarmManager.class);
- final IPackageManager iPm = AppGlobals.getPackageManager();
- try {
- mRequesterPackages = iPm.getAppOpPermissionPackages(PERMISSION, context.getUserId());
- } catch (RemoteException re) {
- Log.e(TAG, "Cannot reach package manager", re);
- mRequesterPackages = EmptyArray.STRING;
- }
+ mPackageManager = context.getPackageManager();
}
private boolean isChangeEnabled(String packageName, int userId) {
@@ -69,6 +65,22 @@
packageName, UserHandle.of(userId));
}
+ private boolean isUeaChangeEnabled(String packageName, int userId) {
+ return CompatChanges.isChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, packageName,
+ UserHandle.of(userId));
+ }
+
+ private String[] getRequestedPermissions(String packageName, int userId) {
+ try {
+ final PackageInfo info = mPackageManager.getPackageInfoAsUser(packageName,
+ PackageManager.GET_PERMISSIONS, userId);
+ return info.requestedPermissions;
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Could not find package " + packageName, e);
+ }
+ return null;
+ }
+
/**
* Returns information regarding {@link Manifest.permission#SCHEDULE_EXACT_ALARM} for the given
* package and uid.
@@ -76,10 +88,17 @@
public AlarmsAndRemindersState createPermissionState(String packageName, int uid) {
final int userId = UserHandle.getUserId(uid);
- final boolean permissionRequested = ArrayUtils.contains(mRequesterPackages, packageName)
+ final String[] requestedPermissions = getRequestedPermissions(packageName, userId);
+
+ final boolean seaRequested = ArrayUtils.contains(requestedPermissions, SEA_PERMISSION)
&& isChangeEnabled(packageName, userId);
- final boolean permissionGranted = mAlarmManager.hasScheduleExactAlarm(packageName, userId);
- return new AlarmsAndRemindersState(permissionRequested, permissionGranted);
+ final boolean ueaRequested = ArrayUtils.contains(requestedPermissions, UEA_PERMISSION)
+ && isUeaChangeEnabled(packageName, userId);
+
+ final boolean seaGranted = mAlarmManager.hasScheduleExactAlarm(packageName, userId);
+ final boolean allowListed = mPowerExemptionManager.isAllowListed(packageName, true);
+
+ return new AlarmsAndRemindersState(seaRequested, ueaRequested, seaGranted, allowListed);
}
@Override
@@ -113,26 +132,32 @@
};
/**
- * Class to denote the state of an app regarding
- * {@link Manifest.permission#SCHEDULE_EXACT_ALARM}.
+ * Class to denote the state of an app regarding "Alarms and Reminders" permission.
+ * This permission state is a combination of {@link Manifest.permission#SCHEDULE_EXACT_ALARM},
+ * {@link Manifest.permission#USE_EXACT_ALARM} and the power allowlist state.
*/
public static class AlarmsAndRemindersState {
- private boolean mPermissionRequested;
- private boolean mPermissionGranted;
+ private boolean mSeaPermissionRequested;
+ private boolean mUeaPermissionRequested;
+ private boolean mSeaPermissionGranted;
+ private boolean mAllowListed;
- AlarmsAndRemindersState(boolean permissionRequested, boolean permissionGranted) {
- mPermissionRequested = permissionRequested;
- mPermissionGranted = permissionGranted;
+ AlarmsAndRemindersState(boolean seaPermissionRequested, boolean ueaPermissionRequested,
+ boolean seaPermissionGranted, boolean allowListed) {
+ mSeaPermissionRequested = seaPermissionRequested;
+ mUeaPermissionRequested = ueaPermissionRequested;
+ mSeaPermissionGranted = seaPermissionGranted;
+ mAllowListed = allowListed;
}
/** Should the app associated with this state appear on the Settings screen */
public boolean shouldBeVisible() {
- return mPermissionRequested;
+ return mSeaPermissionRequested && !mUeaPermissionRequested && !mAllowListed;
}
/** Is the permission granted to the app associated with this state */
public boolean isAllowed() {
- return mPermissionGranted;
+ return mSeaPermissionGranted || mUeaPermissionRequested || mAllowListed;
}
}
}
diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java
index 3186a56..398e4b0 100644
--- a/src/com/android/settings/password/ChooseLockGeneric.java
+++ b/src/com/android/settings/password/ChooseLockGeneric.java
@@ -816,6 +816,14 @@
}
@Override
+ public void onStop() {
+ super.onStop();
+ if (!getActivity().isChangingConfigurations() && !mWaitingForConfirmation) {
+ getActivity().finish();
+ }
+ }
+
+ @Override
public void onDestroy() {
super.onDestroy();
if (mUserPassword != null) {
diff --git a/tests/unit/src/com/android/settings/applications/AppStateAlarmsAndRemindersBridgeTest.java b/tests/unit/src/com/android/settings/applications/AppStateAlarmsAndRemindersBridgeTest.java
index f56da05..cd38767 100644
--- a/tests/unit/src/com/android/settings/applications/AppStateAlarmsAndRemindersBridgeTest.java
+++ b/tests/unit/src/com/android/settings/applications/AppStateAlarmsAndRemindersBridgeTest.java
@@ -16,15 +16,24 @@
package com.android.settings.applications;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
+import android.Manifest;
import android.app.AlarmManager;
import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.PowerExemptionManager;
import android.os.UserHandle;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import libcore.util.EmptyArray;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -34,13 +43,15 @@
@RunWith(AndroidJUnit4.class)
public class AppStateAlarmsAndRemindersBridgeTest {
- private static final String TEST_PACKAGE_1 = "com.example.test.1";
- private static final String TEST_PACKAGE_2 = "com.example.test.2";
- private static final int UID_1 = 12345;
- private static final int UID_2 = 7654321;
+ private static final String TEST_PACKAGE = "com.example.test.1";
+ private static final int TEST_UID = 12345;
@Mock
private AlarmManager mAlarmManager;
+ @Mock
+ private PowerExemptionManager mPowerExemptionManager;
+ @Mock
+ private PackageManager mPackageManager;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@@ -50,65 +61,168 @@
}
@Test
- public void shouldBeVisible_permissionRequestedIsTrue_isTrue() {
- assertThat(new AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState(
- true /* permissionRequested */,
- true /* permissionGranted */)
- .shouldBeVisible()).isTrue();
- assertThat(new AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState(
- true /* permissionRequested */,
- false /* permissionGranted */)
- .shouldBeVisible()).isTrue();
- assertThat(new AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState(
- false /* permissionRequested */,
- true /* permissionGranted */)
- .shouldBeVisible()).isFalse();
- assertThat(new AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState(
- false /* permissionRequested */,
- false /* permissionGranted */)
- .shouldBeVisible()).isFalse();
+ public void alarmsAndRemindersState_shouldBeVisible() {
+ boolean seaPermissionRequested;
+ boolean ueaPermissionRequested;
+ boolean seaPermissionGranted;
+ boolean allowListed;
+
+ for (int i = 0; i < (1 << 4); i++) {
+ seaPermissionRequested = (i & 1) != 0;
+ ueaPermissionRequested = (i & (1 << 1)) != 0;
+ seaPermissionGranted = (i & (1 << 2)) != 0;
+ allowListed = (i & (1 << 3)) != 0;
+
+ final boolean visible = new AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState(
+ seaPermissionRequested,
+ ueaPermissionRequested,
+ seaPermissionGranted,
+ allowListed).shouldBeVisible();
+
+ assertWithMessage("Wrong return value " + visible
+ + " for {seaPermissionRequested = " + seaPermissionRequested
+ + ", ueaPermissionRequested = " + ueaPermissionRequested
+ + ", seaPermissionGranted = " + seaPermissionGranted
+ + ", allowListed = " + allowListed + "}")
+ .that(visible)
+ .isEqualTo(seaPermissionRequested && !ueaPermissionRequested && !allowListed);
+ }
}
@Test
- public void isAllowed_permissionGrantedIsTrue_isTrue() {
- assertThat(new AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState(
- true /* permissionRequested */,
- true /* permissionGranted */)
- .isAllowed()).isTrue();
- assertThat(new AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState(
- true /* permissionRequested */,
- false /* permissionGranted */)
- .isAllowed()).isFalse();
- assertThat(new AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState(
- false /* permissionRequested */,
- true /* permissionGranted */)
- .isAllowed()).isTrue();
- assertThat(new AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState(
- false /* permissionRequested */,
- false /* permissionGranted */)
- .isAllowed()).isFalse();
+ public void alarmsAndRemindersState_isAllowed() {
+ boolean seaPermissionRequested;
+ boolean ueaPermissionRequested;
+ boolean seaPermissionGranted;
+ boolean allowListed;
+
+ for (int i = 0; i < (1 << 4); i++) {
+ seaPermissionRequested = (i & 1) != 0;
+ ueaPermissionRequested = (i & (1 << 1)) != 0;
+ seaPermissionGranted = (i & (1 << 2)) != 0;
+ allowListed = (i & (1 << 3)) != 0;
+
+ final boolean allowed = new AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState(
+ seaPermissionRequested,
+ ueaPermissionRequested,
+ seaPermissionGranted,
+ allowListed).isAllowed();
+
+ assertWithMessage("Wrong return value " + allowed
+ + " for {seaPermissionRequested = " + seaPermissionRequested
+ + ", ueaPermissionRequested = " + ueaPermissionRequested
+ + ", seaPermissionGranted = " + seaPermissionGranted
+ + ", allowListed = " + allowListed + "}")
+ .that(allowed)
+ .isEqualTo(seaPermissionGranted || ueaPermissionRequested || allowListed);
+ }
+ }
+
+ private PackageInfo createPackageInfoWithPermissions(String... requestedPermissions) {
+ final PackageInfo info = new PackageInfo();
+ info.requestedPermissions = requestedPermissions;
+ return info;
}
@Test
- public void createPermissionState() {
+ public void createPermissionState_SeaGrantedNoUeaNoAllowlist() throws Exception {
AppStateAlarmsAndRemindersBridge bridge = new AppStateAlarmsAndRemindersBridge(mContext,
null, null);
bridge.mAlarmManager = mAlarmManager;
- bridge.mRequesterPackages = new String[]{TEST_PACKAGE_1, "some.other.package"};
+ bridge.mPackageManager = mPackageManager;
+ bridge.mPowerExemptionManager = mPowerExemptionManager;
- doReturn(false).when(mAlarmManager).hasScheduleExactAlarm(TEST_PACKAGE_1,
- UserHandle.getUserId(UID_1));
- doReturn(true).when(mAlarmManager).hasScheduleExactAlarm(TEST_PACKAGE_2,
- UserHandle.getUserId(UID_2));
+ doReturn(true).when(mAlarmManager).hasScheduleExactAlarm(TEST_PACKAGE,
+ UserHandle.getUserId(TEST_UID));
+ doReturn(createPackageInfoWithPermissions(Manifest.permission.SCHEDULE_EXACT_ALARM))
+ .when(mPackageManager).getPackageInfoAsUser(eq(TEST_PACKAGE), anyInt(), anyInt());
+ doReturn(false).when(mPowerExemptionManager).isAllowListed(TEST_PACKAGE, true);
- AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState state1 =
- bridge.createPermissionState(TEST_PACKAGE_1, UID_1);
- assertThat(state1.shouldBeVisible()).isTrue();
- assertThat(state1.isAllowed()).isFalse();
+ AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState state =
+ bridge.createPermissionState(TEST_PACKAGE, TEST_UID);
+ assertThat(state.shouldBeVisible()).isTrue();
+ assertThat(state.isAllowed()).isTrue();
+ }
- AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState state2 =
- bridge.createPermissionState(TEST_PACKAGE_2, UID_2);
- assertThat(state2.shouldBeVisible()).isFalse();
- assertThat(state2.isAllowed()).isTrue();
+ @Test
+ public void createPermissionState_requestsBothSeaDeniedNoAllowlist() throws Exception {
+ AppStateAlarmsAndRemindersBridge bridge = new AppStateAlarmsAndRemindersBridge(mContext,
+ null, null);
+ bridge.mAlarmManager = mAlarmManager;
+ bridge.mPackageManager = mPackageManager;
+ bridge.mPowerExemptionManager = mPowerExemptionManager;
+
+ doReturn(false).when(mAlarmManager).hasScheduleExactAlarm(TEST_PACKAGE,
+ UserHandle.getUserId(TEST_UID));
+ doReturn(createPackageInfoWithPermissions(
+ Manifest.permission.SCHEDULE_EXACT_ALARM,
+ Manifest.permission.USE_EXACT_ALARM))
+ .when(mPackageManager).getPackageInfoAsUser(eq(TEST_PACKAGE), anyInt(), anyInt());
+ doReturn(false).when(mPowerExemptionManager).isAllowListed(TEST_PACKAGE, true);
+
+ AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState state =
+ bridge.createPermissionState(TEST_PACKAGE, TEST_UID);
+ assertThat(state.shouldBeVisible()).isFalse();
+ assertThat(state.isAllowed()).isTrue();
+ }
+
+ @Test
+ public void createPermissionState_requestsNoneNoAllowlist() throws Exception {
+ AppStateAlarmsAndRemindersBridge bridge = new AppStateAlarmsAndRemindersBridge(mContext,
+ null, null);
+ bridge.mAlarmManager = mAlarmManager;
+ bridge.mPackageManager = mPackageManager;
+ bridge.mPowerExemptionManager = mPowerExemptionManager;
+
+ doReturn(false).when(mAlarmManager).hasScheduleExactAlarm(TEST_PACKAGE,
+ UserHandle.getUserId(TEST_UID));
+ doReturn(createPackageInfoWithPermissions(EmptyArray.STRING))
+ .when(mPackageManager).getPackageInfoAsUser(eq(TEST_PACKAGE), anyInt(), anyInt());
+ doReturn(false).when(mPowerExemptionManager).isAllowListed(TEST_PACKAGE, true);
+
+ AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState state =
+ bridge.createPermissionState(TEST_PACKAGE, TEST_UID);
+ assertThat(state.shouldBeVisible()).isFalse();
+ assertThat(state.isAllowed()).isFalse();
+ }
+
+ @Test
+ public void createPermissionState_requestsOnlyUeaNoAllowlist() throws Exception {
+ AppStateAlarmsAndRemindersBridge bridge = new AppStateAlarmsAndRemindersBridge(mContext,
+ null, null);
+ bridge.mAlarmManager = mAlarmManager;
+ bridge.mPackageManager = mPackageManager;
+ bridge.mPowerExemptionManager = mPowerExemptionManager;
+
+ doReturn(false).when(mAlarmManager).hasScheduleExactAlarm(TEST_PACKAGE,
+ UserHandle.getUserId(TEST_UID));
+ doReturn(createPackageInfoWithPermissions(Manifest.permission.USE_EXACT_ALARM))
+ .when(mPackageManager).getPackageInfoAsUser(eq(TEST_PACKAGE), anyInt(), anyInt());
+ doReturn(false).when(mPowerExemptionManager).isAllowListed(TEST_PACKAGE, true);
+
+ AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState state =
+ bridge.createPermissionState(TEST_PACKAGE, TEST_UID);
+ assertThat(state.shouldBeVisible()).isFalse();
+ assertThat(state.isAllowed()).isTrue();
+ }
+
+ @Test
+ public void createPermissionState_requestsNoneButAllowlisted() throws Exception {
+ AppStateAlarmsAndRemindersBridge bridge = new AppStateAlarmsAndRemindersBridge(mContext,
+ null, null);
+ bridge.mAlarmManager = mAlarmManager;
+ bridge.mPackageManager = mPackageManager;
+ bridge.mPowerExemptionManager = mPowerExemptionManager;
+
+ doReturn(false).when(mAlarmManager).hasScheduleExactAlarm(TEST_PACKAGE,
+ UserHandle.getUserId(TEST_UID));
+ doReturn(createPackageInfoWithPermissions(EmptyArray.STRING))
+ .when(mPackageManager).getPackageInfoAsUser(eq(TEST_PACKAGE), anyInt(), anyInt());
+ doReturn(true).when(mPowerExemptionManager).isAllowListed(TEST_PACKAGE, true);
+
+ AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState state =
+ bridge.createPermissionState(TEST_PACKAGE, TEST_UID);
+ assertThat(state.shouldBeVisible()).isFalse();
+ assertThat(state.isAllowed()).isTrue();
}
}