1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.settings.applications; 17 18 import static com.google.common.truth.Truth.assertThat; 19 import static com.google.common.truth.Truth.assertWithMessage; 20 21 import static org.mockito.ArgumentMatchers.anyInt; 22 import static org.mockito.ArgumentMatchers.eq; 23 import static org.mockito.Mockito.doReturn; 24 25 import android.Manifest; 26 import android.app.AlarmManager; 27 import android.content.Context; 28 import android.content.pm.PackageInfo; 29 import android.content.pm.PackageManager; 30 import android.os.PowerExemptionManager; 31 import android.os.UserHandle; 32 33 import androidx.test.ext.junit.runners.AndroidJUnit4; 34 35 import libcore.util.EmptyArray; 36 37 import org.junit.Before; 38 import org.junit.Test; 39 import org.junit.runner.RunWith; 40 import org.mockito.Answers; 41 import org.mockito.Mock; 42 import org.mockito.MockitoAnnotations; 43 44 @RunWith(AndroidJUnit4.class) 45 public class AppStateAlarmsAndRemindersBridgeTest { 46 private static final String TEST_PACKAGE = "com.example.test.1"; 47 private static final int TEST_UID = 12345; 48 49 @Mock 50 private AlarmManager mAlarmManager; 51 @Mock 52 private PowerExemptionManager mPowerExemptionManager; 53 @Mock 54 private PackageManager mPackageManager; 55 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 56 private Context mContext; 57 58 @Before initMocks()59 public void initMocks() { 60 MockitoAnnotations.initMocks(this); 61 } 62 63 @Test alarmsAndRemindersState_shouldBeVisible()64 public void alarmsAndRemindersState_shouldBeVisible() { 65 boolean seaPermissionRequested; 66 boolean ueaPermissionRequested; 67 boolean seaPermissionGranted; 68 boolean allowListed; 69 70 for (int i = 0; i < (1 << 4); i++) { 71 seaPermissionRequested = (i & 1) != 0; 72 ueaPermissionRequested = (i & (1 << 1)) != 0; 73 seaPermissionGranted = (i & (1 << 2)) != 0; 74 allowListed = (i & (1 << 3)) != 0; 75 76 final boolean visible = new AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState( 77 seaPermissionRequested, 78 ueaPermissionRequested, 79 seaPermissionGranted, 80 allowListed).shouldBeVisible(); 81 82 assertWithMessage("Wrong return value " + visible 83 + " for {seaPermissionRequested = " + seaPermissionRequested 84 + ", ueaPermissionRequested = " + ueaPermissionRequested 85 + ", seaPermissionGranted = " + seaPermissionGranted 86 + ", allowListed = " + allowListed + "}") 87 .that(visible) 88 .isEqualTo(seaPermissionRequested && !ueaPermissionRequested && !allowListed); 89 } 90 } 91 92 @Test alarmsAndRemindersState_isAllowed()93 public void alarmsAndRemindersState_isAllowed() { 94 boolean seaPermissionRequested; 95 boolean ueaPermissionRequested; 96 boolean seaPermissionGranted; 97 boolean allowListed; 98 99 for (int i = 0; i < (1 << 4); i++) { 100 seaPermissionRequested = (i & 1) != 0; 101 ueaPermissionRequested = (i & (1 << 1)) != 0; 102 seaPermissionGranted = (i & (1 << 2)) != 0; 103 allowListed = (i & (1 << 3)) != 0; 104 105 final boolean allowed = new AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState( 106 seaPermissionRequested, 107 ueaPermissionRequested, 108 seaPermissionGranted, 109 allowListed).isAllowed(); 110 111 assertWithMessage("Wrong return value " + allowed 112 + " for {seaPermissionRequested = " + seaPermissionRequested 113 + ", ueaPermissionRequested = " + ueaPermissionRequested 114 + ", seaPermissionGranted = " + seaPermissionGranted 115 + ", allowListed = " + allowListed + "}") 116 .that(allowed) 117 .isEqualTo(seaPermissionGranted || ueaPermissionRequested || allowListed); 118 } 119 } 120 createPackageInfoWithPermissions(String... requestedPermissions)121 private PackageInfo createPackageInfoWithPermissions(String... requestedPermissions) { 122 final PackageInfo info = new PackageInfo(); 123 info.requestedPermissions = requestedPermissions; 124 return info; 125 } 126 127 @Test createPermissionState_SeaGrantedNoUeaNoAllowlist()128 public void createPermissionState_SeaGrantedNoUeaNoAllowlist() throws Exception { 129 AppStateAlarmsAndRemindersBridge bridge = new AppStateAlarmsAndRemindersBridge(mContext, 130 null, null); 131 bridge.mAlarmManager = mAlarmManager; 132 bridge.mPackageManager = mPackageManager; 133 bridge.mPowerExemptionManager = mPowerExemptionManager; 134 135 doReturn(true).when(mAlarmManager).hasScheduleExactAlarm(TEST_PACKAGE, 136 UserHandle.getUserId(TEST_UID)); 137 doReturn(createPackageInfoWithPermissions(Manifest.permission.SCHEDULE_EXACT_ALARM)) 138 .when(mPackageManager).getPackageInfoAsUser(eq(TEST_PACKAGE), anyInt(), anyInt()); 139 doReturn(false).when(mPowerExemptionManager).isAllowListed(TEST_PACKAGE, true); 140 141 AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState state = 142 bridge.createPermissionState(TEST_PACKAGE, TEST_UID); 143 assertThat(state.shouldBeVisible()).isTrue(); 144 assertThat(state.isAllowed()).isTrue(); 145 } 146 147 @Test createPermissionState_requestsBothSeaDeniedNoAllowlist()148 public void createPermissionState_requestsBothSeaDeniedNoAllowlist() throws Exception { 149 AppStateAlarmsAndRemindersBridge bridge = new AppStateAlarmsAndRemindersBridge(mContext, 150 null, null); 151 bridge.mAlarmManager = mAlarmManager; 152 bridge.mPackageManager = mPackageManager; 153 bridge.mPowerExemptionManager = mPowerExemptionManager; 154 155 doReturn(false).when(mAlarmManager).hasScheduleExactAlarm(TEST_PACKAGE, 156 UserHandle.getUserId(TEST_UID)); 157 doReturn(createPackageInfoWithPermissions( 158 Manifest.permission.SCHEDULE_EXACT_ALARM, 159 Manifest.permission.USE_EXACT_ALARM)) 160 .when(mPackageManager).getPackageInfoAsUser(eq(TEST_PACKAGE), anyInt(), anyInt()); 161 doReturn(false).when(mPowerExemptionManager).isAllowListed(TEST_PACKAGE, true); 162 163 AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState state = 164 bridge.createPermissionState(TEST_PACKAGE, TEST_UID); 165 assertThat(state.shouldBeVisible()).isFalse(); 166 assertThat(state.isAllowed()).isTrue(); 167 } 168 169 @Test createPermissionState_requestsNoneNoAllowlist()170 public void createPermissionState_requestsNoneNoAllowlist() throws Exception { 171 AppStateAlarmsAndRemindersBridge bridge = new AppStateAlarmsAndRemindersBridge(mContext, 172 null, null); 173 bridge.mAlarmManager = mAlarmManager; 174 bridge.mPackageManager = mPackageManager; 175 bridge.mPowerExemptionManager = mPowerExemptionManager; 176 177 doReturn(false).when(mAlarmManager).hasScheduleExactAlarm(TEST_PACKAGE, 178 UserHandle.getUserId(TEST_UID)); 179 doReturn(createPackageInfoWithPermissions(EmptyArray.STRING)) 180 .when(mPackageManager).getPackageInfoAsUser(eq(TEST_PACKAGE), anyInt(), anyInt()); 181 doReturn(false).when(mPowerExemptionManager).isAllowListed(TEST_PACKAGE, true); 182 183 AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState state = 184 bridge.createPermissionState(TEST_PACKAGE, TEST_UID); 185 assertThat(state.shouldBeVisible()).isFalse(); 186 assertThat(state.isAllowed()).isFalse(); 187 } 188 189 @Test createPermissionState_requestsOnlyUeaNoAllowlist()190 public void createPermissionState_requestsOnlyUeaNoAllowlist() throws Exception { 191 AppStateAlarmsAndRemindersBridge bridge = new AppStateAlarmsAndRemindersBridge(mContext, 192 null, null); 193 bridge.mAlarmManager = mAlarmManager; 194 bridge.mPackageManager = mPackageManager; 195 bridge.mPowerExemptionManager = mPowerExemptionManager; 196 197 doReturn(false).when(mAlarmManager).hasScheduleExactAlarm(TEST_PACKAGE, 198 UserHandle.getUserId(TEST_UID)); 199 doReturn(createPackageInfoWithPermissions(Manifest.permission.USE_EXACT_ALARM)) 200 .when(mPackageManager).getPackageInfoAsUser(eq(TEST_PACKAGE), anyInt(), anyInt()); 201 doReturn(false).when(mPowerExemptionManager).isAllowListed(TEST_PACKAGE, true); 202 203 AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState state = 204 bridge.createPermissionState(TEST_PACKAGE, TEST_UID); 205 assertThat(state.shouldBeVisible()).isFalse(); 206 assertThat(state.isAllowed()).isTrue(); 207 } 208 209 @Test createPermissionState_requestsNoneButAllowlisted()210 public void createPermissionState_requestsNoneButAllowlisted() throws Exception { 211 AppStateAlarmsAndRemindersBridge bridge = new AppStateAlarmsAndRemindersBridge(mContext, 212 null, null); 213 bridge.mAlarmManager = mAlarmManager; 214 bridge.mPackageManager = mPackageManager; 215 bridge.mPowerExemptionManager = mPowerExemptionManager; 216 217 doReturn(false).when(mAlarmManager).hasScheduleExactAlarm(TEST_PACKAGE, 218 UserHandle.getUserId(TEST_UID)); 219 doReturn(createPackageInfoWithPermissions(EmptyArray.STRING)) 220 .when(mPackageManager).getPackageInfoAsUser(eq(TEST_PACKAGE), anyInt(), anyInt()); 221 doReturn(true).when(mPowerExemptionManager).isAllowListed(TEST_PACKAGE, true); 222 223 AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState state = 224 bridge.createPermissionState(TEST_PACKAGE, TEST_UID); 225 assertThat(state.shouldBeVisible()).isFalse(); 226 assertThat(state.isAllowed()).isTrue(); 227 } 228 } 229