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.pm;
17
18import static org.junit.Assert.assertNotNull;
19import static org.junit.Assert.assertTrue;
20
21import android.app.ActivityManager;
22import android.app.IStopUserCallback;
23import android.content.Context;
24import android.content.pm.UserInfo;
25import android.os.RemoteException;
26import android.os.UserManager;
27import android.support.test.InstrumentationRegistry;
28import android.support.test.filters.LargeTest;
29import android.support.test.runner.AndroidJUnit4;
30import android.util.Log;
31
32import org.junit.Before;
33import org.junit.Test;
34import org.junit.runner.RunWith;
35
36import java.io.IOException;
37import java.util.concurrent.CountDownLatch;
38import java.util.concurrent.TimeUnit;
39
40/**
41 * To run the test:
42 * bit FrameworksServicesTests:com.android.server.pm.UserLifecycleStressTest
43 */
44@RunWith(AndroidJUnit4.class)
45@LargeTest
46public class UserLifecycleStressTest {
47    private static final String TAG = "UserLifecycleStressTest";
48    // TODO: Make this smaller once we have improved it.
49    private static final int MAX_TIME_STOP_USER_IN_SECOND = 30;
50    private static final int NUM_ITERATIONS_STOP_USER = 10;
51    private static final int WAIT_BEFORE_STOP_USER_IN_SECOND = 3;
52
53    private Context mContext;
54    private UserManager mUserManager;
55    private ActivityManager mActivityManager;
56
57    @Before
58    public void setup() {
59        mContext = InstrumentationRegistry.getInstrumentation().getContext();
60        mUserManager = mContext.getSystemService(UserManager.class);
61        mActivityManager = mContext.getSystemService(ActivityManager.class);
62    }
63
64    /**
65     * Create and stop user 10 times in a row. Check stop user can be finished in a reasonable
66     * amount of time.
67     */
68    @Test
69    public void stopManagedProfileStressTest()
70            throws IOException, RemoteException, InterruptedException {
71        for (int i = 0; i < NUM_ITERATIONS_STOP_USER; i++) {
72            final UserInfo userInfo = mUserManager.createProfileForUser("TestUser",
73                    UserInfo.FLAG_MANAGED_PROFILE, mActivityManager.getCurrentUser());
74            assertNotNull(userInfo);
75            try {
76                assertTrue(
77                        "Failed to start the profile",
78                        ActivityManager.getService().startUserInBackground(userInfo.id));
79                // Seems the broadcast queue is getting more busy if we wait a few seconds before
80                // stopping the user.
81                TimeUnit.SECONDS.sleep(WAIT_BEFORE_STOP_USER_IN_SECOND);
82                stopUser(userInfo.id);
83            } finally {
84                mUserManager.removeUser(userInfo.id);
85            }
86        }
87    }
88
89    private void stopUser(int userId) throws RemoteException, InterruptedException {
90        final long startTime = System.currentTimeMillis();
91        CountDownLatch countDownLatch = new CountDownLatch(1);
92        ActivityManager.getService().
93                stopUser(userId, true,
94                        new IStopUserCallback.Stub() {
95                            @Override
96                            public void userStopped(int userId) throws RemoteException {
97                                countDownLatch.countDown();
98                            }
99
100                            @Override
101                            public void userStopAborted(int userId) throws RemoteException {
102
103                            }
104                        });
105        boolean stoppedBeforeTimeout =
106                countDownLatch.await(MAX_TIME_STOP_USER_IN_SECOND, TimeUnit.SECONDS);
107        assertTrue(
108                "Take more than " + MAX_TIME_STOP_USER_IN_SECOND + "s to stop user",
109                stoppedBeforeTimeout);
110        Log.d(TAG, "stopUser takes " + (System.currentTimeMillis() - startTime) + " ms");
111    }
112}
113
114