1 /*
2  * Copyright (C) 2017 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.server.alarm;
17 
18 import static android.app.AlarmManager.RTC;
19 import static android.app.AlarmManager.RTC_WAKEUP;
20 
21 import static org.junit.Assert.assertEquals;
22 
23 import android.platform.test.annotations.Presubmit;
24 import android.util.SparseArray;
25 
26 import androidx.test.filters.SmallTest;
27 import androidx.test.runner.AndroidJUnit4;
28 
29 import com.android.internal.util.ObjectUtils;
30 
31 import org.junit.Test;
32 import org.junit.runner.RunWith;
33 
34 import java.util.ArrayList;
35 
36 @Presubmit
37 @SmallTest
38 @RunWith(AndroidJUnit4.class)
39 public class BackgroundRestrictedAlarmsTest {
addPendingAlarm( SparseArray<ArrayList<Alarm>> all, int uid, String name, boolean removeIt)40     private SparseArray<ArrayList<Alarm>> addPendingAlarm(
41             SparseArray<ArrayList<Alarm>> all, int uid, String name, boolean removeIt) {
42         ArrayList<Alarm> uidAlarms = all.get(uid);
43         if (uidAlarms == null) {
44             all.put(uid, uidAlarms = new ArrayList<>());
45         }
46         uidAlarms.add(new Alarm(
47                 removeIt ? RTC : RTC_WAKEUP,
48                 0, 0, 0, 0, null, null, null, null, 0, null, uid, name, null, 0));
49         return all;
50     }
51 
toString(SparseArray<ArrayList<Alarm>> pendingAlarms)52     private static String toString(SparseArray<ArrayList<Alarm>> pendingAlarms) {
53         final StringBuilder sb = new StringBuilder();
54 
55         String sep = "";
56         for (int i = 0; i < pendingAlarms.size(); i++) {
57             sb.append(sep);
58             sep = ", ";
59             sb.append("[");
60             sb.append(pendingAlarms.keyAt(i));
61             sb.append(": ");
62             sb.append(toString(pendingAlarms.valueAt(i)));
63             sb.append("]");
64         }
65         return sb.toString();
66     }
67 
toString(ArrayList<Alarm> alarms)68     private static String toString(ArrayList<Alarm> alarms) {
69         final StringBuilder sb = new StringBuilder();
70 
71         alarms.sort((a, b) -> ObjectUtils.compare(a.packageName, b.packageName));
72 
73         String sep = "";
74         for (Alarm a : alarms) {
75             sb.append(sep);
76             sep = ", ";
77             sb.append(a.packageName);
78         }
79         return sb.toString();
80     }
81 
runCheckAllPendingAlarms( SparseArray<ArrayList<Alarm>> pending, ArrayList<Alarm> alarmsToDeliver)82     private void runCheckAllPendingAlarms(
83             SparseArray<ArrayList<Alarm>> pending, ArrayList<Alarm> alarmsToDeliver) {
84         // RTC_WAKEUP alarms are restricted.
85         AlarmManagerService.findAllUnrestrictedPendingBackgroundAlarmsLockedInner(pending,
86                 alarmsToDeliver, alarm -> alarm.type == RTC_WAKEUP);
87     }
88 
89     @Test
findAllUnrestrictedPendingBackgroundAlarmsLockedInner_empty()90     public void findAllUnrestrictedPendingBackgroundAlarmsLockedInner_empty() {
91         SparseArray<ArrayList<Alarm>> pending = new SparseArray<>();
92 
93         final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>();
94 
95         runCheckAllPendingAlarms(pending, alarmsToDeliver);
96 
97         assertEquals("", toString(pending));
98         assertEquals("", toString(alarmsToDeliver));
99     }
100 
101     @Test
findAllUnrestrictedPendingBackgroundAlarmsLockedInner_single_remove()102     public void findAllUnrestrictedPendingBackgroundAlarmsLockedInner_single_remove() {
103         SparseArray<ArrayList<Alarm>> pending = new SparseArray<>();
104 
105         addPendingAlarm(pending, 100001, "a1", false);
106 
107         final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>();
108 
109         runCheckAllPendingAlarms(pending, alarmsToDeliver);
110 
111         assertEquals("[100001: a1]", toString(pending));
112         assertEquals("", toString(alarmsToDeliver));
113     }
114 
115     @Test
findAllUnrestrictedPendingBackgroundAlarmsLockedInner_single_nonremove()116     public void findAllUnrestrictedPendingBackgroundAlarmsLockedInner_single_nonremove() {
117         SparseArray<ArrayList<Alarm>> pending = new SparseArray<>();
118 
119         addPendingAlarm(pending, 100001, "a1", true);
120 
121         final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>();
122         runCheckAllPendingAlarms(pending, alarmsToDeliver);
123 
124 
125         assertEquals("", toString(pending));
126         assertEquals("a1", toString(alarmsToDeliver));
127     }
128 
129     @Test
findAllUnrestrictedPendingBackgroundAlarmsLockedInner_complex()130     public void findAllUnrestrictedPendingBackgroundAlarmsLockedInner_complex() {
131         SparseArray<ArrayList<Alarm>> pending = new SparseArray<>();
132 
133         addPendingAlarm(pending, 100001, "a11", false);
134         addPendingAlarm(pending, 100001, "a12", true);
135         addPendingAlarm(pending, 100001, "a13", false);
136         addPendingAlarm(pending, 100001, "a14", true);
137 
138         addPendingAlarm(pending, 100002, "a21", false);
139 
140         addPendingAlarm(pending, 100003, "a31", true);
141 
142         addPendingAlarm(pending, 100004, "a41", false);
143         addPendingAlarm(pending, 100004, "a42", false);
144 
145         addPendingAlarm(pending, 100005, "a51", true);
146         addPendingAlarm(pending, 100005, "a52", true);
147 
148         addPendingAlarm(pending, 100006, "a61", true);
149         addPendingAlarm(pending, 100006, "a62", false);
150         addPendingAlarm(pending, 100006, "a63", true);
151         addPendingAlarm(pending, 100006, "a64", false);
152 
153         final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>();
154         runCheckAllPendingAlarms(pending, alarmsToDeliver);
155 
156 
157         assertEquals("[100001: a11, a13], [100002: a21], [100004: a41, a42], [100006: a62, a64]",
158                 toString(pending));
159         assertEquals("a12, a14, a31, a51, a52, a61, a63", toString(alarmsToDeliver));
160     }
161 
162     @Test
findAllUnrestrictedPendingBackgroundAlarmsLockedInner_complex_allRemove()163     public void findAllUnrestrictedPendingBackgroundAlarmsLockedInner_complex_allRemove() {
164         SparseArray<ArrayList<Alarm>> pending = new SparseArray<>();
165 
166         addPendingAlarm(pending, 100001, "a11", true);
167         addPendingAlarm(pending, 100001, "a12", true);
168         addPendingAlarm(pending, 100001, "a13", true);
169         addPendingAlarm(pending, 100001, "a14", true);
170 
171         addPendingAlarm(pending, 100002, "a21", true);
172 
173         addPendingAlarm(pending, 100003, "a31", true);
174 
175         addPendingAlarm(pending, 100004, "a41", true);
176         addPendingAlarm(pending, 100004, "a42", true);
177 
178         addPendingAlarm(pending, 100005, "a51", true);
179         addPendingAlarm(pending, 100005, "a52", true);
180 
181         addPendingAlarm(pending, 100006, "a61", true);
182         addPendingAlarm(pending, 100006, "a62", true);
183         addPendingAlarm(pending, 100006, "a63", true);
184         addPendingAlarm(pending, 100006, "a64", true);
185 
186         final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>();
187         runCheckAllPendingAlarms(pending, alarmsToDeliver);
188 
189 
190         assertEquals("", toString(pending));
191         assertEquals("a11, a12, a13, a14, a21, a31, a41, a42, a51, a52, a61, a62, a63, a64",
192                 toString(alarmsToDeliver));
193     }
194 }
195