Loading apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java +7 −6 Original line number Diff line number Diff line Loading @@ -155,6 +155,7 @@ public class UserLifecycleTests { public void tearDown() throws Exception { setSystemProperty("debug.usercontroller.user_switch_timeout_ms", mUserSwitchTimeoutMs); mBroadcastWaiter.close(); mUserSwitchWaiter.close(); for (int userId : mUsersToRemove) { try { mUm.removeUser(userId); Loading Loading @@ -207,10 +208,10 @@ public class UserLifecycleTests { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createUserNoFlags(); runThenWaitForBroadcasts(userId, () -> { mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); runThenWaitForBroadcasts(userId, () -> { mIam.startUserInBackground(userId); }, Intent.ACTION_USER_STARTED); Loading Loading @@ -360,10 +361,10 @@ public class UserLifecycleTests { }, Intent.ACTION_MEDIA_MOUNTED); mUserSwitchWaiter.runThenWaitUntilSwitchCompleted(startUser, () -> { runThenWaitForBroadcasts(userId, () -> { mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); runThenWaitForBroadcasts(userId, () -> { mAm.switchUser(startUser); }, Intent.ACTION_USER_STOPPED); Loading apct-tests/perftests/multiuser/src/android/multiuser/UserSwitchWaiter.java +53 −27 Original line number Diff line number Diff line Loading @@ -17,61 +17,87 @@ package android.multiuser; import android.app.ActivityManager; import android.app.IActivityManager; import android.app.IUserSwitchObserver; import android.app.UserSwitchObserver; import android.os.RemoteException; import android.util.Log; import com.android.internal.util.FunctionalUtils; import java.util.concurrent.CountDownLatch; import java.io.Closeable; import java.io.IOException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; public class UserSwitchWaiter { public class UserSwitchWaiter implements Closeable { private final String mTag; private final int mTimeoutInSecond; private final IActivityManager mActivityManager; private final IUserSwitchObserver mUserSwitchObserver = new UserSwitchObserver() { @Override public void onUserSwitchComplete(int newUserId) { getSemaphoreSwitchComplete(newUserId).release(); } @Override public void onLockedBootComplete(int newUserId) { getSemaphoreBootComplete(newUserId).release(); } }; public UserSwitchWaiter(String tag, int timeoutInSecond) { private final Map<Integer, Semaphore> mSemaphoresMapSwitchComplete = new ConcurrentHashMap<>(); private Semaphore getSemaphoreSwitchComplete(final int userId) { return mSemaphoresMapSwitchComplete.computeIfAbsent(userId, (Integer absentKey) -> new Semaphore(0)); } private final Map<Integer, Semaphore> mSemaphoresMapBootComplete = new ConcurrentHashMap<>(); private Semaphore getSemaphoreBootComplete(final int userId) { return mSemaphoresMapBootComplete.computeIfAbsent(userId, (Integer absentKey) -> new Semaphore(0)); } public UserSwitchWaiter(String tag, int timeoutInSecond) throws RemoteException { mTag = tag; mTimeoutInSecond = timeoutInSecond; mActivityManager = ActivityManager.getService(); mActivityManager.registerUserSwitchObserver(mUserSwitchObserver, mTag); } public void runThenWaitUntilSwitchCompleted(int userId, FunctionalUtils.ThrowingRunnable runnable, Runnable onFail) throws RemoteException { final CountDownLatch latch = new CountDownLatch(1); ActivityManager.getService().registerUserSwitchObserver( new UserSwitchObserver() { @Override public void onUserSwitchComplete(int newUserId) throws RemoteException { if (userId == newUserId) { latch.countDown(); public void close() throws IOException { try { mActivityManager.unregisterUserSwitchObserver(mUserSwitchObserver); } catch (RemoteException e) { Log.e(mTag, "Failed to unregister user switch observer", e); } } }, mTag); public void runThenWaitUntilSwitchCompleted(int userId, FunctionalUtils.ThrowingRunnable runnable, Runnable onFail) throws RemoteException { final Semaphore semaphore = getSemaphoreSwitchComplete(userId); semaphore.drainPermits(); runnable.run(); waitForLatch(latch, onFail); waitForSemaphore(semaphore, onFail); } public void runThenWaitUntilBootCompleted(int userId, FunctionalUtils.ThrowingRunnable runnable, Runnable onFail) throws RemoteException { final CountDownLatch latch = new CountDownLatch(1); ActivityManager.getService().registerUserSwitchObserver( new UserSwitchObserver() { @Override public void onLockedBootComplete(int newUserId) { if (userId == newUserId) { latch.countDown(); } } }, mTag); final Semaphore semaphore = getSemaphoreBootComplete(userId); semaphore.drainPermits(); runnable.run(); waitForLatch(latch, onFail); waitForSemaphore(semaphore, onFail); } private void waitForLatch(CountDownLatch latch, Runnable onFail) { private void waitForSemaphore(Semaphore semaphore, Runnable onFail) { boolean success = false; try { success = latch.await(mTimeoutInSecond, TimeUnit.SECONDS); success = semaphore.tryAcquire(mTimeoutInSecond, TimeUnit.SECONDS); } catch (InterruptedException e) { Log.e(mTag, "Thread interrupted unexpectedly.", e); } Loading Loading
apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java +7 −6 Original line number Diff line number Diff line Loading @@ -155,6 +155,7 @@ public class UserLifecycleTests { public void tearDown() throws Exception { setSystemProperty("debug.usercontroller.user_switch_timeout_ms", mUserSwitchTimeoutMs); mBroadcastWaiter.close(); mUserSwitchWaiter.close(); for (int userId : mUsersToRemove) { try { mUm.removeUser(userId); Loading Loading @@ -207,10 +208,10 @@ public class UserLifecycleTests { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createUserNoFlags(); runThenWaitForBroadcasts(userId, () -> { mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); runThenWaitForBroadcasts(userId, () -> { mIam.startUserInBackground(userId); }, Intent.ACTION_USER_STARTED); Loading Loading @@ -360,10 +361,10 @@ public class UserLifecycleTests { }, Intent.ACTION_MEDIA_MOUNTED); mUserSwitchWaiter.runThenWaitUntilSwitchCompleted(startUser, () -> { runThenWaitForBroadcasts(userId, () -> { mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); runThenWaitForBroadcasts(userId, () -> { mAm.switchUser(startUser); }, Intent.ACTION_USER_STOPPED); Loading
apct-tests/perftests/multiuser/src/android/multiuser/UserSwitchWaiter.java +53 −27 Original line number Diff line number Diff line Loading @@ -17,61 +17,87 @@ package android.multiuser; import android.app.ActivityManager; import android.app.IActivityManager; import android.app.IUserSwitchObserver; import android.app.UserSwitchObserver; import android.os.RemoteException; import android.util.Log; import com.android.internal.util.FunctionalUtils; import java.util.concurrent.CountDownLatch; import java.io.Closeable; import java.io.IOException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; public class UserSwitchWaiter { public class UserSwitchWaiter implements Closeable { private final String mTag; private final int mTimeoutInSecond; private final IActivityManager mActivityManager; private final IUserSwitchObserver mUserSwitchObserver = new UserSwitchObserver() { @Override public void onUserSwitchComplete(int newUserId) { getSemaphoreSwitchComplete(newUserId).release(); } @Override public void onLockedBootComplete(int newUserId) { getSemaphoreBootComplete(newUserId).release(); } }; public UserSwitchWaiter(String tag, int timeoutInSecond) { private final Map<Integer, Semaphore> mSemaphoresMapSwitchComplete = new ConcurrentHashMap<>(); private Semaphore getSemaphoreSwitchComplete(final int userId) { return mSemaphoresMapSwitchComplete.computeIfAbsent(userId, (Integer absentKey) -> new Semaphore(0)); } private final Map<Integer, Semaphore> mSemaphoresMapBootComplete = new ConcurrentHashMap<>(); private Semaphore getSemaphoreBootComplete(final int userId) { return mSemaphoresMapBootComplete.computeIfAbsent(userId, (Integer absentKey) -> new Semaphore(0)); } public UserSwitchWaiter(String tag, int timeoutInSecond) throws RemoteException { mTag = tag; mTimeoutInSecond = timeoutInSecond; mActivityManager = ActivityManager.getService(); mActivityManager.registerUserSwitchObserver(mUserSwitchObserver, mTag); } public void runThenWaitUntilSwitchCompleted(int userId, FunctionalUtils.ThrowingRunnable runnable, Runnable onFail) throws RemoteException { final CountDownLatch latch = new CountDownLatch(1); ActivityManager.getService().registerUserSwitchObserver( new UserSwitchObserver() { @Override public void onUserSwitchComplete(int newUserId) throws RemoteException { if (userId == newUserId) { latch.countDown(); public void close() throws IOException { try { mActivityManager.unregisterUserSwitchObserver(mUserSwitchObserver); } catch (RemoteException e) { Log.e(mTag, "Failed to unregister user switch observer", e); } } }, mTag); public void runThenWaitUntilSwitchCompleted(int userId, FunctionalUtils.ThrowingRunnable runnable, Runnable onFail) throws RemoteException { final Semaphore semaphore = getSemaphoreSwitchComplete(userId); semaphore.drainPermits(); runnable.run(); waitForLatch(latch, onFail); waitForSemaphore(semaphore, onFail); } public void runThenWaitUntilBootCompleted(int userId, FunctionalUtils.ThrowingRunnable runnable, Runnable onFail) throws RemoteException { final CountDownLatch latch = new CountDownLatch(1); ActivityManager.getService().registerUserSwitchObserver( new UserSwitchObserver() { @Override public void onLockedBootComplete(int newUserId) { if (userId == newUserId) { latch.countDown(); } } }, mTag); final Semaphore semaphore = getSemaphoreBootComplete(userId); semaphore.drainPermits(); runnable.run(); waitForLatch(latch, onFail); waitForSemaphore(semaphore, onFail); } private void waitForLatch(CountDownLatch latch, Runnable onFail) { private void waitForSemaphore(Semaphore semaphore, Runnable onFail) { boolean success = false; try { success = latch.await(mTimeoutInSecond, TimeUnit.SECONDS); success = semaphore.tryAcquire(mTimeoutInSecond, TimeUnit.SECONDS); } catch (InterruptedException e) { Log.e(mTag, "Thread interrupted unexpectedly.", e); } Loading