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