blob: 7e7b87137ff86806729e983e01e167eb762c32de [file] [log] [blame]
Sudheer Shanka53c23fd2016-08-17 19:34:58 -07001/*
2 * Copyright (C) 2016 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 android.multiuser;
17
18import android.app.ActivityManager;
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070019import android.app.IActivityManager;
Sudheer Shanka2c4522c2016-08-27 20:53:28 -070020import android.app.IStopUserCallback;
21import android.app.UserSwitchObserver;
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070022import android.content.BroadcastReceiver;
23import android.content.Context;
24import android.content.Intent;
25import android.content.IntentFilter;
26import android.content.pm.UserInfo;
27import android.os.RemoteException;
28import android.os.UserHandle;
29import android.os.UserManager;
Bookatz52b12ac2019-02-28 17:29:26 -080030import android.util.Log;
KOUSHIK PANUGANTI130f0a52018-12-17 14:41:06 -080031
32import androidx.test.InstrumentationRegistry;
33import androidx.test.filters.LargeTest;
34import androidx.test.runner.AndroidJUnit4;
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070035
36import org.junit.After;
37import org.junit.Before;
38import org.junit.Rule;
39import org.junit.Test;
40import org.junit.runner.RunWith;
41
42import java.util.ArrayList;
43import java.util.concurrent.CountDownLatch;
44import java.util.concurrent.TimeUnit;
45
Sudheer Shanka2c4522c2016-08-27 20:53:28 -070046/**
47 * Perf tests for user life cycle events.
48 *
49 * Running the tests:
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -070050 *
Sudheer Shanka2c4522c2016-08-27 20:53:28 -070051 * make MultiUserPerfTests &&
52 * adb install -r \
53 * ${ANDROID_PRODUCT_OUT}/data/app/MultiUserPerfTests/MultiUserPerfTests.apk &&
Sudheer Shanka2d0278b2017-07-12 18:12:31 -070054 * adb shell am instrument -e class android.multiuser.UserLifecycleTests \
KOUSHIK PANUGANTI130f0a52018-12-17 14:41:06 -080055 * -w com.android.perftests.multiuser/androidx.test.runner.AndroidJUnitRunner
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -070056 *
57 * or
58 *
Sudheer Shanka2d0278b2017-07-12 18:12:31 -070059 * bit MultiUserPerfTests:android.multiuser.UserLifecycleTests
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -070060 *
61 * Note: If you use bit for running the tests, benchmark results won't be printed on the host side.
Sudheer Shanka2d0278b2017-07-12 18:12:31 -070062 * But in either case, results can be checked on the device side 'adb logcat -s UserLifecycleTests'
Sudheer Shanka2c4522c2016-08-27 20:53:28 -070063 */
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070064@LargeTest
65@RunWith(AndroidJUnit4.class)
Sudheer Shanka2d0278b2017-07-12 18:12:31 -070066public class UserLifecycleTests {
67 private static final String TAG = UserLifecycleTests.class.getSimpleName();
68
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -070069 private final int TIMEOUT_IN_SECOND = 30;
Tony Makec7c6962017-05-26 15:38:09 +010070 private final int CHECK_USER_REMOVED_INTERVAL_MS = 200;
Sudheer Shanka2c4522c2016-08-27 20:53:28 -070071
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070072 private UserManager mUm;
73 private ActivityManager mAm;
74 private IActivityManager mIam;
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070075 private ArrayList<Integer> mUsersToRemove;
76
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -070077 private final BenchmarkRunner mRunner = new BenchmarkRunner();
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070078 @Rule
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -070079 public BenchmarkResultsReporter mReporter = new BenchmarkResultsReporter(mRunner);
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070080
81 @Before
82 public void setUp() {
83 final Context context = InstrumentationRegistry.getContext();
84 mUm = UserManager.get(context);
85 mAm = context.getSystemService(ActivityManager.class);
Sudheer Shankadc589ac2016-11-10 15:30:17 -080086 mIam = ActivityManager.getService();
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070087 mUsersToRemove = new ArrayList<>();
88 }
89
90 @After
91 public void tearDown() {
92 for (int userId : mUsersToRemove) {
Sudheer Shanka2c4522c2016-08-27 20:53:28 -070093 try {
94 mUm.removeUser(userId);
95 } catch (Exception e) {
96 // Ignore
97 }
Sudheer Shanka53c23fd2016-08-17 19:34:58 -070098 }
99 }
100
101 @Test
Sudheer Shankaa319f8b2017-07-11 15:28:48 -0700102 public void createAndStartUser() throws Exception {
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700103 while (mRunner.keepRunning()) {
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700104 final UserInfo userInfo = mUm.createUser("TestUser", 0);
105
106 final CountDownLatch latch = new CountDownLatch(1);
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700107 registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch, userInfo.id);
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700108 mIam.startUserInBackground(userInfo.id);
Tony Makec7c6962017-05-26 15:38:09 +0100109 latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700110
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700111 mRunner.pauseTiming();
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700112 removeUser(userInfo.id);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700113 mRunner.resumeTiming();
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700114 }
115 }
116
117 @Test
Sudheer Shankaa319f8b2017-07-11 15:28:48 -0700118 public void switchUser() throws Exception {
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700119 while (mRunner.keepRunning()) {
120 mRunner.pauseTiming();
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700121 final int startUser = mAm.getCurrentUser();
122 final UserInfo userInfo = mUm.createUser("TestUser", 0);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700123 mRunner.resumeTiming();
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700124
125 switchUser(userInfo.id);
126
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700127 mRunner.pauseTiming();
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700128 switchUser(startUser);
129 removeUser(userInfo.id);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700130 mRunner.resumeTiming();
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700131 }
132 }
133
Bookatz52b12ac2019-02-28 17:29:26 -0800134 /** Tests switching to an already-created, but no-longer-running, user. */
135 @Test
136 public void switchUser_stopped() throws Exception {
137 while (mRunner.keepRunning()) {
138 mRunner.pauseTiming();
139 final int startUser = mAm.getCurrentUser();
140 final int testUser = initializeNewUserAndSwitchBack(/* stopNewUser */ true);
141 final CountDownLatch latch = new CountDownLatch(1);
142 registerBroadcastReceiver(Intent.ACTION_USER_UNLOCKED, latch, testUser);
143 mRunner.resumeTiming();
144
145 mAm.switchUser(testUser);
146 boolean success = latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
147
148 mRunner.pauseTiming();
149 attestTrue("Failed to achieve 2nd ACTION_USER_UNLOCKED for user " + testUser, success);
150 switchUser(startUser);
151 removeUser(testUser);
152 mRunner.resumeTiming();
153 }
154 }
155
156 /** Tests switching to an already-created already-running non-owner user. */
157 @Test
158 public void switchUser_running() throws Exception {
159 while (mRunner.keepRunning()) {
160 mRunner.pauseTiming();
161 final int startUser = mAm.getCurrentUser();
162 final int testUser = initializeNewUserAndSwitchBack(/* stopNewUser */ false);
163 mRunner.resumeTiming();
164
165 switchUser(testUser);
166
167 mRunner.pauseTiming();
168 attestTrue("Failed to switch to user " + testUser, mAm.isUserRunning(testUser));
169 switchUser(startUser);
170 removeUser(testUser);
171 mRunner.resumeTiming();
172 }
173 }
174
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700175 @Test
Sudheer Shankaa319f8b2017-07-11 15:28:48 -0700176 public void stopUser() throws Exception {
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700177 while (mRunner.keepRunning()) {
178 mRunner.pauseTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700179 final UserInfo userInfo = mUm.createUser("TestUser", 0);
180 final CountDownLatch latch = new CountDownLatch(1);
181 registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch, userInfo.id);
182 mIam.startUserInBackground(userInfo.id);
Tony Makec7c6962017-05-26 15:38:09 +0100183 latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700184 mRunner.resumeTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700185
Tony Makec7c6962017-05-26 15:38:09 +0100186 stopUser(userInfo.id, false);
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700187
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700188 mRunner.pauseTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700189 removeUser(userInfo.id);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700190 mRunner.resumeTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700191 }
192 }
193
194 @Test
Sudheer Shankaa319f8b2017-07-11 15:28:48 -0700195 public void lockedBootCompleted() throws Exception {
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700196 while (mRunner.keepRunning()) {
197 mRunner.pauseTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700198 final int startUser = mAm.getCurrentUser();
199 final UserInfo userInfo = mUm.createUser("TestUser", 0);
200 final CountDownLatch latch = new CountDownLatch(1);
201 registerUserSwitchObserver(null, latch, userInfo.id);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700202 mRunner.resumeTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700203
204 mAm.switchUser(userInfo.id);
Tony Makec7c6962017-05-26 15:38:09 +0100205 latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700206
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700207 mRunner.pauseTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700208 switchUser(startUser);
209 removeUser(userInfo.id);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700210 mRunner.resumeTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700211 }
212 }
213
214 @Test
Sudheer Shankaa319f8b2017-07-11 15:28:48 -0700215 public void managedProfileUnlock() throws Exception {
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700216 while (mRunner.keepRunning()) {
217 mRunner.pauseTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700218 final UserInfo userInfo = mUm.createProfileForUser("TestUser",
219 UserInfo.FLAG_MANAGED_PROFILE, mAm.getCurrentUser());
220 final CountDownLatch latch = new CountDownLatch(1);
221 registerBroadcastReceiver(Intent.ACTION_USER_UNLOCKED, latch, userInfo.id);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700222 mRunner.resumeTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700223
224 mIam.startUserInBackground(userInfo.id);
Tony Makec7c6962017-05-26 15:38:09 +0100225 latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700226
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700227 mRunner.pauseTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700228 removeUser(userInfo.id);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700229 mRunner.resumeTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700230 }
231 }
232
233 @Test
Sudheer Shankaa319f8b2017-07-11 15:28:48 -0700234 public void ephemeralUserStopped() throws Exception {
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700235 while (mRunner.keepRunning()) {
236 mRunner.pauseTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700237 final int startUser = mAm.getCurrentUser();
238 final UserInfo userInfo = mUm.createUser("TestUser",
239 UserInfo.FLAG_EPHEMERAL | UserInfo.FLAG_DEMO);
240 switchUser(userInfo.id);
241 final CountDownLatch latch = new CountDownLatch(1);
242 InstrumentationRegistry.getContext().registerReceiver(new BroadcastReceiver() {
243 @Override
244 public void onReceive(Context context, Intent intent) {
245 if (Intent.ACTION_USER_STOPPED.equals(intent.getAction()) && intent.getIntExtra(
246 Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL) == userInfo.id) {
247 latch.countDown();
248 }
249 }
250 }, new IntentFilter(Intent.ACTION_USER_STOPPED));
251 final CountDownLatch switchLatch = new CountDownLatch(1);
252 registerUserSwitchObserver(switchLatch, null, startUser);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700253 mRunner.resumeTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700254
255 mAm.switchUser(startUser);
Tony Makec7c6962017-05-26 15:38:09 +0100256 latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700257
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700258 mRunner.pauseTiming();
Tony Makec7c6962017-05-26 15:38:09 +0100259 switchLatch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
260 removeUser(userInfo.id);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700261 mRunner.resumeTiming();
Tony Makec7c6962017-05-26 15:38:09 +0100262 }
263 }
264
265 @Test
Sudheer Shankaa319f8b2017-07-11 15:28:48 -0700266 public void managedProfileStopped() throws Exception {
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700267 while (mRunner.keepRunning()) {
268 mRunner.pauseTiming();
Tony Makec7c6962017-05-26 15:38:09 +0100269 final UserInfo userInfo = mUm.createProfileForUser("TestUser",
270 UserInfo.FLAG_MANAGED_PROFILE, mAm.getCurrentUser());
271 final CountDownLatch latch = new CountDownLatch(1);
272 registerBroadcastReceiver(Intent.ACTION_USER_UNLOCKED, latch, userInfo.id);
273 mIam.startUserInBackground(userInfo.id);
274 latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700275 mRunner.resumeTiming();
Tony Makec7c6962017-05-26 15:38:09 +0100276
277 stopUser(userInfo.id, true);
278
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700279 mRunner.pauseTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700280 removeUser(userInfo.id);
Sudheer Shanka5f76e1f2017-06-25 19:40:53 -0700281 mRunner.resumeTiming();
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700282 }
283 }
284
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700285 private void switchUser(int userId) throws Exception {
286 final CountDownLatch latch = new CountDownLatch(1);
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700287 registerUserSwitchObserver(latch, null, userId);
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700288 mAm.switchUser(userId);
Tony Makec7c6962017-05-26 15:38:09 +0100289 latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700290 }
291
Tony Makec7c6962017-05-26 15:38:09 +0100292 private void stopUser(int userId, boolean force) throws Exception {
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700293 final CountDownLatch latch = new CountDownLatch(1);
Tony Makec7c6962017-05-26 15:38:09 +0100294 mIam.stopUser(userId, force /* force */, new IStopUserCallback.Stub() {
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700295 @Override
296 public void userStopped(int userId) throws RemoteException {
297 latch.countDown();
298 }
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700299
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700300 @Override
301 public void userStopAborted(int userId) throws RemoteException {
302 }
303 });
Tony Makec7c6962017-05-26 15:38:09 +0100304 latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700305 }
306
Bookatz52b12ac2019-02-28 17:29:26 -0800307 /**
308 * Creates a user and waits for its ACTION_USER_UNLOCKED.
309 * Then switches to back to the original user and waits for its switchUser() to finish.
310 *
311 * @param stopNewUser whether to stop the new user after switching to otherUser.
312 * @return userId of the newly created user.
313 */
314 private int initializeNewUserAndSwitchBack(boolean stopNewUser) throws Exception {
315 final int origUser = mAm.getCurrentUser();
316 // First, create and switch to testUser, waiting for its ACTION_USER_UNLOCKED
317 final int testUser = mUm.createUser("TestUser", 0).id;
318 final CountDownLatch latch1 = new CountDownLatch(1);
319 registerBroadcastReceiver(Intent.ACTION_USER_UNLOCKED, latch1, testUser);
320 mAm.switchUser(testUser);
321 attestTrue("Failed to achieve initial ACTION_USER_UNLOCKED for user " + testUser,
322 latch1.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS));
323
324 // Second, switch back to origUser, waiting merely for switchUser() to finish
325 switchUser(origUser);
326 attestTrue("Didn't switch back to user, " + origUser, origUser == mAm.getCurrentUser());
327
328 if (stopNewUser) {
329 stopUser(testUser, true);
330 attestFalse("Failed to stop user " + testUser, mAm.isUserRunning(testUser));
331 }
332
333 return testUser;
334 }
335
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700336 private void registerUserSwitchObserver(final CountDownLatch switchLatch,
337 final CountDownLatch bootCompleteLatch, final int userId) throws Exception {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800338 ActivityManager.getService().registerUserSwitchObserver(
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700339 new UserSwitchObserver() {
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700340 @Override
341 public void onUserSwitchComplete(int newUserId) throws RemoteException {
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700342 if (switchLatch != null && userId == newUserId) {
343 switchLatch.countDown();
344 }
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700345 }
346
347 @Override
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700348 public void onLockedBootComplete(int newUserId) {
349 if (bootCompleteLatch != null && userId == newUserId) {
350 bootCompleteLatch.countDown();
351 }
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700352 }
Sudheer Shanka2d0278b2017-07-12 18:12:31 -0700353 }, TAG);
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700354 }
355
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700356 private void registerBroadcastReceiver(final String action, final CountDownLatch latch,
357 final int userId) {
358 InstrumentationRegistry.getContext().registerReceiverAsUser(new BroadcastReceiver() {
359 @Override
360 public void onReceive(Context context, Intent intent) {
361 if (action.equals(intent.getAction()) && intent.getIntExtra(
362 Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL) == userId) {
363 latch.countDown();
364 }
365 }
366 }, UserHandle.of(userId), new IntentFilter(action), null, null);
367 }
368
369 private void removeUser(int userId) {
370 try {
371 mUm.removeUser(userId);
372 final long startTime = System.currentTimeMillis();
Tony Makec7c6962017-05-26 15:38:09 +0100373 final long timeoutInMs = TIMEOUT_IN_SECOND * 1000;
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700374 while (mUm.getUserInfo(userId) != null &&
Tony Makec7c6962017-05-26 15:38:09 +0100375 System.currentTimeMillis() - startTime < timeoutInMs) {
376 TimeUnit.MILLISECONDS.sleep(CHECK_USER_REMOVED_INTERVAL_MS);
Sudheer Shanka2c4522c2016-08-27 20:53:28 -0700377 }
378 } catch (InterruptedException e) {
379 Thread.currentThread().interrupt();
380 } catch (Exception e) {
381 // Ignore
Sudheer Shanka53c23fd2016-08-17 19:34:58 -0700382 }
383 if (mUm.getUserInfo(userId) != null) {
384 mUsersToRemove.add(userId);
385 }
386 }
Bookatz52b12ac2019-02-28 17:29:26 -0800387
388 private void attestTrue(String message, boolean attestion) {
389 if (!attestion) {
390 Log.w(TAG, message);
391 }
392 }
393
394 private void attestFalse(String message, boolean attestion) {
395 attestTrue(message, !attestion);
396 }
John Reck62e5fea2016-10-12 15:27:52 -0700397}