Merge "Add usermanager related perf tests - part1"

This commit is contained in:
Sudheer Shanka
2016-08-23 17:57:36 +00:00
committed by Android (Google) Code Review
4 changed files with 235 additions and 3 deletions

View File

@@ -0,0 +1,31 @@
# 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)

View File

@@ -0,0 +1,31 @@
<?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>

View File

@@ -0,0 +1,161 @@
/*
* 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);
}
}
}

View File

@@ -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(", ");
}