blob: 0889265dd6639975350408949c6decb9fe48809a [file] [log] [blame]
Riddle Hsu7fdd90a2018-05-01 00:37:59 +08001/*
2 * Copyright (C) 2018 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
17package com.android.server.am;
18
19import static org.junit.Assert.assertNull;
20
21import android.content.Intent;
22import android.content.pm.ActivityInfo;
23import android.content.pm.ApplicationInfo;
24import android.content.pm.ResolveInfo;
25import android.os.Process;
26import android.os.UserHandle;
27import android.platform.test.annotations.Presubmit;
Brett Chabota26eda92018-07-23 13:08:30 -070028
29import androidx.test.filters.SmallTest;
Riddle Hsu7fdd90a2018-05-01 00:37:59 +080030
31import org.junit.Test;
Riddle Hsu7fdd90a2018-05-01 00:37:59 +080032
33import java.util.ArrayList;
34import java.util.Collections;
35import java.util.List;
36
37/**
38 * Test class for {@link BroadcastRecord}.
39 *
40 * Build/Install/Run:
Tadashi G. Takaokad3eb6452018-11-03 18:21:40 -070041 * atest FrameworksServicesTests:BroadcastRecordTest
Riddle Hsu7fdd90a2018-05-01 00:37:59 +080042 */
43@SmallTest
44@Presubmit
Riddle Hsu1abb56b2018-10-18 11:51:17 +080045public class BroadcastRecordTest {
Riddle Hsu7fdd90a2018-05-01 00:37:59 +080046
47 @Test
48 public void testCleanupDisabledPackageReceivers() {
49 final int user0 = UserHandle.USER_SYSTEM;
50 final int user1 = user0 + 1;
51 final String pkgToCleanup = "pkg.a";
52 final String pkgOther = "pkg.b";
53
54 // Receivers contain multiple-user (contains [pkg.a@u0, pkg.a@u1, pkg.b@u0, pkg.b@u1]).
55 final List<ResolveInfo> receiversM = createReceiverInfos(
56 new String[] { pkgToCleanup, pkgOther },
57 new int[] { user0, user1 });
58 // Receivers only contain one user (contains [pkg.a@u0, pkg.b@u0]).
59 final List<ResolveInfo> receiversU0 = excludeReceivers(
60 receiversM, null /* packageName */, user1);
61
62 // With given package:
63 // Send to all users, cleanup a package of all users.
64 final BroadcastRecord recordAllAll = createBroadcastRecord(receiversM, UserHandle.USER_ALL);
65 cleanupDisabledPackageReceivers(recordAllAll, pkgToCleanup, UserHandle.USER_ALL);
66 assertNull(verifyRemaining(recordAllAll, excludeReceivers(receiversM, pkgToCleanup, -1)));
67
68 // Send to all users, cleanup a package of one user.
69 final BroadcastRecord recordAllOne = createBroadcastRecord(receiversM, UserHandle.USER_ALL);
70 cleanupDisabledPackageReceivers(recordAllOne, pkgToCleanup, user0);
71 assertNull(verifyRemaining(recordAllOne,
72 excludeReceivers(receiversM, pkgToCleanup, user0)));
73
74 // Send to one user, cleanup a package of all users.
75 final BroadcastRecord recordOneAll = createBroadcastRecord(receiversU0, user0);
76 cleanupDisabledPackageReceivers(recordOneAll, pkgToCleanup, UserHandle.USER_ALL);
77 assertNull(verifyRemaining(recordOneAll, excludeReceivers(receiversU0, pkgToCleanup, -1)));
78
79 // Send to one user, cleanup a package one user.
80 final BroadcastRecord recordOneOne = createBroadcastRecord(receiversU0, user0);
81 cleanupDisabledPackageReceivers(recordOneOne, pkgToCleanup, user0);
82 assertNull(verifyRemaining(recordOneOne, excludeReceivers(receiversU0, pkgToCleanup, -1)));
83
84 // Without given package (e.g. stop user):
85 // Send to all users, cleanup one user.
86 final BroadcastRecord recordAllM = createBroadcastRecord(receiversM, UserHandle.USER_ALL);
87 cleanupDisabledPackageReceivers(recordAllM, null /* packageName */, user1);
88 assertNull(verifyRemaining(recordAllM,
89 excludeReceivers(receiversM, null /* packageName */, user1)));
90
91 // Send to one user, cleanup one user.
92 final BroadcastRecord recordU0 = createBroadcastRecord(receiversU0, user0);
93 cleanupDisabledPackageReceivers(recordU0, null /* packageName */, user0);
94 assertNull(verifyRemaining(recordU0, Collections.emptyList()));
95 }
96
97 private static void cleanupDisabledPackageReceivers(BroadcastRecord record,
98 String packageName, int userId) {
99 record.cleanupDisabledPackageReceiversLocked(packageName, null /* filterByClasses */,
100 userId, true /* doit */);
101 }
102
103 private static String verifyRemaining(BroadcastRecord record,
104 List<ResolveInfo> expectedRemainingReceivers) {
105 final StringBuilder errorMsg = new StringBuilder();
106
107 for (final Object receiver : record.receivers) {
108 final ResolveInfo resolveInfo = (ResolveInfo) receiver;
109 final ApplicationInfo appInfo = resolveInfo.activityInfo.applicationInfo;
110
111 boolean foundExpected = false;
112 for (final ResolveInfo expectedReceiver : expectedRemainingReceivers) {
113 final ApplicationInfo expectedAppInfo =
114 expectedReceiver.activityInfo.applicationInfo;
115 if (appInfo.packageName.equals(expectedAppInfo.packageName)
116 && UserHandle.getUserId(appInfo.uid) == UserHandle
117 .getUserId(expectedAppInfo.uid)) {
118 foundExpected = true;
119 break;
120 }
121 }
122 if (!foundExpected) {
123 errorMsg.append(appInfo.packageName).append("@")
124 .append('u').append(UserHandle.getUserId(appInfo.uid)).append(' ');
125 }
126 }
127
128 return errorMsg.length() == 0 ? null
129 : errorMsg.insert(0, "Contains unexpected receiver: ").toString();
130 }
131
132 private static ResolveInfo createResolveInfo(String packageName, int uid) {
133 final ResolveInfo resolveInfo = new ResolveInfo();
134 final ActivityInfo activityInfo = new ActivityInfo();
135 final ApplicationInfo appInfo = new ApplicationInfo();
136 appInfo.packageName = packageName;
137 appInfo.uid = uid;
138 activityInfo.applicationInfo = appInfo;
139 resolveInfo.activityInfo = activityInfo;
140 return resolveInfo;
141 }
142
143 /**
144 * Generate (packages.length * userIds.length) receivers.
145 */
146 private static List<ResolveInfo> createReceiverInfos(String[] packages, int[] userIds) {
147 final List<ResolveInfo> receivers = new ArrayList<>();
148 for (int i = 0; i < packages.length; i++) {
149 for (final int userId : userIds) {
150 receivers.add(createResolveInfo(packages[i],
151 UserHandle.getUid(userId, Process.FIRST_APPLICATION_UID + i)));
152 }
153 }
154 return receivers;
155 }
156
157 /**
158 * Create a new list which filters out item if package name or user id is matched.
159 * Null package name or user id < 0 will be considered as don't care.
160 */
161 private static List<ResolveInfo> excludeReceivers(List<ResolveInfo> receivers,
162 String packageName, int userId) {
163 final List<ResolveInfo> excludedList = new ArrayList<>();
164 for (final ResolveInfo receiver : receivers) {
165 if ((packageName != null
166 && !packageName.equals(receiver.activityInfo.applicationInfo.packageName))
167 || (userId > -1 && userId != UserHandle
168 .getUserId(receiver.activityInfo.applicationInfo.uid))) {
169 excludedList.add(receiver);
170 }
171 }
172 return excludedList;
173 }
174
175 private static BroadcastRecord createBroadcastRecord(List<ResolveInfo> receivers, int userId) {
176 return new BroadcastRecord(
177 null /* queue */,
178 new Intent(),
179 null /* callerApp */,
180 null /* callerPackage */,
181 0 /* callingPid */,
182 0 /* callingUid */,
183 false /* callerInstantApp */,
184 null /* resolvedType */,
185 null /* requiredPermissions */,
186 0 /* appOp */,
187 null /* options */,
188 new ArrayList<>(receivers), // Make a copy to not affect the original list.
189 null /* resultTo */,
190 0 /* resultCode */,
191 null /* resultData */,
192 null /* resultExtras */,
193 false /* serialized */,
194 false /* sticky */,
195 false /* initialSticky */,
196 userId);
197 }
198}