1 /*
2  * Copyright (C) 2020 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 
17 package com.android.server.alarm;
18 
19 import static android.app.AlarmManager.ELAPSED_REALTIME;
20 import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE;
21 import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_COMPAT;
22 import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
23 import static android.app.AlarmManager.FLAG_STANDALONE;
24 import static android.app.AlarmManager.FLAG_WAKE_FROM_IDLE;
25 import static android.app.AlarmManager.RTC_WAKEUP;
26 
27 import static com.android.server.alarm.Alarm.APP_STANDBY_POLICY_INDEX;
28 import static com.android.server.alarm.Alarm.NUM_POLICIES;
29 import static com.android.server.alarm.Alarm.REQUESTER_POLICY_INDEX;
30 import static com.android.server.alarm.AlarmManagerService.isExemptFromAppStandby;
31 import static com.android.server.alarm.AlarmManagerService.isExemptFromTare;
32 import static com.android.server.alarm.Constants.TEST_CALLING_PACKAGE;
33 import static com.android.server.alarm.Constants.TEST_CALLING_UID;
34 
35 import static org.junit.Assert.assertEquals;
36 import static org.junit.Assert.assertFalse;
37 import static org.junit.Assert.assertTrue;
38 import static org.mockito.Mockito.mock;
39 import static org.mockito.Mockito.when;
40 
41 import android.app.AlarmManager;
42 import android.app.PendingIntent;
43 import android.platform.test.annotations.Presubmit;
44 
45 import androidx.test.runner.AndroidJUnit4;
46 
47 import org.junit.Test;
48 import org.junit.runner.RunWith;
49 
50 import java.util.Random;
51 
52 @Presubmit
53 @RunWith(AndroidJUnit4.class)
54 public class AlarmTest {
55 
createDefaultAlarm(long requestedElapsed, long windowLength, int flags)56     private Alarm createDefaultAlarm(long requestedElapsed, long windowLength, int flags) {
57         return new Alarm(ELAPSED_REALTIME, 0, requestedElapsed, windowLength, 0,
58                 createAlarmSender(), null, null, null, flags, null, TEST_CALLING_UID,
59                 TEST_CALLING_PACKAGE, null, 0);
60     }
61 
createAlarmClock(long requestedRtc)62     private Alarm createAlarmClock(long requestedRtc) {
63         final AlarmManager.AlarmClockInfo info = mock(AlarmManager.AlarmClockInfo.class);
64         return new Alarm(RTC_WAKEUP, requestedRtc, requestedRtc, 0, 0, createAlarmSender(),
65                 null, null, null, FLAG_WAKE_FROM_IDLE | FLAG_STANDALONE, info, TEST_CALLING_UID,
66                 TEST_CALLING_PACKAGE, null, 0);
67     }
68 
createAlarmSender()69     private PendingIntent createAlarmSender() {
70         final PendingIntent alarmPi = mock(PendingIntent.class);
71         when(alarmPi.getCreatorPackage()).thenReturn(TEST_CALLING_PACKAGE);
72         when(alarmPi.getCreatorUid()).thenReturn(TEST_CALLING_UID);
73         return alarmPi;
74     }
75 
76     @Test
initSetsOnlyRequesterPolicy()77     public void initSetsOnlyRequesterPolicy() {
78         final Alarm a = createDefaultAlarm(4567, 2, 0);
79 
80         for (int i = 0; i < NUM_POLICIES; i++) {
81             if (i == REQUESTER_POLICY_INDEX) {
82                 assertEquals(4567, a.getPolicyElapsed(i));
83             } else {
84                 assertEquals(0, a.getPolicyElapsed(i));
85             }
86         }
87     }
88 
89     /**
90      * Generates a long matrix {@code A} of size {@code NxN}, with the property that the {@code i}th
91      * row will have the {@code i}th element largest in that row.
92      *
93      * In other words, {@code A[i][i]} will be the maximum of {@code A[i][j]} over all {@code j},
94      * {@code 0<=j<N}.
95      */
generatePolicyTestMatrix(int n)96     private static long[][] generatePolicyTestMatrix(int n) {
97         final long[][] data = new long[n][n];
98         final Random random = new Random(971);
99         for (int i = 0; i < n; i++) {
100             data[i][i] = 1;
101             for (int j = 0; j < n; j++) {
102                 if (i != j) {
103                     data[i][j] = random.nextInt(1 << 20);
104                     data[i][i] += data[i][j];
105                 }
106             }
107         }
108         return data;
109     }
110 
111     @Test
whenElapsed()112     public void whenElapsed() {
113         final Alarm a = createDefaultAlarm(0, 0, 0);
114 
115         final long[][] uniqueData = generatePolicyTestMatrix(NUM_POLICIES);
116         for (int i = 0; i < NUM_POLICIES; i++) {
117             for (int j = 0; j < NUM_POLICIES; j++) {
118                 a.setPolicyElapsed(j, uniqueData[i][j]);
119             }
120             assertEquals(uniqueData[i][i], a.getWhenElapsed());
121         }
122 
123         for (int i = 0; i < NUM_POLICIES; i++) {
124             a.setPolicyElapsed(i, 3);
125         }
126         assertEquals(3, a.getWhenElapsed());
127     }
128 
129     @Test
maxWhenElapsed()130     public void maxWhenElapsed() {
131         final Alarm a = createDefaultAlarm(10, 12, 0);
132         assertEquals(22, a.getMaxWhenElapsed());
133 
134         a.setPolicyElapsed(REQUESTER_POLICY_INDEX, 15);
135         assertEquals(27, a.getMaxWhenElapsed());
136 
137         a.setPolicyElapsed(REQUESTER_POLICY_INDEX, 2);
138         assertEquals(14, a.getMaxWhenElapsed());
139 
140         for (int i = 0; i < NUM_POLICIES; i++) {
141             if (i == REQUESTER_POLICY_INDEX) {
142                 continue;
143             }
144             a.setPolicyElapsed(i, 17);
145             // getWhenElapsed is 17, so getMaxWhenElapsed will return 17 too.
146             assertEquals(17, a.getMaxWhenElapsed());
147 
148             a.setPolicyElapsed(i, 5);
149             assertEquals(14, a.getMaxWhenElapsed());
150         }
151     }
152 
153     @Test
setPolicyElapsedExact()154     public void setPolicyElapsedExact() {
155         final Alarm exactAlarm = createDefaultAlarm(10, 0, 0);
156 
157         assertTrue(exactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 4));
158         assertTrue(exactAlarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 10));
159 
160         assertFalse(exactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 8));
161         assertFalse(exactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 10));
162         assertFalse(exactAlarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 8));
163 
164         assertTrue(exactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 7));
165 
166     }
167 
168     @Test
setPolicyElapsedInexact()169     public void setPolicyElapsedInexact() {
170         final Alarm inexactAlarm = createDefaultAlarm(10, 5, 0);
171 
172         assertTrue(inexactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 4));
173         assertTrue(inexactAlarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 10));
174 
175         // whenElapsed won't change, but maxWhenElapsed will.
176         assertTrue(inexactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 8));
177         assertTrue(inexactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 10));
178 
179         assertFalse(inexactAlarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 8));
180     }
181 
182     @Test
isExemptFromStandby()183     public void isExemptFromStandby() {
184         final long anything = 35412;    // Arbitrary number, doesn't matter for this test.
185 
186         assertFalse("Basic alarm exempt", isExemptFromAppStandby(
187                 createDefaultAlarm(anything, anything, 0)));
188         assertFalse("FLAG_ALLOW_WHILE_IDLE_COMPAT exempt", isExemptFromAppStandby(
189                 createDefaultAlarm(anything, anything, FLAG_ALLOW_WHILE_IDLE_COMPAT)));
190 
191         assertTrue("ALLOW_WHILE_IDLE not exempt", isExemptFromAppStandby(
192                 createDefaultAlarm(anything, anything, FLAG_ALLOW_WHILE_IDLE)));
193         assertTrue("ALLOW_WHILE_IDLE_UNRESTRICTED not exempt", isExemptFromAppStandby(
194                 createDefaultAlarm(anything, anything, FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED)));
195         assertTrue("Alarm clock not exempt", isExemptFromAppStandby(createAlarmClock(anything)));
196     }
197 
198     @Test
testIsExemptFromTare()199     public void testIsExemptFromTare() {
200         final long anything = 54321;    // Arbitrary number, doesn't matter for this test.
201 
202         assertFalse("Basic alarm exempt", isExemptFromTare(
203                 createDefaultAlarm(anything, anything, 0)));
204         assertFalse("FLAG_ALLOW_WHILE_IDLE_COMPAT exempt", isExemptFromTare(
205                 createDefaultAlarm(anything, anything, FLAG_ALLOW_WHILE_IDLE_COMPAT)));
206         assertFalse("ALLOW_WHILE_IDLE exempt", isExemptFromTare(
207                 createDefaultAlarm(anything, anything, FLAG_ALLOW_WHILE_IDLE)));
208 
209         assertTrue("ALLOW_WHILE_IDLE_UNRESTRICTED not exempt", isExemptFromTare(
210                 createDefaultAlarm(anything, anything, FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED)));
211         assertTrue("Alarm clock not exempt", isExemptFromTare(createAlarmClock(anything)));
212     }
213 
214     @Test
snapshotImmutable()215     public void snapshotImmutable() {
216         final Alarm a = createDefaultAlarm(0, 0, 0);
217 
218         final Random random = new Random(234);
219         final long[] policyElapsed = new long[NUM_POLICIES];
220         for (int i = 0; i < NUM_POLICIES; i++) {
221             a.setPolicyElapsed(i, policyElapsed[i] = random.nextInt(1 << 10));
222         }
223 
224         final Alarm.Snapshot snapshot = new Alarm.Snapshot(a);
225 
226         for (int i = 0; i < NUM_POLICIES; i++) {
227             assertEquals(policyElapsed[i], snapshot.mPolicyWhenElapsed[i]);
228         }
229 
230         for (int i = 0; i < NUM_POLICIES; i++) {
231             a.setPolicyElapsed(i, policyElapsed[i] + 5 + i);
232             assertEquals(policyElapsed[i], snapshot.mPolicyWhenElapsed[i]);
233         }
234     }
235 }
236