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

Commit 53c23fdd authored by Sudheer Shanka's avatar Sudheer Shanka
Browse files

Add usermanager related perf tests - part1

Bug: 30948225
Change-Id: I0668a012435e9954729e5085fdb4b1f5ce422d97
parent 412b630b
Loading
Loading
Loading
Loading
+31 −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.

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := tests

LOCAL_SRC_FILES := $(call all-java-files-under, src)

LOCAL_STATIC_JAVA_LIBRARIES := \
    android-support-test \
    apct-perftests-utils

LOCAL_PACKAGE_NAME := MultiUserPerfTests

LOCAL_CERTIFICATE := platform

include $(BUILD_PACKAGE)
+31 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.android.multiuser.frameworks.perftests">

    <uses-permission android:name="android.permission.MANAGE_USERS" />
    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />

    <application>
        <uses-library android:name="android.test.runner" />
    </application>

    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
            android:targetPackage="com.android.multiuser.frameworks.perftests"/>

</manifest>
 No newline at end of file
+161 −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.multiuser;

import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.SynchronousUserSwitchObserver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.UserInfo;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@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 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 UserManager mUm;
    private ActivityManager mAm;
    private IActivityManager mIam;
    private BenchmarkState mState;
    private ArrayList<Integer> mUsersToRemove;

    @Rule
    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();

    @Before
    public void setUp() {
        final Context context = InstrumentationRegistry.getContext();
        mUm = UserManager.get(context);
        mAm = context.getSystemService(ActivityManager.class);
        mIam = ActivityManagerNative.getDefault();
        mState = mPerfStatusReporter.getBenchmarkState();
        mState.setMinRepeatTimes(MIN_REPEAT_TIMES);
        mUsersToRemove = new ArrayList<>();
    }

    @After
    public void tearDown() {
        for (int userId : mUsersToRemove) {
            mUm.removeUser(userId);
        }
    }

    @Test
    public void createAndStartUserPerf() throws Exception {
        while (mState.keepRunning()) {
            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);
            mIam.startUserInBackground(userInfo.id);
            latch.await(TIMEOUT_USER_START_SEC, TimeUnit.SECONDS);

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

    @Test
    public void switchUserPerf() throws Exception {
        while (mState.keepRunning()) {
            mState.pauseTiming();
            final int startUser = mAm.getCurrentUser();
            final UserInfo userInfo = mUm.createUser("TestUser", 0);
            mState.resumeTiming();

            switchUser(userInfo.id);

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

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

    private void registerUserSwitchObserver(final CountDownLatch latch) throws Exception {
        ActivityManagerNative.getDefault().registerUserSwitchObserver(
                new SynchronousUserSwitchObserver() {
                    @Override
                    public void onUserSwitching(int newUserId) throws RemoteException {
                    }

                    @Override
                    public void onUserSwitchComplete(int newUserId) throws RemoteException {
                        latch.countDown();
                    }

                    @Override
                    public void onForegroundProfileSwitch(int newProfileId) throws RemoteException {
                    }
                }, "UserLifecycleTest");
    }

    private void removeUser(int userId) throws Exception {
        mUm.removeUser(userId);
        final long startTime = System.currentTimeMillis();
        while (mUm.getUserInfo(userId) != null &&
                System.currentTimeMillis() - startTime < TIMEOUT_REMOVE_USER_SEC) {
            Thread.sleep(CHECK_USER_REMOVED_INTERVAL_MS);
        }
        if (mUm.getUserInfo(userId) != null) {
            mUsersToRemove.add(userId);
        }
    }
}
 No newline at end of file
+12 −3
Original line number Diff line number Diff line
@@ -48,7 +48,6 @@ public class BenchmarkState {
    private static final int RUNNING = 2;  // The benchmark is running.
    private static final int RUNNING_PAUSED = 3;  // The benchmark is temporary paused.
    private static final int FINISHED = 4;  // The benchmark has stopped.
    private static final int MIN_REPEAT_TIMES = 16;

    private int mState = NOT_STARTED;  // Current benchmark state.

@@ -64,9 +63,19 @@ public class BenchmarkState {
    private double mMean = 0.0;
    private double mStandardDeviation = 0.0;

    // Number of iterations needed for calculating the stats.
    private int mMinRepeatTimes = 16;

    // Individual duration in nano seconds.
    private ArrayList<Long> mResults = new ArrayList<>();

    /**
     * Sets the number of iterations needed for calculating the stats. Default is 16.
     */
    public void setMinRepeatTimes(int minRepeatTimes) {
        mMinRepeatTimes = minRepeatTimes;
    }

    /**
     * Calculates statistics.
     */
@@ -133,7 +142,7 @@ public class BenchmarkState {
                mNanoPausedDuration = 0;

                // To calculate statistics, needs two or more samples.
                if (mResults.size() > MIN_REPEAT_TIMES && currentTime > mNanoFinishTime) {
                if (mResults.size() > mMinRepeatTimes && currentTime > mNanoFinishTime) {
                    calculateSatistics();
                    mState = FINISHED;
                    return false;
@@ -181,7 +190,7 @@ public class BenchmarkState {
        sb.append("sigma=").append(standardDeviation()).append(", ");
        sb.append("iteration=").append(mResults.size()).append(", ");
        // print out the first few iterations' number for double checking.
        int sampleNumber = Math.min(mResults.size(), MIN_REPEAT_TIMES);
        int sampleNumber = Math.min(mResults.size(), mMinRepeatTimes);
        for (int i = 0; i < sampleNumber; i++) {
            sb.append("No ").append(i).append(" result is ").append(mResults.get(i)).append(", ");
        }