Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 42ed4974 authored by Sudheer Shanka's avatar Sudheer Shanka Committed by Android (Google) Code Review
Browse files

Merge "Add usermanager related perf tests - part2"

parents d9eb6ce2 2c4522cc
Loading
Loading
Loading
Loading
+168 −26
Original line number Diff line number Diff line
@@ -18,7 +18,8 @@ package android.multiuser;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.SynchronousUserSwitchObserver;
import android.app.IStopUserCallback;
import android.app.UserSwitchObserver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -43,18 +44,36 @@ import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * Perf tests for user life cycle events.
 *
 * Running the tests:
 * make MultiUserPerfTests &&
 * adb install -r \
 *     ${ANDROID_PRODUCT_OUT}/data/app/MultiUserPerfTests/MultiUserPerfTests.apk &&
 * adb shell am instrument -e class android.multiuser.UserLifecycleTest \
 *     -w com.android.perftests.multiuser/android.support.test.runner.AndroidJUnitRunner
 */
@LargeTest
@RunWith(AndroidJUnit4.class)
public class UserLifecycleTest {
    private final int MIN_REPEAT_TIMES = 4;

    private final int TIMEOUT_REMOVE_USER_SEC = 4;
    private final int TIMEOUT_REMOVE_USER_MS = 4 * 1000; // 4 sec
    private final int CHECK_USER_REMOVED_INTERVAL_MS = 200; // 0.2 sec

    private final int TIMEOUT_USER_START_SEC = 4; // 4 sec

    private final int TIMEOUT_USER_SWITCH_SEC = 8; // 8 sec

    private final int TIMEOUT_USER_STOP_SEC = 1; // 1 sec

    private final int TIMEOUT_MANAGED_PROFILE_UNLOCK_SEC = 2; // 2 sec

    private final int TIMEOUT_LOCKED_BOOT_COMPLETE_MS = 5 * 1000; // 5 sec

    private final int TIMEOUT_EPHERMAL_USER_STOP_SEC = 6; // 6 sec

    private UserManager mUm;
    private ActivityManager mAm;
    private IActivityManager mIam;
@@ -78,7 +97,11 @@ public class UserLifecycleTest {
    @After
    public void tearDown() {
        for (int userId : mUsersToRemove) {
            try {
                mUm.removeUser(userId);
            } catch (Exception e) {
                // Ignore
            }
        }
    }

@@ -88,14 +111,7 @@ public class UserLifecycleTest {
            final UserInfo userInfo = mUm.createUser("TestUser", 0);

            final CountDownLatch latch = new CountDownLatch(1);
            InstrumentationRegistry.getContext().registerReceiverAsUser(new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    if (Intent.ACTION_USER_STARTED.equals(intent.getAction())) {
                        latch.countDown();
                    }
                }
            }, UserHandle.ALL, new IntentFilter(Intent.ACTION_USER_STARTED), null, null);
            registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch, userInfo.id);
            mIam.startUserInBackground(userInfo.id);
            latch.await(TIMEOUT_USER_START_SEC, TimeUnit.SECONDS);

@@ -122,38 +138,164 @@ public class UserLifecycleTest {
        }
    }

    @Test
    public void stopUserPerf() throws Exception {
        while (mState.keepRunning()) {
            mState.pauseTiming();
            final UserInfo userInfo = mUm.createUser("TestUser", 0);
            final CountDownLatch latch = new CountDownLatch(1);
            registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch, userInfo.id);
            mIam.startUserInBackground(userInfo.id);
            latch.await(TIMEOUT_USER_START_SEC, TimeUnit.SECONDS);
            mState.resumeTiming();

            stopUser(userInfo.id);

            mState.pauseTiming();
            removeUser(userInfo.id);
            mState.resumeTiming();
        }
    }

    @Test
    public void lockedBootCompletedPerf() throws Exception {
        while (mState.keepRunning()) {
            mState.pauseTiming();
            final int startUser = mAm.getCurrentUser();
            final UserInfo userInfo = mUm.createUser("TestUser", 0);
            final CountDownLatch latch = new CountDownLatch(1);
            registerUserSwitchObserver(null, latch, userInfo.id);
            mState.resumeTiming();

            mAm.switchUser(userInfo.id);
            latch.await(TIMEOUT_LOCKED_BOOT_COMPLETE_MS, TimeUnit.SECONDS);

            mState.pauseTiming();
            switchUser(startUser);
            removeUser(userInfo.id);
            mState.resumeTiming();
        }
    }

    @Test
    public void managedProfileUnlockPerf() throws Exception {
        while (mState.keepRunning()) {
            mState.pauseTiming();
            final UserInfo userInfo = mUm.createProfileForUser("TestUser",
                    UserInfo.FLAG_MANAGED_PROFILE, mAm.getCurrentUser());
            final CountDownLatch latch = new CountDownLatch(1);
            registerBroadcastReceiver(Intent.ACTION_USER_UNLOCKED, latch, userInfo.id);
            mState.resumeTiming();

            mIam.startUserInBackground(userInfo.id);
            latch.await(TIMEOUT_MANAGED_PROFILE_UNLOCK_SEC, TimeUnit.SECONDS);

            mState.pauseTiming();
            removeUser(userInfo.id);
            mState.resumeTiming();
        }
    }

    @Test
    public void ephemeralUserStoppedPerf() throws Exception {
        while (mState.keepRunning()) {
            mState.pauseTiming();
            final int startUser = mAm.getCurrentUser();
            final UserInfo userInfo = mUm.createUser("TestUser",
                    UserInfo.FLAG_EPHEMERAL | UserInfo.FLAG_DEMO);
            switchUser(userInfo.id);
            final CountDownLatch latch = new CountDownLatch(1);
            InstrumentationRegistry.getContext().registerReceiver(new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    if (Intent.ACTION_USER_STOPPED.equals(intent.getAction()) && intent.getIntExtra(
                            Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL) == userInfo.id) {
                        latch.countDown();
                    }
                }
            }, new IntentFilter(Intent.ACTION_USER_STOPPED));
            final CountDownLatch switchLatch = new CountDownLatch(1);
            registerUserSwitchObserver(switchLatch, null, startUser);
            mState.resumeTiming();

            mAm.switchUser(startUser);
            latch.await(TIMEOUT_EPHERMAL_USER_STOP_SEC, TimeUnit.SECONDS);

            mState.pauseTiming();
            switchLatch.await(TIMEOUT_USER_SWITCH_SEC, TimeUnit.SECONDS);
            removeUser(userInfo.id);
            mState.resumeTiming();
        }
    }

    private void switchUser(int userId) throws Exception {
        final CountDownLatch latch = new CountDownLatch(1);
        registerUserSwitchObserver(latch);
        registerUserSwitchObserver(latch, null, userId);
        mAm.switchUser(userId);
        latch.await(TIMEOUT_USER_SWITCH_SEC, TimeUnit.SECONDS);
    }

    private void registerUserSwitchObserver(final CountDownLatch latch) throws Exception {
        ActivityManagerNative.getDefault().registerUserSwitchObserver(
                new SynchronousUserSwitchObserver() {
    private void stopUser(int userId) throws Exception {
        final CountDownLatch latch = new CountDownLatch(1);
        mIam.stopUser(userId, false /* force */, new IStopUserCallback.Stub() {
            @Override
                    public void onUserSwitching(int newUserId) throws RemoteException {
            public void userStopped(int userId) throws RemoteException {
                latch.countDown();
            }

            @Override
            public void userStopAborted(int userId) throws RemoteException {
            }
        });
        latch.await(TIMEOUT_USER_STOP_SEC, TimeUnit.SECONDS);
    }

    private void registerUserSwitchObserver(final CountDownLatch switchLatch,
            final CountDownLatch bootCompleteLatch, final int userId) throws Exception {
        ActivityManagerNative.getDefault().registerUserSwitchObserver(
                new UserSwitchObserver() {
                    @Override
                    public void onUserSwitchComplete(int newUserId) throws RemoteException {
                        latch.countDown();
                        if (switchLatch != null && userId == newUserId) {
                            switchLatch.countDown();
                        }
                    }

                    @Override
                    public void onForegroundProfileSwitch(int newProfileId) throws RemoteException {
                    public void onLockedBootComplete(int newUserId) {
                        if (bootCompleteLatch != null && userId == newUserId) {
                            bootCompleteLatch.countDown();
                        }
                    }
                }, "UserLifecycleTest");
    }

    private void removeUser(int userId) throws Exception {
    private void registerBroadcastReceiver(final String action, final CountDownLatch latch,
            final int userId) {
        InstrumentationRegistry.getContext().registerReceiverAsUser(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (action.equals(intent.getAction()) && intent.getIntExtra(
                        Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL) == userId) {
                    latch.countDown();
                }
            }
        }, UserHandle.of(userId), new IntentFilter(action), null, null);
    }

    private void removeUser(int userId) {
        try {
            mUm.removeUser(userId);
            final long startTime = System.currentTimeMillis();
            while (mUm.getUserInfo(userId) != null &&
                System.currentTimeMillis() - startTime < TIMEOUT_REMOVE_USER_SEC) {
                    System.currentTimeMillis() - startTime < TIMEOUT_REMOVE_USER_MS) {
                Thread.sleep(CHECK_USER_REMOVED_INTERVAL_MS);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            // Ignore
        }
        if (mUm.getUserInfo(userId) != null) {
            mUsersToRemove.add(userId);
        }
+1 −0
Original line number Diff line number Diff line
@@ -23,4 +23,5 @@ oneway interface IUserSwitchObserver {
    void onUserSwitching(int newUserId, IRemoteCallback reply);
    void onUserSwitchComplete(int newUserId);
    void onForegroundProfileSwitch(int newProfileId);
    void onLockedBootComplete(int newUserId);
}
+1 −1
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ import android.os.RemoteException;
 *
 * @hide
 */
public abstract class SynchronousUserSwitchObserver extends IUserSwitchObserver.Stub {
public abstract class SynchronousUserSwitchObserver extends UserSwitchObserver {
    /**
     * Calls {@link #onUserSwitching(int)} and notifies {@code reply} by calling
     * {@link IRemoteCallback#sendResult(Bundle)}.
+41 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package android.app;

import android.os.IRemoteCallback;
import android.os.RemoteException;

/**
 * @hide
 */
public class UserSwitchObserver extends IUserSwitchObserver.Stub {
    @Override
    public void onUserSwitching(int newUserId, IRemoteCallback reply) throws RemoteException {
        if (reply != null) {
            reply.sendResult(null);
        }
    }

    @Override
    public void onUserSwitchComplete(int newUserId) throws RemoteException {}

    @Override
    public void onForegroundProfileSwitch(int newProfileId) throws RemoteException {}

    @Override
    public void onLockedBootComplete(int newUserId) throws RemoteException {}
}
 No newline at end of file
+2 −6
Original line number Diff line number Diff line
@@ -29,8 +29,8 @@ import static android.os.BatteryManager.EXTRA_STATUS;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.AlarmManager;
import android.app.IUserSwitchObserver;
import android.app.PendingIntent;
import android.app.UserSwitchObserver;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
@@ -1071,7 +1071,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
        mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
        try {
            ActivityManagerNative.getDefault().registerUserSwitchObserver(
                    new IUserSwitchObserver.Stub() {
                    new UserSwitchObserver() {
                        @Override
                        public void onUserSwitching(int newUserId, IRemoteCallback reply) {
                            mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
@@ -1082,10 +1082,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
                            mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
                                    newUserId, 0));
                        }
                        @Override
                        public void onForegroundProfileSwitch(int newProfileId) {
                            // Ignore.
                        }
                    }, TAG);
        } catch (RemoteException e) {
            e.rethrowAsRuntimeException();
Loading