Merge "Convert to Mockito: GceManagerTest"
diff --git a/common_util/com/android/tradefed/util/FuseUtil.java b/common_util/com/android/tradefed/util/FuseUtil.java
index bcd5541..f82ed87 100644
--- a/common_util/com/android/tradefed/util/FuseUtil.java
+++ b/common_util/com/android/tradefed/util/FuseUtil.java
@@ -49,7 +49,7 @@
     public boolean canMountZip() {
         if (sCanMountZip == null) {
             CommandResult res =
-                    getRunUtil().runTimedCmd(FUSE_ZIP_TIMEOUT_MILLIS, "test", "/dev/fuse");
+                    getRunUtil().runTimedCmd(FUSE_ZIP_TIMEOUT_MILLIS, "test", "-c", "/dev/fuse");
             CommandResult res2 =
                     getRunUtil().runTimedCmd(FUSE_ZIP_TIMEOUT_MILLIS, "fuse-zip", "-h");
             sCanMountZip =
diff --git a/global_configuration/com/android/tradefed/host/HostOptions.java b/global_configuration/com/android/tradefed/host/HostOptions.java
index f280130..43a7ec4 100644
--- a/global_configuration/com/android/tradefed/host/HostOptions.java
+++ b/global_configuration/com/android/tradefed/host/HostOptions.java
@@ -31,7 +31,9 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
+import java.util.concurrent.Semaphore;
 
 /**
  * Host options holder class.
@@ -52,6 +54,10 @@
     )
     private Integer mConcurrentDownloadLimit = null;
 
+    @Option(name = "concurrent-limits", description =
+            "The maximum number of concurrent actions of a given type.")
+    private Map<PermitLimitType, Integer> mConcurrentLimit = new HashMap<>();
+
     @Option(
         name = "fastboot-tmpdir",
         description = "The location of temporary directory used by fastboot"
@@ -106,6 +112,8 @@
             description = "The network interface used to connect to test devices.")
     private String mNetworkInterface = null;
 
+    private Map<PermitLimitType, Semaphore> mConcurrentLocks = new HashMap<>();
+
     /** {@inheritDoc} */
     @Override
     public Integer getConcurrentFlasherLimit() {
@@ -210,4 +218,57 @@
         }
         return null;
     }
+
+    @Override
+    public void initConcurrentLocks() {
+        // Do not reinit if it has been called before
+        if (!mConcurrentLocks.isEmpty()) {
+            return;
+        }
+        // Backfill flasher & download limit from their dedicated option
+        if (!mConcurrentLimit.containsKey(PermitLimitType.CONCURRENT_FLASHER)) {
+            mConcurrentLimit.put(PermitLimitType.CONCURRENT_FLASHER, mConcurrentFlasherLimit);
+        }
+        if (!mConcurrentLimit.containsKey(PermitLimitType.CONCURRENT_DOWNLOAD)) {
+            mConcurrentLimit.put(PermitLimitType.CONCURRENT_DOWNLOAD, mConcurrentDownloadLimit);
+        }
+
+        for (Entry<PermitLimitType, Integer> limits : mConcurrentLimit.entrySet()) {
+            if (limits.getValue() == null) {
+                continue;
+            }
+            mConcurrentLocks.put(limits.getKey(),
+                    new Semaphore(limits.getValue(), true /* fair */));
+        }
+    }
+
+    @Override
+    public void takePermit(PermitLimitType type) {
+        if (!mConcurrentLocks.containsKey(type)) {
+            return;
+        }
+        CLog.i(
+                "Requesting a '%s' permit out of the max limit of %s. Current queue "
+                        + "length: %s",
+                        type,
+                        mConcurrentLimit.get(type),
+                        mConcurrentLocks.get(type).getQueueLength());
+        mConcurrentLocks.get(type).acquireUninterruptibly();
+    }
+
+    @Override
+    public void returnPermit(PermitLimitType type) {
+        if (!mConcurrentLocks.containsKey(type)) {
+            return;
+        }
+        mConcurrentLocks.get(type).release();
+    }
+
+    @Override
+    public Integer getAvailablePermits(PermitLimitType type) {
+        if (!mConcurrentLocks.containsKey(type)) {
+            return Integer.MAX_VALUE;
+        }
+        return mConcurrentLocks.get(type).availablePermits();
+    }
 }
diff --git a/global_configuration/com/android/tradefed/host/IHostOptions.java b/global_configuration/com/android/tradefed/host/IHostOptions.java
index 3426587..4b4216a 100644
--- a/global_configuration/com/android/tradefed/host/IHostOptions.java
+++ b/global_configuration/com/android/tradefed/host/IHostOptions.java
@@ -32,6 +32,14 @@
 public interface IHostOptions {
 
     /**
+     * Enum describing the possible permit limiters
+     */
+    public enum PermitLimitType {
+        CONCURRENT_FLASHER,
+        CONCURRENT_DOWNLOAD;
+    }
+
+    /**
      * Returns the max number of concurrent flashing to allow. Used by {@link DeviceFlashPreparer}.
      *
      * @return the concurrent flasher limit.
@@ -76,4 +84,16 @@
 
     /** Returns the network interface used to connect to remote test devices. */
     String getNetworkInterface();
+
+    /** Initializes the concurrent locks */
+    public void initConcurrentLocks();
+
+    /** Takes a permit of the given type */
+    public void takePermit(PermitLimitType type);
+
+    /** Returns a permit of the given type */
+    public void returnPermit(PermitLimitType type);
+
+    /** Returns the number of available permit of a given type */
+    public Integer getAvailablePermits(PermitLimitType type);
 }
diff --git a/invocation_interfaces/com/android/tradefed/config/ConfigurationDescriptor.java b/invocation_interfaces/com/android/tradefed/config/ConfigurationDescriptor.java
index c5aa2a6..f693a39 100644
--- a/invocation_interfaces/com/android/tradefed/config/ConfigurationDescriptor.java
+++ b/invocation_interfaces/com/android/tradefed/config/ConfigurationDescriptor.java
@@ -143,6 +143,13 @@
         }
     }
 
+    /**
+     * Remove the tracking of the specified metadata key.
+     */
+    public List<String> removeMetadata(String key) {
+        return mMetaData.remove(key);
+    }
+
     /** Returns if the configuration is shardable or not as part of a suite */
     public boolean isNotShardable() {
         return mNotShardable;
diff --git a/javatests/com/android/tradefed/UnitTests.java b/javatests/com/android/tradefed/UnitTests.java
index d159fc3..b4b9f62 100644
--- a/javatests/com/android/tradefed/UnitTests.java
+++ b/javatests/com/android/tradefed/UnitTests.java
@@ -175,12 +175,8 @@
 import com.android.tradefed.result.ConsoleResultReporterTest;
 import com.android.tradefed.result.CountingTestResultListenerTest;
 import com.android.tradefed.result.DeviceFileReporterTest;
-import com.android.tradefed.result.DeviceUnavailEmailResultReporterTest;
-import com.android.tradefed.result.EmailResultReporterTest;
 import com.android.tradefed.result.FailureDescriptionTest;
-import com.android.tradefed.result.FailureEmailResultReporterTest;
 import com.android.tradefed.result.FileSystemLogSaverTest;
-import com.android.tradefed.result.InvocationFailureEmailResultReporterTest;
 import com.android.tradefed.result.InvocationToJUnitResultForwarderTest;
 import com.android.tradefed.result.JUnitToInvocationResultForwarderTest;
 import com.android.tradefed.result.JsonHttpTestResultReporterTest;
@@ -194,7 +190,6 @@
 import com.android.tradefed.result.SnapshotInputStreamSourceTest;
 import com.android.tradefed.result.SubprocessResultsReporterTest;
 import com.android.tradefed.result.TestDescriptionTest;
-import com.android.tradefed.result.TestFailureEmailResultReporterTest;
 import com.android.tradefed.result.TestResultListenerTest;
 import com.android.tradefed.result.TestResultTest;
 import com.android.tradefed.result.TestRunResultTest;
@@ -660,12 +655,8 @@
     ConsoleResultReporterTest.class,
     CountingTestResultListenerTest.class,
     DeviceFileReporterTest.class,
-    DeviceUnavailEmailResultReporterTest.class,
-    EmailResultReporterTest.class,
     FailureDescriptionTest.class,
-    FailureEmailResultReporterTest.class,
     FileSystemLogSaverTest.class,
-    InvocationFailureEmailResultReporterTest.class,
     InvocationToJUnitResultForwarderTest.class,
     JsonHttpTestResultReporterTest.class,
     JUnitToInvocationResultForwarderTest.class,
@@ -676,7 +667,6 @@
     MultiFailureDescriptionTest.class,
     SnapshotInputStreamSourceTest.class,
     SubprocessResultsReporterTest.class,
-    TestFailureEmailResultReporterTest.class,
     PassingTestFileReporterTest.class,
     ReportPassedTestsTest.class,
     TestDescriptionTest.class,
diff --git a/javatests/com/android/tradefed/build/DeviceBuildDescriptorTest.java b/javatests/com/android/tradefed/build/DeviceBuildDescriptorTest.java
index 853543f..adbe973 100644
--- a/javatests/com/android/tradefed/build/DeviceBuildDescriptorTest.java
+++ b/javatests/com/android/tradefed/build/DeviceBuildDescriptorTest.java
@@ -15,27 +15,31 @@
  */
 package com.android.tradefed.build;
 
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
 
-import org.easymock.EasyMock;
+/** Unit tests for {@link DeviceBuildDescriptor}. */
+@RunWith(JUnit4.class)
+public class DeviceBuildDescriptorTest {
 
-/**
- * Unit tests for {@link DeviceBuildDescriptor}.
- */
-public class DeviceBuildDescriptorTest extends TestCase {
-
+    @Test
     public void testDeviceBuildDescriptor() throws DeviceNotAvailableException {
         BuildInfo b = new BuildInfo();
-        ITestDevice d = EasyMock.createNiceMock(ITestDevice.class);
-        EasyMock.expect(d.getProperty("ro.product.name")).andReturn("yakju");
-        EasyMock.expect(d.getProperty("ro.build.type")).andReturn("userdebug");
-        EasyMock.expect(d.getProperty("ro.product.brand")).andReturn("google");
-        EasyMock.expect(d.getProperty("ro.product.model")).andReturn("Galaxy Nexus");
-        EasyMock.expect(d.getProperty("ro.build.version.release")).andReturn("4.2");
-        EasyMock.replay(d);
+        ITestDevice d = mock(ITestDevice.class);
+        when(d.getProperty("ro.product.name")).thenReturn("yakju");
+        when(d.getProperty("ro.build.type")).thenReturn("userdebug");
+        when(d.getProperty("ro.product.brand")).thenReturn("google");
+        when(d.getProperty("ro.product.model")).thenReturn("Galaxy Nexus");
+        when(d.getProperty("ro.build.version.release")).thenReturn("4.2");
+
         DeviceBuildDescriptor.injectDeviceAttributes(d, b);
         DeviceBuildDescriptor db = new DeviceBuildDescriptor(b);
         assertEquals("yakju-userdebug", db.getDeviceBuildFlavor());
diff --git a/javatests/com/android/tradefed/build/FileDownloadCacheTest.java b/javatests/com/android/tradefed/build/FileDownloadCacheTest.java
index 9a1c3e1..7f96be2 100644
--- a/javatests/com/android/tradefed/build/FileDownloadCacheTest.java
+++ b/javatests/com/android/tradefed/build/FileDownloadCacheTest.java
@@ -21,6 +21,12 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.when;
 
 import com.android.tradefed.result.error.InfraErrorIdentifier;
 import com.android.tradefed.util.CommandResult;
@@ -29,14 +35,14 @@
 import com.android.tradefed.util.RunUtil;
 import com.android.tradefed.util.StreamUtil;
 
-import org.easymock.EasyMock;
-import org.easymock.IAnswer;
-import org.easymock.IExpectationSetters;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -52,8 +58,7 @@
     private static final String REMOTE_PATH = "foo/path";
     private static final String DOWNLOADED_CONTENTS = "downloaded contents";
 
-
-    private IFileDownloader mMockDownloader;
+    @Mock IFileDownloader mMockDownloader;
 
     private File mCacheDir;
     private FileDownloadCache mCache;
@@ -61,7 +66,8 @@
 
     @Before
     public void setUp() throws Exception {
-        mMockDownloader = EasyMock.createMock(IFileDownloader.class);
+        MockitoAnnotations.initMocks(this);
+
         mCacheDir = FileUtil.createTempDir("unittest");
         mCache = new FileDownloadCache(mCacheDir);
     }
@@ -75,10 +81,9 @@
     /** Test basic case for {@link FileDownloadCache#fetchRemoteFile(IFileDownloader, String)}. */
     @Test
     public void testFetchRemoteFile() throws Exception {
-        setDownloadExpections();
-        EasyMock.replay(mMockDownloader);
+        setDownloadExpectations();
+
         assertFetchRemoteFile();
-        EasyMock.verify(mMockDownloader);
     }
 
     /**
@@ -86,23 +91,21 @@
      */
     @Test
     public void testFetchRemoteFile_destFile() throws Exception {
-        setDownloadExpections();
-        EasyMock.replay(mMockDownloader);
+        setDownloadExpectations();
+
         File destFile = FileUtil.createTempFile("test-download-cache", "txt");
         assertFetchRemoteFile(REMOTE_PATH, null, destFile);
-        EasyMock.verify(mMockDownloader);
     }
 
     @Test
     public void testFetchRemoteFile_destFile_nullPath() throws Exception {
-        EasyMock.replay(mMockDownloader);
+
         try {
             assertFetchRemoteFile(null, null, null);
             fail("Should have thrown an exception.");
         } catch (BuildRetrievalError expected) {
             assertEquals("remote path was null.", expected.getMessage());
         }
-        EasyMock.verify(mMockDownloader);
     }
 
     /**
@@ -111,18 +114,16 @@
      */
     @Test
     public void testFetchRemoteFile_cacheHit() throws Exception {
-        setDownloadExpections();
-        EasyMock.replay(mMockDownloader);
+        setDownloadExpectations();
+
         assertFetchRemoteFile();
-        EasyMock.verify(mMockDownloader);
 
         // now retrieve file again
-        EasyMock.reset(mMockDownloader);
-        setFreshnessExpections(true);
-        EasyMock.replay(mMockDownloader);
+        reset(mMockDownloader);
+        setFreshnessExpectations(true);
+
         assertFetchRemoteFile();
         // verify only one download call occurred. It is not called at the second time.
-        EasyMock.verify(mMockDownloader);
     }
 
     /**
@@ -131,19 +132,17 @@
      */
     @Test
     public void testFetchRemoteFile_cacheHit_notFresh() throws Exception {
-        setDownloadExpections();
-        EasyMock.replay(mMockDownloader);
+        setDownloadExpectations();
+
         assertFetchRemoteFile();
-        EasyMock.verify(mMockDownloader);
 
         // now retrieve file again
-        EasyMock.reset(mMockDownloader);
-        setFreshnessExpections(false);
-        setDownloadExpections();
-        EasyMock.replay(mMockDownloader);
+        reset(mMockDownloader);
+        setFreshnessExpectations(false);
+        setDownloadExpectations();
+
         assertFetchRemoteFile();
         // Assert the download is called again.
-        EasyMock.verify(mMockDownloader);
     }
 
     /**
@@ -155,15 +154,14 @@
         final String remotePath2 = "anotherpath";
         // set cache size to be small
         mCache.setMaxCacheSize(DOWNLOADED_CONTENTS.length() + 1);
-        setDownloadExpections(remotePath2);
-        setDownloadExpections();
-        EasyMock.replay(mMockDownloader);
+        setDownloadExpectations(remotePath2);
+        setDownloadExpectations();
+
         assertFetchRemoteFile(remotePath2, null);
         // now retrieve another file, which will exceed size of cache
         assertFetchRemoteFile();
         assertNotNull(mCache.getCachedFile(REMOTE_PATH));
         assertNull(mCache.getCachedFile(remotePath2));
-        EasyMock.verify(mMockDownloader);
     }
 
     /**
@@ -171,13 +169,12 @@
      */
     @Test
     public void testFetchRemoteFile_downloadFailed() throws Exception {
-        mMockDownloader.downloadFile(EasyMock.eq(REMOTE_PATH),
-                (File)EasyMock.anyObject());
-        EasyMock.expectLastCall()
-                .andThrow(
+        doThrow(
                         new BuildRetrievalError(
-                                "download error", InfraErrorIdentifier.ARTIFACT_DOWNLOAD_ERROR));
-        EasyMock.replay(mMockDownloader);
+                                "download error", InfraErrorIdentifier.ARTIFACT_DOWNLOAD_ERROR))
+                .when(mMockDownloader)
+                .downloadFile(eq(REMOTE_PATH), any(File.class));
+
         try {
             mCache.fetchRemoteFile(mMockDownloader, REMOTE_PATH);
             fail("BuildRetrievalError not thrown");
@@ -185,7 +182,6 @@
             // expected
         }
         assertNull(mCache.getCachedFile(REMOTE_PATH));
-        EasyMock.verify(mMockDownloader);
     }
 
     /**
@@ -194,9 +190,10 @@
      */
     @Test
     public void testFetchRemoteFile_downloadFailed_Runtime() throws Exception {
-        mMockDownloader.downloadFile(EasyMock.eq(REMOTE_PATH), (File) EasyMock.anyObject());
-        EasyMock.expectLastCall().andThrow(new RuntimeException("download error"));
-        EasyMock.replay(mMockDownloader);
+        doThrow(new RuntimeException("download error"))
+                .when(mMockDownloader)
+                .downloadFile(eq(REMOTE_PATH), any(File.class));
+
         try {
             mCache.fetchRemoteFile(mMockDownloader, REMOTE_PATH);
             fail("RuntimeException not thrown");
@@ -204,7 +201,6 @@
             // expected
         }
         assertNull(mCache.getCachedFile(REMOTE_PATH));
-        EasyMock.verify(mMockDownloader);
     }
 
     /**
@@ -214,10 +210,10 @@
     @Test
     public void testFetchRemoteFile_cacheMissing() throws Exception {
         // perform successful download
-        setDownloadExpections(REMOTE_PATH);
-        EasyMock.replay(mMockDownloader);
+        setDownloadExpectations(REMOTE_PATH);
+
         assertFetchRemoteFile();
-        EasyMock.verify(mMockDownloader);
+
         // now be sneaky and delete the cachedFile, so copy will fail
         File cachedFile = mCache.getCachedFile(REMOTE_PATH);
         assertNotNull(cachedFile);
@@ -225,14 +221,13 @@
         assertTrue(res);
         File file = null;
         try {
-            EasyMock.reset(mMockDownloader);
-            setDownloadExpections(REMOTE_PATH);
-            EasyMock.replay(mMockDownloader);
+            reset(mMockDownloader);
+            setDownloadExpectations(REMOTE_PATH);
+
             file = mCache.fetchRemoteFile(mMockDownloader, REMOTE_PATH);
             // file should have been updated in cache.
             assertNotNull(file);
             assertNotNull(mCache.getCachedFile(REMOTE_PATH));
-            EasyMock.verify(mMockDownloader);
         } finally {
             FileUtil.deleteFile(file);
         }
@@ -256,16 +251,15 @@
                     }
                 };
         // perform successful download
-        setDownloadExpections(REMOTE_PATH);
-        EasyMock.replay(mMockDownloader);
+        setDownloadExpectations(REMOTE_PATH);
+
         assertFetchRemoteFile();
-        EasyMock.verify(mMockDownloader);
 
         mFailCopy = true;
         try {
-            EasyMock.reset(mMockDownloader);
-            setFreshnessExpections(true);
-            EasyMock.replay(mMockDownloader);
+            reset(mMockDownloader);
+            setFreshnessExpectations(true);
+
             mCache.fetchRemoteFile(mMockDownloader, REMOTE_PATH);
             fail("BuildRetrievalError not thrown");
         } catch (BuildRetrievalError e) {
@@ -273,7 +267,6 @@
         }
         // file should be removed from cache
         assertNull(mCache.getCachedFile(REMOTE_PATH));
-        EasyMock.verify(mMockDownloader);
     }
 
     /**
@@ -286,10 +279,9 @@
         relativePaths.add("file.txt");
         relativePaths.add("folder1/file1.txt");
         relativePaths.add("folder1/folder2/file2.txt");
-        setDownloadExpections(REMOTE_PATH, relativePaths);
-        EasyMock.replay(mMockDownloader);
+        setDownloadExpectations(REMOTE_PATH, relativePaths);
+
         assertFetchRemoteFile(REMOTE_PATH, relativePaths);
-        EasyMock.verify(mMockDownloader);
     }
 
     /** Test that when the cache is rebuilt we can find the file without a new download. */
@@ -302,14 +294,12 @@
         File cacheFile = null;
         try {
             mCache = new FileDownloadCache(cacheDir);
-            setFreshnessExpections(true);
+            setFreshnessExpectations(true);
 
-            EasyMock.replay(mMockDownloader);
             cacheFile =
                     mCache.fetchRemoteFile(
                             mMockDownloader, subDir.getName() + "/" + file.getName());
             assertNotNull(cacheFile);
-            EasyMock.verify(mMockDownloader);
         } finally {
             FileUtil.recursiveDelete(cacheDir);
             FileUtil.deleteFile(cacheFile);
@@ -321,10 +311,9 @@
     public void testCacheRebuild_multiSlashPath() throws Exception {
         String gsPath = "foo//bar";
         // Perform successful download
-        setDownloadExpections(gsPath);
-        EasyMock.replay(mMockDownloader);
+        setDownloadExpectations(gsPath);
+
         assertFetchRemoteFile(gsPath, null);
-        EasyMock.verify(mMockDownloader);
 
         File cachedFile = mCache.getCachedFile(gsPath);
         try {
@@ -378,57 +367,49 @@
                     assertEquals(DOWNLOADED_CONTENTS, FileUtil.readStringFromFile(file));
                 }
             }
-
         } finally {
             FileUtil.recursiveDelete(fileCopy);
         }
     }
 
-    /**
-     * Set EasyMock expectations for a downloadFile call for default remote path
-     */
-    private void setDownloadExpections() throws BuildRetrievalError {
-        setDownloadExpections(REMOTE_PATH, null);
+    /** Set EasyMock expectations for a downloadFile call for default remote path */
+    private void setDownloadExpectations() throws BuildRetrievalError {
+        setDownloadExpectations(REMOTE_PATH, null);
     }
 
     /** Set EasyMock expectations for a downloadFile call. */
-    private void setDownloadExpections(String remotePath) throws BuildRetrievalError {
-        setDownloadExpections(remotePath, null);
+    private void setDownloadExpectations(String remotePath) throws BuildRetrievalError {
+        setDownloadExpectations(remotePath, null);
     }
 
     /** Set EasyMock expectations for a downloadFile call */
-    private IExpectationSetters<Object> setDownloadExpections(
-            String remotePath, List<String> relativePaths) throws BuildRetrievalError {
-        IAnswer<Object> downloadAnswer =
-                new IAnswer<Object>() {
-                    @Override
-                    public Object answer() throws Throwable {
-                        File fileArg = (File) EasyMock.getCurrentArguments()[1];
-                        if (relativePaths == null || relativePaths.size() == 0) {
-                            FileUtil.writeToFile(DOWNLOADED_CONTENTS, fileArg);
-                        } else {
-                            fileArg.mkdir();
-                            for (String relativePath : relativePaths) {
-                                File file =
-                                        Paths.get(fileArg.getAbsolutePath(), relativePath).toFile();
-                                file.getParentFile().mkdirs();
-                                FileUtil.writeToFile(DOWNLOADED_CONTENTS, file);
-                            }
-                        }
-                        return null;
-                    }
-                };
+    private void setDownloadExpectations(String remotePath, List<String> relativePaths)
+            throws BuildRetrievalError {
 
-        mMockDownloader.downloadFile(EasyMock.eq(remotePath),
-                EasyMock.<File>anyObject());
-        return EasyMock.expectLastCall().andAnswer(downloadAnswer);
+        doAnswer(
+                        invocation -> {
+                            File fileArg = (File) invocation.getArguments()[1];
+                            if (relativePaths == null || relativePaths.size() == 0) {
+                                FileUtil.writeToFile(DOWNLOADED_CONTENTS, fileArg);
+                            } else {
+                                fileArg.mkdir();
+                                for (String relativePath : relativePaths) {
+                                    File file =
+                                            Paths.get(fileArg.getAbsolutePath(), relativePath)
+                                                    .toFile();
+                                    file.getParentFile().mkdirs();
+                                    FileUtil.writeToFile(DOWNLOADED_CONTENTS, file);
+                                }
+                            }
+                            return null;
+                        })
+                .when(mMockDownloader)
+                .downloadFile(eq(remotePath), Mockito.<File>any());
     }
 
     /** Set EasyMock expectations for a checkFreshness call */
-    private void setFreshnessExpections(boolean freshness) throws BuildRetrievalError {
-        EasyMock.expect(
-                        mMockDownloader.isFresh(
-                                EasyMock.<File>anyObject(), EasyMock.<String>anyObject()))
-                .andReturn(freshness);
+    private void setFreshnessExpectations(boolean freshness) throws BuildRetrievalError {
+        when(mMockDownloader.isFresh(Mockito.<File>any(), Mockito.<String>any()))
+                .thenReturn(freshness);
     }
 }
diff --git a/javatests/com/android/tradefed/cluster/ClusterCommandSchedulerTest.java b/javatests/com/android/tradefed/cluster/ClusterCommandSchedulerTest.java
index 1b73ab8..8da4680 100644
--- a/javatests/com/android/tradefed/cluster/ClusterCommandSchedulerTest.java
+++ b/javatests/com/android/tradefed/cluster/ClusterCommandSchedulerTest.java
@@ -44,6 +44,8 @@
 import com.android.tradefed.device.MockDeviceManager;
 import com.android.tradefed.device.NoDeviceException;
 import com.android.tradefed.device.StubDevice;
+import com.android.tradefed.host.IHostOptions;
+import com.android.tradefed.host.IHostOptions.PermitLimitType;
 import com.android.tradefed.invoker.IInvocationContext;
 import com.android.tradefed.invoker.InvocationContext;
 import com.android.tradefed.invoker.logger.InvocationMetricLogger.InvocationMetricKey;
@@ -121,6 +123,7 @@
     @Rule public TestLogData mTestLog = new TestLogData();
 
     private IDeviceManager mMockDeviceManager;
+    private IHostOptions mMockHostOptions;
     private IRestApiHelper mMockApiHelper;
     private IClusterClient mMockClusterClient;
     private ClusterOptions mMockClusterOptions;
@@ -147,6 +150,7 @@
     public void setUp() throws Exception {
         mMockHostUploader = EasyMock.createMock(IClusterEventUploader.class);
         mMockDeviceManager = EasyMock.createMock(IDeviceManager.class);
+        mMockHostOptions = EasyMock.createMock(IHostOptions.class);
         mMockApiHelper = EasyMock.createMock(IRestApiHelper.class);
         mMockEventUploader = EasyMock.createMock(ICommandEventUploader.class);
         mMockClusterOptions = new ClusterOptions();
@@ -194,6 +198,11 @@
                     }
 
                     @Override
+                    protected IHostOptions getHostOptions() {
+                        return mMockHostOptions;
+                    }
+
+                    @Override
                     public void execCommand(IScheduledInvocationListener listener, String[] args)
                             throws ConfigurationException, NoDeviceException {
                         ArrayList<String> execCmdArgs = new ArrayList<>();
@@ -465,10 +474,11 @@
                                                 Integer.toString(1))),
                                 EasyMock.capture(capture)))
                 .andReturn(buildHttpResponse(product1Response.toString()));
-        EasyMock.expect(mMockDeviceManager.getAvailableFlashingPermits()).andReturn(1);
+        EasyMock.expect(mMockHostOptions.getAvailablePermits(PermitLimitType.CONCURRENT_FLASHER))
+                .andReturn(1);
 
         // Actually fetch commands
-        EasyMock.replay(mMockApiHelper, mMockEventUploader, mMockDeviceManager);
+        EasyMock.replay(mMockApiHelper, mMockEventUploader, mMockDeviceManager, mMockHostOptions);
         final List<ClusterCommand> commands = mScheduler.fetchHostCommands(deviceMap);
         assertEquals(1, commands.size());
         ClusterCommand command = commands.get(0);
diff --git a/javatests/com/android/tradefed/config/ConfigurationTest.java b/javatests/com/android/tradefed/config/ConfigurationTest.java
index 6483253..ad85694 100644
--- a/javatests/com/android/tradefed/config/ConfigurationTest.java
+++ b/javatests/com/android/tradefed/config/ConfigurationTest.java
@@ -15,7 +15,15 @@
  */
 package com.android.tradefed.config;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 
 import com.android.ddmlib.Log.LogLevel;
 import com.android.tradefed.build.BuildRetrievalError;
@@ -36,9 +44,10 @@
 import com.android.tradefed.util.FileUtil;
 import com.android.tradefed.util.IDisableable;
 
-import junit.framework.TestCase;
-
-import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -52,10 +61,9 @@
 import java.util.List;
 import java.util.Map;
 
-/**
- * Unit tests for {@link Configuration}.
- */
-public class ConfigurationTest extends TestCase {
+/** Unit tests for {@link Configuration}. */
+@RunWith(JUnit4.class)
+public class ConfigurationTest {
 
     private static final String CONFIG_NAME = "name";
     private static final String CONFIG_DESCRIPTION = "config description";
@@ -64,9 +72,7 @@
     private static final String OPTION_NAME = "bool";
     private static final String ALT_OPTION_NAME = "map";
 
-    /**
-     * Interface for test object stored in a {@link IConfiguration}.
-     */
+    /** Interface for test object stored in a {@link IConfiguration}. */
     private static interface TestConfig {
 
         public boolean getBool();
@@ -107,12 +113,9 @@
 
     private Configuration mConfig;
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    /** {@inheritDoc} */
+    @Before
+    public void setUp() throws Exception {
         mConfig = new Configuration(CONFIG_NAME, CONFIG_DESCRIPTION);
 
         try {
@@ -122,9 +125,10 @@
     }
 
     /**
-     * Test that {@link Configuration#getConfigurationObject(String)} can retrieve
-     * a previously stored object.
+     * Test that {@link Configuration#getConfigurationObject(String)} can retrieve a previously
+     * stored object.
      */
+    @Test
     public void testGetConfigurationObject() throws ConfigurationException {
         TestConfigObject testConfigObject = new TestConfigObject();
         mConfig.setConfigurationObject(CONFIG_OBJECT_TYPE_NAME, testConfigObject);
@@ -132,23 +136,23 @@
         assertEquals(testConfigObject, fromConfig);
     }
 
-    /**
-     * Test {@link Configuration#getConfigurationObjectList(String)}
-     */
+    /** Test {@link Configuration#getConfigurationObjectList(String)} */
     @SuppressWarnings("unchecked")
-    public void testGetConfigurationObjectList() throws ConfigurationException  {
+    @Test
+    public void testGetConfigurationObjectList() throws ConfigurationException {
         TestConfigObject testConfigObject = new TestConfigObject();
         mConfig.setConfigurationObject(CONFIG_OBJECT_TYPE_NAME, testConfigObject);
-        List<TestConfig> configList = (List<TestConfig>)mConfig.getConfigurationObjectList(
-                CONFIG_OBJECT_TYPE_NAME);
+        List<TestConfig> configList =
+                (List<TestConfig>) mConfig.getConfigurationObjectList(CONFIG_OBJECT_TYPE_NAME);
         assertEquals(testConfigObject, configList.get(0));
     }
 
     /**
-     * Test that {@link Configuration#getConfigurationObject(String)} with a name that does
-     * not exist.
+     * Test that {@link Configuration#getConfigurationObject(String)} with a name that does not
+     * exist.
      */
-    public void testGetConfigurationObject_wrongname()  {
+    @Test
+    public void testGetConfigurationObject_wrongname() {
         assertNull(mConfig.getConfigurationObject("non-existent"));
     }
 
@@ -156,7 +160,8 @@
      * Test that calling {@link Configuration#getConfigurationObject(String)} for a built-in config
      * type that supports lists.
      */
-    public void testGetConfigurationObject_typeIsList()  {
+    @Test
+    public void testGetConfigurationObject_typeIsList() {
         try {
             mConfig.getConfigurationObject(Configuration.TEST_TYPE_NAME);
             fail("IllegalStateException not thrown");
@@ -166,10 +171,11 @@
     }
 
     /**
-     * Test that calling {@link Configuration#getConfigurationObject(String)} for a config type
-     * that is a list.
+     * Test that calling {@link Configuration#getConfigurationObject(String)} for a config type that
+     * is a list.
      */
-    public void testGetConfigurationObject_forList() throws ConfigurationException  {
+    @Test
+    public void testGetConfigurationObject_forList() throws ConfigurationException {
         List<TestConfigObject> list = new ArrayList<TestConfigObject>();
         list.add(new TestConfigObject());
         list.add(new TestConfigObject());
@@ -186,7 +192,8 @@
      * Test that setConfigurationObject throws a ConfigurationException when config object provided
      * is not the correct type
      */
-    public void testSetConfigurationObject_wrongtype()  {
+    @Test
+    public void testSetConfigurationObject_wrongtype() {
         try {
             // arbitrarily, use the "Test" type as expected type
             mConfig.setConfigurationObject(Configuration.TEST_TYPE_NAME, new TestConfigObject());
@@ -197,17 +204,19 @@
     }
 
     /**
-     * Test {@link Configuration#getConfigurationObjectList(String)} when config object
-     * with given name does not exist.
+     * Test {@link Configuration#getConfigurationObjectList(String)} when config object with given
+     * name does not exist.
      */
+    @Test
     public void testGetConfigurationObjectList_wrongname() {
         assertNull(mConfig.getConfigurationObjectList("non-existent"));
     }
 
     /**
-     * Test {@link Configuration#setConfigurationObjectList(String, List)} when config object
-     * is the wrong type
+     * Test {@link Configuration#setConfigurationObjectList(String, List)} when config object is the
+     * wrong type
      */
+    @Test
     public void testSetConfigurationObjectList_wrongtype() {
         try {
             List<TestConfigObject> myList = new ArrayList<TestConfigObject>(1);
@@ -220,120 +229,112 @@
         }
     }
 
-    /**
-     * Test method for {@link Configuration#getBuildProvider()}.
-     */
+    /** Test method for {@link Configuration#getBuildProvider()}. */
+    @Test
     public void testGetBuildProvider() throws BuildRetrievalError {
         // check that the default provider is present and doesn't blow up
         assertNotNull(mConfig.getBuildProvider().getBuild());
         // check set and get
-        final IBuildProvider provider = EasyMock.createMock(IBuildProvider.class);
+        final IBuildProvider provider = mock(IBuildProvider.class);
         mConfig.setBuildProvider(provider);
         assertEquals(provider, mConfig.getBuildProvider());
     }
 
-    /**
-     * Test method for {@link Configuration#getTargetPreparers()}.
-     */
+    /** Test method for {@link Configuration#getTargetPreparers()}. */
+    @Test
     public void testGetTargetPreparers() throws Exception {
         // check that the callback is working and doesn't blow up
         assertEquals(0, mConfig.getTargetPreparers().size());
         // test set and get
-        final ITargetPreparer prep = EasyMock.createMock(ITargetPreparer.class);
+        final ITargetPreparer prep = mock(ITargetPreparer.class);
         mConfig.setTargetPreparer(prep);
         assertEquals(prep, mConfig.getTargetPreparers().get(0));
     }
 
-    /**
-     * Test method for {@link Configuration#getTests()}.
-     */
+    /** Test method for {@link Configuration#getTests()}. */
+    @Test
     public void testGetTests() throws DeviceNotAvailableException {
         // check that the default test is present and doesn't blow up
         mConfig.getTests()
                 .get(0)
                 .run(TestInformation.newBuilder().build(), new TextResultReporter());
-        IRemoteTest test1 = EasyMock.createMock(IRemoteTest.class);
+        IRemoteTest test1 = mock(IRemoteTest.class);
         mConfig.setTest(test1);
         assertEquals(test1, mConfig.getTests().get(0));
     }
 
-    /**
-     * Test method for {@link Configuration#getDeviceRecovery()}.
-     */
+    /** Test method for {@link Configuration#getDeviceRecovery()}. */
+    @Test
     public void testGetDeviceRecovery() {
         // check that the default recovery is present
         assertNotNull(mConfig.getDeviceRecovery());
-        final IDeviceRecovery recovery = EasyMock.createMock(IDeviceRecovery.class);
+        final IDeviceRecovery recovery = mock(IDeviceRecovery.class);
         mConfig.setDeviceRecovery(recovery);
         assertEquals(recovery, mConfig.getDeviceRecovery());
     }
 
-    /**
-     * Test method for {@link Configuration#getLogOutput()}.
-     */
+    /** Test method for {@link Configuration#getLogOutput()}. */
+    @Test
     public void testGetLogOutput() {
         // check that the default logger is present and doesn't blow up
         mConfig.getLogOutput().printLog(LogLevel.INFO, "testGetLogOutput", "test");
-        final ILeveledLogOutput logger = EasyMock.createMock(ILeveledLogOutput.class);
+        final ILeveledLogOutput logger = mock(ILeveledLogOutput.class);
         mConfig.setLogOutput(logger);
         assertEquals(logger, mConfig.getLogOutput());
     }
 
     /**
      * Test method for {@link Configuration#getTestInvocationListeners()}.
+     *
      * @throws ConfigurationException
      */
+    @Test
     public void testGetTestInvocationListeners() throws ConfigurationException {
         // check that the default listener is present and doesn't blow up
         ITestInvocationListener defaultListener = mConfig.getTestInvocationListeners().get(0);
         defaultListener.invocationStarted(new InvocationContext());
         defaultListener.invocationEnded(1);
 
-        final ITestInvocationListener listener1 = EasyMock.createMock(
-                ITestInvocationListener.class);
+        final ITestInvocationListener listener1 = mock(ITestInvocationListener.class);
         mConfig.setTestInvocationListener(listener1);
         assertEquals(listener1, mConfig.getTestInvocationListeners().get(0));
     }
 
-    /**
-     * Test method for {@link Configuration#getCommandOptions()}.
-     */
+    /** Test method for {@link Configuration#getCommandOptions()}. */
+    @Test
     public void testGetCommandOptions() {
         // check that the default object is present
         assertNotNull(mConfig.getCommandOptions());
-        final ICommandOptions cmdOptions = EasyMock.createMock(ICommandOptions.class);
+        final ICommandOptions cmdOptions = mock(ICommandOptions.class);
         mConfig.setCommandOptions(cmdOptions);
         assertEquals(cmdOptions, mConfig.getCommandOptions());
     }
 
-    /**
-     * Test method for {@link Configuration#getDeviceRequirements()}.
-     */
+    /** Test method for {@link Configuration#getDeviceRequirements()}. */
+    @Test
     public void testGetDeviceRequirements() {
         // check that the default object is present
         assertNotNull(mConfig.getDeviceRequirements());
-        final IDeviceSelection deviceSelection = EasyMock.createMock(
-                IDeviceSelection.class);
+        final IDeviceSelection deviceSelection = mock(IDeviceSelection.class);
         mConfig.setDeviceRequirements(deviceSelection);
         assertEquals(deviceSelection, mConfig.getDeviceRequirements());
     }
 
     /**
-     * Test {@link Configuration#setConfigurationObject(String, Object)} with a
-     * {@link IConfigurationReceiver}
+     * Test {@link Configuration#setConfigurationObject(String, Object)} with a {@link
+     * IConfigurationReceiver}
      */
+    @Test
     public void testSetConfigurationObject_configReceiver() throws ConfigurationException {
-        final IConfigurationReceiver mockConfigReceiver = EasyMock.createMock(
-                IConfigurationReceiver.class);
-        mockConfigReceiver.setConfiguration(mConfig);
-        EasyMock.replay(mockConfigReceiver);
+        final IConfigurationReceiver mockConfigReceiver = mock(IConfigurationReceiver.class);
+
         mConfig.setConfigurationObject("example", mockConfigReceiver);
-        EasyMock.verify(mockConfigReceiver);
+
+        verify(mockConfigReceiver).setConfiguration(mConfig);
     }
 
-    /**
-     * Test {@link Configuration#injectOptionValue(String, String)}
-     */
+    /** Test {@link Configuration#injectOptionValue(String, String)} */
+    @Test
     public void testInjectOptionValue() throws ConfigurationException {
         TestConfigObject testConfigObject = new TestConfigObject();
         mConfig.setConfigurationObject(CONFIG_OBJECT_TYPE_NAME, testConfigObject);
@@ -344,9 +345,8 @@
         assertEquals(OPTION_NAME, optionDef.name);
     }
 
-    /**
-     * Test {@link Configuration#injectOptionValue(String, String, String)}
-     */
+    /** Test {@link Configuration#injectOptionValue(String, String, String)} */
+    @Test
     public void testInjectMapOptionValue() throws ConfigurationException {
         final String key = "hello";
 
@@ -362,9 +362,10 @@
     }
 
     /**
-     * Test {@link Configuration#injectOptionValue(String, String)} is throwing an exception
-     * for map options without no map key provided in the option value
+     * Test {@link Configuration#injectOptionValue(String, String)} is throwing an exception for map
+     * options without no map key provided in the option value
      */
+    @Test
     public void testInjectParsedMapOptionValueNoKey() throws ConfigurationException {
         TestConfigObject testConfigObject = new TestConfigObject();
         mConfig.setConfigurationObject(CONFIG_OBJECT_TYPE_NAME, testConfigObject);
@@ -379,9 +380,10 @@
     }
 
     /**
-     * Test {@link Configuration#injectOptionValue(String, String)} is throwing an exception
-     * for map options with ambiguous map key provided in the option value (multiple equal signs)
+     * Test {@link Configuration#injectOptionValue(String, String)} is throwing an exception for map
+     * options with ambiguous map key provided in the option value (multiple equal signs)
      */
+    @Test
     public void testInjectParsedMapOptionValueAmbiguousKey() throws ConfigurationException {
         TestConfigObject testConfigObject = new TestConfigObject();
         mConfig.setConfigurationObject(CONFIG_OBJECT_TYPE_NAME, testConfigObject);
@@ -398,6 +400,7 @@
     /**
      * Test {@link Configuration#injectOptionValue(String, String)} is correctly parsing map options
      */
+    @Test
     public void testInjectParsedMapOptionValue() throws ConfigurationException {
         final String key = "hello\\=key";
 
@@ -412,9 +415,8 @@
         assertTrue(map.get(key));
     }
 
-    /**
-     * Test {@link Configuration#injectOptionValues(List)}
-     */
+    /** Test {@link Configuration#injectOptionValues(List)} */
+    @Test
     public void testInjectOptionValues() throws ConfigurationException {
         final String key = "hello";
         List<OptionDef> options = new ArrayList<>();
@@ -435,9 +437,8 @@
         assertEquals(OPTION_NAME, optionDef.name);
     }
 
-    /**
-     * Basic test for {@link Configuration#printCommandUsage(boolean, java.io.PrintStream)}.
-     */
+    /** Basic test for {@link Configuration#printCommandUsage(boolean, java.io.PrintStream)}. */
+    @Test
     public void testPrintCommandUsage() throws ConfigurationException {
         TestConfigObject testConfigObject = new TestConfigObject();
         mConfig.setConfigurationObject(CONFIG_OBJECT_TYPE_NAME, testConfigObject);
@@ -450,23 +451,27 @@
         // all expected names are present
         final String usageString = outputStream.toString();
         assertTrue("Usage text does not contain config name", usageString.contains(CONFIG_NAME));
-        assertTrue("Usage text does not contain config description", usageString.contains(
-                CONFIG_DESCRIPTION));
-        assertTrue("Usage text does not contain object name", usageString.contains(
-                CONFIG_OBJECT_TYPE_NAME));
+        assertTrue(
+                "Usage text does not contain config description",
+                usageString.contains(CONFIG_DESCRIPTION));
+        assertTrue(
+                "Usage text does not contain object name",
+                usageString.contains(CONFIG_OBJECT_TYPE_NAME));
         assertTrue("Usage text does not contain option name", usageString.contains(OPTION_NAME));
-        assertTrue("Usage text does not contain option description",
+        assertTrue(
+                "Usage text does not contain option description",
                 usageString.contains(OPTION_DESCRIPTION));
 
         // ensure help prints out options from default config types
-        assertTrue("Usage text does not contain --serial option name",
-                usageString.contains("serial"));
+        assertTrue(
+                "Usage text does not contain --serial option name", usageString.contains("serial"));
     }
 
     /**
-     * Test that {@link Configuration#validateOptions()} doesn't throw when all mandatory fields
-     * are set.
+     * Test that {@link Configuration#validateOptions()} doesn't throw when all mandatory fields are
+     * set.
      */
+    @Test
     public void testValidateOptions() throws ConfigurationException {
         mConfig.validateOptions();
     }
@@ -475,6 +480,7 @@
      * Test that {@link Configuration#validateOptions()} throw when all mandatory fields are not set
      * and object is not disabled.
      */
+    @Test
     public void testValidateOptions_nonDisabledObject() throws ConfigurationException {
         TestConfigObject object = new TestConfigObject();
         object.setDisable(false);
@@ -491,6 +497,7 @@
      * Test that {@link Configuration#validateOptions()} doesn't throw when all mandatory fields are
      * not set but the object is disabled.
      */
+    @Test
     public void testValidateOptions_disabledObject() throws ConfigurationException {
         TestConfigObject object = new TestConfigObject();
         object.setDisable(true);
@@ -499,63 +506,72 @@
     }
 
     /**
-     * Test that {@link Configuration#validateOptions()} throws a config exception when shard
-     * count is negative number.
+     * Test that {@link Configuration#validateOptions()} throws a config exception when shard count
+     * is negative number.
      */
+    @Test
     public void testValidateOptionsShardException() throws ConfigurationException {
-        ICommandOptions option = new CommandOptions() {
-            @Override
-            public Integer getShardCount() {return -1;}
-        };
+        ICommandOptions option =
+                new CommandOptions() {
+                    @Override
+                    public Integer getShardCount() {
+                        return -1;
+                    }
+                };
         mConfig.setConfigurationObject(Configuration.CMD_OPTIONS_TYPE_NAME, option);
         try {
             mConfig.validateOptions();
             fail("Should have thrown an exception.");
-        } catch(ConfigurationException expected) {
+        } catch (ConfigurationException expected) {
             assertEquals("a shard count must be a positive number", expected.getMessage());
         }
     }
 
     /**
-     * Test that {@link Configuration#validateOptions()} throws a config exception when shard
-     * index is not valid.
+     * Test that {@link Configuration#validateOptions()} throws a config exception when shard index
+     * is not valid.
      */
+    @Test
     public void testValidateOptionsShardIndexException() throws ConfigurationException {
-        ICommandOptions option = new CommandOptions() {
-            @Override
-            public Integer getShardIndex() {
-                return -1;
-            }
-        };
+        ICommandOptions option =
+                new CommandOptions() {
+                    @Override
+                    public Integer getShardIndex() {
+                        return -1;
+                    }
+                };
         mConfig.setConfigurationObject(Configuration.CMD_OPTIONS_TYPE_NAME, option);
         try {
             mConfig.validateOptions();
             fail("Should have thrown an exception.");
-        } catch(ConfigurationException expected) {
+        } catch (ConfigurationException expected) {
             assertEquals("a shard index must be in range [0, shard count)", expected.getMessage());
         }
     }
 
     /**
-     * Test that {@link Configuration#validateOptions()} throws a config exception when shard
-     * index is above the shard count.
+     * Test that {@link Configuration#validateOptions()} throws a config exception when shard index
+     * is above the shard count.
      */
+    @Test
     public void testValidateOptionsShardIndexAboveShardCount() throws ConfigurationException {
-        ICommandOptions option = new CommandOptions() {
-            @Override
-            public Integer getShardIndex() {
-                return 3;
-            }
-            @Override
-            public Integer getShardCount() {
-                return 2;
-            }
-        };
+        ICommandOptions option =
+                new CommandOptions() {
+                    @Override
+                    public Integer getShardIndex() {
+                        return 3;
+                    }
+
+                    @Override
+                    public Integer getShardCount() {
+                        return 2;
+                    }
+                };
         mConfig.setConfigurationObject(Configuration.CMD_OPTIONS_TYPE_NAME, option);
         try {
             mConfig.validateOptions();
             fail("Should have thrown an exception.");
-        } catch(ConfigurationException expected) {
+        } catch (ConfigurationException expected) {
             assertEquals("a shard index must be in range [0, shard count)", expected.getMessage());
         }
     }
@@ -565,6 +581,7 @@
      * sharding. If that was the case, the downloaded files would be cleaned up right after the
      * shards are kicked-off in new invocations.
      */
+    @Test
     public void testValidateOptions_localSharding_skipDownload() throws Exception {
         mConfig =
                 new Configuration(CONFIG_NAME, CONFIG_DESCRIPTION) {
@@ -589,9 +606,8 @@
         assertEquals(fakeConfigFile, deviceOptions.getAvdConfigFile());
     }
 
-    /**
-     * Test that {@link Configuration#dumpXml(PrintWriter)} produce the xml output.
-     */
+    /** Test that {@link Configuration#dumpXml(PrintWriter)} produce the xml output. */
+    @Test
     public void testDumpXml() throws IOException {
         File test = FileUtil.createTempFile("dumpxml", "xml");
         try {
@@ -611,6 +627,7 @@
      * Test that {@link Configuration#dumpXml(PrintWriter)} produce the xml output without objects
      * that have been filtered.
      */
+    @Test
     public void testDumpXml_withFilter() throws IOException {
         File test = FileUtil.createTempFile("dumpxml", "xml");
         try {
@@ -632,6 +649,7 @@
      * Test that {@link Configuration#dumpXml(PrintWriter)} produce the xml output even for a multi
      * device situation.
      */
+    @Test
     public void testDumpXml_multi_device() throws Exception {
         List<IDeviceConfiguration> deviceObjectList = new ArrayList<IDeviceConfiguration>();
         deviceObjectList.add(new DeviceConfigurationHolder("device1"));
@@ -655,6 +673,7 @@
      * Test that {@link Configuration#dumpXml(PrintWriter)} produce the xml output even for a multi
      * device situation when one of the device is fake.
      */
+    @Test
     public void testDumpXml_multi_device_fake() throws Exception {
         List<IDeviceConfiguration> deviceObjectList = new ArrayList<IDeviceConfiguration>();
         deviceObjectList.add(new DeviceConfigurationHolder("device1", true));
@@ -675,6 +694,7 @@
     }
 
     /** Ensure that the dump xml only considere trully changed option on the same object. */
+    @Test
     public void testDumpChangedOption() throws Exception {
         CommandOptions options1 = new CommandOptions();
         Configuration one = new Configuration("test", "test");
@@ -707,6 +727,7 @@
     }
 
     /** Ensure we print modified option if they are structures. */
+    @Test
     public void testDumpChangedOption_structure() throws Exception {
         CommandOptions options1 = new CommandOptions();
         Configuration one = new Configuration("test", "test");
@@ -734,6 +755,7 @@
                         "<option name=\"auto-collect\" value=\"LOGCAT_ON_FAILURE\" />"));
     }
 
+    @Test
     public void testDeepClone() throws Exception {
         Configuration original =
                 (Configuration)
@@ -755,6 +777,7 @@
         copy.validateOptions();
     }
 
+    @Test
     public void testDeepClone_innerDevice() throws Exception {
         Configuration original =
                 (Configuration)
diff --git a/javatests/com/android/tradefed/config/SandboxConfigurationFactoryTest.java b/javatests/com/android/tradefed/config/SandboxConfigurationFactoryTest.java
index 2591f0b..a9548cb 100644
--- a/javatests/com/android/tradefed/config/SandboxConfigurationFactoryTest.java
+++ b/javatests/com/android/tradefed/config/SandboxConfigurationFactoryTest.java
@@ -15,13 +15,12 @@
  */
 package com.android.tradefed.config;
 
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.contains;
-import static org.easymock.EasyMock.endsWith;
-import static org.easymock.EasyMock.eq;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import com.android.tradefed.build.StubBuildProvider;
 import com.android.tradefed.config.proxy.AutomatedReporters;
@@ -36,13 +35,14 @@
 import com.android.tradefed.util.IRunUtil.EnvPriority;
 import com.android.tradefed.util.keystore.StubKeyStoreClient;
 
-import org.easymock.EasyMock;
-import org.easymock.IAnswer;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 
 import java.io.File;
 import java.io.IOException;
@@ -54,15 +54,16 @@
 
     private SandboxConfigurationFactory mFactory;
     private File mConfig;
-    private ISandbox mFakeSandbox;
-    private IRunUtil mMockRunUtil;
+    @Mock ISandbox mFakeSandbox;
+    @Mock IRunUtil mMockRunUtil;
 
     @Before
     public void setUp() throws IOException, ConfigurationException {
+        MockitoAnnotations.initMocks(this);
+
         mFactory = SandboxConfigurationFactory.getInstance();
         mConfig = FileUtil.createTempFile("sandbox-config-test", ".xml");
-        mFakeSandbox = EasyMock.createMock(ISandbox.class);
-        mMockRunUtil = EasyMock.createMock(IRunUtil.class);
+
         try {
             GlobalConfiguration.createGlobalConfiguration(new String[] {});
         } catch (IllegalStateException ignore) {
@@ -76,28 +77,24 @@
     }
 
     private void expectDumpCmd(CommandResult res) {
-        EasyMock.expect(
-                        mMockRunUtil.runTimedCmd(
-                                EasyMock.anyLong(),
-                                endsWith("/java"),
-                                contains("-Djava.io.tmpdir="),
-                                eq("-cp"),
-                                anyObject(),
-                                eq(SandboxConfigDump.class.getCanonicalName()),
-                                eq(DumpCmd.NON_VERSIONED_CONFIG.toString()),
-                                EasyMock.anyObject(),
-                                eq(mConfig.getAbsolutePath())))
-                .andAnswer(
-                        new IAnswer<CommandResult>() {
-                            @Override
-                            public CommandResult answer() throws Throwable {
-                                String resFile = (String) EasyMock.getCurrentArguments()[7];
-                                FileUtil.writeToFile(
-                                        "<configuration><test class=\"com.android.tradefed.test"
-                                                + "type.StubTest\" /></configuration>",
-                                        new File(resFile));
-                                return res;
-                            }
+        when(mMockRunUtil.runTimedCmd(
+                        Mockito.anyLong(),
+                        Mockito.endsWith("/java"),
+                        Mockito.contains("-Djava.io.tmpdir="),
+                        Mockito.eq("-cp"),
+                        Mockito.any(),
+                        Mockito.eq(SandboxConfigDump.class.getCanonicalName()),
+                        Mockito.eq(DumpCmd.NON_VERSIONED_CONFIG.toString()),
+                        Mockito.any(),
+                        Mockito.eq(mConfig.getAbsolutePath())))
+                .thenAnswer(
+                        invocation -> {
+                            String resFile = (String) invocation.getArguments()[7];
+                            FileUtil.writeToFile(
+                                    "<configuration><test class=\"com.android.tradefed.test"
+                                            + "type.StubTest\" /></configuration>",
+                                    new File(resFile));
+                            return res;
                         });
     }
 
@@ -107,21 +104,23 @@
     @Test
     public void testCreateConfigurationFromArgs() throws ConfigurationException {
         String[] args = new String[] {mConfig.getAbsolutePath()};
-        mMockRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE);
-        EasyMock.expectLastCall().times(2);
-        mMockRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_SERVER_CONFIG_VARIABLE);
-        mMockRunUtil.unsetEnvVariable(AutomatedReporters.PROTO_REPORTING_PORT);
-        mMockRunUtil.setEnvVariable(
-                EasyMock.eq(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE), EasyMock.anyObject());
-        mMockRunUtil.setEnvVariablePriority(EnvPriority.SET);
+
         CommandResult results = new CommandResult();
         results.setStatus(CommandStatus.SUCCESS);
         expectDumpCmd(results);
-        EasyMock.replay(mFakeSandbox, mMockRunUtil);
+
         IConfiguration config =
                 mFactory.createConfigurationFromArgs(
                         args, new StubKeyStoreClient(), mFakeSandbox, mMockRunUtil);
-        EasyMock.verify(mFakeSandbox, mMockRunUtil);
+
+        verify(mMockRunUtil, times(2)).unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE);
+        verify(mMockRunUtil)
+                .unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_SERVER_CONFIG_VARIABLE);
+        verify(mMockRunUtil).unsetEnvVariable(AutomatedReporters.PROTO_REPORTING_PORT);
+        verify(mMockRunUtil)
+                .setEnvVariable(
+                        Mockito.eq(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE), Mockito.any());
+        verify(mMockRunUtil).setEnvVariablePriority(EnvPriority.SET);
         assertNotNull(config.getConfigurationObject(Configuration.SANDBOX_TYPE_NAME));
         assertEquals(mFakeSandbox, config.getConfigurationObject(Configuration.SANDBOX_TYPE_NAME));
     }
@@ -130,26 +129,17 @@
     @Test
     public void testCreateConfigurationFromArgs_fail() throws Exception {
         String[] args = new String[] {mConfig.getAbsolutePath()};
-        mMockRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE);
-        EasyMock.expectLastCall().times(2);
-        mMockRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_SERVER_CONFIG_VARIABLE);
-        mMockRunUtil.unsetEnvVariable(AutomatedReporters.PROTO_REPORTING_PORT);
-        mMockRunUtil.setEnvVariable(
-                EasyMock.eq(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE), EasyMock.anyObject());
-        mMockRunUtil.setEnvVariablePriority(EnvPriority.SET);
+
         CommandResult results = new CommandResult();
         results.setStatus(CommandStatus.FAILED);
         results.setStderr("I failed");
         expectDumpCmd(results);
         // Thin launcher is attempted, and in this case fails, so original exception is thrown.
-        EasyMock.expect(
-                        mFakeSandbox.createThinLauncherConfig(
-                                EasyMock.anyObject(), EasyMock.anyObject(),
-                                EasyMock.anyObject(), EasyMock.anyObject()))
-                .andReturn(null);
-        // in case of failure, tearDown is called right away for cleaning up
-        mFakeSandbox.tearDown();
-        EasyMock.replay(mFakeSandbox, mMockRunUtil);
+        when(mFakeSandbox.createThinLauncherConfig(
+                        Mockito.any(), Mockito.any(),
+                        Mockito.any(), Mockito.any()))
+                .thenReturn(null);
+
         try {
             mFactory.createConfigurationFromArgs(
                     args, new StubKeyStoreClient(), mFakeSandbox, mMockRunUtil);
@@ -157,7 +147,17 @@
         } catch (SandboxConfigurationException expected) {
             // expected
         }
-        EasyMock.verify(mFakeSandbox, mMockRunUtil);
+
+        verify(mMockRunUtil, times(2)).unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE);
+        verify(mMockRunUtil)
+                .unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_SERVER_CONFIG_VARIABLE);
+        verify(mMockRunUtil).unsetEnvVariable(AutomatedReporters.PROTO_REPORTING_PORT);
+        verify(mMockRunUtil)
+                .setEnvVariable(
+                        Mockito.eq(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE), Mockito.any());
+        verify(mMockRunUtil).setEnvVariablePriority(EnvPriority.SET);
+        // in case of failure, tearDown is called right away for cleaning up
+        verify(mFakeSandbox).tearDown();
     }
 
     @Test
diff --git a/javatests/com/android/tradefed/config/filter/CommandOptionsGetterTest.java b/javatests/com/android/tradefed/config/filter/CommandOptionsGetterTest.java
index 23bcd0c..40593a3 100644
--- a/javatests/com/android/tradefed/config/filter/CommandOptionsGetterTest.java
+++ b/javatests/com/android/tradefed/config/filter/CommandOptionsGetterTest.java
@@ -47,7 +47,9 @@
     }
 
     @Test
-    public void getCommandOptionsValue() {
+    public void getCommandOptionsValue() throws Exception {
+        OptionSetter setter = new OptionSetter(mConfiguration.getCommandOptions());
+        setter.setOptionValue("filter-previous-passed", "false");
         FeatureResponse response = mGetter.execute(FeatureRequest.newBuilder()
                 .setName(CommandOptionsGetter.COMMAND_OPTIONS_GETTER)
                 .putArgs(CommandOptionsGetter.OPTION_NAME, "filter-previous-passed").build());
diff --git a/javatests/com/android/tradefed/device/DeviceManagerTest.java b/javatests/com/android/tradefed/device/DeviceManagerTest.java
index c000a22..ed66f17 100644
--- a/javatests/com/android/tradefed/device/DeviceManagerTest.java
+++ b/javatests/com/android/tradefed/device/DeviceManagerTest.java
@@ -38,7 +38,6 @@
 import com.android.tradefed.util.CommandStatus;
 import com.android.tradefed.util.FileUtil;
 import com.android.tradefed.util.IRunUtil;
-import com.android.tradefed.util.RunUtil;
 import com.android.tradefed.util.ZipUtil;
 
 import org.easymock.Capture;
@@ -56,7 +55,6 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
 /** Unit tests for {@link DeviceManager}. */
@@ -1393,123 +1391,6 @@
         verifyMocks(mockMonitor);
     }
 
-    /** Ensure that the flasher instance limiting machinery is working as expected. */
-    @Test
-    public void testFlashLimit() throws Exception {
-        setCheckAvailableDeviceExpectations();
-        replayMocks();
-        final DeviceManager manager = createDeviceManager(null, mMockIDevice);
-        try {
-            Thread waiter = new Thread() {
-                @Override
-                public void run() {
-                    manager.takeFlashingPermit();
-                    manager.returnFlashingPermit();
-                }
-            };
-            EasyMock.expect(mMockHostOptions.getConcurrentFlasherLimit())
-                .andReturn(null).anyTimes();
-            EasyMock.replay(mMockHostOptions);
-            manager.setConcurrentFlashSettings(new Semaphore(1), true);
-            // take the permit; the next attempt to take the permit should block
-            manager.takeFlashingPermit();
-            assertFalse(manager.getConcurrentFlashLock().hasQueuedThreads());
-
-            waiter.start();
-            RunUtil.getDefault().sleep(200); // Thread start should take <200ms
-            assertTrue("Invalid state: waiter thread is not alive", waiter.isAlive());
-            assertTrue("No queued threads", manager.getConcurrentFlashLock().hasQueuedThreads());
-
-            manager.returnFlashingPermit();
-            RunUtil.getDefault().sleep(200); // Thread start should take <200ms
-            assertFalse("Unexpected queued threads",
-                    manager.getConcurrentFlashLock().hasQueuedThreads());
-
-            waiter.join(1000);
-            assertFalse("waiter thread has not returned", waiter.isAlive());
-        } finally {
-            // Attempt to reset concurrent flash settings to defaults
-            manager.setConcurrentFlashSettings(null, true);
-        }
-    }
-
-    /** Ensure that the flasher limiting respects {@link IHostOptions}. */
-    @Test
-    public void testFlashLimit_withHostOptions() throws Exception {
-        setCheckAvailableDeviceExpectations();
-        replayMocks();
-        final DeviceManager manager = createDeviceManager(null, mMockIDevice);
-        try {
-            Thread waiter = new Thread() {
-                @Override
-                public void run() {
-                    manager.takeFlashingPermit();
-                    manager.returnFlashingPermit();
-                }
-            };
-            EasyMock.expect(mMockHostOptions.getConcurrentFlasherLimit()).andReturn(1).anyTimes();
-            EasyMock.replay(mMockHostOptions);
-            // take the permit; the next attempt to take the permit should block
-            manager.takeFlashingPermit();
-            assertFalse(manager.getConcurrentFlashLock().hasQueuedThreads());
-
-            waiter.start();
-            RunUtil.getDefault().sleep(100);  // Thread start should take <100ms
-            assertTrue("Invalid state: waiter thread is not alive", waiter.isAlive());
-            assertTrue("No queued threads", manager.getConcurrentFlashLock().hasQueuedThreads());
-
-            manager.returnFlashingPermit();
-            RunUtil.getDefault().sleep(100);  // Thread start should take <100ms
-            assertFalse("Unexpected queued threads",
-                    manager.getConcurrentFlashLock().hasQueuedThreads());
-
-            waiter.join(1000);
-            assertFalse("waiter thread has not returned", waiter.isAlive());
-            EasyMock.verify(mMockHostOptions);
-        } finally {
-            // Attempt to reset concurrent flash settings to defaults
-            manager.setConcurrentFlashSettings(null, true);
-        }
-    }
-
-    /** Ensure that the flasher instance limiting machinery is working as expected. */
-    @Test
-    public void testUnlimitedFlashLimit() throws Exception {
-        setCheckAvailableDeviceExpectations();
-        replayMocks();
-        final DeviceManager manager = createDeviceManager(null, mMockIDevice);
-        try {
-            Thread waiter = new Thread() {
-                @Override
-                public void run() {
-                    manager.takeFlashingPermit();
-                    manager.returnFlashingPermit();
-                }
-            };
-            manager.setConcurrentFlashSettings(null, true);
-            // take a permit; the next attempt to take the permit should proceed without blocking
-            manager.takeFlashingPermit();
-            assertNull("Flash lock is non-null", manager.getConcurrentFlashLock());
-
-            waiter.start();
-            RunUtil.getDefault().sleep(100);  // Thread start should take <100ms
-            Thread.State waiterState = waiter.getState();
-            assertTrue("Invalid state: waiter thread hasn't started",
-                    waiter.isAlive() || Thread.State.TERMINATED.equals(waiterState));
-            assertNull("Flash lock is non-null", manager.getConcurrentFlashLock());
-
-            manager.returnFlashingPermit();
-            RunUtil.getDefault().sleep(100);  // Thread start should take <100ms
-            assertNull("Flash lock is non-null", manager.getConcurrentFlashLock());
-
-            waiter.join(1000);
-            assertFalse("waiter thread has not returned", waiter.isAlive());
-        } finally {
-            // Attempt to reset concurrent flash settings to defaults
-            manager.setConcurrentFlashSettings(null, true);
-        }
-    }
-
     /** Test the command fails without execution when the device is not available. */
     @Test
     public void testExecCmdOnAvailableDevice_deviceNotAvailable() {
diff --git a/javatests/com/android/tradefed/device/MockDeviceManager.java b/javatests/com/android/tradefed/device/MockDeviceManager.java
index d76dca7..52ced5b 100644
--- a/javatests/com/android/tradefed/device/MockDeviceManager.java
+++ b/javatests/com/android/tradefed/device/MockDeviceManager.java
@@ -438,21 +438,6 @@
     }
 
     @Override
-    public int getAvailableFlashingPermits() {
-        return 0;
-    }
-
-    @Override
-    public void takeFlashingPermit() {
-        // ignore
-    }
-
-    @Override
-    public void returnFlashingPermit() {
-        // ignore
-    }
-
-    @Override
     public CommandResult executeCmdOnAvailableDevice(
             String serial, String command, long timeout, TimeUnit timeUnit) {
         return null;
diff --git a/javatests/com/android/tradefed/device/MockitoFileUtil.java b/javatests/com/android/tradefed/device/MockitoFileUtil.java
new file mode 100644
index 0000000..0689c32
--- /dev/null
+++ b/javatests/com/android/tradefed/device/MockitoFileUtil.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2010 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 com.android.tradefed.device;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.android.ddmlib.FileListingService;
+
+import org.mockito.Mockito;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Helper class for mocking out device file system contents. Mockito verson of MockFileUtil (to be
+ * renamed back after all tests referencing MockFileUtil are converted to Mockito).
+ */
+public class MockitoFileUtil {
+
+    /**
+     * Helper method to mock out a remote filesystem contents
+     *
+     * @param mockDevice the mock {@link ITestDevice}
+     * @param rootPath the path to the root
+     * @param childNames the child file names of directory to simulate
+     * @throws DeviceNotAvailableException
+     */
+    public static void setMockDirContents(
+            ITestDevice mockDevice, String rootPath, String... childNames)
+            throws DeviceNotAvailableException {
+        IFileEntry rootEntry = mock(IFileEntry.class);
+        when(mockDevice.getFileEntry(rootPath)).thenReturn(rootEntry);
+        boolean isDir = childNames.length != 0;
+        when(rootEntry.isDirectory()).thenReturn(isDir);
+        when(rootEntry.getFullEscapedPath()).thenReturn(rootPath);
+        when(rootEntry.getName()).thenReturn(rootPath);
+        Collection<IFileEntry> mockChildren = new ArrayList<IFileEntry>(childNames.length);
+        for (String childName : childNames) {
+            IFileEntry childMockEntry = mock(IFileEntry.class);
+            when(childMockEntry.getName()).thenReturn(childName);
+            String fullPath = rootPath + FileListingService.FILE_SEPARATOR + childName;
+            when(childMockEntry.getFullEscapedPath()).thenReturn(fullPath);
+            when(childMockEntry.isDirectory()).thenReturn(Boolean.FALSE);
+            mockChildren.add(childMockEntry);
+        }
+        when(rootEntry.getChildren(Mockito.anyBoolean())).thenReturn(mockChildren);
+    }
+
+    /**
+     * Helper method to mock out a remote nested filesystem contents
+     *
+     * @param mockDevice the mock {@link ITestDevice}
+     * @param rootPath the path to the root
+     * @param pathSegments the nested file path to simulate. This method will mock out IFileEntry
+     *     objects to simulate a filesystem structure of rootPath/pathSegments
+     * @throws DeviceNotAvailableException
+     */
+    public static void setMockDirPath(
+            ITestDevice mockDevice, String rootPath, String... pathSegments)
+            throws DeviceNotAvailableException {
+        IFileEntry rootEntry = mock(IFileEntry.class);
+        when(mockDevice.getFileEntry(rootPath)).thenReturn(rootEntry);
+        when(rootEntry.getFullEscapedPath()).thenReturn(rootPath);
+        when(rootEntry.getName()).thenReturn(rootPath);
+        for (int i = 0; i < pathSegments.length; i++) {
+            IFileEntry childMockEntry = mock(IFileEntry.class);
+            when(childMockEntry.getName()).thenReturn(pathSegments[i]);
+            rootPath = rootPath + FileListingService.FILE_SEPARATOR + pathSegments[i];
+            when(childMockEntry.getFullEscapedPath()).thenReturn(rootPath);
+            Collection<IFileEntry> childrenResult = new ArrayList<IFileEntry>(1);
+            childrenResult.add(childMockEntry);
+            when(rootEntry.getChildren(Mockito.anyBoolean())).thenReturn(childrenResult);
+            when(rootEntry.isDirectory()).thenReturn(Boolean.TRUE);
+
+            rootEntry = childMockEntry;
+        }
+        // leaf node - not a directory
+        when(rootEntry.isDirectory()).thenReturn(Boolean.FALSE);
+    }
+}
diff --git a/javatests/com/android/tradefed/invoker/InvocationExecutionTest.java b/javatests/com/android/tradefed/invoker/InvocationExecutionTest.java
index 08e8f98..505ddc2 100644
--- a/javatests/com/android/tradefed/invoker/InvocationExecutionTest.java
+++ b/javatests/com/android/tradefed/invoker/InvocationExecutionTest.java
@@ -23,6 +23,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import com.android.tradefed.build.BuildInfo;
 import com.android.tradefed.config.Configuration;
@@ -53,7 +54,6 @@
 import com.android.tradefed.testtype.suite.TestSuiteStub;
 import com.android.tradefed.util.IDisableable;
 
-import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -107,16 +107,16 @@
     @Test
     public void testCleanUp() throws Exception {
         DeviceConfigurationHolder holder = new DeviceConfigurationHolder("default");
-        ITargetHostCleaner cleaner = EasyMock.createMock(ITargetHostCleaner.class);
+        ITargetHostCleaner cleaner = mock(ITargetHostCleaner.class);
         holder.addSpecificConfig(cleaner);
         mConfig.setDeviceConfig(holder);
-        mContext.addAllocatedDevice("default", EasyMock.createMock(ITestDevice.class));
-        EasyMock.expect(cleaner.isDisabled()).andReturn(false);
-        EasyMock.expect(cleaner.isTearDownDisabled()).andReturn(false);
-        cleaner.cleanUp(null, null);
-        EasyMock.replay(cleaner);
+        mContext.addAllocatedDevice("default", mock(ITestDevice.class));
+        when(cleaner.isDisabled()).thenReturn(false);
+        when(cleaner.isTearDownDisabled()).thenReturn(false);
+
         mExec.doCleanUp(mContext, mConfig, null);
-        EasyMock.verify(cleaner);
+
+        verify(cleaner).cleanUp(null, null);
     }
 
     /**
@@ -126,16 +126,15 @@
     @Test
     public void testCleanUp_disabled() throws Exception {
         DeviceConfigurationHolder holder = new DeviceConfigurationHolder("default");
-        ITargetHostCleaner cleaner = EasyMock.createMock(ITargetHostCleaner.class);
+        ITargetHostCleaner cleaner = mock(ITargetHostCleaner.class);
         holder.addSpecificConfig(cleaner);
         mConfig.setDeviceConfig(holder);
-        mContext.addAllocatedDevice("default", EasyMock.createMock(ITestDevice.class));
-        EasyMock.expect(cleaner.isDisabled()).andReturn(true);
+        mContext.addAllocatedDevice("default", mock(ITestDevice.class));
+        when(cleaner.isDisabled()).thenReturn(true);
         // cleaner.isTearDownDisabled not expected, because isDisabled true stops || execution.
         // cleanUp call is not expected
-        EasyMock.replay(cleaner);
+
         mExec.doCleanUp(mContext, mConfig, null);
-        EasyMock.verify(cleaner);
     }
 
     /**
@@ -145,16 +144,15 @@
     @Test
     public void testCleanUp_tearDownDisabled() throws Exception {
         DeviceConfigurationHolder holder = new DeviceConfigurationHolder("default");
-        ITargetHostCleaner cleaner = EasyMock.createMock(ITargetHostCleaner.class);
+        ITargetHostCleaner cleaner = mock(ITargetHostCleaner.class);
         holder.addSpecificConfig(cleaner);
         mConfig.setDeviceConfig(holder);
-        mContext.addAllocatedDevice("default", EasyMock.createMock(ITestDevice.class));
-        EasyMock.expect(cleaner.isDisabled()).andReturn(false);
-        EasyMock.expect(cleaner.isTearDownDisabled()).andReturn(true);
+        mContext.addAllocatedDevice("default", mock(ITestDevice.class));
+        when(cleaner.isDisabled()).thenReturn(false);
+        when(cleaner.isTearDownDisabled()).thenReturn(true);
         // cleanUp call is not expected
-        EasyMock.replay(cleaner);
+
         mExec.doCleanUp(mContext, mConfig, null);
-        EasyMock.verify(cleaner);
     }
 
     /**
diff --git a/javatests/com/android/tradefed/invoker/TestInvocationTest.java b/javatests/com/android/tradefed/invoker/TestInvocationTest.java
index 13fa81f..f5ed4fd 100644
--- a/javatests/com/android/tradefed/invoker/TestInvocationTest.java
+++ b/javatests/com/android/tradefed/invoker/TestInvocationTest.java
@@ -673,6 +673,8 @@
         IRemoteTest test = EasyMock.createMock(IRemoteTest.class);
         mMockDevice.setRecoveryMode(RecoveryMode.NONE);
         EasyMock.expectLastCall();
+        EasyMock.expect(mMockDevice.getRecoveryMode()).andReturn(RecoveryMode.AVAILABLE);
+        mMockDevice.setRecoveryMode(RecoveryMode.NONE);
         EasyMock.expect(
                         mMockDevice.logBugreport(
                                 EasyMock.startsWith("target_setup_error_bugreport"),
@@ -717,8 +719,11 @@
         mMockPreparer.setUp(EasyMock.anyObject());
         EasyMock.expectLastCall().andThrow(exception);
         setupMockFailureListeners(exception);
+        EasyMock.expect(mMockDevice.getRecoveryMode()).andReturn(RecoveryMode.AVAILABLE);
+        mMockDevice.setRecoveryMode(RecoveryMode.NONE);
         EasyMock.expect(mMockDevice.getBugreport())
                 .andReturn(new ByteArrayInputStreamSource(new byte[0]));
+        mMockDevice.setRecoveryMode(RecoveryMode.AVAILABLE);
         setEarlyDeviceReleaseExpectation();
         setupInvokeWithBuild();
 
diff --git a/javatests/com/android/tradefed/invoker/shard/StrictShardHelperTest.java b/javatests/com/android/tradefed/invoker/shard/StrictShardHelperTest.java
index 47a791f..b3fd888 100644
--- a/javatests/com/android/tradefed/invoker/shard/StrictShardHelperTest.java
+++ b/javatests/com/android/tradefed/invoker/shard/StrictShardHelperTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
 
 import com.android.tradefed.build.BuildInfo;
 import com.android.tradefed.build.StubBuildProvider;
@@ -48,8 +49,6 @@
 import com.android.tradefed.testtype.suite.ITestSuite;
 import com.android.tradefed.util.FileUtil;
 
-import java.util.Arrays;
-import org.easymock.EasyMock;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -61,6 +60,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -289,7 +289,7 @@
     }
 
     private List<IRemoteTest> testShard(int shardIndex) throws Exception {
-        mContext.addAllocatedDevice("default", EasyMock.createMock(ITestDevice.class));
+        mContext.addAllocatedDevice("default", mock(ITestDevice.class));
         List<IRemoteTest> test = new ArrayList<>();
         test.add(createFakeSuite("module2"));
         test.add(createFakeSuite("module1"));
@@ -351,47 +351,41 @@
         assertEquals(1, ((ITestSuite) res.get(2)).getDirectModule().numTests());
     }
 
-    /**
-     * Test that the unsorted test modules are re-ordered.
-     */
+    /** Test that the unsorted test modules are re-ordered. */
     @Test
     public void testReorderTestModules() throws Exception {
         List<String> unSortedModules =
-            Arrays.asList(
-                "module1[com.android.mod1.apex]",
-                "module1[com.android.mod1.apex+com.android.mod2.apex]",
-                "module2[com.android.mod1.apex]",
-                "module1[com.android.mod3.apk]",
-                "module2[com.android.mod1.apex+com.android.mod2.apex]",
-                "module2[com.android.mod3.apk]",
-                "module3[com.android.mod1.apex+com.android.mod2.apex]",
-                "module3[com.android.mod3.apk]",
-                "module4[com.android.mod3.apk]",
-                "module5[com.android.mod3.apk]"
-            );
+                Arrays.asList(
+                        "module1[com.android.mod1.apex]",
+                        "module1[com.android.mod1.apex+com.android.mod2.apex]",
+                        "module2[com.android.mod1.apex]",
+                        "module1[com.android.mod3.apk]",
+                        "module2[com.android.mod1.apex+com.android.mod2.apex]",
+                        "module2[com.android.mod3.apk]",
+                        "module3[com.android.mod1.apex+com.android.mod2.apex]",
+                        "module3[com.android.mod3.apk]",
+                        "module4[com.android.mod3.apk]",
+                        "module5[com.android.mod3.apk]");
         List<IRemoteTest> res = createITestSuiteList(unSortedModules);
 
         List<String> sortedModules =
-            Arrays.asList(
-                "module1[com.android.mod1.apex]",
-                "module2[com.android.mod1.apex]",
-                "module1[com.android.mod1.apex+com.android.mod2.apex]",
-                "module2[com.android.mod1.apex+com.android.mod2.apex]",
-                "module3[com.android.mod1.apex+com.android.mod2.apex]",
-                "module1[com.android.mod3.apk]",
-                "module2[com.android.mod3.apk]",
-                "module3[com.android.mod3.apk]",
-                "module4[com.android.mod3.apk]",
-                "module5[com.android.mod3.apk]"
-            );
-        for (int i = 0 ; i < sortedModules.size() ; i++) {
-            assertEquals(sortedModules.get(i), ((ITestSuite)res.get(i)).getDirectModule().getId());
+                Arrays.asList(
+                        "module1[com.android.mod1.apex]",
+                        "module2[com.android.mod1.apex]",
+                        "module1[com.android.mod1.apex+com.android.mod2.apex]",
+                        "module2[com.android.mod1.apex+com.android.mod2.apex]",
+                        "module3[com.android.mod1.apex+com.android.mod2.apex]",
+                        "module1[com.android.mod3.apk]",
+                        "module2[com.android.mod3.apk]",
+                        "module3[com.android.mod3.apk]",
+                        "module4[com.android.mod3.apk]",
+                        "module5[com.android.mod3.apk]");
+        for (int i = 0; i < sortedModules.size(); i++) {
+            assertEquals(sortedModules.get(i), ((ITestSuite) res.get(i)).getDirectModule().getId());
         }
     }
 
-    /**
-     * Test that the there exist a module with invalid parameterized modules defined.
-     */
+    /** Test that the there exist a module with invalid parameterized modules defined. */
     @Test
     public void testReorderTestModulesWithUnexpectedMainlineModules() throws Exception {
         List<String> modules = Arrays.asList("module1[com.mod1.apex]", "module1[com.mod1]");
@@ -400,9 +394,12 @@
             fail("Should have thrown an exception.");
         } catch (RuntimeException expected) {
             // expected
-            assertTrue(expected.getMessage().contains(
-                    "Module: module1[com.mod1] doesn't match the pattern for mainline " +
-                        "modules. The pattern should end with apk/apex/apks."));
+            assertTrue(
+                    expected.getMessage()
+                            .contains(
+                                    "Module: module1[com.mod1] doesn't match the pattern for"
+                                            + " mainline modules. The pattern should end with"
+                                            + " apk/apex/apks."));
         }
     }
 
@@ -481,7 +478,7 @@
     /** Test that no exception occurs when sharding for any possible interfaces. */
     @Test
     public void testSuite_withAllInterfaces() throws Exception {
-        mContext.addAllocatedDevice("default", EasyMock.createMock(ITestDevice.class));
+        mContext.addAllocatedDevice("default", mock(ITestDevice.class));
         IRemoteTest forceTest = new TestInterfaceClass();
         IRemoteTest test = new SplitITestSuite("suite-interface", forceTest);
 
diff --git a/javatests/com/android/tradefed/log/TerribleFailureEmailHandlerTest.java b/javatests/com/android/tradefed/log/TerribleFailureEmailHandlerTest.java
index e32d7f5..73699b7 100644
--- a/javatests/com/android/tradefed/log/TerribleFailureEmailHandlerTest.java
+++ b/javatests/com/android/tradefed/log/TerribleFailureEmailHandlerTest.java
@@ -15,64 +15,79 @@
  */
 package com.android.tradefed.log;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
 import com.android.tradefed.util.IEmail;
 import com.android.tradefed.util.IEmail.Message;
 
-import junit.framework.TestCase;
-
-import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 
-/**
- * Unit tests for {@link TerribleFailureEmailHandler}.
- */
-public class TerribleFailureEmailHandlerTest extends TestCase {
-    private IEmail mMockEmail;
+/** Unit tests for {@link TerribleFailureEmailHandler}. */
+@RunWith(JUnit4.class)
+public class TerribleFailureEmailHandlerTest {
+    @Mock IEmail mMockEmail;
     private TerribleFailureEmailHandler mWtfEmailHandler;
-    private final static String MOCK_HOST_NAME = "myhostname.mydomain.com";
+    private static final String MOCK_HOST_NAME = "myhostname.mydomain.com";
     private long mCurrentTimeMillis;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mMockEmail = EasyMock.createMock(IEmail.class);
-        mWtfEmailHandler = new TerribleFailureEmailHandler(mMockEmail) {
-            @Override
-            protected String getLocalHostName() {
-                return MOCK_HOST_NAME;
-            }
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
 
-            @Override
-            protected long getCurrentTimeMillis() {
-                return mCurrentTimeMillis;
-            }
-        };
+        mWtfEmailHandler =
+                new TerribleFailureEmailHandler(mMockEmail) {
+                    @Override
+                    protected String getLocalHostName() {
+                        return MOCK_HOST_NAME;
+                    }
+
+                    @Override
+                    protected long getCurrentTimeMillis() {
+                        return mCurrentTimeMillis;
+                    }
+                };
         mCurrentTimeMillis = System.currentTimeMillis();
     }
 
     /**
-     * Test normal success case for {@link TerribleFailureEmailHandler#onTerribleFailure(String, Throwable)}.
+     * Test normal success case for {@link TerribleFailureEmailHandler#onTerribleFailure(String,
+     * Throwable)}.
+     *
      * @throws IOException
      */
+    @Test
     public void testOnTerribleFailure() throws IllegalArgumentException, IOException {
-        mMockEmail.send(EasyMock.<Message>anyObject());
-        EasyMock.replay(mMockEmail);
+
         mWtfEmailHandler.addDestination("user@domain.com");
         boolean retValue = mWtfEmailHandler.onTerribleFailure("something terrible happened", null);
-        EasyMock.verify(mMockEmail);
+
+        verify(mMockEmail).send(Mockito.<Message>any());
         assertTrue(retValue);
     }
 
     /**
      * Test that onTerribleFailure catches IllegalArgumentException when Mailer state is incorrect
      */
+    @Test
     public void testOnTerribleFailure_catchesIllegalArgumentException() throws IOException {
-        mMockEmail.send(EasyMock.<Message>anyObject());
-        EasyMock.expectLastCall().andThrow(new IllegalArgumentException("Mailer state illegal"));
-        EasyMock.replay(mMockEmail);
+        doThrow(new IllegalArgumentException("Mailer state illegal"))
+                .when(mMockEmail)
+                .send(Mockito.<Message>any());
 
         mWtfEmailHandler.addDestination("user@domain.com");
         boolean retValue = mWtfEmailHandler.onTerribleFailure("something terrible happened", null);
@@ -80,66 +95,64 @@
     }
 
     /** Test that onTerribleFailure catches IOException */
+    @Test
     public void testOnTerribleFailure_catchesIOException() throws IOException {
-        mMockEmail.send(EasyMock.<Message>anyObject());
-        EasyMock.expectLastCall().andThrow(new IOException("Mailer had an IO Exception"));
-        EasyMock.replay(mMockEmail);
+        doThrow(new IOException("Mailer had an IO Exception"))
+                .when(mMockEmail)
+                .send(Mockito.<Message>any());
 
         mWtfEmailHandler.addDestination("user@domain.com");
         boolean retValue = mWtfEmailHandler.onTerribleFailure("something terrible happened", null);
         assertFalse(retValue);
     }
 
-    /**
-     * Test that no email is attempted to be sent when there is no destination set
-     */
+    /** Test that no email is attempted to be sent when there is no destination set */
+    @Test
     public void testOnTerribleFailure_emptyDestinations() {
         boolean retValue = mWtfEmailHandler.onTerribleFailure("something terrible happened", null);
         assertFalse(retValue);
     }
 
-    /**
-     * Test that no email is attempted to be sent if it is too adjacent to the previous failure.
-     */
-    public void testOnTerribleFailure_adjacentFailures() throws IllegalArgumentException,
-            IOException {
-        mMockEmail.send(EasyMock.<Message>anyObject());
+    /** Test that no email is attempted to be sent if it is too adjacent to the previous failure. */
+    @Test
+    public void testOnTerribleFailure_adjacentFailures()
+            throws IllegalArgumentException, IOException {
         mWtfEmailHandler.setMinEmailInterval(60000);
 
-        EasyMock.replay(mMockEmail);
         mWtfEmailHandler.addDestination("user@domain.com");
         boolean retValue = mWtfEmailHandler.onTerribleFailure("something terrible happened", null);
         assertTrue(retValue);
         mCurrentTimeMillis += 30000;
         retValue = mWtfEmailHandler.onTerribleFailure("something terrible happened again", null);
         assertFalse(retValue);
-        EasyMock.verify(mMockEmail);
+
+        verify(mMockEmail).send(Mockito.<Message>any());
     }
 
     /**
      * Test that the second email is attempted to be sent if it is not adjacent to the previous
      * failure.
      */
-    public void testOnTerribleFailure_notAdjacentFailures() throws IllegalArgumentException,
-            IOException {
-        mMockEmail.send(EasyMock.<Message>anyObject());
-        mMockEmail.send(EasyMock.<Message>anyObject());
+    @Test
+    public void testOnTerribleFailure_notAdjacentFailures()
+            throws IllegalArgumentException, IOException {
         mWtfEmailHandler.setMinEmailInterval(60000);
 
-        EasyMock.replay(mMockEmail);
         mWtfEmailHandler.addDestination("user@domain.com");
         boolean retValue = mWtfEmailHandler.onTerribleFailure("something terrible happened", null);
         assertTrue(retValue);
         mCurrentTimeMillis += 90000;
         retValue = mWtfEmailHandler.onTerribleFailure("something terrible happened again", null);
         assertTrue(retValue);
-        EasyMock.verify(mMockEmail);
+
+        verify(mMockEmail, times(2)).send(Mockito.<Message>any());
     }
 
     /**
-     * Test that the generated email message actually contains the sender and
-     * destination email addresses.
+     * Test that the generated email message actually contains the sender and destination email
+     * addresses.
      */
+    @Test
     public void testGenerateEmailMessage() {
         Collection<String> destinations = new ArrayList<String>();
         String sender = "alerter@email.address.com";
@@ -151,18 +164,18 @@
         mWtfEmailHandler.setSender(sender);
         mWtfEmailHandler.addDestination(destA);
         mWtfEmailHandler.addDestination(destB);
-        Message msg = mWtfEmailHandler.generateEmailMessage("something terrible happened",
-                new Throwable("hello"));
+        Message msg =
+                mWtfEmailHandler.generateEmailMessage(
+                        "something terrible happened", new Throwable("hello"));
         assertEquals(msg.getSender(), sender);
         assertTrue(msg.getTo().equals(destinations));
     }
 
-    /**
-     * Test normal success case for
-     * {@link TerribleFailureEmailHandler#generateEmailSubject()}.
-     */
+    /** Test normal success case for {@link TerribleFailureEmailHandler#generateEmailSubject()}. */
+    @Test
     public void testGenerateEmailSubject() {
-        assertEquals("WTF happened to tradefed on " + MOCK_HOST_NAME,
+        assertEquals(
+                "WTF happened to tradefed on " + MOCK_HOST_NAME,
                 mWtfEmailHandler.generateEmailSubject());
     }
 }
diff --git a/javatests/com/android/tradefed/presubmit/TestMappingsValidation.java b/javatests/com/android/tradefed/presubmit/TestMappingsValidation.java
index eba2379..6089f23 100644
--- a/javatests/com/android/tradefed/presubmit/TestMappingsValidation.java
+++ b/javatests/com/android/tradefed/presubmit/TestMappingsValidation.java
@@ -218,7 +218,17 @@
             }
         }
         if (!errors.isEmpty()) {
-            String error = format("Fail test entry check:\n%s", Joiner.on("\n").join(errors));
+            String error =
+                    format(
+                            "Fail test entry check. Some test modules are not found or the module"
+                                + " name has been changed or been removed from build file. \n\n"
+                                + "To locate owner that is responsible for the breakage, try to do"
+                                + " code search on the test modules, check the changelog/blame of"
+                                + " the broken TEST_MAPPING file or Android.bp/mk to locate the"
+                                + " owner.\n\n"
+                                + "Details: \n"
+                                + "%s",
+                            Joiner.on("\n").join(errors));
             if (!mEnforceModuleNameCheck) {
                 CLog.w(error);
             } else {
diff --git a/javatests/com/android/tradefed/result/DeviceFileReporterTest.java b/javatests/com/android/tradefed/result/DeviceFileReporterTest.java
index 789ac9c..247cd1a 100644
--- a/javatests/com/android/tradefed/result/DeviceFileReporterTest.java
+++ b/javatests/com/android/tradefed/result/DeviceFileReporterTest.java
@@ -16,15 +16,20 @@
 package com.android.tradefed.result;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
 
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.util.ArrayUtil;
 
-import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 
 import java.io.File;
 import java.util.HashMap;
@@ -34,12 +39,12 @@
 /** Unit tests for {@link DeviceFileReporter}. */
 @RunWith(JUnit4.class)
 public class DeviceFileReporterTest {
-    DeviceFileReporter dfr = null;
-    ITestDevice mDevice = null;
-    ITestInvocationListener mListener = null;
+    private DeviceFileReporter dfr = null;
+    @Mock ITestDevice mDevice;
+    @Mock ITestInvocationListener mListener;
 
     // Used to control what ISS is returned
-    InputStreamSource mDfrIss = null;
+    private InputStreamSource mDfrIss = null;
 
     @SuppressWarnings("serial")
     private static class FakeFile extends File {
@@ -51,10 +56,12 @@
             mName = name;
             mSize = size;
         }
+
         @Override
         public String toString() {
             return mName;
         }
+
         @Override
         public long length() {
             return mSize;
@@ -63,10 +70,10 @@
 
     @Before
     public void setUp() throws Exception {
-        mDevice = EasyMock.createMock(ITestDevice.class);
-        EasyMock.expect(mDevice.getSerialNumber()).andStubReturn("serial");
+        MockitoAnnotations.initMocks(this);
 
-        mListener = EasyMock.createMock(ITestInvocationListener.class);
+        when(mDevice.getSerialNumber()).thenReturn("serial");
+
         dfr =
                 new DeviceFileReporter(mDevice, mListener) {
                     @Override
@@ -83,20 +90,18 @@
         final String tombstone = "What do you want on your tombstone?";
         dfr.addPatterns("/data/tombstones/*");
 
-        EasyMock.expect(mDevice.executeShellCommand(EasyMock.eq("ls /data/tombstones/*")))
-          .andReturn(result);
+        when(mDevice.executeShellCommand(Mockito.eq("ls /data/tombstones/*"))).thenReturn(result);
         // This gets passed verbatim to createIssForFile above
-        EasyMock.expect(mDevice.pullFile(EasyMock.eq(filename)))
-                .andReturn(new FakeFile(filename, tombstone.length()));
+        when(mDevice.pullFile(Mockito.eq(filename)))
+                .thenReturn(new FakeFile(filename, tombstone.length()));
 
         mDfrIss = new ByteArrayInputStreamSource(tombstone.getBytes());
-        // FIXME: use captures here to make sure we get the string back out
-        mListener.testLog(EasyMock.eq(filename), EasyMock.eq(LogDataType.UNKNOWN),
-                EasyMock.eq(mDfrIss));
 
-        replayMocks();
         dfr.run();
-        verifyMocks();
+
+        verify(mListener)
+                .testLog(
+                        Mockito.eq(filename), Mockito.eq(LogDataType.UNKNOWN), Mockito.eq(mDfrIss));
     }
 
     /** Files' paths should be trimmed to remove white spaces at the end of the lines. */
@@ -109,20 +114,19 @@
         final String tombstone = "What do you want on your tombstone?";
         dfr.addPatterns("/data/tombstones/*");
 
-        EasyMock.expect(mDevice.executeShellCommand(EasyMock.eq("ls /data/tombstones/*")))
-            .andReturn(result);
+        when(mDevice.executeShellCommand(Mockito.eq("ls /data/tombstones/*"))).thenReturn(result);
         // This gets passed verbatim to createIssForFile above
-        EasyMock.expect(mDevice.pullFile(EasyMock.eq(filename)))
-            .andReturn(new FakeFile(filename, tombstone.length()));
+        when(mDevice.pullFile(Mockito.eq(filename)))
+                .thenReturn(new FakeFile(filename, tombstone.length()));
 
         mDfrIss = new ByteArrayInputStreamSource(tombstone.getBytes());
-        mListener.testLog(EasyMock.eq(filename), EasyMock.eq(LogDataType.UNKNOWN),
-            EasyMock.eq(mDfrIss));
 
-        replayMocks();
         List<String> filenames = dfr.run();
         assertEquals(filename, filenames.get(0));
-        verifyMocks();
+
+        verify(mListener)
+                .testLog(
+                        Mockito.eq(filename), Mockito.eq(LogDataType.UNKNOWN), Mockito.eq(mDfrIss));
     }
 
     @Test
@@ -135,86 +139,99 @@
         final String result = "/data/tombstones/tombstone_00  \r\n" + filename1 + "   " + filename2;
         dfr.addPatterns("/data/tombstones/*");
 
-        EasyMock.expect(mDevice.executeShellCommand(EasyMock.eq("ls /data/tombstones/*")))
-                .andReturn(result);
+        when(mDevice.executeShellCommand(Mockito.eq("ls /data/tombstones/*"))).thenReturn(result);
         // This gets passed verbatim to createIssForFile above
-        EasyMock.expect(mDevice.pullFile(EasyMock.eq(filename)))
-                .andReturn(new FakeFile(filename, tombstone.length()));
-        EasyMock.expect(mDevice.pullFile(EasyMock.eq(filename1)))
-                .andReturn(new FakeFile(filename1, tombstone.length()));
-        EasyMock.expect(mDevice.pullFile(EasyMock.eq(filename2)))
-                .andReturn(new FakeFile(filename2, tombstone.length()));
+        when(mDevice.pullFile(Mockito.eq(filename)))
+                .thenReturn(new FakeFile(filename, tombstone.length()));
+        when(mDevice.pullFile(Mockito.eq(filename1)))
+                .thenReturn(new FakeFile(filename1, tombstone.length()));
+        when(mDevice.pullFile(Mockito.eq(filename2)))
+                .thenReturn(new FakeFile(filename2, tombstone.length()));
 
         mDfrIss = new ByteArrayInputStreamSource(tombstone.getBytes());
-        mListener.testLog(
-                EasyMock.eq(filename), EasyMock.eq(LogDataType.UNKNOWN), EasyMock.eq(mDfrIss));
-        mListener.testLog(
-                EasyMock.eq(filename1), EasyMock.eq(LogDataType.UNKNOWN), EasyMock.eq(mDfrIss));
-        mListener.testLog(
-                EasyMock.eq(filename2), EasyMock.eq(LogDataType.UNKNOWN), EasyMock.eq(mDfrIss));
 
-        replayMocks();
         List<String> filenames = dfr.run();
         assertEquals(filename, filenames.get(0));
         assertEquals(filename1, filenames.get(1));
         assertEquals(filename2, filenames.get(2));
-        verifyMocks();
+
+        verify(mListener)
+                .testLog(
+                        Mockito.eq(filename), Mockito.eq(LogDataType.UNKNOWN), Mockito.eq(mDfrIss));
+        verify(mListener)
+                .testLog(
+                        Mockito.eq(filename1),
+                        Mockito.eq(LogDataType.UNKNOWN),
+                        Mockito.eq(mDfrIss));
+        verify(mListener)
+                .testLog(
+                        Mockito.eq(filename2),
+                        Mockito.eq(LogDataType.UNKNOWN),
+                        Mockito.eq(mDfrIss));
     }
 
     @Test
     public void testLineEnding_LF() throws Exception {
-        final String[] filenames = {"/data/tombstones/tombstone_00",
-                "/data/tombstones/tombstone_01",
-                "/data/tombstones/tombstone_02",
-                "/data/tombstones/tombstone_03",
-                "/data/tombstones/tombstone_04"};
-        String result = ArrayUtil.join("\n", (Object[])filenames);
+        final String[] filenames = {
+            "/data/tombstones/tombstone_00",
+            "/data/tombstones/tombstone_01",
+            "/data/tombstones/tombstone_02",
+            "/data/tombstones/tombstone_03",
+            "/data/tombstones/tombstone_04"
+        };
+        String result = ArrayUtil.join("\n", (Object[]) filenames);
         final String tombstone = "What do you want on your tombstone?";
         dfr.addPatterns("/data/tombstones/*");
 
-        EasyMock.expect(mDevice.executeShellCommand((String)EasyMock.anyObject()))
-                .andReturn(result);
+        when(mDevice.executeShellCommand((String) Mockito.any())).thenReturn(result);
         mDfrIss = new ByteArrayInputStreamSource(tombstone.getBytes());
         // This gets passed verbatim to createIssForFile above
         for (String filename : filenames) {
-            EasyMock.expect(mDevice.pullFile(EasyMock.eq(filename))).andReturn(
-                    new FakeFile(filename, tombstone.length()));
-
-            // FIXME: use captures here to make sure we get the string back out
-            mListener.testLog(EasyMock.eq(filename), EasyMock.eq(LogDataType.UNKNOWN),
-                    EasyMock.eq(mDfrIss));
+            when(mDevice.pullFile(Mockito.eq(filename)))
+                    .thenReturn(new FakeFile(filename, tombstone.length()));
         }
-        replayMocks();
+
         dfr.run();
-        verifyMocks();
+
+        for (String filename : filenames) {
+            verify(mListener)
+                    .testLog(
+                            Mockito.eq(filename),
+                            Mockito.eq(LogDataType.UNKNOWN),
+                            Mockito.eq(mDfrIss));
+        }
     }
 
     @Test
     public void testLineEnding_CRLF() throws Exception {
-        final String[] filenames = {"/data/tombstones/tombstone_00",
-                "/data/tombstones/tombstone_01",
-                "/data/tombstones/tombstone_02",
-                "/data/tombstones/tombstone_03",
-                "/data/tombstones/tombstone_04"};
-        String result = ArrayUtil.join("\r\n", (Object[])filenames);
+        final String[] filenames = {
+            "/data/tombstones/tombstone_00",
+            "/data/tombstones/tombstone_01",
+            "/data/tombstones/tombstone_02",
+            "/data/tombstones/tombstone_03",
+            "/data/tombstones/tombstone_04"
+        };
+        String result = ArrayUtil.join("\r\n", (Object[]) filenames);
         final String tombstone = "What do you want on your tombstone?";
         dfr.addPatterns("/data/tombstones/*");
 
-        EasyMock.expect(mDevice.executeShellCommand((String)EasyMock.anyObject()))
-                .andReturn(result);
+        when(mDevice.executeShellCommand((String) Mockito.any())).thenReturn(result);
         mDfrIss = new ByteArrayInputStreamSource(tombstone.getBytes());
         // This gets passed verbatim to createIssForFile above
         for (String filename : filenames) {
-            EasyMock.expect(mDevice.pullFile(EasyMock.eq(filename))).andReturn(
-                    new FakeFile(filename, tombstone.length()));
-
-            // FIXME: use captures here to make sure we get the string back out
-            mListener.testLog(EasyMock.eq(filename), EasyMock.eq(LogDataType.UNKNOWN),
-                    EasyMock.eq(mDfrIss));
+            when(mDevice.pullFile(Mockito.eq(filename)))
+                    .thenReturn(new FakeFile(filename, tombstone.length()));
         }
-        replayMocks();
+
         dfr.run();
-        verifyMocks();
+
+        for (String filename : filenames) {
+            verify(mListener)
+                    .testLog(
+                            Mockito.eq(filename),
+                            Mockito.eq(LogDataType.UNKNOWN),
+                            Mockito.eq(mDfrIss));
+        }
     }
 
     /**
@@ -253,24 +270,21 @@
         // Set file listing pulling, and reporting expectations
         // Expect that we go through the entire process for the PNG file, and then go through
         // the entire process again for the XML file
-        EasyMock.expect(mDevice.executeShellCommand((String)EasyMock.anyObject()))
-                .andReturn(result1);
-        EasyMock.expect(mDevice.pullFile(EasyMock.eq(pngFilename)))
-                .andReturn(new FakeFile(pngFilename, pngContents.length()));
-        mListener.testLog(EasyMock.eq(pngFilename), EasyMock.eq(LogDataType.PNG),
-                EasyMock.eq(pngIss));
+        when(mDevice.executeShellCommand((String) Mockito.any())).thenReturn(result1, result2);
+        when(mDevice.pullFile(Mockito.eq(pngFilename)))
+                .thenReturn(new FakeFile(pngFilename, pngContents.length()));
+        when(mDevice.pullFile(Mockito.eq(xmlFilename)))
+                .thenReturn(new FakeFile(xmlFilename, xmlContents.length()));
 
-        EasyMock.expect(mDevice.executeShellCommand((String)EasyMock.anyObject()))
-                .andReturn(result2);
-        EasyMock.expect(mDevice.pullFile(EasyMock.eq(xmlFilename)))
-                .andReturn(new FakeFile(xmlFilename, xmlContents.length()));
-        mListener.testLog(EasyMock.eq(xmlFilename), EasyMock.eq(LogDataType.UNKNOWN),
-                EasyMock.eq(xmlIss));
-
-        replayMocks();
         dfr.run();
-        verifyMocks();
-        // FIXME: use captures here to make sure we get the string back out
+
+        verify(mListener)
+                .testLog(Mockito.eq(pngFilename), Mockito.eq(LogDataType.PNG), Mockito.eq(pngIss));
+        verify(mListener)
+                .testLog(
+                        Mockito.eq(xmlFilename),
+                        Mockito.eq(LogDataType.UNKNOWN),
+                        Mockito.eq(xmlIss));
     }
 
     /**
@@ -311,29 +325,32 @@
         // Set file listing pulling, and reporting expectations
         // Expect that we go through the entire process for the PNG file, and then go through
         // the entire process again for the PNG file (again) and the XML file
-        EasyMock.expect(mDevice.executeShellCommand((String)EasyMock.anyObject()))
-                .andReturn(result1);
-        EasyMock.expect(mDevice.pullFile(EasyMock.eq(pngFilename)))
-                .andReturn(new FakeFile(pngFilename, pngContents.length()));
-        mListener.testLog(EasyMock.eq(pngFilename), EasyMock.eq(LogDataType.PNG),
-                EasyMock.eq(pngIss));
+        when(mDevice.executeShellCommand((String) Mockito.any())).thenReturn(result1);
+        when(mDevice.pullFile(Mockito.eq(pngFilename)))
+                .thenReturn(new FakeFile(pngFilename, pngContents.length()));
 
         // Note that the PNG file is picked up with the UNKNOWN data type this time
-        EasyMock.expect(mDevice.executeShellCommand((String)EasyMock.anyObject()))
-                .andReturn(result2);
-        EasyMock.expect(mDevice.pullFile(EasyMock.eq(pngFilename)))
-                .andReturn(new FakeFile(pngFilename, pngContents.length()));
-        mListener.testLog(EasyMock.eq(pngFilename), EasyMock.eq(LogDataType.UNKNOWN),
-                EasyMock.eq(pngIss));
-        EasyMock.expect(mDevice.pullFile(EasyMock.eq(xmlFilename)))
-                .andReturn(new FakeFile(xmlFilename, xmlContents.length()));
-        mListener.testLog(EasyMock.eq(xmlFilename), EasyMock.eq(LogDataType.UNKNOWN),
-                EasyMock.eq(xmlIss));
+        when(mDevice.executeShellCommand((String) Mockito.any())).thenReturn(result2);
+        when(mDevice.pullFile(Mockito.eq(pngFilename)))
+                .thenReturn(new FakeFile(pngFilename, pngContents.length()));
 
-        replayMocks();
+        when(mDevice.pullFile(Mockito.eq(xmlFilename)))
+                .thenReturn(new FakeFile(xmlFilename, xmlContents.length()));
+
         dfr.run();
-        verifyMocks();
-        // FIXME: use captures here to make sure we get the string back out
+
+        verify(mListener)
+                .testLog(Mockito.eq(pngFilename), Mockito.eq(LogDataType.PNG), Mockito.eq(pngIss));
+        verify(mListener)
+                .testLog(
+                        Mockito.eq(pngFilename),
+                        Mockito.eq(LogDataType.UNKNOWN),
+                        Mockito.eq(pngIss));
+        verify(mListener)
+                .testLog(
+                        Mockito.eq(xmlFilename),
+                        Mockito.eq(LogDataType.UNKNOWN),
+                        Mockito.eq(xmlIss));
     }
 
     /**
@@ -350,13 +367,12 @@
         final String result = file + ": No such file or directory\r\n";
         dfr.addPatterns(file);
 
-        EasyMock.expect(mDevice.executeShellCommand((String)EasyMock.anyObject()))
-                .andReturn(result);
+        when(mDevice.executeShellCommand((String) Mockito.any())).thenReturn(result);
 
-        replayMocks();
         dfr.run();
         // No pull attempt should happen
-        verifyMocks();
+        verify(mDevice).executeShellCommand((String) Mockito.any());
+        verifyNoMoreInteractions(mDevice);
     }
 
     @Test
@@ -368,69 +384,63 @@
         dfr.addPatterns("/data/tombstones/*");
 
         // Search the filesystem
-        EasyMock.expect(mDevice.executeShellCommand((String)EasyMock.anyObject()))
-                .andReturn(result);
+        when(mDevice.executeShellCommand((String) Mockito.any())).thenReturn(result);
 
         // Log the first file
         // This gets passed verbatim to createIssForFile above
-        EasyMock.expect(mDevice.pullFile(EasyMock.eq(filename1)))
-                .andReturn(new FakeFile(filename1, tombstone.length()));
+        when(mDevice.pullFile(Mockito.eq(filename1)))
+                .thenReturn(new FakeFile(filename1, tombstone.length()));
         mDfrIss = new ByteArrayInputStreamSource(tombstone.getBytes());
-        // FIXME: use captures here to make sure we get the string back out
-        mListener.testLog(EasyMock.eq(filename1), EasyMock.eq(LogDataType.UNKNOWN),
-                EasyMock.eq(mDfrIss));
 
         // Log the second file
         // This gets passed verbatim to createIssForFile above
-        EasyMock.expect(mDevice.pullFile(EasyMock.eq(filename2)))
-                .andReturn(new FakeFile(filename2, tombstone.length()));
-        // FIXME: use captures here to make sure we get the string back out
-        mListener.testLog(EasyMock.eq(filename2), EasyMock.eq(LogDataType.UNKNOWN),
-                EasyMock.eq(mDfrIss));
+        when(mDevice.pullFile(Mockito.eq(filename2)))
+                .thenReturn(new FakeFile(filename2, tombstone.length()));
 
-        replayMocks();
         dfr.run();
-        verifyMocks();
+
+        verify(mListener)
+                .testLog(
+                        Mockito.eq(filename1),
+                        Mockito.eq(LogDataType.UNKNOWN),
+                        Mockito.eq(mDfrIss));
+        verify(mListener)
+                .testLog(
+                        Mockito.eq(filename2),
+                        Mockito.eq(LogDataType.UNKNOWN),
+                        Mockito.eq(mDfrIss));
     }
 
     /** Make sure that data type inference works as expected */
     @Test
     public void testInferDataTypes() throws Exception {
-        final String result = "/data/files/file.png\r\n/data/files/file.xml\r\n" +
-                "/data/files/file.zip\r\n";
-        final String[] filenames = {"/data/files/file.png", "/data/files/file.xml",
-                "/data/files/file.zip"};
+        final String result =
+                "/data/files/file.png\r\n/data/files/file.xml\r\n" + "/data/files/file.zip\r\n";
+        final String[] filenames = {
+            "/data/files/file.png", "/data/files/file.xml", "/data/files/file.zip"
+        };
         final LogDataType[] expTypes = {LogDataType.PNG, LogDataType.XML, LogDataType.ZIP};
         dfr.addPatterns("/data/files/*");
 
         final String contents = "these are file contents";
         mDfrIss = new ByteArrayInputStreamSource(contents.getBytes());
 
-        EasyMock.expect(mDevice.executeShellCommand((String)EasyMock.anyObject()))
-                .andReturn(result);
+        when(mDevice.executeShellCommand((String) Mockito.any())).thenReturn(result);
         // This gets passed verbatim to createIssForFile above
         for (int i = 0; i < filenames.length; ++i) {
             final String filename = filenames[i];
             final LogDataType expType = expTypes[i];
-            EasyMock.expect(mDevice.pullFile(EasyMock.eq(filename)))
-                    .andReturn(new FakeFile(filename, contents.length()));
-
-            // FIXME: use captures here to make sure we get the string back out
-            mListener.testLog(EasyMock.eq(filename), EasyMock.eq(expType),
-                    EasyMock.eq(mDfrIss));
+            when(mDevice.pullFile(Mockito.eq(filename)))
+                    .thenReturn(new FakeFile(filename, contents.length()));
         }
 
-        replayMocks();
         dfr.run();
-        verifyMocks();
-    }
 
-
-    private void replayMocks() {
-        EasyMock.replay(mDevice, mListener);
-    }
-
-    private void verifyMocks() {
-        EasyMock.verify(mDevice, mListener);
+        for (int i = 0; i < filenames.length; ++i) {
+            final String filename = filenames[i];
+            final LogDataType expType = expTypes[i];
+            verify(mListener)
+                    .testLog(Mockito.eq(filename), Mockito.eq(expType), Mockito.eq(mDfrIss));
+        }
     }
 }
diff --git a/javatests/com/android/tradefed/result/DeviceUnavailEmailResultReporterTest.java b/javatests/com/android/tradefed/result/DeviceUnavailEmailResultReporterTest.java
deleted file mode 100644
index 6ae9237..0000000
--- a/javatests/com/android/tradefed/result/DeviceUnavailEmailResultReporterTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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 com.android.tradefed.result;
-
-import static org.junit.Assert.*;
-
-import com.android.tradefed.build.BuildInfo;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.invoker.IInvocationContext;
-import com.android.tradefed.invoker.InvocationContext;
-
-import org.easymock.EasyMock;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-/**
- * Test for {@link DeviceUnavailEmailResultReporter}.
- */
-@RunWith(JUnit4.class)
-public class DeviceUnavailEmailResultReporterTest {
-
-    private DeviceUnavailEmailResultReporter mDnaeEmailReporter;
-
-    @Before
-    public void setUp() {
-        mDnaeEmailReporter = new DeviceUnavailEmailResultReporter() {
-            @Override
-            String getHostname() {
-                return "FAKE_HOST.com";
-            }
-        };
-    }
-
-    @Test
-    public void testGenerateEmailSubject() {
-        IInvocationContext context = new InvocationContext();
-        context.addAllocatedDevice("fakeDevice", EasyMock.createMock(ITestDevice.class));
-        context.addDeviceBuildInfo("fakeDevice", new BuildInfo("888", "mybuild"));
-        mDnaeEmailReporter.invocationStarted(context);
-        assertEquals("Device unavailable BuildInfo{bid=888, target=mybuild} hostname FAKE_HOST.com",
-                mDnaeEmailReporter.generateEmailSubject());
-    }
-}
diff --git a/javatests/com/android/tradefed/result/EmailResultReporterTest.java b/javatests/com/android/tradefed/result/EmailResultReporterTest.java
deleted file mode 100644
index 9a08eeb..0000000
--- a/javatests/com/android/tradefed/result/EmailResultReporterTest.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.tradefed.result;
-
-import com.android.tradefed.build.BuildInfo;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.invoker.IInvocationContext;
-import com.android.tradefed.invoker.InvocationContext;
-import com.android.tradefed.util.IEmail;
-import com.android.tradefed.util.IEmail.Message;
-
-import junit.framework.TestCase;
-
-import org.easymock.EasyMock;
-
-import java.io.IOException;
-
-/**
- * Unit tests for {@link EmailResultReporter}.
- */
-public class EmailResultReporterTest extends TestCase {
-    private IEmail mMockMailer;
-    private EmailResultReporter mEmailReporter;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mMockMailer = EasyMock.createMock(IEmail.class);
-        mEmailReporter = new EmailResultReporter(mMockMailer);
-    }
-
-    /**
-     * Test normal success case for {@link EmailResultReporter#invocationEnded(long)}.
-     * @throws IOException
-     */
-    public void testInvocationEnded() throws IllegalArgumentException, IOException {
-        mMockMailer.send(EasyMock.<Message>anyObject());
-        EasyMock.replay(mMockMailer);
-        IInvocationContext context = new InvocationContext();
-        context.addDeviceBuildInfo("fakeDevice", new BuildInfo("888", "mybuild"));
-        context.setTestTag("mytest");
-        mEmailReporter.invocationStarted(context);
-        mEmailReporter.addDestination("foo");
-        mEmailReporter.invocationEnded(0);
-        EasyMock.verify(mMockMailer);
-
-        assertEquals("Tradefed result for mytest  on BuildInfo{bid=888, target=mybuild}: SUCCESS",
-                mEmailReporter.generateEmailSubject());
-    }
-
-    /**
-     * Test normal success case for {@link EmailResultReporter#invocationEnded(long)} with multiple
-     * builds.
-     */
-    public void testInvocationEnded_multiBuild() throws IllegalArgumentException, IOException {
-        mMockMailer.send(EasyMock.<Message>anyObject());
-        EasyMock.replay(mMockMailer);
-        IInvocationContext context = new InvocationContext();
-        context.addAllocatedDevice("fakeDevice", EasyMock.createMock(ITestDevice.class));
-        context.addDeviceBuildInfo("fakeDevice", new BuildInfo("888", "mybuild"));
-        context.addAllocatedDevice("fakeDevice2", EasyMock.createMock(ITestDevice.class));
-        context.addDeviceBuildInfo("fakeDevice2", new BuildInfo("999", "mybuild2"));
-        context.setTestTag("mytest");
-        mEmailReporter.invocationStarted(context);
-        mEmailReporter.addDestination("foo");
-        mEmailReporter.invocationEnded(0);
-        EasyMock.verify(mMockMailer);
-
-        assertEquals("Tradefed result for mytest  on BuildInfo{bid=888, target=mybuild}"
-                + "BuildInfo{bid=999, target=mybuild2}: SUCCESS",
-                mEmailReporter.generateEmailSubject());
-    }
-
-    /**
-     * Make sure that we don't include the string "null" in a generated email subject
-     */
-    public void testNullFlavorAndBranch() throws Exception {
-        mMockMailer.send(EasyMock.<Message>anyObject());
-        EasyMock.replay(mMockMailer);
-        IInvocationContext context = new InvocationContext();
-        context.addDeviceBuildInfo("fakeDevice", new BuildInfo("888", null));
-        mEmailReporter.invocationStarted(context);
-        mEmailReporter.addDestination("foo");
-        mEmailReporter.invocationEnded(0);
-
-        EasyMock.verify(mMockMailer);
-
-        assertEquals("Tradefed result for (unknown suite) on BuildInfo{bid=888}: SUCCESS",
-                mEmailReporter.generateEmailSubject());
-    }
-}
diff --git a/javatests/com/android/tradefed/result/FailureEmailResultReporterTest.java b/javatests/com/android/tradefed/result/FailureEmailResultReporterTest.java
deleted file mode 100644
index f240be6..0000000
--- a/javatests/com/android/tradefed/result/FailureEmailResultReporterTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2011 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 com.android.tradefed.result;
-
-import junit.framework.TestCase;
-
-/**
- * Unit tests for {@link FailureEmailResultReporter}.
- */
-public class FailureEmailResultReporterTest extends TestCase {
-    private class FakeEmailResultReporter extends FailureEmailResultReporter {
-        private boolean mHasFailedTests;
-        private InvocationStatus mInvocationStatus;
-
-        FakeEmailResultReporter(boolean hasFailedTests, InvocationStatus invocationStatus) {
-            mHasFailedTests = hasFailedTests;
-            mInvocationStatus = invocationStatus;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public boolean hasFailedTests() {
-            return mHasFailedTests;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public InvocationStatus getInvocationStatus() {
-            return mInvocationStatus;
-        }
-    }
-
-    /**
-     * Test that {@link FailureEmailResultReporter#shouldSendMessage()} returns true if
-     * {@link EmailResultReporter#getInvocationStatus()} is not {@link InvocationStatus#SUCCESS}.
-     */
-    public void testShouldSendMessage() {
-        // Don't send email if there is no test failure and no invocation failure.
-        FakeEmailResultReporter r = new FakeEmailResultReporter(false, InvocationStatus.SUCCESS);
-        assertFalse(r.shouldSendMessage());
-
-        // Send email if there is an invocation failure.
-        r = new FakeEmailResultReporter(false, InvocationStatus.BUILD_ERROR);
-        assertTrue(r.shouldSendMessage());
-
-        // Send email if there is an invocation failure.
-        r = new FakeEmailResultReporter(false, InvocationStatus.FAILED);
-        assertTrue(r.shouldSendMessage());
-
-        // Send email if there is an test failure.
-        r = new FakeEmailResultReporter(true, InvocationStatus.SUCCESS);
-        assertTrue(r.shouldSendMessage());
-
-        // Send email if there is an test failure and an invocation failure.
-        r = new FakeEmailResultReporter(true, InvocationStatus.FAILED);
-        assertTrue(r.shouldSendMessage());
-    }
-}
\ No newline at end of file
diff --git a/javatests/com/android/tradefed/result/InvocationFailureEmailResultReporterTest.java b/javatests/com/android/tradefed/result/InvocationFailureEmailResultReporterTest.java
deleted file mode 100644
index aef79c3..0000000
--- a/javatests/com/android/tradefed/result/InvocationFailureEmailResultReporterTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.tradefed.result;
-
-import junit.framework.TestCase;
-
-/**
- * Unit tests for {@link InvocationFailureEmailResultReporter}.
- */
-public class InvocationFailureEmailResultReporterTest extends TestCase {
-    private class FakeEmailResultReporter extends InvocationFailureEmailResultReporter {
-        private InvocationStatus mInvocationStatus;
-
-        FakeEmailResultReporter(InvocationStatus invocationStatus) {
-            mInvocationStatus = invocationStatus;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public InvocationStatus getInvocationStatus() {
-            return mInvocationStatus;
-        }
-    }
-
-    /**
-     * Test that {@link InvocationFailureEmailResultReporter#shouldSendMessage()} returns true if
-     * {@link EmailResultReporter#getInvocationStatus()} is not {@link InvocationStatus#SUCCESS}.
-     */
-    public void testShouldSendMessage() {
-        // Don't send email if there is no invocation failure.
-        FakeEmailResultReporter r = new FakeEmailResultReporter(InvocationStatus.SUCCESS);
-        assertFalse(r.shouldSendMessage());
-
-        // Send email if there is an invocation failure.
-        r = new FakeEmailResultReporter(InvocationStatus.BUILD_ERROR);
-        assertTrue(r.shouldSendMessage());
-
-        // Send email if there is an invocation failure.
-        r = new FakeEmailResultReporter(InvocationStatus.FAILED);
-        assertTrue(r.shouldSendMessage());
-    }
-}
\ No newline at end of file
diff --git a/javatests/com/android/tradefed/result/LegacySubprocessResultsReporterTest.java b/javatests/com/android/tradefed/result/LegacySubprocessResultsReporterTest.java
index 6e6bf57..a8c36bb 100644
--- a/javatests/com/android/tradefed/result/LegacySubprocessResultsReporterTest.java
+++ b/javatests/com/android/tradefed/result/LegacySubprocessResultsReporterTest.java
@@ -15,6 +15,9 @@
  */
 package com.android.tradefed.result;
 
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
 import com.android.ddmlib.testrunner.TestIdentifier;
 import com.android.tradefed.config.OptionSetter;
 import com.android.tradefed.invoker.InvocationContext;
@@ -22,11 +25,11 @@
 import com.android.tradefed.util.SubprocessTestResultsParser;
 import com.android.tradefed.util.proto.TfMetricProtoUtil;
 
-import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mockito;
 
 import java.util.Collections;
 import java.util.HashMap;
@@ -64,7 +67,7 @@
     public void testPrintEvent_printToSocket() throws Exception {
         TestIdentifier testId = new TestIdentifier("com.fakeclass", "faketest");
         TestDescription testDescrip = new TestDescription("com.fakeclass", "faketest");
-        ITestInvocationListener mMockListener = EasyMock.createMock(ITestInvocationListener.class);
+        ITestInvocationListener mMockListener = mock(ITestInvocationListener.class);
         SubprocessTestResultsParser receiver =
                 new SubprocessTestResultsParser(mMockListener, true, new InvocationContext());
         try {
@@ -72,19 +75,19 @@
             setter.setOptionValue(
                     "subprocess-report-port", Integer.toString(receiver.getSocketServerPort()));
             // mirror calls between receiver and sender.
-            mMockListener.testIgnored(testDescrip);
-            mMockListener.testAssumptionFailure(testDescrip, "fake trace");
-            mMockListener.testRunFailed(
-                    FailureDescription.create("no reason", FailureStatus.UNSET));
-            mMockListener.invocationFailed((Throwable) EasyMock.anyObject());
-            EasyMock.replay(mMockListener);
+
             mReporter.testIgnored(testId);
             mReporter.testAssumptionFailure(testId, "fake trace");
             mReporter.testRunFailed("no reason");
             mReporter.invocationFailed(new Throwable());
             mReporter.close();
             receiver.joinReceiver(500);
-            EasyMock.verify(mMockListener);
+
+            verify(mMockListener).testIgnored(testDescrip);
+            verify(mMockListener).testAssumptionFailure(testDescrip, "fake trace");
+            verify(mMockListener)
+                    .testRunFailed(FailureDescription.create("no reason", FailureStatus.UNSET));
+            verify(mMockListener).invocationFailed((Throwable) Mockito.any());
         } finally {
             receiver.close();
         }
@@ -96,7 +99,7 @@
      */
     @Test
     public void testPrintEvent_legacyMethodCalls() throws Exception {
-        ITestInvocationListener mMockListener = EasyMock.createMock(ITestInvocationListener.class);
+        ITestInvocationListener mMockListener = mock(ITestInvocationListener.class);
         SubprocessTestResultsParser receiver =
                 new SubprocessTestResultsParser(mMockListener, true, new InvocationContext());
         try {
@@ -107,15 +110,19 @@
             Map<String, String> map = new HashMap<>();
             map.put("key1", "value1");
             map.put("key2", "value2");
-            mMockListener.testRunStarted(
-                    EasyMock.eq("test run"), EasyMock.eq(2), EasyMock.eq(0), EasyMock.anyLong());
-            mMockListener.testRunEnded(50, TfMetricProtoUtil.upgradeConvert(map));
-            EasyMock.replay(mMockListener);
+
             mReporter.testRunStarted("test run", 2);
             mReporter.testRunEnded(50, map);
             mReporter.close();
             receiver.joinReceiver(500);
-            EasyMock.verify(mMockListener);
+
+            verify(mMockListener)
+                    .testRunStarted(
+                            Mockito.eq("test run"),
+                            Mockito.eq(2),
+                            Mockito.eq(0),
+                            Mockito.anyLong());
+            verify(mMockListener).testRunEnded(50, TfMetricProtoUtil.upgradeConvert(map));
         } finally {
             receiver.close();
         }
diff --git a/javatests/com/android/tradefed/result/LogcatCrashResultForwarderTest.java b/javatests/com/android/tradefed/result/LogcatCrashResultForwarderTest.java
index a42c21d..8bdff38 100644
--- a/javatests/com/android/tradefed/result/LogcatCrashResultForwarderTest.java
+++ b/javatests/com/android/tradefed/result/LogcatCrashResultForwarderTest.java
@@ -16,18 +16,22 @@
 package com.android.tradefed.result;
 
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
 import com.android.tradefed.result.error.DeviceErrorIdentifier;
 import com.android.tradefed.result.proto.TestRecordProto.FailureStatus;
 
-import org.easymock.Capture;
-import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 
 import java.util.HashMap;
 
@@ -35,13 +39,12 @@
 @RunWith(JUnit4.class)
 public class LogcatCrashResultForwarderTest {
     private LogcatCrashResultForwarder mReporter;
-    private ITestInvocationListener mMockListener;
-    private ITestDevice mMockDevice;
+    @Mock ITestInvocationListener mMockListener;
+    @Mock ITestDevice mMockDevice;
 
     @Before
     public void setUp() {
-        mMockListener = EasyMock.createMock(ITestInvocationListener.class);
-        mMockDevice = EasyMock.createMock(ITestDevice.class);
+        MockitoAnnotations.initMocks(this);
     }
 
     /** Test if a crash is detected but no crash is found in the logcat. */
@@ -51,20 +54,21 @@
         mReporter = new LogcatCrashResultForwarder(mMockDevice, mMockListener);
         TestDescription test = new TestDescription("com.class", "test");
 
-        mMockListener.testStarted(test, 0L);
-        EasyMock.expect(mMockDevice.getLogcatSince(0L))
-                .andReturn(new ByteArrayInputStreamSource("".getBytes()));
-        mMockListener.testFailed(
-                test,
-                FailureDescription.create("instrumentation failed. reason: 'Process crashed.'")
-                        .setErrorIdentifier(DeviceErrorIdentifier.INSTRUMENTATION_CRASH));
-        mMockListener.testEnded(test, 5L, new HashMap<String, Metric>());
+        when(mMockDevice.getLogcatSince(0L))
+                .thenReturn(new ByteArrayInputStreamSource("".getBytes()));
 
-        EasyMock.replay(mMockListener, mMockDevice);
         mReporter.testStarted(test, 0L);
         mReporter.testFailed(test, "instrumentation failed. reason: 'Process crashed.'");
         mReporter.testEnded(test, 5L, new HashMap<String, Metric>());
-        EasyMock.verify(mMockListener, mMockDevice);
+
+        verify(mMockListener).testStarted(test, 0L);
+        verify(mMockListener)
+                .testFailed(
+                        test,
+                        FailureDescription.create(
+                                        "instrumentation failed. reason: 'Process crashed.'")
+                                .setErrorIdentifier(DeviceErrorIdentifier.INSTRUMENTATION_CRASH));
+        verify(mMockListener).testEnded(test, 5L, new HashMap<String, Metric>());
     }
 
     /**
@@ -77,7 +81,6 @@
         mReporter = new LogcatCrashResultForwarder(mMockDevice, mMockListener);
         TestDescription test = new TestDescription("com.class", "test");
 
-        mMockListener.testStarted(test, 0L);
         String logcat =
                 "03-20 09:57:36.709 11 11 E AndroidRuntime: FATAL EXCEPTION: Thread-2\n"
                         + "03-20 09:57:36.709 11 11 E AndroidRuntime: Process: android.gesture.cts"
@@ -91,22 +94,24 @@
                         + "03-20 09:57:36.711 11 11 I TestRunner: started: testGetStrokesCount"
                         + "(android.gesture.cts.GestureTest)\n";
 
-        EasyMock.expect(mMockDevice.getLogcatSince(0L))
-                .andReturn(new ByteArrayInputStreamSource(logcat.getBytes()));
-        // Some crash was added to the failure
-        Capture<FailureDescription> captured_1 = new Capture<>();
-        mMockListener.testFailed(EasyMock.eq(test), EasyMock.capture(captured_1));
-        mMockListener.testEnded(test, 5L, new HashMap<String, Metric>());
-        // If a run failure follows, expect it to contain the additional stack too.
-        Capture<FailureDescription> captured_2 = new Capture<>();
-        mMockListener.testRunFailed(EasyMock.capture(captured_2));
+        when(mMockDevice.getLogcatSince(0L))
+                .thenReturn(new ByteArrayInputStreamSource(logcat.getBytes()));
 
-        EasyMock.replay(mMockListener, mMockDevice);
         mReporter.testStarted(test, 0L);
         mReporter.testFailed(test, "instrumentation failed. reason: 'Process crashed.'");
         mReporter.testEnded(test, 5L, new HashMap<String, Metric>());
         mReporter.testRunFailed("Something went wrong.");
-        EasyMock.verify(mMockListener, mMockDevice);
+
+        verify(mMockListener).testStarted(test, 0L);
+        // Some crash was added to the failure
+        ArgumentCaptor<FailureDescription> captured_1 =
+                ArgumentCaptor.forClass(FailureDescription.class);
+        verify(mMockListener).testFailed(Mockito.eq(test), captured_1.capture());
+        verify(mMockListener).testEnded(test, 5L, new HashMap<String, Metric>());
+        // If a run failure follows, expect it to contain the additional stack too.
+        ArgumentCaptor<FailureDescription> captured_2 =
+                ArgumentCaptor.forClass(FailureDescription.class);
+        verify(mMockListener).testRunFailed(captured_2.capture());
         assertTrue(
                 captured_1
                         .getValue()
@@ -138,7 +143,6 @@
         mReporter = new LogcatCrashResultForwarder(mMockDevice, mMockListener);
         TestDescription test = new TestDescription("com.class", "test");
 
-        mMockListener.testStarted(test, 0L);
         String logcat =
                 "03-20 09:57:36.709 11 11 E AndroidRuntime: FATAL EXCEPTION: Thread-2\n"
                         + "03-20 09:57:36.709 11 11 E AndroidRuntime: Process: android.gesture.cts"
@@ -152,21 +156,22 @@
                         + "03-20 09:57:36.711 11 11 I TestRunner: started: testGetStrokesCount"
                         + "(android.gesture.cts.GestureTest)\n";
 
-        EasyMock.expect(mMockDevice.getLogcatSince(0L))
-                .andReturn(new ByteArrayInputStreamSource(logcat.getBytes()));
-        // No crash added at the point of testFailed.
-        mMockListener.testFailed(test, FailureDescription.create("Something went wrong."));
-        mMockListener.testEnded(test, 5L, new HashMap<String, Metric>());
-        // If a run failure comes with a crash detected, expect it to contain the additional stack.
-        Capture<FailureDescription> captured = new Capture<>();
-        mMockListener.testRunFailed(EasyMock.capture(captured));
+        when(mMockDevice.getLogcatSince(0L))
+                .thenReturn(new ByteArrayInputStreamSource(logcat.getBytes()));
 
-        EasyMock.replay(mMockListener, mMockDevice);
         mReporter.testStarted(test, 0L);
         mReporter.testFailed(test, "Something went wrong.");
         mReporter.testEnded(test, 5L, new HashMap<String, Metric>());
         mReporter.testRunFailed("instrumentation failed. reason: 'Process crashed.'");
-        EasyMock.verify(mMockListener, mMockDevice);
+
+        verify(mMockListener).testStarted(test, 0L);
+        // No crash added at the point of testFailed.
+        verify(mMockListener).testFailed(test, FailureDescription.create("Something went wrong."));
+        verify(mMockListener).testEnded(test, 5L, new HashMap<String, Metric>());
+        // If a run failure comes with a crash detected, expect it to contain the additional stack.
+        ArgumentCaptor<FailureDescription> captured =
+                ArgumentCaptor.forClass(FailureDescription.class);
+        verify(mMockListener).testRunFailed(captured.capture());
         assertTrue(
                 captured.getValue()
                         .getErrorMessage()
@@ -186,8 +191,6 @@
         mReporter = new LogcatCrashResultForwarder(mMockDevice, mMockListener);
         TestDescription test = new TestDescription("com.class", "test");
 
-        mMockListener.testStarted(test, 0L);
-
         String logcat =
                 "04-25 09:55:47.799  wifi  64  82 E AndroidRuntime: java.lang.Exception: test\n"
                         + "04-25 09:55:47.799  wifi  64  82 E AndroidRuntime: "
@@ -201,21 +204,22 @@
                         + "04-25 09:55:47.799  wifi  65  90 E AndroidRuntime: "
                         + "\tat class.method2(Class.java:2)\n";
 
-        EasyMock.expect(mMockDevice.getLogcatSince(0L))
-                .andReturn(new ByteArrayInputStreamSource(logcat.getBytes()));
-        // No crash added at the point of testFailed.
-        mMockListener.testFailed(test, FailureDescription.create("Something went wrong."));
-        mMockListener.testEnded(test, 5L, new HashMap<String, Metric>());
-        // If a run failure comes with a crash detected, expect it to contain the additional stack.
-        Capture<FailureDescription> captured = new Capture<>();
-        mMockListener.testRunFailed(EasyMock.capture(captured));
+        when(mMockDevice.getLogcatSince(0L))
+                .thenReturn(new ByteArrayInputStreamSource(logcat.getBytes()));
 
-        EasyMock.replay(mMockListener, mMockDevice);
         mReporter.testStarted(test, 0L);
         mReporter.testFailed(test, "Something went wrong.");
         mReporter.testEnded(test, 5L, new HashMap<String, Metric>());
         mReporter.testRunFailed("instrumentation failed. reason: 'Process crashed.'");
-        EasyMock.verify(mMockListener, mMockDevice);
+
+        verify(mMockListener).testStarted(test, 0L);
+        // No crash added at the point of testFailed.
+        verify(mMockListener).testFailed(test, FailureDescription.create("Something went wrong."));
+        verify(mMockListener).testEnded(test, 5L, new HashMap<String, Metric>());
+        // If a run failure comes with a crash detected, expect it to contain the additional stack.
+        ArgumentCaptor<FailureDescription> captured =
+                ArgumentCaptor.forClass(FailureDescription.class);
+        verify(mMockListener).testRunFailed(captured.capture());
         assertTrue(
                 captured.getValue()
                         .getErrorMessage()
@@ -237,17 +241,16 @@
         mReporter = new LogcatCrashResultForwarder(mMockDevice, mMockListener);
         TestDescription test = new TestDescription("com.class", "test");
 
-        mMockListener.testStarted(test, 0L);
+        ArgumentCaptor<FailureDescription> captured =
+                ArgumentCaptor.forClass(FailureDescription.class);
 
-        Capture<FailureDescription> captured = new Capture<>();
-        mMockListener.testFailed(EasyMock.eq(test), EasyMock.capture(captured));
-        mMockListener.testEnded(test, 5L, new HashMap<String, Metric>());
-
-        EasyMock.replay(mMockListener, mMockDevice);
         mReporter.testStarted(test, 0L);
         mReporter.testFailed(test, trace);
         mReporter.testEnded(test, 5L, new HashMap<String, Metric>());
-        EasyMock.verify(mMockListener, mMockDevice);
+
+        verify(mMockListener).testStarted(test, 0L);
+        verify(mMockListener).testFailed(Mockito.eq(test), captured.capture());
+        verify(mMockListener).testEnded(test, 5L, new HashMap<String, Metric>());
         assertTrue(captured.getValue().getErrorMessage().contains(trace));
         assertTrue(FailureStatus.TIMED_OUT.equals(captured.getValue().getFailureStatus()));
     }
@@ -264,17 +267,16 @@
         mReporter = new LogcatCrashResultForwarder(mMockDevice, mMockListener);
         TestDescription test = new TestDescription("com.class", "test");
 
-        mMockListener.testStarted(test, 0L);
+        ArgumentCaptor<FailureDescription> captured =
+                ArgumentCaptor.forClass(FailureDescription.class);
 
-        Capture<FailureDescription> captured = new Capture<>();
-        mMockListener.testFailed(EasyMock.eq(test), EasyMock.capture(captured));
-        mMockListener.testEnded(test, 5L, new HashMap<String, Metric>());
-
-        EasyMock.replay(mMockListener, mMockDevice);
         mReporter.testStarted(test, 0L);
         mReporter.testFailed(test, trace);
         mReporter.testEnded(test, 5L, new HashMap<String, Metric>());
-        EasyMock.verify(mMockListener, mMockDevice);
+
+        verify(mMockListener).testStarted(test, 0L);
+        verify(mMockListener).testFailed(Mockito.eq(test), captured.capture());
+        verify(mMockListener).testEnded(test, 5L, new HashMap<String, Metric>());
         assertTrue(captured.getValue().getErrorMessage().contains(trace));
         assertTrue(FailureStatus.TIMED_OUT.equals(captured.getValue().getFailureStatus()));
     }
diff --git a/javatests/com/android/tradefed/result/TestFailureEmailResultReporterTest.java b/javatests/com/android/tradefed/result/TestFailureEmailResultReporterTest.java
deleted file mode 100644
index 9ca0123..0000000
--- a/javatests/com/android/tradefed/result/TestFailureEmailResultReporterTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.tradefed.result;
-
-import junit.framework.TestCase;
-
-/**
- * Unit tests for {@link TestFailureEmailResultReporter}.
- */
-public class TestFailureEmailResultReporterTest extends TestCase {
-    private class FakeEmailResultReporter extends TestFailureEmailResultReporter {
-        private boolean mHasFailedTests;
-
-        FakeEmailResultReporter(boolean hasFailedTests) {
-            mHasFailedTests = hasFailedTests;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public boolean hasFailedTests() {
-            return mHasFailedTests;
-        }
-    }
-
-    /**
-     * Test that {@link TestFailureEmailResultReporter#shouldSendMessage()} returns
-     * {@link CollectingTestListener#hasFailedTests()}.
-     */
-    public void testShouldSendMessage() {
-        // Send email if there is a test failure.
-        FakeEmailResultReporter r = new FakeEmailResultReporter(true);
-        assertTrue(r.shouldSendMessage());
-
-        // Don't send email if there is no test failure.
-        r = new FakeEmailResultReporter(false);
-        assertFalse(r.shouldSendMessage());
-    }
-}
diff --git a/javatests/com/android/tradefed/result/ddmlib/InstrumentationResultProtoParserTest.java b/javatests/com/android/tradefed/result/ddmlib/InstrumentationResultProtoParserTest.java
index 3dbd1f4..86fabc2 100644
--- a/javatests/com/android/tradefed/result/ddmlib/InstrumentationResultProtoParserTest.java
+++ b/javatests/com/android/tradefed/result/ddmlib/InstrumentationResultProtoParserTest.java
@@ -17,6 +17,8 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 
 import com.android.commands.am.InstrumentationData.ResultsBundle;
 import com.android.commands.am.InstrumentationData.ResultsBundleEntry;
@@ -27,13 +29,16 @@
 import com.android.ddmlib.testrunner.ITestRunListener;
 import com.android.ddmlib.testrunner.TestIdentifier;
 
-import org.easymock.Capture;
-import org.easymock.EasyMock;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -49,7 +54,7 @@
 public class InstrumentationResultProtoParserTest {
 
     private InstrumentationResultProtoParser mParser;
-    private ITestRunListener mMockListener;
+    @Mock ITestRunListener mMockListener;
 
     private static final String RUN_KEY = "testing";
     private static final String CLASS_NAME_1 = "class_1";
@@ -60,8 +65,8 @@
     private static final String RUN_FAILURE_MESSAGE = "Unable to find instrumentation info:";
     private static final String TEST_COMPLETED_STATUS_1 = "Expected 2 tests, received 0";
     private static final String TEST_COMPLETED_STATUS_2 = "Expected 2 tests, received 1";
-    private static final String INCOMPLETE_TEST_ERR_MSG_PREFIX = "Test failed to run"
-            + " to completion";
+    private static final String INCOMPLETE_TEST_ERR_MSG_PREFIX =
+            "Test failed to run" + " to completion";
     private static final String INCOMPLETE_RUN_ERR_MSG_PREFIX = "Test run failed to complete";
     private static final String FATAL_EXCEPTION_MSG = "Fatal exception when running tests";
 
@@ -69,8 +74,10 @@
 
     @Before
     public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
         List<ITestRunListener> runListeners = new ArrayList<>();
-        mMockListener = EasyMock.createStrictMock(ITestRunListener.class);
+
         runListeners.add(mMockListener);
         mParser = new InstrumentationResultProtoParser(RUN_KEY, runListeners);
     }
@@ -159,12 +166,19 @@
     @Test
     public void testNullProtoFile() throws IOException {
         protoTestFile = null;
-        mMockListener.testRunStarted(RUN_KEY, 0);
-        mMockListener.testRunFailed(EasyMock
-                .eq(InstrumentationResultProtoParser.NO_TEST_RESULTS_FILE));
-        mMockListener.testRunEnded(0, Collections.emptyMap());
 
-        processProtoAndVerify(protoTestFile);
+        mParser.processProtoFile(protoTestFile);
+
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted(RUN_KEY, 0);
+        inOrder.verify(mMockListener)
+                .testRunFailed(Mockito.eq(InstrumentationResultProtoParser.NO_TEST_RESULTS_FILE));
+        inOrder.verify(mMockListener).testRunEnded(0, Collections.emptyMap());
+
+        verify(mMockListener).testRunStarted(RUN_KEY, 0);
+        verify(mMockListener)
+                .testRunFailed(Mockito.eq(InstrumentationResultProtoParser.NO_TEST_RESULTS_FILE));
+        verify(mMockListener).testRunEnded(0, Collections.emptyMap());
     }
 
     /**
@@ -175,12 +189,19 @@
     @Test
     public void testEmptyProtoFile() throws IOException {
         protoTestFile = File.createTempFile("tmp", ".pb");
-        mMockListener.testRunStarted(RUN_KEY, 0);
-        mMockListener.testRunFailed(EasyMock
-                .eq(InstrumentationResultProtoParser.NO_TEST_RESULTS_MSG));
-        mMockListener.testRunEnded(0, Collections.emptyMap());
 
-        processProtoAndVerify(protoTestFile);
+        mParser.processProtoFile(protoTestFile);
+
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted(RUN_KEY, 0);
+        inOrder.verify(mMockListener)
+                .testRunFailed(Mockito.eq(InstrumentationResultProtoParser.NO_TEST_RESULTS_MSG));
+        inOrder.verify(mMockListener).testRunEnded(0, Collections.emptyMap());
+
+        verify(mMockListener).testRunStarted(RUN_KEY, 0);
+        verify(mMockListener)
+                .testRunFailed(Mockito.eq(InstrumentationResultProtoParser.NO_TEST_RESULTS_MSG));
+        verify(mMockListener).testRunEnded(0, Collections.emptyMap());
     }
 
     /**
@@ -194,12 +215,21 @@
         FileOutputStream fout = new FileOutputStream(protoTestFile);
         fout.write(65);
         fout.close();
-        mMockListener.testRunStarted(RUN_KEY, 0);
-        mMockListener.testRunFailed(EasyMock
-                .eq(InstrumentationResultProtoParser.INVALID_TEST_RESULTS_FILE));
-        mMockListener.testRunEnded(0, Collections.emptyMap());
 
-        processProtoAndVerify(protoTestFile);
+        mParser.processProtoFile(protoTestFile);
+
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted(RUN_KEY, 0);
+        inOrder.verify(mMockListener)
+                .testRunFailed(
+                        Mockito.eq(InstrumentationResultProtoParser.INVALID_TEST_RESULTS_FILE));
+        inOrder.verify(mMockListener).testRunEnded(0, Collections.emptyMap());
+
+        verify(mMockListener).testRunStarted(RUN_KEY, 0);
+        verify(mMockListener)
+                .testRunFailed(
+                        Mockito.eq(InstrumentationResultProtoParser.INVALID_TEST_RESULTS_FILE));
+        verify(mMockListener).testRunEnded(0, Collections.emptyMap());
     }
 
     /**
@@ -212,10 +242,14 @@
 
         protoTestFile = buildNoTestResultsProtoFile();
 
-        mMockListener.testRunStarted(RUN_KEY, 0);
-        mMockListener.testRunEnded(27013, Collections.emptyMap());
+        mParser.processProtoFile(protoTestFile);
 
-        processProtoAndVerify(protoTestFile);
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted(RUN_KEY, 0);
+        inOrder.verify(mMockListener).testRunEnded(27013, Collections.emptyMap());
+
+        verify(mMockListener).testRunStarted(RUN_KEY, 0);
+        verify(mMockListener).testRunEnded(27013, Collections.emptyMap());
     }
 
     /**
@@ -228,21 +262,24 @@
         protoTestFile = buildSingleTestMetricSuccessProtoFile();
 
         TestIdentifier td = new TestIdentifier(CLASS_NAME_1, METHOD_NAME_1);
-        Capture<Map<String, String>> captureTestMetrics = new Capture<Map<String, String>>();
+        ArgumentCaptor<Map<String, String>> captureTestMetrics = ArgumentCaptor.forClass(Map.class);
 
-        mMockListener.testRunStarted(RUN_KEY, 1);
-        mMockListener.testStarted(td);
-        mMockListener.testEnded(EasyMock.eq(td), EasyMock.capture(captureTestMetrics));
-        mMockListener.testRunEnded(27013, Collections.emptyMap());
+        mParser.processProtoFile(protoTestFile);
 
-        processProtoAndVerify(protoTestFile);
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted(RUN_KEY, 1);
+        inOrder.verify(mMockListener).testStarted(td);
+        inOrder.verify(mMockListener).testEnded(Mockito.eq(td), captureTestMetrics.capture());
+        inOrder.verify(mMockListener).testRunEnded(27013, Collections.emptyMap());
+
+        verify(mMockListener).testRunStarted(RUN_KEY, 1);
+        verify(mMockListener).testStarted(td);
+        verify(mMockListener).testEnded(Mockito.eq(td), captureTestMetrics.capture());
+        verify(mMockListener).testRunEnded(27013, Collections.emptyMap());
 
         // Verify the test metrics
-        assertEquals("626",
-                captureTestMetrics.getValue().get("metric_key1"));
-        assertEquals("1",
-                captureTestMetrics.getValue()
-                        .get("metric_key2"));
+        assertEquals("626", captureTestMetrics.getValue().get("metric_key1"));
+        assertEquals("1", captureTestMetrics.getValue().get("metric_key2"));
     }
 
     /**
@@ -255,8 +292,8 @@
     public void testOneTestSuccessWithMultipleListeners() throws IOException {
 
         List<ITestRunListener> runListeners = new ArrayList<>();
-        ITestRunListener mMockListener1 = EasyMock.createStrictMock(ITestRunListener.class);
-        ITestRunListener mMockListener2 = EasyMock.createStrictMock(ITestRunListener.class);
+        ITestRunListener mMockListener1 = mock(ITestRunListener.class);
+        ITestRunListener mMockListener2 = mock(ITestRunListener.class);
         runListeners.add(mMockListener1);
         runListeners.add(mMockListener2);
 
@@ -265,38 +302,40 @@
         protoTestFile = buildSingleTestMetricSuccessProtoFile();
 
         TestIdentifier td = new TestIdentifier(CLASS_NAME_1, METHOD_NAME_1);
-        Capture<Map<String, String>> captureListener1Metrics = new Capture<Map<String, String>>();
-        Capture<Map<String, String>> captureListener2Metrics = new Capture<Map<String, String>>();
 
-        mMockListener1.testRunStarted(RUN_KEY, 1);
-        mMockListener1.testStarted(td);
-        mMockListener1.testEnded(EasyMock.eq(td), EasyMock.capture(captureListener1Metrics));
-        mMockListener1.testRunEnded(27013, Collections.emptyMap());
-
-        mMockListener2.testRunStarted(RUN_KEY, 1);
-        mMockListener2.testStarted(td);
-        mMockListener2.testEnded(EasyMock.eq(td), EasyMock.capture(captureListener2Metrics));
-        mMockListener2.testRunEnded(27013, Collections.emptyMap());
-
-        EasyMock.replay(mMockListener1);
-        EasyMock.replay(mMockListener2);
         mParser.processProtoFile(protoTestFile);
-        EasyMock.verify(mMockListener1);
-        EasyMock.verify(mMockListener2);
+
+        InOrder inOrder = Mockito.inOrder(mMockListener1, mMockListener2);
+        inOrder.verify(mMockListener1).testRunStarted(RUN_KEY, 1);
+        inOrder.verify(mMockListener2).testRunStarted(RUN_KEY, 1);
+        inOrder.verify(mMockListener1).testStarted(td);
+        inOrder.verify(mMockListener2).testStarted(td);
+        inOrder.verify(mMockListener1).testEnded(Mockito.eq(td), Mockito.any(Map.class));
+        inOrder.verify(mMockListener2).testEnded(Mockito.eq(td), Mockito.any(Map.class));
+        inOrder.verify(mMockListener1).testRunEnded(27013, Collections.emptyMap());
+        inOrder.verify(mMockListener2).testRunEnded(27013, Collections.emptyMap());
+
+        verify(mMockListener1).testRunStarted(RUN_KEY, 1);
+        verify(mMockListener1).testStarted(td);
+        ArgumentCaptor<Map<String, String>> captureListener1Metrics =
+                ArgumentCaptor.forClass(Map.class);
+        verify(mMockListener1).testEnded(Mockito.eq(td), captureListener1Metrics.capture());
+        verify(mMockListener1).testRunEnded(27013, Collections.emptyMap());
+
+        verify(mMockListener2).testRunStarted(RUN_KEY, 1);
+        verify(mMockListener2).testStarted(td);
+        ArgumentCaptor<Map<String, String>> captureListener2Metrics =
+                ArgumentCaptor.forClass(Map.class);
+        verify(mMockListener2).testEnded(Mockito.eq(td), captureListener2Metrics.capture());
+        verify(mMockListener2).testRunEnded(27013, Collections.emptyMap());
 
         // Verify the test metrics
-        assertEquals("626",
-                captureListener1Metrics.getValue().get("metric_key1"));
-        assertEquals("1",
-                captureListener1Metrics.getValue()
-                        .get("metric_key2"));
+        assertEquals("626", captureListener1Metrics.getValue().get("metric_key1"));
+        assertEquals("1", captureListener1Metrics.getValue().get("metric_key2"));
 
         // Verify the test metrics
-        assertEquals("626",
-                captureListener2Metrics.getValue().get("metric_key1"));
-        assertEquals("1",
-                captureListener2Metrics.getValue()
-                        .get("metric_key2"));
+        assertEquals("626", captureListener2Metrics.getValue().get("metric_key1"));
+        assertEquals("1", captureListener2Metrics.getValue().get("metric_key2"));
     }
 
     /**
@@ -309,17 +348,23 @@
         protoTestFile = buildRunMetricSuccessProtoFile();
 
         TestIdentifier td = new TestIdentifier(CLASS_NAME_1, METHOD_NAME_1);
-        Capture<Map<String, String>> captureRunMetrics = new Capture<Map<String, String>>();
-        mMockListener.testRunStarted(RUN_KEY, 1);
-        mMockListener.testStarted(td);
-        mMockListener.testEnded(td, Collections.emptyMap());
-        mMockListener.testRunEnded(EasyMock.eq(27013L), EasyMock.capture(captureRunMetrics));
+        ArgumentCaptor<Map<String, String>> captureRunMetrics = ArgumentCaptor.forClass(Map.class);
 
-        processProtoAndVerify(protoTestFile);
+        mParser.processProtoFile(protoTestFile);
+
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted(RUN_KEY, 1);
+        inOrder.verify(mMockListener).testStarted(td);
+        inOrder.verify(mMockListener).testEnded(td, Collections.emptyMap());
+        inOrder.verify(mMockListener).testRunEnded(Mockito.eq(27013L), captureRunMetrics.capture());
+
+        verify(mMockListener).testRunStarted(RUN_KEY, 1);
+        verify(mMockListener).testStarted(td);
+        verify(mMockListener).testEnded(td, Collections.emptyMap());
+        verify(mMockListener).testRunEnded(Mockito.eq(27013L), captureRunMetrics.capture());
 
         // Verify run metrics
-        assertEquals("39584",
-                captureRunMetrics.getValue().get("run_metric_key"));
+        assertEquals("39584", captureRunMetrics.getValue().get("run_metric_key"));
     }
 
     /**
@@ -332,25 +377,28 @@
         protoTestFile = buildTestAndRunMetricSuccessProtoFile();
 
         TestIdentifier td = new TestIdentifier(CLASS_NAME_1, METHOD_NAME_1);
-        Capture<Map<String, String>> captureTestMetrics = new Capture<Map<String, String>>();
-        Capture<Map<String, String>> captureRunMetrics = new Capture<Map<String, String>>();
-        mMockListener.testRunStarted(RUN_KEY, 1);
-        mMockListener.testStarted(td);
-        mMockListener.testEnded(EasyMock.eq(td), EasyMock.capture(captureTestMetrics));
-        mMockListener.testRunEnded(EasyMock.eq(27013L), EasyMock.capture(captureRunMetrics));
+        ArgumentCaptor<Map<String, String>> captureTestMetrics = ArgumentCaptor.forClass(Map.class);
+        ArgumentCaptor<Map<String, String>> captureRunMetrics = ArgumentCaptor.forClass(Map.class);
 
-        processProtoAndVerify(protoTestFile);
+        mParser.processProtoFile(protoTestFile);
+
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted(RUN_KEY, 1);
+        inOrder.verify(mMockListener).testStarted(td);
+        inOrder.verify(mMockListener).testEnded(Mockito.eq(td), captureTestMetrics.capture());
+        inOrder.verify(mMockListener).testRunEnded(Mockito.eq(27013L), captureRunMetrics.capture());
+
+        verify(mMockListener).testRunStarted(RUN_KEY, 1);
+        verify(mMockListener).testStarted(td);
+        verify(mMockListener).testEnded(Mockito.eq(td), captureTestMetrics.capture());
+        verify(mMockListener).testRunEnded(Mockito.eq(27013L), captureRunMetrics.capture());
 
         // Verify the test metrics
-        assertEquals("626",
-                captureTestMetrics.getValue().get("metric_key1"));
-        assertEquals("1",
-                captureTestMetrics.getValue()
-                        .get("metric_key2"));
+        assertEquals("626", captureTestMetrics.getValue().get("metric_key1"));
+        assertEquals("1", captureTestMetrics.getValue().get("metric_key2"));
 
         // Verify run metrics
-        assertEquals("39584",
-                captureRunMetrics.getValue().get("run_metric_key"));
+        assertEquals("39584", captureRunMetrics.getValue().get("run_metric_key"));
     }
 
     /**
@@ -365,34 +413,37 @@
         TestIdentifier td1 = new TestIdentifier(CLASS_NAME_1, METHOD_NAME_1);
         TestIdentifier td2 = new TestIdentifier(CLASS_NAME_2, METHOD_NAME_2);
 
-        Capture<Map<String, String>> captureTest1Metrics = new Capture<Map<String, String>>();
-        Capture<Map<String, String>> captureTest2Metrics = new Capture<Map<String, String>>();
-        Capture<Map<String, String>> captureRunMetrics = new Capture<Map<String, String>>();
+        ArgumentCaptor<Map<String, String>> captureTest1Metrics =
+                ArgumentCaptor.forClass(Map.class);
+        ArgumentCaptor<Map<String, String>> captureTest2Metrics =
+                ArgumentCaptor.forClass(Map.class);
+        ArgumentCaptor<Map<String, String>> captureRunMetrics = ArgumentCaptor.forClass(Map.class);
 
-        mMockListener.testRunStarted(RUN_KEY, 2);
-        mMockListener.testStarted(td1);
-        mMockListener.testEnded(EasyMock.eq(td1), EasyMock.capture(captureTest1Metrics));
-        mMockListener.testStarted(td2);
-        mMockListener.testEnded(EasyMock.eq(td2), EasyMock.capture(captureTest2Metrics));
-        mMockListener.testRunEnded(EasyMock.eq(27013L), EasyMock.capture(captureRunMetrics));
+        mParser.processProtoFile(protoTestFile);
 
-        processProtoAndVerify(protoTestFile);
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted(RUN_KEY, 2);
+        inOrder.verify(mMockListener).testStarted(td1);
+        inOrder.verify(mMockListener).testEnded(Mockito.eq(td1), captureTest1Metrics.capture());
+        inOrder.verify(mMockListener).testStarted(td2);
+        inOrder.verify(mMockListener).testEnded(Mockito.eq(td2), captureTest2Metrics.capture());
+        inOrder.verify(mMockListener).testRunEnded(Mockito.eq(27013L), captureRunMetrics.capture());
+
+        verify(mMockListener).testRunStarted(RUN_KEY, 2);
+        verify(mMockListener).testStarted(td1);
+        verify(mMockListener).testEnded(Mockito.eq(td1), captureTest1Metrics.capture());
+        verify(mMockListener).testStarted(td2);
+        verify(mMockListener).testEnded(Mockito.eq(td2), captureTest2Metrics.capture());
+        verify(mMockListener).testRunEnded(Mockito.eq(27013L), captureRunMetrics.capture());
 
         // Verify the test1 and test2 metrics
-        assertEquals("626",
-                captureTest1Metrics.getValue().get("metric_key1"));
-        assertEquals("1",
-                captureTest1Metrics.getValue()
-                        .get("metric_key2"));
-        assertEquals("626",
-                captureTest2Metrics.getValue().get("metric_key1"));
-        assertEquals("1",
-                captureTest2Metrics.getValue()
-                        .get("metric_key2"));
+        assertEquals("626", captureTest1Metrics.getValue().get("metric_key1"));
+        assertEquals("1", captureTest1Metrics.getValue().get("metric_key2"));
+        assertEquals("626", captureTest2Metrics.getValue().get("metric_key1"));
+        assertEquals("1", captureTest2Metrics.getValue().get("metric_key2"));
 
         // Verify run metrics
-        assertEquals("39584",
-                captureRunMetrics.getValue().get("run_metric_key"));
+        assertEquals("39584", captureRunMetrics.getValue().get("run_metric_key"));
     }
 
     /**
@@ -405,22 +456,27 @@
         protoTestFile = buildSingleTestFailureProtoFile();
 
         TestIdentifier td = new TestIdentifier(CLASS_NAME_1, METHOD_NAME_1);
-        Capture<Map<String, String>> captureTestMetrics = new Capture<Map<String, String>>();
+        ArgumentCaptor<Map<String, String>> captureTestMetrics = ArgumentCaptor.forClass(Map.class);
 
-        mMockListener.testRunStarted(RUN_KEY, 1);
-        mMockListener.testStarted(td);
-        mMockListener.testFailed(EasyMock.eq(td), EasyMock.eq(TEST_FAILURE_MESSAGE_1));
-        mMockListener.testEnded(EasyMock.eq(td), EasyMock.capture(captureTestMetrics));
-        mMockListener.testRunEnded(27013, Collections.emptyMap());
+        mParser.processProtoFile(protoTestFile);
 
-        processProtoAndVerify(protoTestFile);
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted(RUN_KEY, 1);
+        inOrder.verify(mMockListener).testStarted(td);
+        inOrder.verify(mMockListener)
+                .testFailed(Mockito.eq(td), Mockito.eq(TEST_FAILURE_MESSAGE_1));
+        inOrder.verify(mMockListener).testEnded(Mockito.eq(td), captureTestMetrics.capture());
+        inOrder.verify(mMockListener).testRunEnded(27013, Collections.emptyMap());
+
+        verify(mMockListener).testRunStarted(RUN_KEY, 1);
+        verify(mMockListener).testStarted(td);
+        verify(mMockListener).testFailed(Mockito.eq(td), Mockito.eq(TEST_FAILURE_MESSAGE_1));
+        verify(mMockListener).testEnded(Mockito.eq(td), captureTestMetrics.capture());
+        verify(mMockListener).testRunEnded(27013, Collections.emptyMap());
 
         // Verify the test metrics
-        assertEquals("626",
-                captureTestMetrics.getValue().get("metric_key1"));
-        assertEquals("1",
-                captureTestMetrics.getValue()
-                        .get("metric_key2"));
+        assertEquals("626", captureTestMetrics.getValue().get("metric_key1"));
+        assertEquals("1", captureTestMetrics.getValue().get("metric_key2"));
     }
 
     /**
@@ -435,26 +491,32 @@
         TestIdentifier td1 = new TestIdentifier(CLASS_NAME_1, METHOD_NAME_1);
         TestIdentifier td2 = new TestIdentifier(CLASS_NAME_2, METHOD_NAME_2);
 
-        Capture<Map<String, String>> captureTest1Metrics = new Capture<Map<String, String>>();
+        ArgumentCaptor<Map<String, String>> captureTest1Metrics =
+                ArgumentCaptor.forClass(Map.class);
 
-        mMockListener.testRunStarted(RUN_KEY, 2);
-        mMockListener.testStarted(td1);
-        mMockListener.testEnded(EasyMock.eq(td1), EasyMock.capture(captureTest1Metrics));
+        mParser.processProtoFile(protoTestFile);
 
-        mMockListener.testStarted(td2);
-        mMockListener.testFailed(EasyMock.eq(td2), EasyMock.eq(TEST_FAILURE_MESSAGE_1));
-        mMockListener.testEnded(td2, Collections.emptyMap());
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted(RUN_KEY, 2);
+        inOrder.verify(mMockListener).testStarted(td1);
+        inOrder.verify(mMockListener).testEnded(Mockito.eq(td1), captureTest1Metrics.capture());
+        inOrder.verify(mMockListener).testStarted(td2);
+        inOrder.verify(mMockListener)
+                .testFailed(Mockito.eq(td2), Mockito.eq(TEST_FAILURE_MESSAGE_1));
+        inOrder.verify(mMockListener).testEnded(td2, Collections.emptyMap());
+        inOrder.verify(mMockListener).testRunEnded(27013, Collections.emptyMap());
 
-        mMockListener.testRunEnded(27013, Collections.emptyMap());
-
-        processProtoAndVerify(protoTestFile);
+        verify(mMockListener).testRunStarted(RUN_KEY, 2);
+        verify(mMockListener).testStarted(td1);
+        verify(mMockListener).testEnded(Mockito.eq(td1), captureTest1Metrics.capture());
+        verify(mMockListener).testStarted(td2);
+        verify(mMockListener).testFailed(Mockito.eq(td2), Mockito.eq(TEST_FAILURE_MESSAGE_1));
+        verify(mMockListener).testEnded(td2, Collections.emptyMap());
+        verify(mMockListener).testRunEnded(27013, Collections.emptyMap());
 
         // Verify the test metrics
-        assertEquals("626",
-                captureTest1Metrics.getValue().get("metric_key1"));
-        assertEquals("1",
-                captureTest1Metrics.getValue()
-                        .get("metric_key2"));
+        assertEquals("626", captureTest1Metrics.getValue().get("metric_key1"));
+        assertEquals("1", captureTest1Metrics.getValue().get("metric_key2"));
     }
 
     /**
@@ -465,25 +527,32 @@
     @Test
     public void testAllTestsIncomplete() throws IOException {
         protoTestFile = buildTestsIncompleteProtoFile();
-        Capture<String> testOutputErrorMessage = new Capture<>();
-        Capture<String> runOutputErrorMessage = new Capture<>();
+        ArgumentCaptor<String> testOutputErrorMessage = ArgumentCaptor.forClass(String.class);
+        ArgumentCaptor<String> runOutputErrorMessage = ArgumentCaptor.forClass(String.class);
 
         TestIdentifier td1 = new TestIdentifier(CLASS_NAME_1, METHOD_NAME_1);
-        mMockListener.testRunStarted(RUN_KEY, 2);
-        mMockListener.testStarted(td1);
-        mMockListener.testFailed(EasyMock.eq(td1), EasyMock.capture(testOutputErrorMessage));
-        mMockListener.testEnded(td1, Collections.emptyMap());
-        mMockListener.testRunFailed(EasyMock.capture(runOutputErrorMessage));
-        mMockListener.testRunEnded(0, Collections.emptyMap());
 
-        processProtoAndVerify(protoTestFile);
+        mParser.processProtoFile(protoTestFile);
 
-        assertTrue(testOutputErrorMessage.toString().contains(
-                INCOMPLETE_TEST_ERR_MSG_PREFIX));
-        assertTrue(testOutputErrorMessage.toString().contains(TEST_COMPLETED_STATUS_1));
-        assertTrue(runOutputErrorMessage.toString().contains(
-                INCOMPLETE_RUN_ERR_MSG_PREFIX));
-        assertTrue(runOutputErrorMessage.toString().contains(TEST_COMPLETED_STATUS_1));
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted(RUN_KEY, 2);
+        inOrder.verify(mMockListener).testStarted(td1);
+        inOrder.verify(mMockListener).testFailed(Mockito.eq(td1), Mockito.any(String.class));
+        inOrder.verify(mMockListener).testEnded(td1, Collections.emptyMap());
+        inOrder.verify(mMockListener).testRunFailed(Mockito.any(String.class));
+        inOrder.verify(mMockListener).testRunEnded(0, Collections.emptyMap());
+
+        verify(mMockListener).testRunStarted(RUN_KEY, 2);
+        verify(mMockListener).testStarted(td1);
+        verify(mMockListener).testFailed(Mockito.eq(td1), testOutputErrorMessage.capture());
+        verify(mMockListener).testEnded(td1, Collections.emptyMap());
+        verify(mMockListener).testRunFailed(runOutputErrorMessage.capture());
+        verify(mMockListener).testRunEnded(0, Collections.emptyMap());
+
+        assertTrue(testOutputErrorMessage.getValue().contains(INCOMPLETE_TEST_ERR_MSG_PREFIX));
+        assertTrue(testOutputErrorMessage.getValue().contains(TEST_COMPLETED_STATUS_1));
+        assertTrue(runOutputErrorMessage.getValue().contains(INCOMPLETE_RUN_ERR_MSG_PREFIX));
+        assertTrue(runOutputErrorMessage.getValue().contains(TEST_COMPLETED_STATUS_1));
     }
 
     /**
@@ -495,34 +564,40 @@
     public void testPartialTestsIncomplete() throws IOException {
         protoTestFile = buildPartialTestsIncompleteProtoFile();
 
-        Capture<String> testOutputErrorMessage = new Capture<>();
-        Capture<String> runOutputErrorMessage = new Capture<>();
+        ArgumentCaptor<String> testOutputErrorMessage = ArgumentCaptor.forClass(String.class);
+        ArgumentCaptor<String> runOutputErrorMessage = ArgumentCaptor.forClass(String.class);
         TestIdentifier td1 = new TestIdentifier(CLASS_NAME_1, METHOD_NAME_1);
         TestIdentifier td2 = new TestIdentifier(CLASS_NAME_2, METHOD_NAME_2);
-        Capture<Map<String, String>> captureTest1Metrics = new Capture<Map<String, String>>();
+        ArgumentCaptor<Map<String, String>> captureTest1Metrics =
+                ArgumentCaptor.forClass(Map.class);
 
-        mMockListener.testRunStarted(RUN_KEY, 2);
-        mMockListener.testStarted(td1);
-        mMockListener.testEnded(EasyMock.eq(td1), EasyMock.capture(captureTest1Metrics));
-        mMockListener.testStarted(td2);
-        mMockListener.testFailed(EasyMock.eq(td2), EasyMock.capture(testOutputErrorMessage));
-        mMockListener.testEnded(td2, Collections.emptyMap());
-        mMockListener.testRunFailed(EasyMock.capture(runOutputErrorMessage));
-        mMockListener.testRunEnded(0, Collections.emptyMap());
+        mParser.processProtoFile(protoTestFile);
 
-        processProtoAndVerify(protoTestFile);
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted(RUN_KEY, 2);
+        inOrder.verify(mMockListener).testStarted(td1);
+        inOrder.verify(mMockListener).testEnded(Mockito.eq(td1), Mockito.any(Map.class));
+        inOrder.verify(mMockListener).testStarted(td2);
+        inOrder.verify(mMockListener).testFailed(Mockito.eq(td2), Mockito.any(String.class));
+        inOrder.verify(mMockListener).testEnded(td2, Collections.emptyMap());
+        inOrder.verify(mMockListener).testRunFailed(Mockito.any(String.class));
+        inOrder.verify(mMockListener).testRunEnded(0, Collections.emptyMap());
 
-        assertEquals("626",
-                captureTest1Metrics.getValue().get("metric_key1"));
-        assertEquals("1",
-                captureTest1Metrics.getValue()
-                        .get("metric_key2"));
-        assertTrue(testOutputErrorMessage.toString().contains(
-                INCOMPLETE_TEST_ERR_MSG_PREFIX));
-        assertTrue(testOutputErrorMessage.toString().contains(TEST_COMPLETED_STATUS_2));
-        assertTrue(runOutputErrorMessage.toString().contains(
-                INCOMPLETE_RUN_ERR_MSG_PREFIX));
-        assertTrue(runOutputErrorMessage.toString().contains(TEST_COMPLETED_STATUS_2));
+        verify(mMockListener).testRunStarted(RUN_KEY, 2);
+        verify(mMockListener).testStarted(td1);
+        verify(mMockListener).testEnded(Mockito.eq(td1), captureTest1Metrics.capture());
+        verify(mMockListener).testStarted(td2);
+        verify(mMockListener).testFailed(Mockito.eq(td2), testOutputErrorMessage.capture());
+        verify(mMockListener).testEnded(td2, Collections.emptyMap());
+        verify(mMockListener).testRunFailed(runOutputErrorMessage.capture());
+        verify(mMockListener).testRunEnded(0, Collections.emptyMap());
+
+        assertEquals("626", captureTest1Metrics.getValue().get("metric_key1"));
+        assertEquals("1", captureTest1Metrics.getValue().get("metric_key2"));
+        assertTrue(testOutputErrorMessage.getValue().contains(INCOMPLETE_TEST_ERR_MSG_PREFIX));
+        assertTrue(testOutputErrorMessage.getValue().contains(TEST_COMPLETED_STATUS_2));
+        assertTrue(runOutputErrorMessage.getValue().contains(INCOMPLETE_RUN_ERR_MSG_PREFIX));
+        assertTrue(runOutputErrorMessage.getValue().contains(TEST_COMPLETED_STATUS_2));
     }
 
     /**
@@ -533,26 +608,30 @@
     @Test
     public void testOneTestNotStarted() throws IOException {
         protoTestFile = buildOneTestNotStarted();
-        Capture<String> runOutputErrorMessage = new Capture<>();
+        ArgumentCaptor<String> runOutputErrorMessage = ArgumentCaptor.forClass(String.class);
         TestIdentifier td1 = new TestIdentifier(CLASS_NAME_1, METHOD_NAME_1);
-        Capture<Map<String, String>> captureTest1Metrics = new Capture<Map<String, String>>();
+        ArgumentCaptor<Map<String, String>> captureTest1Metrics =
+                ArgumentCaptor.forClass(Map.class);
 
-        mMockListener.testRunStarted(RUN_KEY, 2);
-        mMockListener.testStarted(td1);
-        mMockListener.testEnded(EasyMock.eq(td1), EasyMock.capture(captureTest1Metrics));
-        mMockListener.testRunFailed(EasyMock.capture(runOutputErrorMessage));
-        mMockListener.testRunEnded(0, Collections.emptyMap());
+        mParser.processProtoFile(protoTestFile);
 
-        processProtoAndVerify(protoTestFile);
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted(RUN_KEY, 2);
+        inOrder.verify(mMockListener).testStarted(td1);
+        inOrder.verify(mMockListener).testEnded(Mockito.eq(td1), Mockito.any(Map.class));
+        inOrder.verify(mMockListener).testRunFailed(Mockito.any(String.class));
+        inOrder.verify(mMockListener).testRunEnded(0, Collections.emptyMap());
 
-        assertEquals("626",
-                captureTest1Metrics.getValue().get("metric_key1"));
-        assertEquals("1",
-                captureTest1Metrics.getValue()
-                        .get("metric_key2"));
-        assertTrue(runOutputErrorMessage.toString().contains(
-                INCOMPLETE_RUN_ERR_MSG_PREFIX));
-        assertTrue(runOutputErrorMessage.toString().contains(TEST_COMPLETED_STATUS_2));
+        verify(mMockListener).testRunStarted(RUN_KEY, 2);
+        verify(mMockListener).testStarted(td1);
+        verify(mMockListener).testEnded(Mockito.eq(td1), captureTest1Metrics.capture());
+        verify(mMockListener).testRunFailed(runOutputErrorMessage.capture());
+        verify(mMockListener).testRunEnded(0, Collections.emptyMap());
+
+        assertEquals("626", captureTest1Metrics.getValue().get("metric_key1"));
+        assertEquals("1", captureTest1Metrics.getValue().get("metric_key2"));
+        assertTrue(runOutputErrorMessage.getValue().contains(INCOMPLETE_RUN_ERR_MSG_PREFIX));
+        assertTrue(runOutputErrorMessage.getValue().contains(TEST_COMPLETED_STATUS_2));
     }
 
     /**
@@ -564,10 +643,14 @@
     public void testTimeStampMissingNotEnforced() throws IOException {
         protoTestFile = buildInvalidTimeStampResultsProto(false);
 
-        mMockListener.testRunStarted(RUN_KEY, 0);
-        mMockListener.testRunEnded(0, Collections.emptyMap());
+        mParser.processProtoFile(protoTestFile);
 
-        processProtoAndVerify(protoTestFile);
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted(RUN_KEY, 0);
+        inOrder.verify(mMockListener).testRunEnded(0, Collections.emptyMap());
+
+        verify(mMockListener).testRunStarted(RUN_KEY, 0);
+        verify(mMockListener).testRunEnded(0, Collections.emptyMap());
     }
 
     /**
@@ -581,12 +664,18 @@
     public void testDirectFailure() throws IOException {
         protoTestFile = buildValidTimeStampWithFatalExceptionResultsProto();
 
-        Capture<String> capture = new Capture<>();
-        mMockListener.testRunStarted(RUN_KEY, 0);
-        mMockListener.testRunFailed(EasyMock.capture(capture));
-        mMockListener.testRunEnded(0, Collections.emptyMap());
+        ArgumentCaptor<String> capture = ArgumentCaptor.forClass(String.class);
 
-        processProtoAndVerify(protoTestFile);
+        mParser.processProtoFile(protoTestFile);
+
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted(RUN_KEY, 0);
+        inOrder.verify(mMockListener).testRunFailed(capture.capture());
+        inOrder.verify(mMockListener).testRunEnded(0, Collections.emptyMap());
+
+        verify(mMockListener).testRunStarted(RUN_KEY, 0);
+        verify(mMockListener).testRunFailed(capture.capture());
+        verify(mMockListener).testRunEnded(0, Collections.emptyMap());
 
         String failure = capture.getValue();
         assertTrue(failure.contains("java.lang.RuntimeException: it failed super fast."));
@@ -601,14 +690,22 @@
     public void testIgnoreProtoResult() throws IOException {
         protoTestFile = buildTestIgnoredResultsProto();
 
-        mMockListener.testRunStarted(RUN_KEY, 1);
         TestIdentifier td1 = new TestIdentifier(CLASS_NAME_1, METHOD_NAME_1);
-        mMockListener.testStarted(td1);
-        mMockListener.testIgnored(td1);
-        mMockListener.testEnded(td1, Collections.emptyMap());
-        mMockListener.testRunEnded(27013, Collections.emptyMap());
 
-        processProtoAndVerify(protoTestFile);
+        mParser.processProtoFile(protoTestFile);
+
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted(RUN_KEY, 1);
+        inOrder.verify(mMockListener).testStarted(td1);
+        inOrder.verify(mMockListener).testIgnored(td1);
+        inOrder.verify(mMockListener).testEnded(td1, Collections.emptyMap());
+        inOrder.verify(mMockListener).testRunEnded(27013, Collections.emptyMap());
+
+        verify(mMockListener).testRunStarted(RUN_KEY, 1);
+        verify(mMockListener).testStarted(td1);
+        verify(mMockListener).testIgnored(td1);
+        verify(mMockListener).testEnded(td1, Collections.emptyMap());
+        verify(mMockListener).testRunEnded(27013, Collections.emptyMap());
     }
 
     /**
@@ -620,17 +717,32 @@
     public void testAssumptionProtoResult() throws IOException {
         protoTestFile = buildTestAssumptionResultsProto();
 
-        mMockListener.testRunStarted(RUN_KEY, 1);
         TestIdentifier td1 = new TestIdentifier(CLASS_NAME_1, METHOD_NAME_1);
-        mMockListener.testStarted(td1);
-        mMockListener.testAssumptionFailure(EasyMock.eq(td1),
-                EasyMock.startsWith(
-                        "org.junit.AssumptionViolatedException:"
-                                + " got: <false>, expected: is <true>"));
-        mMockListener.testEnded(td1, Collections.emptyMap());
-        mMockListener.testRunEnded(27013, Collections.emptyMap());
-        processProtoAndVerify(protoTestFile);
 
+        mParser.processProtoFile(protoTestFile);
+
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted(RUN_KEY, 1);
+        inOrder.verify(mMockListener).testStarted(td1);
+        inOrder.verify(mMockListener)
+                .testAssumptionFailure(
+                        Mockito.eq(td1),
+                        Mockito.startsWith(
+                                "org.junit.AssumptionViolatedException:"
+                                        + " got: <false>, expected: is <true>"));
+        inOrder.verify(mMockListener).testEnded(td1, Collections.emptyMap());
+        inOrder.verify(mMockListener).testRunEnded(27013, Collections.emptyMap());
+
+        verify(mMockListener).testRunStarted(RUN_KEY, 1);
+        verify(mMockListener).testStarted(td1);
+        verify(mMockListener)
+                .testAssumptionFailure(
+                        Mockito.eq(td1),
+                        Mockito.startsWith(
+                                "org.junit.AssumptionViolatedException:"
+                                        + " got: <false>, expected: is <true>"));
+        verify(mMockListener).testEnded(td1, Collections.emptyMap());
+        verify(mMockListener).testRunEnded(27013, Collections.emptyMap());
     }
 
     @After
@@ -640,15 +752,9 @@
         }
     }
 
-    private void processProtoAndVerify(File protoTestFile) throws IOException {
-        EasyMock.replay(mMockListener);
-        mParser.processProtoFile(protoTestFile);
-        EasyMock.verify(mMockListener);
-    }
-
     private File buildNoTestResultsProtoFile() throws IOException {
-        Session sessionProto = Session.newBuilder()
-                .setSessionStatus(getSessionStatusProto(false, false)).build();
+        Session sessionProto =
+                Session.newBuilder().setSessionStatus(getSessionStatusProto(false, false)).build();
         File protoFile = File.createTempFile("tmp", ".pb");
         sessionProto.writeTo(new FileOutputStream(protoFile));
         return protoFile;
@@ -662,8 +768,11 @@
         testStatusList.add(getTestStatusProto(true));
         // Test End
         testStatusList.add(getTestInfoProto(CLASS_NAME_1, METHOD_NAME_1, 1, 1, false, false));
-        Session sessionProto = Session.newBuilder().addAllTestStatus(testStatusList)
-                .setSessionStatus(getSessionStatusProto(false, false)).build();
+        Session sessionProto =
+                Session.newBuilder()
+                        .addAllTestStatus(testStatusList)
+                        .setSessionStatus(getSessionStatusProto(false, false))
+                        .build();
         File protoFile = File.createTempFile("tmp", ".pb");
         sessionProto.writeTo(new FileOutputStream(protoFile));
         return protoFile;
@@ -678,8 +787,11 @@
         // Test End.
         testStatusList.add(getTestInfoProto(CLASS_NAME_1, METHOD_NAME_1, 1, 1, false, false));
         // Session with metrics.
-        Session sessionProto = Session.newBuilder().addAllTestStatus(testStatusList)
-                .setSessionStatus(getSessionStatusProto(true, false)).build();
+        Session sessionProto =
+                Session.newBuilder()
+                        .addAllTestStatus(testStatusList)
+                        .setSessionStatus(getSessionStatusProto(true, false))
+                        .build();
         File protoFile = File.createTempFile("tmp", ".pb");
         sessionProto.writeTo(new FileOutputStream(protoFile));
         return protoFile;
@@ -694,8 +806,11 @@
         // Test End.
         testStatusList.add(getTestInfoProto(CLASS_NAME_1, METHOD_NAME_1, 1, 1, false, false));
         // Session with metrics.
-        Session sessionProto = Session.newBuilder().addAllTestStatus(testStatusList)
-                .setSessionStatus(getSessionStatusProto(true, false)).build();
+        Session sessionProto =
+                Session.newBuilder()
+                        .addAllTestStatus(testStatusList)
+                        .setSessionStatus(getSessionStatusProto(true, false))
+                        .build();
         File protoFile = File.createTempFile("tmp", ".pb");
         sessionProto.writeTo(new FileOutputStream(protoFile));
         return protoFile;
@@ -716,8 +831,11 @@
         // Test End.
         testStatusList.add(getTestInfoProto(CLASS_NAME_2, METHOD_NAME_2, 2, 2, false, false));
         // Session with metrics.
-        Session sessionProto = Session.newBuilder().addAllTestStatus(testStatusList)
-                .setSessionStatus(getSessionStatusProto(true, false)).build();
+        Session sessionProto =
+                Session.newBuilder()
+                        .addAllTestStatus(testStatusList)
+                        .setSessionStatus(getSessionStatusProto(true, false))
+                        .build();
         File protoFile = File.createTempFile("tmp", ".pb");
         sessionProto.writeTo(new FileOutputStream(protoFile));
         return protoFile;
@@ -732,8 +850,11 @@
         // Test End.
         testStatusList.add(getTestInfoProto(CLASS_NAME_1, METHOD_NAME_1, 1, 1, false, true));
         // Session with metrics.
-        Session sessionProto = Session.newBuilder().addAllTestStatus(testStatusList)
-                .setSessionStatus(getSessionStatusProto(false, false)).build();
+        Session sessionProto =
+                Session.newBuilder()
+                        .addAllTestStatus(testStatusList)
+                        .setSessionStatus(getSessionStatusProto(false, false))
+                        .build();
         File protoFile = File.createTempFile("tmp", ".pb");
         sessionProto.writeTo(new FileOutputStream(protoFile));
         return protoFile;
@@ -753,8 +874,11 @@
         // Test End.
         testStatusList.add(getTestInfoProto(CLASS_NAME_2, METHOD_NAME_2, 2, 2, false, true));
         // Session with metrics.
-        Session sessionProto = Session.newBuilder().addAllTestStatus(testStatusList)
-                .setSessionStatus(getSessionStatusProto(false, false)).build();
+        Session sessionProto =
+                Session.newBuilder()
+                        .addAllTestStatus(testStatusList)
+                        .setSessionStatus(getSessionStatusProto(false, false))
+                        .build();
         File protoFile = File.createTempFile("tmp", ".pb");
         sessionProto.writeTo(new FileOutputStream(protoFile));
         return protoFile;
@@ -766,12 +890,10 @@
         testStatusList.add(getTestInfoProto(CLASS_NAME_1, METHOD_NAME_1, 1, 2, true, false));
 
         // Session with metrics.
-        Session sessionProto = Session.newBuilder().addAllTestStatus(testStatusList)
-                .build();
+        Session sessionProto = Session.newBuilder().addAllTestStatus(testStatusList).build();
         File protoFile = File.createTempFile("tmp", ".pb");
         sessionProto.writeTo(new FileOutputStream(protoFile));
         return protoFile;
-
     }
 
     private File buildPartialTestsIncompleteProtoFile() throws IOException {
@@ -815,26 +937,29 @@
         List<ResultsBundleEntry> entryList = new LinkedList<ResultsBundleEntry>();
 
         if (isWithStack) {
-            entryList.add(ResultsBundleEntry.newBuilder()
-                    .setKey("stream")
-                    .setValueString(FATAL_EXCEPTION_MSG
-                            + " java.lang.IllegalArgumentException: Ambiguous arguments: "
-                            + "cannot provide both test package and test class(es) to run")
-                    .build());
+            entryList.add(
+                    ResultsBundleEntry.newBuilder()
+                            .setKey("stream")
+                            .setValueString(
+                                    FATAL_EXCEPTION_MSG
+                                            + " java.lang.IllegalArgumentException: Ambiguous"
+                                            + " arguments: cannot provide both test package and"
+                                            + " test class(es) to run")
+                            .build());
         } else {
-            entryList.add(ResultsBundleEntry.newBuilder()
-                    .setKey("stream").setValueString("")
-                    .build());
+            entryList.add(
+                    ResultsBundleEntry.newBuilder().setKey("stream").setValueString("").build());
         }
 
-        SessionStatus sessionStatus = SessionStatus.newBuilder().setResultCode(-1)
-                .setStatusCode(SessionStatusCode.SESSION_FINISHED)
-                .setResults(ResultsBundle.newBuilder().addAllEntries(entryList).build())
-                .build();
+        SessionStatus sessionStatus =
+                SessionStatus.newBuilder()
+                        .setResultCode(-1)
+                        .setStatusCode(SessionStatusCode.SESSION_FINISHED)
+                        .setResults(ResultsBundle.newBuilder().addAllEntries(entryList).build())
+                        .build();
 
         // Session with metrics.
-        Session sessionProto = Session.newBuilder()
-                .setSessionStatus(sessionStatus).build();
+        Session sessionProto = Session.newBuilder().setSessionStatus(sessionStatus).build();
         File protoFile = File.createTempFile("tmp", ".pb");
         sessionProto.writeTo(new FileOutputStream(protoFile));
         return protoFile;
@@ -843,24 +968,26 @@
     private File buildValidTimeStampWithFatalExceptionResultsProto() throws IOException {
         List<ResultsBundleEntry> entryList = new LinkedList<ResultsBundleEntry>();
 
-        entryList.add(ResultsBundleEntry.newBuilder()
-                .setKey("stream")
-                .setValueString(FATAL_EXCEPTION_MSG
-                        + "Time: 0 \n"
-                        + "1) Fatal exception when running tests"
-                        + "java.lang.RuntimeException: it failed super fast."
-                        + "at stackstack"
-                )
-                .build());
+        entryList.add(
+                ResultsBundleEntry.newBuilder()
+                        .setKey("stream")
+                        .setValueString(
+                                FATAL_EXCEPTION_MSG
+                                        + "Time: 0 \n"
+                                        + "1) Fatal exception when running tests"
+                                        + "java.lang.RuntimeException: it failed super fast."
+                                        + "at stackstack")
+                        .build());
 
-        SessionStatus sessionStatus = SessionStatus.newBuilder().setResultCode(-1)
-                .setStatusCode(SessionStatusCode.SESSION_FINISHED)
-                .setResults(ResultsBundle.newBuilder().addAllEntries(entryList).build())
-                .build();
+        SessionStatus sessionStatus =
+                SessionStatus.newBuilder()
+                        .setResultCode(-1)
+                        .setStatusCode(SessionStatusCode.SESSION_FINISHED)
+                        .setResults(ResultsBundle.newBuilder().addAllEntries(entryList).build())
+                        .build();
 
         // Session with metrics.
-        Session sessionProto = Session.newBuilder()
-                .setSessionStatus(sessionStatus).build();
+        Session sessionProto = Session.newBuilder().setSessionStatus(sessionStatus).build();
         File protoFile = File.createTempFile("tmp", ".pb");
         sessionProto.writeTo(new FileOutputStream(protoFile));
         return protoFile;
@@ -874,24 +1001,36 @@
 
         // Test ignore status result.
         List<ResultsBundleEntry> entryList = new LinkedList<ResultsBundleEntry>();
-        entryList.add(ResultsBundleEntry.newBuilder().setKey("class").setValueString(CLASS_NAME_1)
-                .build());
-        entryList.add(ResultsBundleEntry.newBuilder().setKey("current").setValueInt(1)
-                .build());
-        entryList.add(ResultsBundleEntry.newBuilder().setKey("id")
-                .setValueString("AndroidJUnitRunner").build());
-        entryList.add(ResultsBundleEntry.newBuilder().setKey("numtests").setValueInt(1)
-                .build());
+        entryList.add(
+                ResultsBundleEntry.newBuilder()
+                        .setKey("class")
+                        .setValueString(CLASS_NAME_1)
+                        .build());
+        entryList.add(ResultsBundleEntry.newBuilder().setKey("current").setValueInt(1).build());
+        entryList.add(
+                ResultsBundleEntry.newBuilder()
+                        .setKey("id")
+                        .setValueString("AndroidJUnitRunner")
+                        .build());
+        entryList.add(ResultsBundleEntry.newBuilder().setKey("numtests").setValueInt(1).build());
 
-        entryList.add(ResultsBundleEntry.newBuilder().setKey("test").setValueString(METHOD_NAME_1)
-                .build());
+        entryList.add(
+                ResultsBundleEntry.newBuilder()
+                        .setKey("test")
+                        .setValueString(METHOD_NAME_1)
+                        .build());
 
-        testStatusList.add(TestStatus.newBuilder().setResultCode(-3)
-                .setResults(ResultsBundle.newBuilder().addAllEntries(entryList).build())
-                .build());
+        testStatusList.add(
+                TestStatus.newBuilder()
+                        .setResultCode(-3)
+                        .setResults(ResultsBundle.newBuilder().addAllEntries(entryList).build())
+                        .build());
 
-        Session sessionProto = Session.newBuilder().addAllTestStatus(testStatusList)
-                .setSessionStatus(getSessionStatusProto(false, false)).build();
+        Session sessionProto =
+                Session.newBuilder()
+                        .addAllTestStatus(testStatusList)
+                        .setSessionStatus(getSessionStatusProto(false, false))
+                        .build();
         File protoFile = File.createTempFile("tmp", ".pb");
         sessionProto.writeTo(new FileOutputStream(protoFile));
         return protoFile;
@@ -906,25 +1045,41 @@
 
         // Test ignore status result.
         List<ResultsBundleEntry> entryList = new LinkedList<ResultsBundleEntry>();
-        entryList.add(ResultsBundleEntry.newBuilder().setKey("class").setValueString(CLASS_NAME_1)
-                .build());
-        entryList.add(ResultsBundleEntry.newBuilder().setKey("current").setValueInt(1)
-                .build());
-        entryList.add(ResultsBundleEntry.newBuilder().setKey("id")
-                .setValueString("AndroidJUnitRunner").build());
-        entryList.add(ResultsBundleEntry.newBuilder().setKey("numtests").setValueInt(1)
-                .build());
-        entryList.add(ResultsBundleEntry.newBuilder().setKey("test").setValueString(METHOD_NAME_1)
-                .build());
-        entryList.add(ResultsBundleEntry.newBuilder().setKey("stack").setValueString(
-                "org.junit.AssumptionViolatedException: got: <false>, expected: is <true>")
-                .build());
-        testStatusList.add(TestStatus.newBuilder().setResultCode(-4)
-                .setResults(ResultsBundle.newBuilder().addAllEntries(entryList).build())
-                .build());
+        entryList.add(
+                ResultsBundleEntry.newBuilder()
+                        .setKey("class")
+                        .setValueString(CLASS_NAME_1)
+                        .build());
+        entryList.add(ResultsBundleEntry.newBuilder().setKey("current").setValueInt(1).build());
+        entryList.add(
+                ResultsBundleEntry.newBuilder()
+                        .setKey("id")
+                        .setValueString("AndroidJUnitRunner")
+                        .build());
+        entryList.add(ResultsBundleEntry.newBuilder().setKey("numtests").setValueInt(1).build());
+        entryList.add(
+                ResultsBundleEntry.newBuilder()
+                        .setKey("test")
+                        .setValueString(METHOD_NAME_1)
+                        .build());
+        entryList.add(
+                ResultsBundleEntry.newBuilder()
+                        .setKey("stack")
+                        .setValueString(
+                                "org.junit.AssumptionViolatedException: got: <false>, expected: is"
+                                        + " <true>")
+                        .build());
+        testStatusList.add(
+                TestStatus.newBuilder()
+                        .setResultCode(-4)
+                        .setResults(ResultsBundle.newBuilder().addAllEntries(entryList).build())
+                        .build());
 
-        Session sessionProto = Session.newBuilder().addAllTestStatus(testStatusList)
-                .setSessionStatus(getSessionStatusProto(false, false)).build();
+        Session sessionProto =
+                Session.newBuilder()
+                        .addAllTestStatus(testStatusList)
+                        .setSessionStatus(getSessionStatusProto(false, false))
+                        .build();
         File protoFile = File.createTempFile("tmp", ".pb");
         sessionProto.writeTo(new FileOutputStream(protoFile));
         return protoFile;
@@ -941,46 +1096,61 @@
      * @param isFailure true if the test if failed.
      * @return
      */
-    private TestStatus getTestInfoProto(String className, String methodName, int current,
-            int numTests, boolean isStart, boolean isFailure) {
+    private TestStatus getTestInfoProto(
+            String className,
+            String methodName,
+            int current,
+            int numTests,
+            boolean isStart,
+            boolean isFailure) {
         List<ResultsBundleEntry> entryList = new LinkedList<ResultsBundleEntry>();
-        entryList.add(ResultsBundleEntry.newBuilder().setKey("class").setValueString(className)
-                .build());
-        entryList.add(ResultsBundleEntry.newBuilder().setKey("current").setValueInt(current)
-                .build());
-        entryList.add(ResultsBundleEntry.newBuilder().setKey("id")
-                .setValueString("AndroidJUnitRunner").build());
-        entryList.add(ResultsBundleEntry.newBuilder().setKey("numtests").setValueInt(numTests)
-                .build());
+        entryList.add(
+                ResultsBundleEntry.newBuilder().setKey("class").setValueString(className).build());
+        entryList.add(
+                ResultsBundleEntry.newBuilder().setKey("current").setValueInt(current).build());
+        entryList.add(
+                ResultsBundleEntry.newBuilder()
+                        .setKey("id")
+                        .setValueString("AndroidJUnitRunner")
+                        .build());
+        entryList.add(
+                ResultsBundleEntry.newBuilder().setKey("numtests").setValueInt(numTests).build());
 
-        entryList.add(ResultsBundleEntry.newBuilder().setKey("test").setValueString(methodName)
-                .build());
+        entryList.add(
+                ResultsBundleEntry.newBuilder().setKey("test").setValueString(methodName).build());
 
         if (isFailure) {
-            entryList.add(ResultsBundleEntry.newBuilder().setKey("stack")
-                    .setValueString(TEST_FAILURE_MESSAGE_1)
-                    .build());
-            entryList.add(ResultsBundleEntry.newBuilder().setKey("stream")
-                    .setValueString(TEST_FAILURE_MESSAGE_1)
-                    .build());
+            entryList.add(
+                    ResultsBundleEntry.newBuilder()
+                            .setKey("stack")
+                            .setValueString(TEST_FAILURE_MESSAGE_1)
+                            .build());
+            entryList.add(
+                    ResultsBundleEntry.newBuilder()
+                            .setKey("stream")
+                            .setValueString(TEST_FAILURE_MESSAGE_1)
+                            .build());
             // Test failure will have result code "-2"
-            return TestStatus.newBuilder().setResultCode(-2)
+            return TestStatus.newBuilder()
+                    .setResultCode(-2)
                     .setResults(ResultsBundle.newBuilder().addAllEntries(entryList).build())
                     .build();
         }
 
-        entryList.add(ResultsBundleEntry.newBuilder().setKey("stream").setValueString("\nabc:")
-                .build());
+        entryList.add(
+                ResultsBundleEntry.newBuilder().setKey("stream").setValueString("\nabc:").build());
 
         if (isStart) {
             // Test start will have result code 1.
-            return TestStatus.newBuilder().setResultCode(1)
+            return TestStatus.newBuilder()
+                    .setResultCode(1)
                     .setResults(ResultsBundle.newBuilder().addAllEntries(entryList).build())
                     .build();
         }
 
         return TestStatus.newBuilder()
-                .setResults(ResultsBundle.newBuilder().addAllEntries(entryList).build()).build();
+                .setResults(ResultsBundle.newBuilder().addAllEntries(entryList).build())
+                .build();
     }
 
     /**
@@ -992,16 +1162,21 @@
     private TestStatus getTestStatusProto(boolean isWithMetrics) {
         List<ResultsBundleEntry> entryList = new LinkedList<ResultsBundleEntry>();
         if (isWithMetrics) {
-            entryList.add(ResultsBundleEntry.newBuilder()
-                    .setKey("metric_key1").setValueString("626")
-                    .build());
-            entryList.add(ResultsBundleEntry.newBuilder()
-                    .setKey("metric_key2").setValueString("1")
-                    .build());
+            entryList.add(
+                    ResultsBundleEntry.newBuilder()
+                            .setKey("metric_key1")
+                            .setValueString("626")
+                            .build());
+            entryList.add(
+                    ResultsBundleEntry.newBuilder()
+                            .setKey("metric_key2")
+                            .setValueString("1")
+                            .build());
         }
 
         // Metric status will be in progress
-        return TestStatus.newBuilder().setResultCode(2)
+        return TestStatus.newBuilder()
+                .setResultCode(2)
                 .setResults(ResultsBundle.newBuilder().addAllEntries(entryList).build())
                 .build();
     }
@@ -1018,31 +1193,38 @@
         List<ResultsBundleEntry> entryList = new LinkedList<ResultsBundleEntry>();
 
         if (isFailure) {
-            entryList.add(ResultsBundleEntry.newBuilder()
-                    .setKey("Error").setValueString(RUN_FAILURE_MESSAGE)
-                    .build());
-            entryList.add(ResultsBundleEntry.newBuilder()
-                    .setKey("id").setValueString("ActivityManagerService")
-                    .build());
-            return SessionStatus.newBuilder().setResultCode(-1)
+            entryList.add(
+                    ResultsBundleEntry.newBuilder()
+                            .setKey("Error")
+                            .setValueString(RUN_FAILURE_MESSAGE)
+                            .build());
+            entryList.add(
+                    ResultsBundleEntry.newBuilder()
+                            .setKey("id")
+                            .setValueString("ActivityManagerService")
+                            .build());
+            return SessionStatus.newBuilder()
+                    .setResultCode(-1)
                     .setStatusCode(SessionStatusCode.SESSION_FINISHED)
                     .setResults(ResultsBundle.newBuilder().addAllEntries(entryList).build())
                     .build();
-
         }
-        entryList.add(ResultsBundleEntry.newBuilder()
-                .setKey("stream").setValueString("\n\nTime: 27.013\n\nOK (1 test)\n\n")
-                .build());
+        entryList.add(
+                ResultsBundleEntry.newBuilder()
+                        .setKey("stream")
+                        .setValueString("\n\nTime: 27.013\n\nOK (1 test)\n\n")
+                        .build());
 
         if (isWithMetrics) {
-            entryList.add(ResultsBundleEntry.newBuilder()
-                    .setKey("run_metric_key").setValueString("39584")
-                    .build());
+            entryList.add(
+                    ResultsBundleEntry.newBuilder()
+                            .setKey("run_metric_key")
+                            .setValueString("39584")
+                            .build());
         }
 
-
-
-        return SessionStatus.newBuilder().setResultCode(-1)
+        return SessionStatus.newBuilder()
+                .setResultCode(-1)
                 .setStatusCode(SessionStatusCode.SESSION_FINISHED)
                 .setResults(ResultsBundle.newBuilder().addAllEntries(entryList).build())
                 .build();
diff --git a/javatests/com/android/tradefed/result/proto/FileProtoResultReporterTest.java b/javatests/com/android/tradefed/result/proto/FileProtoResultReporterTest.java
index 51e0cc6..1938b4c 100644
--- a/javatests/com/android/tradefed/result/proto/FileProtoResultReporterTest.java
+++ b/javatests/com/android/tradefed/result/proto/FileProtoResultReporterTest.java
@@ -18,6 +18,8 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 
 import com.android.tradefed.config.ConfigurationDescriptor;
 import com.android.tradefed.config.OptionSetter;
@@ -34,12 +36,14 @@
 
 import com.google.protobuf.Any;
 
-import org.easymock.EasyMock;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -53,14 +57,15 @@
     private FileProtoResultReporter mReporter;
     private File mOutput;
     private List<File> mToDelete = new ArrayList<>();
-    private ITestInvocationListener mMockListener;
+    @Mock ITestInvocationListener mMockListener;
 
     @Before
     public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
         mOutput = FileUtil.createTempFile("proto-file-reporter-test", ".pb");
         mReporter = new FileProtoResultReporter();
         mReporter.setFileOutput(mOutput);
-        mMockListener = EasyMock.createMock(ITestInvocationListener.class);
     }
 
     @After
@@ -123,30 +128,6 @@
             fail("Should have output at least one file");
         }
 
-        mMockListener.invocationStarted(EasyMock.anyObject());
-        mMockListener.testModuleStarted(EasyMock.anyObject());
-        mMockListener.testRunStarted(
-                EasyMock.eq("run1"), EasyMock.eq(1), EasyMock.eq(0), EasyMock.anyLong());
-        mMockListener.testStarted(EasyMock.eq(test1), EasyMock.anyLong());
-        mMockListener.testEnded(
-                EasyMock.eq(test1),
-                EasyMock.anyLong(),
-                EasyMock.<HashMap<String, Metric>>anyObject());
-        mMockListener.testRunEnded(200L, new HashMap<String, Metric>());
-        mMockListener.testModuleEnded();
-        mMockListener.testModuleStarted(EasyMock.anyObject());
-        mMockListener.testModuleEnded();
-        mMockListener.testRunStarted(
-                EasyMock.eq("run2"), EasyMock.eq(1), EasyMock.eq(0), EasyMock.anyLong());
-        mMockListener.testStarted(EasyMock.eq(test1), EasyMock.anyLong());
-        mMockListener.testEnded(
-                EasyMock.eq(test1),
-                EasyMock.anyLong(),
-                EasyMock.<HashMap<String, Metric>>anyObject());
-        mMockListener.testRunEnded(200L, new HashMap<String, Metric>());
-        mMockListener.invocationEnded(500L);
-
-        EasyMock.replay(mMockListener);
         ProtoResultParser parser = new ProtoResultParser(mMockListener, context, true);
         while (currentOutput.exists()) {
             mToDelete.add(currentOutput);
@@ -154,7 +135,24 @@
             index++;
             currentOutput = new File(mOutput.getAbsolutePath() + index);
         }
-        EasyMock.verify(mMockListener);
+
+        verify(mMockListener).invocationStarted(Mockito.any());
+        verify(mMockListener, times(2)).testModuleStarted(Mockito.any());
+        verify(mMockListener)
+                .testRunStarted(
+                        Mockito.eq("run1"), Mockito.eq(1), Mockito.eq(0), Mockito.anyLong());
+        verify(mMockListener, times(2)).testStarted(Mockito.eq(test1), Mockito.anyLong());
+        verify(mMockListener, times(2))
+                .testEnded(
+                        Mockito.eq(test1),
+                        Mockito.anyLong(),
+                        Mockito.<HashMap<String, Metric>>any());
+        verify(mMockListener, times(2)).testRunEnded(200L, new HashMap<String, Metric>());
+        verify(mMockListener, times(2)).testModuleEnded();
+        verify(mMockListener)
+                .testRunStarted(
+                        Mockito.eq("run2"), Mockito.eq(1), Mockito.eq(0), Mockito.anyLong());
+        verify(mMockListener).invocationEnded(500L);
     }
 
     private IInvocationContext createModuleContext(String moduleId) {
diff --git a/javatests/com/android/tradefed/suite/checker/DeviceStorageStatusCheckerTest.java b/javatests/com/android/tradefed/suite/checker/DeviceStorageStatusCheckerTest.java
index e094071..f2d4986 100644
--- a/javatests/com/android/tradefed/suite/checker/DeviceStorageStatusCheckerTest.java
+++ b/javatests/com/android/tradefed/suite/checker/DeviceStorageStatusCheckerTest.java
@@ -16,16 +16,19 @@
 package com.android.tradefed.suite.checker;
 
 import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import com.android.tradefed.config.OptionSetter;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.suite.checker.StatusCheckerResult.CheckStatus;
 
-import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mockito;
 
 /** Unit tests for {@link DeviceStorageStatusChecker} */
 @RunWith(JUnit4.class)
@@ -37,7 +40,7 @@
 
     @Before
     public void setup() throws Exception {
-        mMockDevice = EasyMock.createMock(ITestDevice.class);
+        mMockDevice = mock(ITestDevice.class);
         mChecker = new DeviceStorageStatusChecker();
         mOptionSetter = new OptionSetter(mChecker);
         mOptionSetter.setOptionValue("partition", "/data");
@@ -47,50 +50,43 @@
     /** Test that device checker passes if device has enough storage. */
     @Test
     public void testEnoughDeviceStorage() throws Exception {
-        EasyMock.expect(mMockDevice.getPartitionFreeSpace(EasyMock.eq("/data")))
-                .andReturn(54L * 1024); // 54MB
-        EasyMock.expect(mMockDevice.getPartitionFreeSpace(EasyMock.eq("/data2")))
-                .andReturn(54L * 1024); // 54MB
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getPartitionFreeSpace(Mockito.eq("/data"))).thenReturn(54L * 1024); // 54MB
+        when(mMockDevice.getPartitionFreeSpace(Mockito.eq("/data2")))
+                .thenReturn(54L * 1024); // 54MB
+
         assertEquals(CheckStatus.SUCCESS, mChecker.preExecutionCheck(mMockDevice).getStatus());
-        EasyMock.verify(mMockDevice);
     }
 
     /** Test that device checker fails if device has not enough storage on 1 partition. */
     @Test
     public void testInEnoughDeviceStorageOn1Partition() throws Exception {
-        EasyMock.expect(mMockDevice.getPartitionFreeSpace(EasyMock.eq("/data")))
-            .andReturn(48L * 1024); // 48MB
-        EasyMock.expect(mMockDevice.getPartitionFreeSpace(EasyMock.eq("/data2")))
-            .andReturn(54L * 1024); // 54MB
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getPartitionFreeSpace(Mockito.eq("/data"))).thenReturn(48L * 1024); // 48MB
+        when(mMockDevice.getPartitionFreeSpace(Mockito.eq("/data2")))
+                .thenReturn(54L * 1024); // 54MB
+
         assertEquals(CheckStatus.FAILED, mChecker.preExecutionCheck(mMockDevice).getStatus());
-        EasyMock.verify(mMockDevice);
     }
 
     /** Test that device checker fails if device has not enough given storage. */
     @Test
     public void testNotEnoughDeviceStorageWithGivenStorageParameter() throws Exception {
         mOptionSetter.setOptionValue("minimal-storage-bytes", "104857600"); // 100MB
-        EasyMock.expect(mMockDevice.getPartitionFreeSpace(EasyMock.eq("/data")))
-                .andReturn(54L * 1024); // 54MB
-        EasyMock.expect(mMockDevice.getPartitionFreeSpace(EasyMock.eq("/data2")))
-                .andReturn(54L * 1024); // 54MB
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getPartitionFreeSpace(Mockito.eq("/data"))).thenReturn(54L * 1024); // 54MB
+        when(mMockDevice.getPartitionFreeSpace(Mockito.eq("/data2")))
+                .thenReturn(54L * 1024); // 54MB
+
         assertEquals(CheckStatus.FAILED, mChecker.preExecutionCheck(mMockDevice).getStatus());
-        EasyMock.verify(mMockDevice);
     }
 
     /** Test that device checker passes if device has enough given storage. */
     @Test
     public void testEnoughDeviceStorageWithGivenStorageParameter() throws Exception {
         mOptionSetter.setOptionValue("minimal-storage-bytes", "104857600"); // 100MB
-        EasyMock.expect(mMockDevice.getPartitionFreeSpace(EasyMock.eq("/data")))
-                .andReturn(101L * 1024); // 101MB
-        EasyMock.expect(mMockDevice.getPartitionFreeSpace(EasyMock.eq("/data2")))
-                .andReturn(101L * 1024); // 101MB
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getPartitionFreeSpace(Mockito.eq("/data")))
+                .thenReturn(101L * 1024); // 101MB
+        when(mMockDevice.getPartitionFreeSpace(Mockito.eq("/data2")))
+                .thenReturn(101L * 1024); // 101MB
+
         assertEquals(CheckStatus.SUCCESS, mChecker.preExecutionCheck(mMockDevice).getStatus());
-        EasyMock.verify(mMockDevice);
     }
 }
diff --git a/javatests/com/android/tradefed/suite/checker/SystemServerFileDescriptorCheckerTest.java b/javatests/com/android/tradefed/suite/checker/SystemServerFileDescriptorCheckerTest.java
index 3793d0e..a8fec2b 100644
--- a/javatests/com/android/tradefed/suite/checker/SystemServerFileDescriptorCheckerTest.java
+++ b/javatests/com/android/tradefed/suite/checker/SystemServerFileDescriptorCheckerTest.java
@@ -17,98 +17,92 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
 
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.suite.checker.StatusCheckerResult.CheckStatus;
 
-import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 
 /** Unit tests for {@link SystemServerFileDescriptorChecker} */
 @RunWith(JUnit4.class)
 public class SystemServerFileDescriptorCheckerTest {
 
     private SystemServerFileDescriptorChecker mChecker;
-    private ITestDevice mMockDevice;
+    @Mock ITestDevice mMockDevice;
 
     @Before
     public void setUp() {
-        mMockDevice = EasyMock.createMock(ITestDevice.class);
+        MockitoAnnotations.initMocks(this);
+
         mChecker = new SystemServerFileDescriptorChecker();
     }
 
     @Test
     public void testFailToGetPid() throws Exception {
-        EasyMock.expect(mMockDevice.getProperty(EasyMock.eq("ro.build.type")))
-                .andReturn("userdebug");
-        EasyMock.expect(mMockDevice.executeShellCommand(EasyMock.eq("pidof system_server")))
-                .andReturn("not found\n");
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getProperty(Mockito.eq("ro.build.type"))).thenReturn("userdebug");
+        when(mMockDevice.executeShellCommand(Mockito.eq("pidof system_server")))
+                .thenReturn("not found\n");
+
         assertEquals(CheckStatus.SUCCESS, mChecker.preExecutionCheck(mMockDevice).getStatus());
         assertEquals(CheckStatus.SUCCESS, mChecker.postExecutionCheck(mMockDevice).getStatus());
-        EasyMock.verify(mMockDevice);
     }
 
     @Test
     public void testFailToGetFdCount() throws Exception {
-        EasyMock.expect(mMockDevice.getProperty(EasyMock.eq("ro.build.type")))
-                .andReturn("userdebug");
-        EasyMock.expect(mMockDevice.executeShellCommand(EasyMock.eq("pidof system_server")))
-                .andReturn("1024\n");
-        EasyMock.expect(
-                        mMockDevice.executeShellCommand(
-                                EasyMock.eq("su root ls /proc/1024/fd | wc -w")))
-                .andReturn("not found\n");
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getProperty(Mockito.eq("ro.build.type"))).thenReturn("userdebug");
+        when(mMockDevice.executeShellCommand(Mockito.eq("pidof system_server")))
+                .thenReturn("1024\n");
+        when(mMockDevice.executeShellCommand(Mockito.eq("su root ls /proc/1024/fd | wc -w")))
+                .thenReturn("not found\n");
+
         assertEquals(CheckStatus.SUCCESS, mChecker.preExecutionCheck(mMockDevice).getStatus());
         assertEquals(CheckStatus.SUCCESS, mChecker.postExecutionCheck(mMockDevice).getStatus());
-        EasyMock.verify(mMockDevice);
     }
 
     @Test
     public void testAcceptableFdCount() throws Exception {
-        EasyMock.expect(mMockDevice.getProperty(EasyMock.eq("ro.build.type")))
-                .andReturn("userdebug");
-        EasyMock.expect(mMockDevice.executeShellCommand(EasyMock.eq("pidof system_server")))
-                .andReturn("914\n");
-        EasyMock.expect(
-                        mMockDevice.executeShellCommand(
-                                EasyMock.eq("su root ls /proc/914/fd | wc -w")))
-                .andReturn("382  \n");
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getProperty(Mockito.eq("ro.build.type"))).thenReturn("userdebug");
+        when(mMockDevice.executeShellCommand(Mockito.eq("pidof system_server")))
+                .thenReturn("914\n");
+        when(mMockDevice.executeShellCommand(Mockito.eq("su root ls /proc/914/fd | wc -w")))
+                .thenReturn("382  \n");
+
         assertEquals(CheckStatus.SUCCESS, mChecker.preExecutionCheck(mMockDevice).getStatus());
         assertEquals(CheckStatus.SUCCESS, mChecker.postExecutionCheck(mMockDevice).getStatus());
-        EasyMock.verify(mMockDevice);
     }
 
     @Test
     public void testUnacceptableFdCount() throws Exception {
-        EasyMock.expect(mMockDevice.getProperty(EasyMock.eq("ro.build.type")))
-                .andReturn("userdebug");
-        EasyMock.expect(mMockDevice.executeShellCommand(EasyMock.eq("pidof system_server")))
-                .andReturn("914\n");
-        EasyMock.expect(
-                        mMockDevice.executeShellCommand(
-                                EasyMock.eq("su root ls /proc/914/fd | wc -w")))
-                .andReturn("1002  \n");
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getProperty(Mockito.eq("ro.build.type"))).thenReturn("userdebug");
+        when(mMockDevice.executeShellCommand(Mockito.eq("pidof system_server")))
+                .thenReturn("914\n");
+        when(mMockDevice.executeShellCommand(Mockito.eq("su root ls /proc/914/fd | wc -w")))
+                .thenReturn("1002  \n");
+
         assertEquals(CheckStatus.SUCCESS, mChecker.preExecutionCheck(mMockDevice).getStatus());
         StatusCheckerResult postResult = mChecker.postExecutionCheck(mMockDevice);
         assertEquals(CheckStatus.FAILED, postResult.getStatus());
         assertNotNull(postResult.getErrorMessage());
-        EasyMock.verify(mMockDevice);
     }
 
     @Test
     public void testUserBuild() throws Exception {
-        EasyMock.expect(mMockDevice.getProperty(EasyMock.eq("ro.build.type"))).andReturn("user");
-        // no further calls should happen after above
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getProperty(Mockito.eq("ro.build.type"))).thenReturn("user");
+
         assertEquals(CheckStatus.SUCCESS, mChecker.preExecutionCheck(mMockDevice).getStatus());
         assertEquals(CheckStatus.SUCCESS, mChecker.postExecutionCheck(mMockDevice).getStatus());
-        EasyMock.verify(mMockDevice);
+
+        verify(mMockDevice).getProperty(Mockito.eq("ro.build.type"));
+        // no further calls should happen after above
+        verifyNoMoreInteractions(mMockDevice);
     }
 }
diff --git a/javatests/com/android/tradefed/suite/checker/TimeStatusCheckerTest.java b/javatests/com/android/tradefed/suite/checker/TimeStatusCheckerTest.java
index 93ac4d1..592c0a1 100644
--- a/javatests/com/android/tradefed/suite/checker/TimeStatusCheckerTest.java
+++ b/javatests/com/android/tradefed/suite/checker/TimeStatusCheckerTest.java
@@ -16,27 +16,33 @@
 package com.android.tradefed.suite.checker;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.suite.checker.StatusCheckerResult.CheckStatus;
 
-import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 
 /** Unit tests for {@link TimeStatusChecker}. */
 @RunWith(JUnit4.class)
 public class TimeStatusCheckerTest {
 
     private TimeStatusChecker mChecker;
-    private ITestDevice mMockDevice;
+    @Mock ITestDevice mMockDevice;
 
     @Before
     public void setUp() {
-        mMockDevice = EasyMock.createMock(ITestDevice.class);
+        MockitoAnnotations.initMocks(this);
+
         mChecker = new TimeStatusChecker();
     }
 
@@ -46,10 +52,9 @@
      */
     @Test
     public void testCheckTimeDiff_small() throws DeviceNotAvailableException {
-        EasyMock.expect(mMockDevice.getDeviceTimeOffset(EasyMock.anyObject())).andReturn(2000L);
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getDeviceTimeOffset(Mockito.any())).thenReturn(2000L);
+
         assertEquals(CheckStatus.SUCCESS, mChecker.postExecutionCheck(mMockDevice).getStatus());
-        EasyMock.verify(mMockDevice);
     }
 
     /**
@@ -58,13 +63,13 @@
      */
     @Test
     public void testCheckTimeDiff_large() throws DeviceNotAvailableException {
-        EasyMock.expect(mMockDevice.getDeviceTimeOffset(EasyMock.anyObject())).andReturn(15000L);
-        mMockDevice.logOnDevice(
-                EasyMock.anyObject(), EasyMock.anyObject(), EasyMock.contains("reset the time."));
-        mMockDevice.setDate(EasyMock.anyObject());
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getDeviceTimeOffset(Mockito.any())).thenReturn(15000L);
+
         assertEquals(CheckStatus.FAILED, mChecker.postExecutionCheck(mMockDevice).getStatus());
-        EasyMock.verify(mMockDevice);
+
+        verify(mMockDevice)
+                .logOnDevice(Mockito.any(), Mockito.any(), Mockito.contains("reset the time."));
+        verify(mMockDevice).setDate(Mockito.any());
     }
 
     /**
@@ -73,18 +78,15 @@
      */
     @Test
     public void testCheckTimeDiff_multiFailure() throws DeviceNotAvailableException {
-        EasyMock.expect(mMockDevice.getDeviceTimeOffset(EasyMock.anyObject()))
-                .andReturn(15000L)
-                .times(2);
-        mMockDevice.logOnDevice(
-                EasyMock.anyObject(), EasyMock.anyObject(), EasyMock.contains("reset the time."));
-        EasyMock.expectLastCall().times(2);
-        mMockDevice.setDate(EasyMock.anyObject());
-        EasyMock.expectLastCall().times(2);
-        EasyMock.expect(mMockDevice.getSerialNumber()).andReturn("serial");
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getDeviceTimeOffset(Mockito.any())).thenReturn(15000L);
+
+        when(mMockDevice.getSerialNumber()).thenReturn("serial");
+
         assertEquals(CheckStatus.FAILED, mChecker.postExecutionCheck(mMockDevice).getStatus());
         assertEquals(CheckStatus.SUCCESS, mChecker.postExecutionCheck(mMockDevice).getStatus());
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, times(2))
+                .logOnDevice(Mockito.any(), Mockito.any(), Mockito.contains("reset the time."));
+        verify(mMockDevice, times(2)).setDate(Mockito.any());
+        verify(mMockDevice, times(2)).getDeviceTimeOffset(Mockito.any());
     }
 }
diff --git a/javatests/com/android/tradefed/targetprep/DefaultTestsZipInstallerTest.java b/javatests/com/android/tradefed/targetprep/DefaultTestsZipInstallerTest.java
index 06d1d1a..4408668 100644
--- a/javatests/com/android/tradefed/targetprep/DefaultTestsZipInstallerTest.java
+++ b/javatests/com/android/tradefed/targetprep/DefaultTestsZipInstallerTest.java
@@ -16,26 +16,40 @@
 
 package com.android.tradefed.targetprep;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import com.android.ddmlib.FileListingService;
 import com.android.tradefed.build.DeviceBuildInfo;
 import com.android.tradefed.build.IDeviceBuildInfo;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.device.ITestDevice.RecoveryMode;
-import com.android.tradefed.device.MockFileUtil;
+import com.android.tradefed.device.MockitoFileUtil;
 import com.android.tradefed.util.IRunUtil;
 
-import junit.framework.TestCase;
-
-import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 
 import java.io.File;
-import java.util.Arrays;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Set;
 
-public class DefaultTestsZipInstallerTest extends TestCase {
+@RunWith(JUnit4.class)
+public class DefaultTestsZipInstallerTest {
     private static final String SKIP_THIS = "skipThis";
 
     private static final String TEST_STRING = "foo";
@@ -44,43 +58,45 @@
 
     private static final File SOME_PATH_2 = new File("/some/path/2");
 
-    private ITestDevice mMockDevice;
+    @Mock ITestDevice mMockDevice;
     private IDeviceBuildInfo mDeviceBuild;
     private DefaultTestsZipInstaller mZipInstaller;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
         ArrayList<String> skipThis = new ArrayList<String>(Arrays.asList(SKIP_THIS));
-        mZipInstaller = new DefaultTestsZipInstaller(skipThis) {
-            @Override
-            File[] getTestsZipDataFiles(File hostDir, ITestDevice device) {
-                return new File[] { new File(TEST_STRING) };
-            }
+        mZipInstaller =
+                new DefaultTestsZipInstaller(skipThis) {
+                    @Override
+                    File[] getTestsZipDataFiles(File hostDir, ITestDevice device) {
+                        return new File[] {new File(TEST_STRING)};
+                    }
 
-            @Override
-            Set<File> findDirs(File hostDir, File deviceRootPath) {
-                Set<File> files = new HashSet<File>(2);
-                files.add(SOME_PATH_1);
-                files.add(SOME_PATH_2);
-                return files;
-            }
+                    @Override
+                    Set<File> findDirs(File hostDir, File deviceRootPath) {
+                        Set<File> files = new HashSet<File>(2);
+                        files.add(SOME_PATH_1);
+                        files.add(SOME_PATH_2);
+                        return files;
+                    }
 
-            @Override
-            IRunUtil getRunUtil() {
-                return EasyMock.createNiceMock(IRunUtil.class);
-            }
-         };
+                    @Override
+                    IRunUtil getRunUtil() {
+                        return mock(IRunUtil.class);
+                    }
+                };
 
-        mMockDevice = EasyMock.createMock(ITestDevice.class);
-        EasyMock.expect(mMockDevice.getSerialNumber()).andStubReturn(TEST_STRING);
-        EasyMock.expect(mMockDevice.getProductType()).andStubReturn(TEST_STRING);
-        EasyMock.expect(mMockDevice.getBuildId()).andStubReturn("1");
+        when(mMockDevice.getSerialNumber()).thenReturn(TEST_STRING);
+        when(mMockDevice.getProductType()).thenReturn(TEST_STRING);
+        when(mMockDevice.getBuildId()).thenReturn("1");
 
-        EasyMock.expect(mMockDevice.getDeviceDescriptor()).andStubReturn(null);
+        when(mMockDevice.getDeviceDescriptor()).thenReturn(null);
         mDeviceBuild = new DeviceBuildInfo("1", TEST_STRING);
     }
 
+    @Test
     public void testSkipWipeFileSetup() throws Exception {
         DefaultTestsZipInstaller testZipInstaller = new DefaultTestsZipInstaller();
         Set<String> skipList = testZipInstaller.getDataWipeSkipList();
@@ -93,110 +109,105 @@
         skipArrayList.add("foobar");
         testZipInstaller.setDataWipeSkipList(skipArrayList);
         skipList = testZipInstaller.getDataWipeSkipList();
-        assertFalse("Invalid wipe list set, should not contain old value.",
-                skipList.contains("foo"));
+        assertFalse(
+                "Invalid wipe list set, should not contain old value.", skipList.contains("foo"));
         assertTrue("Invalid wipe list set. Missing value set.", skipList.contains("bar"));
         assertTrue("Invalid wipe list set. Missing value set.", skipList.contains("foobar"));
     }
 
+    @Test
     public void testCantTouchFilesystem() throws Exception {
         // expect initial android stop
-        EasyMock.expect(mMockDevice.getSerialNumber()).andStubReturn("serial_number_stub");
-        EasyMock.expect(mMockDevice.getRecoveryMode()).andReturn(RecoveryMode.AVAILABLE);
-        EasyMock.expect(mMockDevice.executeShellCommand("stop")).andReturn("");
-        EasyMock.expect(mMockDevice.executeShellCommand("stop installd")).andReturn("");
-        mMockDevice.setRecoveryMode(RecoveryMode.ONLINE);
+        when(mMockDevice.getSerialNumber()).thenReturn("serial_number_stub");
+        when(mMockDevice.getRecoveryMode()).thenReturn(RecoveryMode.AVAILABLE);
+        when(mMockDevice.executeShellCommand("stop")).thenReturn("");
+        when(mMockDevice.executeShellCommand("stop installd")).thenReturn("");
 
         // turtle!  (return false, for "write failed")
-        EasyMock.expect(mMockDevice.pushString((String) EasyMock.anyObject(),
-                (String) EasyMock.anyObject())).andReturn(false);
+        when(mMockDevice.pushString((String) Mockito.any(), (String) Mockito.any()))
+                .thenReturn(false);
 
-        EasyMock.replay(mMockDevice);
         try {
             mZipInstaller.deleteData(mMockDevice);
             fail("Didn't throw TargetSetupError on failed write test");
         } catch (TargetSetupError e) {
             // expected
         }
-        EasyMock.verify(mMockDevice);
+
+        verify(mMockDevice).setRecoveryMode(RecoveryMode.ONLINE);
     }
 
-    /**
-     * Exercise the core logic on a successful scenario.
-     */
+    /** Exercise the core logic on a successful scenario. */
+    @Test
     public void testPushTestsZipOntoData() throws Exception {
         // mock a filesystem with these contents:
         // /data/app
         // /data/$SKIP_THIS
-        MockFileUtil.setMockDirContents(
+        MockitoFileUtil.setMockDirContents(
                 mMockDevice, FileListingService.DIRECTORY_DATA, "app", SKIP_THIS);
 
         // expect initial android stop
-        EasyMock.expect(mMockDevice.getSerialNumber()).andStubReturn("serial_number_stub");
-        EasyMock.expect(mMockDevice.getRecoveryMode()).andReturn(RecoveryMode.AVAILABLE);
-        mMockDevice.setRecoveryMode(RecoveryMode.ONLINE);
-        EasyMock.expect(mMockDevice.executeShellCommand("stop")).andReturn("");
-        EasyMock.expect(mMockDevice.executeShellCommand("stop installd")).andReturn("");
+        when(mMockDevice.getSerialNumber()).thenReturn("serial_number_stub");
+        when(mMockDevice.getRecoveryMode()).thenReturn(RecoveryMode.AVAILABLE);
+
+        when(mMockDevice.executeShellCommand("stop")).thenReturn("");
+        when(mMockDevice.executeShellCommand("stop installd")).thenReturn("");
 
         // turtle!  (to make sure filesystem is writable)
-        EasyMock.expect(mMockDevice.pushString((String) EasyMock.anyObject(),
-                (String) EasyMock.anyObject())).andReturn(true);
+        when(mMockDevice.pushString((String) Mockito.any(), (String) Mockito.any()))
+                .thenReturn(true);
 
         // expect 'rm app' but not 'rm $SKIP_THIS'
-        EasyMock.expect(mMockDevice.doesFileExist("data/app")).andReturn(false);
-        mMockDevice.deleteFile("data/app");
+        when(mMockDevice.doesFileExist("data/app")).thenReturn(false);
 
-        mMockDevice.setRecoveryMode(RecoveryMode.AVAILABLE);
+        when(mMockDevice.syncFiles(
+                        (File) Mockito.any(), Mockito.contains(FileListingService.DIRECTORY_DATA)))
+                .thenReturn(Boolean.TRUE);
 
-        EasyMock.expect(mMockDevice.syncFiles((File) EasyMock.anyObject(),
-                EasyMock.contains(FileListingService.DIRECTORY_DATA)))
-                .andReturn(Boolean.TRUE);
+        when(mMockDevice.executeShellCommand(
+                        Mockito.startsWith("chown system.system " + SOME_PATH_1.getPath())))
+                .thenReturn("");
+        when(mMockDevice.executeShellCommand(
+                        Mockito.startsWith("chown system.system " + SOME_PATH_2.getPath())))
+                .thenReturn("");
 
-        EasyMock.expect(
-                mMockDevice.executeShellCommand(EasyMock.startsWith("chown system.system "
-                        + SOME_PATH_1.getPath()))).andReturn("");
-        EasyMock.expect(
-                mMockDevice.executeShellCommand(EasyMock.startsWith("chown system.system "
-                        + SOME_PATH_2.getPath()))).andReturn("");
-
-        EasyMock.replay(mMockDevice);
         mZipInstaller.pushTestsZipOntoData(mMockDevice, mDeviceBuild);
-        EasyMock.verify(mMockDevice);
+
+        verify(mMockDevice).setRecoveryMode(RecoveryMode.ONLINE);
+        verify(mMockDevice).deleteFile("data/app");
+        verify(mMockDevice).setRecoveryMode(RecoveryMode.AVAILABLE);
     }
 
-    /**
-     * Test repeats to delete a dir are aborted
-     */
+    /** Test repeats to delete a dir are aborted */
+    @Test
     public void testPushTestsZipOntoData_retry() throws Exception {
         // mock a filesystem with these contents:
         // /data/app
         // /data/$SKIP_THIS
-        MockFileUtil.setMockDirContents(
+        MockitoFileUtil.setMockDirContents(
                 mMockDevice, FileListingService.DIRECTORY_DATA, "app", SKIP_THIS);
 
         // expect initial android stop
-        EasyMock.expect(mMockDevice.getSerialNumber()).andStubReturn("serial_number_stub");
-        EasyMock.expect(mMockDevice.getRecoveryMode()).andReturn(RecoveryMode.AVAILABLE);
-        mMockDevice.setRecoveryMode(RecoveryMode.ONLINE);
-        EasyMock.expect(mMockDevice.executeShellCommand("stop")).andReturn("");
-        EasyMock.expect(mMockDevice.executeShellCommand("stop installd")).andReturn("");
+        when(mMockDevice.getSerialNumber()).thenReturn("serial_number_stub");
+        when(mMockDevice.getRecoveryMode()).thenReturn(RecoveryMode.AVAILABLE);
+
+        when(mMockDevice.executeShellCommand("stop")).thenReturn("");
+        when(mMockDevice.executeShellCommand("stop installd")).thenReturn("");
 
         // turtle!  (to make sure filesystem is writable)
-        EasyMock.expect(mMockDevice.pushString((String) EasyMock.anyObject(),
-                (String) EasyMock.anyObject())).andReturn(true);
+        when(mMockDevice.pushString((String) Mockito.any(), (String) Mockito.any()))
+                .thenReturn(true);
 
         // expect 'rm app' but not 'rm $SKIP_THIS'
-        EasyMock.expect(mMockDevice.doesFileExist("data/app")).andStubReturn(true);
-        mMockDevice.deleteFile("data/app");
-        EasyMock.expectLastCall().times(3);
+        when(mMockDevice.doesFileExist("data/app")).thenReturn(true);
 
-        EasyMock.replay(mMockDevice);
         try {
             mZipInstaller.pushTestsZipOntoData(mMockDevice, mDeviceBuild);
             fail("TargetSetupError not thrown");
         } catch (TargetSetupError e) {
             // expected
         }
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, times(3)).deleteFile("data/app");
+        verify(mMockDevice).setRecoveryMode(RecoveryMode.ONLINE);
     }
 }
diff --git a/javatests/com/android/tradefed/targetprep/DeviceFlashPreparerTest.java b/javatests/com/android/tradefed/targetprep/DeviceFlashPreparerTest.java
index 09344ce..840a79b 100644
--- a/javatests/com/android/tradefed/targetprep/DeviceFlashPreparerTest.java
+++ b/javatests/com/android/tradefed/targetprep/DeviceFlashPreparerTest.java
@@ -29,7 +29,6 @@
 import com.android.tradefed.device.DeviceAllocationState;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.DeviceUnresponsiveException;
-import com.android.tradefed.device.IDeviceManager;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.device.ITestDevice.RecoveryMode;
 import com.android.tradefed.device.TestDeviceOptions;
@@ -56,7 +55,6 @@
 @RunWith(JUnit4.class)
 public class DeviceFlashPreparerTest {
 
-    private IDeviceManager mMockDeviceManager;
     private IDeviceFlasher mMockFlasher;
     private DeviceFlashPreparer mDeviceFlashPreparer;
     private ITestDevice mMockDevice;
@@ -69,7 +67,6 @@
 
     @Before
     public void setUp() throws Exception {
-        mMockDeviceManager = EasyMock.createMock(IDeviceManager.class);
         mMockFlasher = EasyMock.createMock(IDeviceFlasher.class);
         mMockDevice = EasyMock.createMock(ITestDevice.class);
         EasyMock.expect(mMockDevice.getSerialNumber()).andReturn("foo").anyTimes();
@@ -92,11 +89,6 @@
             }
 
             @Override
-            IDeviceManager getDeviceManager() {
-                return mMockDeviceManager;
-            }
-
-            @Override
             protected IHostOptions getHostOptions() {
                 return mMockHostOptions;
             }
diff --git a/javatests/com/android/tradefed/targetprep/DeviceSetupTest.java b/javatests/com/android/tradefed/targetprep/DeviceSetupTest.java
index 9a41fe9..2bd6d5a 100644
--- a/javatests/com/android/tradefed/targetprep/DeviceSetupTest.java
+++ b/javatests/com/android/tradefed/targetprep/DeviceSetupTest.java
@@ -16,6 +16,15 @@
 
 package com.android.tradefed.targetprep;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import com.android.ddmlib.IDevice;
 import com.android.tradefed.build.DeviceBuildInfo;
 import com.android.tradefed.build.IDeviceBuildInfo;
@@ -32,18 +41,20 @@
 import com.android.tradefed.util.BinaryState;
 import com.android.tradefed.util.FileUtil;
 
-import junit.framework.TestCase;
-
-import org.easymock.Capture;
-import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
 
 import java.io.File;
 import java.util.LinkedHashMap;
 
-/**
- * Unit tests for {@link DeviceSetup}.
- */
-public class DeviceSetupTest extends TestCase {
+/** Unit tests for {@link DeviceSetup}. */
+@RunWith(JUnit4.class)
+public class DeviceSetupTest {
 
     private DeviceSetup mDeviceSetup;
     private ITestDevice mMockDevice;
@@ -54,20 +65,16 @@
 
     private static final int DEFAULT_API_LEVEL = 23;
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mMockDevice = EasyMock.createMock(ITestDevice.class);
-        mMockIDevice = EasyMock.createMock(IDevice.class);
-        EasyMock.expect(mMockDevice.getSerialNumber()).andReturn("foo").anyTimes();
-        EasyMock.expect(mMockDevice.getDeviceDescriptor()).andStubReturn(null);
-        EasyMock.expect(mMockDevice.getIDevice()).andStubReturn(mMockIDevice);
-        EasyMock.expect(mMockDevice.getDeviceState()).andStubReturn(TestDeviceState.ONLINE);
-        mMockDevice.waitForDeviceAvailable();
-        EasyMock.expectLastCall().anyTimes();
+    /** {@inheritDoc} */
+    @Before
+    public void setUp() throws Exception {
+        mMockDevice = mock(ITestDevice.class);
+        mMockIDevice = mock(IDevice.class);
+        when(mMockDevice.getSerialNumber()).thenReturn("foo");
+        when(mMockDevice.getDeviceDescriptor()).thenReturn(null);
+        when(mMockDevice.getIDevice()).thenReturn(mMockIDevice);
+        when(mMockDevice.getDeviceState()).thenReturn(TestDeviceState.ONLINE);
+
         mMockBuildInfo = new DeviceBuildInfo("0", "");
         mDeviceSetup = new DeviceSetup();
         mTmpDir = FileUtil.createTempDir("tmp");
@@ -77,172 +84,181 @@
         mTestInfo = TestInformation.newBuilder().setInvocationContext(context).build();
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected void tearDown() throws Exception {
+    /** {@inheritDoc} */
+    @After
+    public void tearDown() throws Exception {
         FileUtil.recursiveDelete(mTmpDir);
-        super.tearDown();
     }
 
     /** Simple normal case test for {@link DeviceSetup#setUp(TestInformation)}. */
+    @Test
     public void testSetup() throws Exception {
-        Capture<String> setPropCapture = new Capture<>();
+        ArgumentCaptor<String> setPropCapture = ArgumentCaptor.forClass(String.class);
         doSetupExpectations(true, setPropCapture);
         doCheckExternalStoreSpaceExpectations();
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
 
         String setProp = setPropCapture.getValue();
-        assertTrue("Set prop doesn't contain ro.telephony.disable-call=true",
+        assertTrue(
+                "Set prop doesn't contain ro.telephony.disable-call=true",
                 setProp.contains("ro.telephony.disable-call=true\n"));
-        assertTrue("Set prop doesn't contain ro.audio.silent=1",
+        assertTrue(
+                "Set prop doesn't contain ro.audio.silent=1",
                 setProp.contains("ro.audio.silent=1\n"));
-        assertTrue("Set prop doesn't contain ro.test_harness=1",
+        assertTrue(
+                "Set prop doesn't contain ro.test_harness=1",
                 setProp.contains("ro.test_harness=1\n"));
-        assertTrue("Set prop doesn't contain ro.monkey=1",
-                setProp.contains("ro.monkey=1\n"));
+        assertTrue("Set prop doesn't contain ro.monkey=1", setProp.contains("ro.monkey=1\n"));
     }
 
+    @Test
     public void testSetup_airplane_mode_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "airplane_mode_on", "1");
         doCommandsExpectations(
                 "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setAirplaneMode(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "airplane_mode_on", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_airplane_mode_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "airplane_mode_on", "0");
         doCommandsExpectations(
                 "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setAirplaneMode(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "airplane_mode_on", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_data_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "mobile_data", "1");
         doCommandsExpectations("svc data enable");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setData(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "mobile_data", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_data_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "mobile_data", "0");
         doCommandsExpectations("svc data disable");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setData(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "mobile_data", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_cell_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "cell_on", "1");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setCell(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "cell_on", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_cell_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "cell_on", "0");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setCell(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "cell_on", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_cell_auto_setting_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "clockwork_cell_auto_setting", "1");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setCellAutoSetting(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "clockwork_cell_auto_setting", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_cell_auto_setting_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "clockwork_cell_auto_setting", "0");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setCellAutoSetting(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "clockwork_cell_auto_setting", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_wifi_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "wifi_on", "1");
         doCommandsExpectations("svc wifi enable");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setWifi(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "wifi_on", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_wifi_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "wifi_on", "0");
         doCommandsExpectations("svc wifi disable");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setWifi(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "wifi_on", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_wifi_network_name() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "wifi_on", "1");
         doCommandsExpectations("svc wifi enable");
-        EasyMock.expect(mMockDevice.connectToWifiNetwork("wifi_network", "psk")).andReturn(true);
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.connectToWifiNetwork("wifi_network", "psk")).thenReturn(true);
 
         mDeviceSetup.setWifiNetwork("wifi_network");
         mDeviceSetup.setWifiPsk("psk");
@@ -250,16 +266,17 @@
         mDeviceSetup.setWifi(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "wifi_on", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_wifi_network_name_emptyPsk() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "wifi_on", "1");
         doCommandsExpectations("svc wifi enable");
-        EasyMock.expect(mMockDevice.connectToWifiNetwork("wifi_network", null)).andReturn(true);
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.connectToWifiNetwork("wifi_network", null)).thenReturn(true);
 
         mDeviceSetup.setWifiNetwork("wifi_network");
         mDeviceSetup.setWifiPsk(""); // empty psk becomes null in connectToWifiNetwork
@@ -267,15 +284,16 @@
         mDeviceSetup.setWifi(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "wifi_on", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_wifi_network_empty() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "wifi_on", "1");
         doCommandsExpectations("svc wifi enable");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setWifiNetwork("");
         mDeviceSetup.setWifiPsk("psk");
@@ -283,18 +301,19 @@
         mDeviceSetup.setWifi(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "wifi_on", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_wifi_multiple_network_names() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "wifi_on", "1");
         doCommandsExpectations("svc wifi enable");
-        EasyMock.expect(mMockDevice.connectToWifiNetwork("old_network", "abc")).andReturn(false);
-        EasyMock.expect(mMockDevice.connectToWifiNetwork("network", "def")).andReturn(false);
-        EasyMock.expect(mMockDevice.connectToWifiNetwork("new_network", "ghi")).andReturn(true);
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.connectToWifiNetwork("old_network", "abc")).thenReturn(false);
+        when(mMockDevice.connectToWifiNetwork("network", "def")).thenReturn(false);
+        when(mMockDevice.connectToWifiNetwork("new_network", "ghi")).thenReturn(true);
 
         mDeviceSetup.setWifiNetwork("old_network");
         mDeviceSetup.setWifiPsk("abc");
@@ -306,18 +325,19 @@
         mDeviceSetup.setWifi(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "wifi_on", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_wifi_multiple_network_names_unsecured() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "wifi_on", "1");
         doCommandsExpectations("svc wifi enable");
-        EasyMock.expect(mMockDevice.connectToWifiNetwork("old_network", null)).andReturn(false);
-        EasyMock.expect(mMockDevice.connectToWifiNetwork("network", null)).andReturn(false);
-        EasyMock.expect(mMockDevice.connectToWifiNetwork("new_network", null)).andReturn(true);
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.connectToWifiNetwork("old_network", null)).thenReturn(false);
+        when(mMockDevice.connectToWifiNetwork("network", null)).thenReturn(false);
+        when(mMockDevice.connectToWifiNetwork("new_network", null)).thenReturn(true);
 
         mDeviceSetup.setWifiNetwork("old_network");
         mDeviceSetup.setWifiPsk(null);
@@ -329,637 +349,679 @@
         mDeviceSetup.setWifi(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "wifi_on", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_wifi_watchdog_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "wifi_watchdog", "1");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setWifiWatchdog(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "wifi_watchdog", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_wifi_watchdog_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "wifi_watchdog", "0");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setWifiWatchdog(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "wifi_watchdog", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_disable_cw_wifi_mediator_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "cw_disable_wifimediator", "1");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setDisableCwWifiMediator(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "cw_disable_wifimediator", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_disable_cw_wifi_mediator_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "cw_disable_wifimediator", "0");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setDisableCwWifiMediator(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "cw_disable_wifimediator", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_wifi_scan_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "wifi_scan_always_enabled", "1");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setWifiScanAlwaysEnabled(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "wifi_scan_always_enabled", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_wifi_scan_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "wifi_scan_always_enabled", "0");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setWifiScanAlwaysEnabled(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "wifi_scan_always_enabled", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_ethernet_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doCommandsExpectations("ifconfig eth0 up");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setEthernet(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_ethernet_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doCommandsExpectations("ifconfig eth0 down");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setEthernet(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_bluetooth_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doCommandsExpectations("svc bluetooth enable");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setBluetooth(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_bluetooth_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doCommandsExpectations("svc bluetooth disable");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setBluetooth(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_nfc_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doCommandsExpectations("svc nfc enable");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setNfc(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_nfc_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doCommandsExpectations("svc nfc disable");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setNfc(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_screen_adaptive_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("system", "screen_brightness_mode", "1");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setScreenAdaptiveBrightness(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("system", "screen_brightness_mode", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_screen_adaptive_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("system", "screen_brightness_mode", "0");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setScreenAdaptiveBrightness(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("system", "screen_brightness_mode", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_screen_brightness() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("system", "screen_brightness", "50");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setScreenBrightness(50);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("system", "screen_brightness", "50");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_screen_stayon_default() throws Exception {
-        doSetupExpectations(false /* Expect no screen on command */, new Capture<String>());
+        doSetupExpectations(
+                false /* Expect no screen on command */, ArgumentCaptor.forClass(String.class));
         doCheckExternalStoreSpaceExpectations();
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setScreenAlwaysOn(BinaryState.IGNORE);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_screen_stayon_off() throws Exception {
-        doSetupExpectations(false /* Expect no screen on command */, new Capture<String>());
+        doSetupExpectations(
+                false /* Expect no screen on command */, ArgumentCaptor.forClass(String.class));
         doCheckExternalStoreSpaceExpectations();
         doCommandsExpectations("svc power stayon false");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setScreenAlwaysOn(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_screen_timeout() throws Exception {
-        doSetupExpectations(false /* Expect no screen on command */, new Capture<String>());
+        doSetupExpectations(
+                false /* Expect no screen on command */, ArgumentCaptor.forClass(String.class));
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("system", "screen_off_timeout", "5000");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setScreenAlwaysOn(BinaryState.IGNORE);
         mDeviceSetup.setScreenTimeoutSecs(5L);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("system", "screen_off_timeout", "5000");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_screen_ambient_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("secure", "doze_enabled", "1");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setScreenAmbientMode(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("secure", "doze_enabled", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_screen_ambient_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("secure", "doze_enabled", "0");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setScreenAmbientMode(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("secure", "doze_enabled", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_wake_gesture_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("secure", "wake_gesture_enabled", "1");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setWakeGesture(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("secure", "wake_gesture_enabled", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_wake_gesture_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("secure", "wake_gesture_enabled", "0");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setWakeGesture(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("secure", "wake_gesture_enabled", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_screen_saver_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("secure", "screensaver_enabled", "1");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setScreenSaver(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("secure", "screensaver_enabled", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_screen_saver_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("secure", "screensaver_enabled", "0");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setScreenSaver(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("secure", "screensaver_enabled", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_notification_led_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("system", "notification_light_pulse", "1");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setNotificationLed(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("system", "notification_light_pulse", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_notification_led_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("system", "notification_light_pulse", "0");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setNotificationLed(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("system", "notification_light_pulse", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testInstallNonMarketApps_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("secure", "install_non_market_apps", "1");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setInstallNonMarketApps(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("secure", "install_non_market_apps", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testInstallNonMarketApps_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("secure", "install_non_market_apps", "0");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setInstallNonMarketApps(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("secure", "install_non_market_apps", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_trigger_media_mounted() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doCommandsExpectations(
                 "am broadcast -a android.intent.action.MEDIA_MOUNTED "
                         + "-d file://${EXTERNAL_STORAGE} --receiver-include-background");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setTriggerMediaMounted(true);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_location_gps_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("secure", "location_providers_allowed", "+gps");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setLocationGps(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("secure", "location_providers_allowed", "+gps");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_location_gps_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("secure", "location_providers_allowed", "-gps");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setLocationGps(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("secure", "location_providers_allowed", "-gps");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_location_network_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("secure", "location_providers_allowed", "+network");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setLocationNetwork(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("secure", "location_providers_allowed", "+network");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_location_network_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("secure", "location_providers_allowed", "-network");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setLocationNetwork(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("secure", "location_providers_allowed", "-network");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_rotate_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("system", "accelerometer_rotation", "1");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setAutoRotate(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("system", "accelerometer_rotation", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_rotate_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("system", "accelerometer_rotation", "0");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setAutoRotate(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("system", "accelerometer_rotation", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_battery_saver_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "low_power", "1");
         doCommandsExpectations("dumpsys battery unplug");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setBatterySaver(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "low_power", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_legacy_battery_saver_on() throws Exception {
         doSetupExpectations(21); // API level Lollipop
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "low_power", "1");
         doCommandsExpectations("dumpsys battery set usb 0");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setBatterySaver(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "low_power", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_battery_saver_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "low_power", "0");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setBatterySaver(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "low_power", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_battery_saver_trigger() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "low_power_trigger_level", "50");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setBatterySaverTrigger(50);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "low_power_trigger_level", "50");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_enable_full_battery_stats_history() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doCommandsExpectations("dumpsys batterystats --enable full-history");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setEnableFullBatteryStatsHistory(true);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_disable_doze() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doCommandsExpectations("dumpsys deviceidle disable");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setDisableDoze(true);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_update_time_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "auto_time", "1");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setAutoUpdateTime(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "auto_time", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_update_time_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "auto_time", "0");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setAutoUpdateTime(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "auto_time", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_update_timezone_on() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "auto_timezone", "1");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setAutoUpdateTimezone(BinaryState.ON);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "auto_timezone", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_update_timezone_off() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "auto_timezone", "0");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setAutoUpdateTimezone(BinaryState.OFF);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "auto_timezone", "0");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_set_timezone_LA() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
-        EasyMock.expect(mMockDevice.setProperty("persist.sys.timezone", "America/Los_Angeles"))
-                .andReturn(true);
-        EasyMock.expect(mMockDevice.getProperty("persist.sys.timezone"))
-                .andReturn("America/Los_Angeles")
-                .anyTimes();
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.setProperty("persist.sys.timezone", "America/Los_Angeles"))
+                .thenReturn(true);
+        when(mMockDevice.getProperty("persist.sys.timezone")).thenReturn("America/Los_Angeles");
 
         mDeviceSetup.setTimezone("America/Los_Angeles");
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_no_disable_dialing() throws Exception {
-        Capture<String> setPropCapture = new Capture<>();
+        ArgumentCaptor<String> setPropCapture = ArgumentCaptor.forClass(String.class);
         doSetupExpectations(true, setPropCapture);
         doCheckExternalStoreSpaceExpectations();
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setDisableDialing(false);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
 
-        assertFalse("Set prop contains ro.telephony.disable-call=true",
+        assertFalse(
+                "Set prop contains ro.telephony.disable-call=true",
                 setPropCapture.getValue().contains("ro.telephony.disable-call=true\n"));
     }
 
+    @Test
     public void testSetup_sim_data() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "multi_sim_data_call", "1");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setDefaultSimData(1);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "multi_sim_data_call", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_sim_voice() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "multi_sim_voice_call", "1");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setDefaultSimVoice(1);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "multi_sim_voice_call", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_sim_sms() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSettingExpectations("global", "multi_sim_sms", "1");
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setDefaultSimSms(1);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice).setSetting("global", "multi_sim_sms", "1");
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_no_disable_audio() throws Exception {
-        Capture<String> setPropCapture = new Capture<>();
+        ArgumentCaptor<String> setPropCapture = ArgumentCaptor.forClass(String.class);
         doSetupExpectations(true, setPropCapture);
         doCheckExternalStoreSpaceExpectations();
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setDisableAudio(false);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
 
-        assertFalse("Set prop contains ro.audio.silent=1",
+        assertFalse(
+                "Set prop contains ro.audio.silent=1",
                 setPropCapture.getValue().contains("ro.audio.silent=1\n"));
     }
 
+    @Test
     public void testSetup_no_test_harness() throws Exception {
-        Capture<String> setPropCapture = new Capture<>();
+        ArgumentCaptor<String> setPropCapture = ArgumentCaptor.forClass(String.class);
         doSetupExpectations(
                 true /* screen on */,
                 true /* root enabled */,
@@ -968,45 +1030,42 @@
                 DEFAULT_API_LEVEL,
                 setPropCapture);
         doCheckExternalStoreSpaceExpectations();
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setTestHarness(false);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
 
         String setProp = setPropCapture.getValue();
-        assertFalse("Set prop contains ro.test_harness=1",
-                setProp.contains("ro.test_harness=1\n"));
-        assertFalse("Set prop contains ro.monkey=1",
-                setProp.contains("ro.monkey=1\n"));
+        assertFalse("Set prop contains ro.test_harness=1", setProp.contains("ro.test_harness=1\n"));
+        assertFalse("Set prop contains ro.monkey=1", setProp.contains("ro.monkey=1\n"));
     }
 
+    @Test
     public void testSetup_disalbe_dalvik_verifier() throws Exception {
-        Capture<String> setPropCapture = new Capture<>();
+        ArgumentCaptor<String> setPropCapture = ArgumentCaptor.forClass(String.class);
         doSetupExpectations(true, setPropCapture);
         doCheckExternalStoreSpaceExpectations();
-        EasyMock.expect(mMockDevice.getProperty("dalvik.vm.dexopt-flags"))
-                .andReturn("v=n")
-                .anyTimes();
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getProperty("dalvik.vm.dexopt-flags")).thenReturn("v=n");
 
         mDeviceSetup.setDisableDalvikVerifier(true);
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
 
         String setProp = setPropCapture.getValue();
-        assertTrue("Set prop doesn't contain dalvik.vm.dexopt-flags=v=n",
+        assertTrue(
+                "Set prop doesn't contain dalvik.vm.dexopt-flags=v=n",
                 setProp.contains("dalvik.vm.dexopt-flags=v=n\n"));
     }
 
     /** Test {@link DeviceSetup#setUp(TestInformation)} when free space check fails. */
+    @Test
     public void testSetup_freespace() throws Exception {
         doSetupExpectations();
         mDeviceSetup.setMinExternalStorageKb(500);
-        EasyMock.expect(mMockDevice.getExternalStoreFreeSpace()).andReturn(1L);
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getExternalStoreFreeSpace()).thenReturn(1L);
+
         try {
             mDeviceSetup.setUp(mTestInfo);
             fail("DeviceNotAvailableException not thrown");
@@ -1016,10 +1075,11 @@
     }
 
     /** Test {@link DeviceSetup#setUp(TestInformation)} when local data path does not exist. */
+    @Test
     public void testSetup_badLocalData() throws Exception {
         doSetupExpectations();
         mDeviceSetup.setLocalDataPath(new File("idontexist"));
-        EasyMock.replay(mMockDevice);
+
         try {
             mDeviceSetup.setUp(mTestInfo);
             fail("TargetSetupError not thrown");
@@ -1029,21 +1089,22 @@
     }
 
     /** Test normal case {@link DeviceSetup#setUp(TestInformation)} when local data is synced */
+    @Test
     public void testSetup_syncData() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
         doSyncDataExpectations(true);
 
-        EasyMock.replay(mMockDevice, mMockIDevice);
         mDeviceSetup.setUp(mTestInfo);
-        EasyMock.verify(mMockDevice, mMockIDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
     /** Test case {@link DeviceSetup#setUp(TestInformation)} when local data fails to be synced. */
+    @Test
     public void testSetup_syncDataFails() throws Exception {
         doSetupExpectations();
         doSyncDataExpectations(false);
-        EasyMock.replay(mMockDevice, mMockIDevice);
+
         try {
             mDeviceSetup.setUp(mTestInfo);
             fail("TargetSetupError not thrown");
@@ -1053,35 +1114,35 @@
     }
 
     @SuppressWarnings("deprecation")
+    @Test
     public void testSetup_legacy() throws Exception {
-        Capture<String> setPropCapture = new Capture<>();
+        ArgumentCaptor<String> setPropCapture = ArgumentCaptor.forClass(String.class);
         doSetupExpectations(true, setPropCapture);
         doCheckExternalStoreSpaceExpectations();
-        EasyMock.expect(mMockDevice.getProperty("key")).andReturn("value").anyTimes();
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getProperty("key")).thenReturn("value");
 
         mDeviceSetup.setDeprecatedAudioSilent(false);
         mDeviceSetup.setDeprecatedMinExternalStoreSpace(1000);
         mDeviceSetup.setDeprecatedSetProp("key=value");
         mDeviceSetup.setUp(mTestInfo);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
 
         String setProp = setPropCapture.getValue();
-        assertTrue("Set prop doesn't contain ro.telephony.disable-call=true",
+        assertTrue(
+                "Set prop doesn't contain ro.telephony.disable-call=true",
                 setProp.contains("ro.telephony.disable-call=true\n"));
-        assertTrue("Set prop doesn't contain ro.test_harness=1",
+        assertTrue(
+                "Set prop doesn't contain ro.test_harness=1",
                 setProp.contains("ro.test_harness=1\n"));
-        assertTrue("Set prop doesn't contain ro.monkey=1",
-                setProp.contains("ro.monkey=1\n"));
-        assertTrue("Set prop doesn't contain key=value",
-                setProp.contains("key=value\n"));
+        assertTrue("Set prop doesn't contain ro.monkey=1", setProp.contains("ro.monkey=1\n"));
+        assertTrue("Set prop doesn't contain key=value", setProp.contains("key=value\n"));
     }
 
     @SuppressWarnings("deprecation")
+    @Test
     public void testSetup_legacy_storage_conflict() throws Exception {
         doSetupExpectations();
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setMinExternalStorageKb(1000);
         mDeviceSetup.setDeprecatedMinExternalStoreSpace(1000);
@@ -1094,9 +1155,9 @@
     }
 
     @SuppressWarnings("deprecation")
+    @Test
     public void testSetup_legacy_silent_conflict() throws Exception {
         doSetupExpectations();
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setDisableAudio(false);
         mDeviceSetup.setDeprecatedAudioSilent(false);
@@ -1109,9 +1170,9 @@
     }
 
     @SuppressWarnings("deprecation")
+    @Test
     public void testSetup_legacy_setprop_conflict() throws Exception {
         doSetupExpectations();
-        EasyMock.replay(mMockDevice);
 
         mDeviceSetup.setProperty("key", "value");
         mDeviceSetup.setDeprecatedSetProp("key=value");
@@ -1123,66 +1184,58 @@
         }
     }
 
+    @Test
     public void test_restore_properties_previous_exists() throws Exception {
         File f = new File("");
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
-        EasyMock.expect(mMockDevice.pullFile("/data/local.prop")).andReturn(f).once();
-        EasyMock.expect(mMockDevice.pushFile(f, "/data/local.prop")).andReturn(true).once();
-        mMockDevice.reboot();
-        EasyMock.expectLastCall().once();
-        EasyMock.expect(mMockDevice.getProperty("key")).andReturn("value").anyTimes();
+        when(mMockDevice.pullFile("/data/local.prop")).thenReturn(f);
+        when(mMockDevice.pushFile(f, "/data/local.prop")).thenReturn(true);
 
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getProperty("key")).thenReturn("value");
 
         mDeviceSetup.setRestoreProperties(true);
         mDeviceSetup.setProperty("key", "value");
         mDeviceSetup.setUp(mTestInfo);
         mDeviceSetup.tearDown(mTestInfo, null);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
+        // doSetupExpectations, changeSystemProps, tearDown
+        verify(mMockDevice, times(3)).reboot();
+        verify(mMockDevice, times(1)).pullFile("/data/local.prop");
+        verify(mMockDevice, times(1)).pushFile(f, "/data/local.prop");
     }
 
+    @Test
     public void test_restore_properties_previous_doesnt_exists() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
-        EasyMock.expect(mMockDevice.pullFile("/data/local.prop")).andReturn(null).once();
-        mMockDevice.deleteFile("/data/local.prop");
-        mMockDevice.reboot();
-        EasyMock.expectLastCall().once();
-        EasyMock.expect(mMockDevice.getProperty("key")).andReturn("value").anyTimes();
+        when(mMockDevice.pullFile("/data/local.prop")).thenReturn(null);
 
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getProperty("key")).thenReturn("value");
 
         mDeviceSetup.setRestoreProperties(true);
         mDeviceSetup.setProperty("key", "value");
         mDeviceSetup.setUp(mTestInfo);
         mDeviceSetup.tearDown(mTestInfo, null);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
+        // doSetupExpectations, changeSystemProps, tearDown
+        verify(mMockDevice, times(3)).reboot();
+        verify(mMockDevice, times(1)).pullFile("/data/local.prop");
+        verify(mMockDevice).deleteFile("/data/local.prop");
     }
 
+    @Test
     public void test_restore_settings() throws Exception {
         doSetupExpectations();
         doCheckExternalStoreSpaceExpectations();
-        EasyMock.expect(mMockDevice.getApiLevel()).andStubReturn(23);
-        EasyMock.expect(mMockDevice.getSetting("system", "key")).andReturn("orig").once();
-        mMockDevice.setSetting("system", "key", "value");
-        EasyMock.expectLastCall().once();
-        EasyMock.expect(mMockDevice.getSetting("global", "key2")).andReturn("orig2").once();
-        mMockDevice.setSetting("global", "key2", "value2");
-        EasyMock.expectLastCall().once();
-        EasyMock.expect(mMockDevice.getSetting("secure", "key3")).andReturn("orig3").once();
-        mMockDevice.setSetting("secure", "key3", "value3");
-        EasyMock.expectLastCall().once();
-        mMockDevice.setSetting("system", "key", "orig");
-        EasyMock.expectLastCall().once();
-        mMockDevice.setSetting("global", "key2", "orig2");
-        EasyMock.expectLastCall().once();
-        mMockDevice.setSetting("secure", "key3", "orig3");
-        EasyMock.expectLastCall().once();
+        when(mMockDevice.getApiLevel()).thenReturn(23);
+        when(mMockDevice.getSetting("system", "key")).thenReturn("orig");
 
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getSetting("global", "key2")).thenReturn("orig2");
+
+        when(mMockDevice.getSetting("secure", "key3")).thenReturn("orig3");
 
         mDeviceSetup.setRestoreSettings(true);
         mDeviceSetup.setSystemSetting("key", "value");
@@ -1191,32 +1244,42 @@
         mDeviceSetup.setUp(mTestInfo);
         mDeviceSetup.tearDown(mTestInfo, null);
 
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
+        verify(mMockDevice, times(1)).setSetting("system", "key", "value");
+        verify(mMockDevice, times(1)).setSetting("global", "key2", "value2");
+        verify(mMockDevice, times(1)).setSetting("secure", "key3", "value3");
+        verify(mMockDevice, times(1)).setSetting("system", "key", "orig");
+        verify(mMockDevice, times(1)).setSetting("global", "key2", "orig2");
+        verify(mMockDevice, times(1)).setSetting("secure", "key3", "orig3");
+        verify(mMockDevice, times(1)).getSetting("system", "key");
+        verify(mMockDevice, times(1)).getSetting("global", "key2");
+        verify(mMockDevice, times(1)).getSetting("secure", "key3");
     }
 
+    @Test
     public void testTearDown() throws Exception {
-        EasyMock.replay(mMockDevice);
+
         mDeviceSetup.tearDown(mTestInfo, null);
-        EasyMock.verify(mMockDevice);
     }
 
+    @Test
     public void testTearDown_disconnectFromWifi() throws Exception {
-        EasyMock.expect(mMockDevice.isWifiEnabled()).andReturn(Boolean.TRUE);
-        EasyMock.expect(mMockDevice.disconnectFromWifi()).andReturn(Boolean.TRUE);
+        when(mMockDevice.isWifiEnabled()).thenReturn(Boolean.TRUE);
+        when(mMockDevice.disconnectFromWifi()).thenReturn(Boolean.TRUE);
         mDeviceSetup.setWifiNetwork("wifi_network");
-        EasyMock.replay(mMockDevice);
+
         mDeviceSetup.tearDown(mTestInfo, null);
-        EasyMock.verify(mMockDevice);
     }
 
     /** Test that tearDown is inop when using a stub device instance. */
+    @Test
     public void testTearDown_tcpDevice() throws Exception {
-        EasyMock.expect(mMockDevice.getIDevice()).andReturn(new TcpDevice("tcp-device-0"));
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getIDevice()).thenReturn(new TcpDevice("tcp-device-0"));
+
         mDeviceSetup.tearDown(mTestInfo, null);
-        EasyMock.verify(mMockDevice);
     }
 
+    @Test
     public void testSetup_rootDisabled_withoutChangeSystemProp() throws Exception {
         doSetupExpectations(
                 true /* screenOn */,
@@ -1224,16 +1287,17 @@
                 false /* root response */,
                 false /* test harness */,
                 DEFAULT_API_LEVEL,
-                new Capture<>());
+                ArgumentCaptor.forClass(String.class));
         doCheckExternalStoreSpaceExpectations();
-        EasyMock.replay(mMockDevice);
+
         mDeviceSetup.setDisableDialing(false);
         mDeviceSetup.setDisableAudio(false);
         mDeviceSetup.setTestHarness(false);
         mDeviceSetup.setUp(mTestInfo);
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_rootDisabled_withSkipChangeSystemProp() throws Exception {
         doSetupExpectations(
                 true /* screenOn */,
@@ -1241,23 +1305,24 @@
                 false /* root response */,
                 false /* test harness */,
                 DEFAULT_API_LEVEL,
-                new Capture<>());
+                ArgumentCaptor.forClass(String.class));
         doCheckExternalStoreSpaceExpectations();
-        EasyMock.replay(mMockDevice);
+
         mDeviceSetup.setForceSkipSystemProps(true);
         mDeviceSetup.setUp(mTestInfo);
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
+    @Test
     public void testSetup_rootDisabled_withChangeSystemProp() throws Exception {
         doSetupExpectations(
                 true /* screenOn */,
                 false /* root enabled */,
                 false /* root response */,
                 DEFAULT_API_LEVEL,
-                new Capture<>());
+                ArgumentCaptor.forClass(String.class));
         doCheckExternalStoreSpaceExpectations();
-        EasyMock.replay(mMockDevice);
+
         mDeviceSetup.setProperty("key", "value");
         try {
             mDeviceSetup.setUp(mTestInfo);
@@ -1267,10 +1332,15 @@
         }
     }
 
+    @Test
     public void testSetup_rootFailed() throws Exception {
-        doSetupExpectations(true /* screenOn */, true /* root enabled */,
-                false /* root response */, DEFAULT_API_LEVEL, new Capture<>());
-        EasyMock.replay(mMockDevice);
+        doSetupExpectations(
+                true /* screenOn */,
+                true /* root enabled */,
+                false /* root response */,
+                DEFAULT_API_LEVEL,
+                ArgumentCaptor.forClass(String.class));
+
         try {
             mDeviceSetup.setUp(mTestInfo);
             fail("TargetSetupError expected");
@@ -1279,6 +1349,7 @@
         }
     }
 
+    @Test
     public void testSetup_rootDisabled_withOptimizedPropSetting() throws Exception {
         doSetupExpectations(
                 true /* screenOn */,
@@ -1287,15 +1358,15 @@
                 true /* test harness */,
                 DEFAULT_API_LEVEL,
                 false,
-                new Capture<>());
+                ArgumentCaptor.forClass(String.class));
         doCheckExternalStoreSpaceExpectations();
-        EasyMock.expect(mMockDevice.getProperty("fooProperty")).andReturn("1").anyTimes();
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getProperty("fooProperty")).thenReturn("1");
+
         OptionSetter setter = new OptionSetter(mDeviceSetup);
         setter.setOptionValue("optimized-property-setting", "true");
         setter.setOptionValue("set-property", "fooProperty", "1");
         mDeviceSetup.setUp(mTestInfo);
-        EasyMock.verify(mMockDevice);
+        verify(mMockDevice, atLeastOnce()).getOptions();
     }
 
     /** Set EasyMock expectations for a normal setup call */
@@ -1306,7 +1377,7 @@
                 true /* root response */,
                 true /* test harness mode */,
                 DEFAULT_API_LEVEL,
-                new Capture<String>());
+                ArgumentCaptor.forClass(String.class));
     }
 
     /** Set EasyMock expectations for a normal setup call */
@@ -1318,11 +1389,11 @@
                 true /* root response */,
                 true /* test harness mode */,
                 apiLevel,
-                new Capture<String>());
+                ArgumentCaptor.forClass(String.class));
     }
 
     /** Set EasyMock expectations for a normal setup call */
-    private void doSetupExpectations(boolean screenOn, Capture<String> setPropCapture)
+    private void doSetupExpectations(boolean screenOn, ArgumentCaptor<String> setPropCapture)
             throws DeviceNotAvailableException, ConfigurationException {
         doSetupExpectations(
                 screenOn,
@@ -1339,7 +1410,7 @@
             boolean adbRootEnabled,
             boolean adbRootResponse,
             int apiLevel,
-            Capture<String> setPropCapture)
+            ArgumentCaptor<String> setPropCapture)
             throws DeviceNotAvailableException, ConfigurationException {
         doSetupExpectations(
                 screenOn,
@@ -1357,7 +1428,7 @@
             boolean adbRootResponse,
             boolean testHarness,
             int apiLevel,
-            Capture<String> setPropCapture)
+            ArgumentCaptor<String> setPropCapture)
             throws DeviceNotAvailableException, ConfigurationException {
         doSetupExpectations(
                 screenOn,
@@ -1377,80 +1448,63 @@
             boolean testHarness,
             int apiLevel,
             boolean localPropPush,
-            Capture<String> setPropCapture)
+            ArgumentCaptor<String> setPropCapture)
             throws DeviceNotAvailableException, ConfigurationException {
         TestDeviceOptions options = new TestDeviceOptions();
         OptionSetter setter = new OptionSetter(options);
         setter.setOptionValue("enable-root", Boolean.toString(adbRootEnabled));
-        EasyMock.expect(mMockDevice.getOptions()).andReturn(options).atLeastOnce();
+        when(mMockDevice.getOptions()).thenReturn(options);
         if (adbRootEnabled) {
-            EasyMock.expect(mMockDevice.enableAdbRoot()).andReturn(adbRootResponse);
+            when(mMockDevice.enableAdbRoot()).thenReturn(adbRootResponse);
         }
 
-        EasyMock.expect(mMockDevice.clearErrorDialogs()).andReturn(Boolean.TRUE);
-        EasyMock.expect(mMockDevice.getApiLevel()).andReturn(apiLevel);
+        when(mMockDevice.clearErrorDialogs()).thenReturn(Boolean.TRUE);
+        when(mMockDevice.getApiLevel()).thenReturn(apiLevel);
         if (adbRootResponse && localPropPush) {
             // expect push of local.prop file to change system properties
-            EasyMock.expect(
-                            mMockDevice.pushString(
-                                    EasyMock.capture(setPropCapture),
-                                    EasyMock.contains("local.prop")))
-                    .andReturn(Boolean.TRUE);
-            EasyMock.expect(
-                            mMockDevice.executeShellCommand(
-                                    EasyMock.matches("chmod 644 .*local.prop")))
-                    .andReturn("");
+            when(mMockDevice.pushString(setPropCapture.capture(), Mockito.contains("local.prop")))
+                    .thenReturn(Boolean.TRUE);
+            when(mMockDevice.executeShellCommand(Mockito.matches("chmod 644 .*local.prop")))
+                    .thenReturn("");
             mMockDevice.reboot();
         }
         if (screenOn) {
-            EasyMock.expect(mMockDevice.executeShellCommand("svc power stayon true")).andReturn("");
-            EasyMock.expect(mMockDevice.executeShellCommand("input keyevent 82")).andReturn("");
-            EasyMock.expect(mMockDevice.hasFeature("android.hardware.type.watch"))
-                    .andStubReturn(false);
-            EasyMock.expect(mMockDevice.executeShellCommand("input keyevent 3")).andReturn("");
+            when(mMockDevice.executeShellCommand("svc power stayon true")).thenReturn("");
+            when(mMockDevice.executeShellCommand("input keyevent 82")).thenReturn("");
+            when(mMockDevice.hasFeature("android.hardware.type.watch")).thenReturn(false);
+            when(mMockDevice.executeShellCommand("input keyevent 3")).thenReturn("");
         }
         if (testHarness) {
-            EasyMock.expect(mMockDevice.setProperty("persist.sys.test_harness", "1"))
-                    .andReturn(true);
-            EasyMock.expect(mMockDevice.getProperty("persist.sys.test_harness"))
-                    .andReturn("1")
-                    .anyTimes();
+            when(mMockDevice.setProperty("persist.sys.test_harness", "1")).thenReturn(true);
+            when(mMockDevice.getProperty("persist.sys.test_harness")).thenReturn("1");
         }
-        EasyMock.expect(mMockDevice.getProperty("ro.telephony.disable-call"))
-                .andReturn("true")
-                .anyTimes();
-        EasyMock.expect(mMockDevice.getProperty("ro.audio.silent")).andReturn("1").anyTimes();
-        EasyMock.expect(mMockDevice.getProperty("ro.test_harness")).andReturn("1").anyTimes();
-        EasyMock.expect(mMockDevice.getProperty("ro.monkey")).andReturn("1").anyTimes();
+        when(mMockDevice.getProperty("ro.telephony.disable-call")).thenReturn("true");
+        when(mMockDevice.getProperty("ro.audio.silent")).thenReturn("1");
+        when(mMockDevice.getProperty("ro.test_harness")).thenReturn("1");
+        when(mMockDevice.getProperty("ro.monkey")).thenReturn("1");
     }
 
-    /**
-     * Perform common EasyMock expect operations for a setUp call which syncs local data
-     */
+    /** Perform common EasyMock expect operations for a setUp call which syncs local data */
     private void doSyncDataExpectations(boolean result) throws DeviceNotAvailableException {
         mDeviceSetup.setLocalDataPath(mTmpDir);
-        EasyMock.expect(mMockDevice.getIDevice()).andReturn(mMockIDevice);
+        when(mMockDevice.getIDevice()).thenReturn(mMockIDevice);
         String mntPoint = "/sdcard";
-        EasyMock.expect(mMockIDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE)).andReturn(
-                mntPoint);
-        EasyMock.expect(mMockDevice.syncFiles(mTmpDir, mntPoint)).andReturn(result);
+        when(mMockIDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE)).thenReturn(mntPoint);
+        when(mMockDevice.syncFiles(mTmpDir, mntPoint)).thenReturn(result);
     }
 
     private void doCheckExternalStoreSpaceExpectations() throws DeviceNotAvailableException {
-        EasyMock.expect(mMockDevice.getExternalStoreFreeSpace()).andReturn(1000L);
+        when(mMockDevice.getExternalStoreFreeSpace()).thenReturn(1000L);
     }
 
-    private void doCommandsExpectations(String... commands)
-            throws DeviceNotAvailableException {
+    private void doCommandsExpectations(String... commands) throws DeviceNotAvailableException {
         for (String command : commands) {
-            EasyMock.expect(mMockDevice.executeShellCommand(command)).andReturn("");
+            when(mMockDevice.executeShellCommand(command)).thenReturn("");
         }
     }
 
     private void doSettingExpectations(String namespace, String key, String value)
             throws DeviceNotAvailableException {
-        EasyMock.expect(mMockDevice.getApiLevel()).andReturn(22);
-        mMockDevice.setSetting(namespace, key, value);
-        EasyMock.expectLastCall();
+        when(mMockDevice.getApiLevel()).thenReturn(22);
     }
 }
diff --git a/javatests/com/android/tradefed/targetprep/GkiDeviceFlashPreparerTest.java b/javatests/com/android/tradefed/targetprep/GkiDeviceFlashPreparerTest.java
index 52c377d..ed9e50c 100644
--- a/javatests/com/android/tradefed/targetprep/GkiDeviceFlashPreparerTest.java
+++ b/javatests/com/android/tradefed/targetprep/GkiDeviceFlashPreparerTest.java
@@ -27,13 +27,13 @@
 import com.android.tradefed.build.DeviceBuildInfo;
 import com.android.tradefed.build.IDeviceBuildInfo;
 import com.android.tradefed.command.remote.DeviceDescriptor;
-import com.android.tradefed.config.OptionSetter;
 import com.android.tradefed.device.DeviceAllocationState;
 import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.IDeviceManager;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.device.ITestDevice.RecoveryMode;
 import com.android.tradefed.device.TestDeviceOptions;
+import com.android.tradefed.host.HostOptions;
+import com.android.tradefed.host.IHostOptions;
 import com.android.tradefed.invoker.IInvocationContext;
 import com.android.tradefed.invoker.InvocationContext;
 import com.android.tradefed.invoker.TestInformation;
@@ -54,18 +54,15 @@
 import java.io.File;
 import java.util.List;
 
-/** Unit tests for {@link GkiDevicePreparer}. */
+/** Unit tests for {@link GkiDeviceFlashPreparer}. */
 @RunWith(JUnit4.class)
 public class GkiDeviceFlashPreparerTest {
 
-    @Mock IDeviceManager mMockDeviceManager;
-    private IDeviceFlasher mMockFlasher;
     private GkiDeviceFlashPreparer mPreparer;
     @Mock ITestDevice mMockDevice;
     private IDeviceBuildInfo mBuildInfo;
     private File mTmpDir;
     private TestInformation mTestInfo;
-    private OptionSetter mOptionSetter;
     private CommandResult mSuccessResult;
     private CommandResult mFailureResult;
     @Mock IRunUtil mMockRunUtil;
@@ -98,12 +95,11 @@
                     }
 
                     @Override
-                    IDeviceManager getDeviceManager() {
-                        return mMockDeviceManager;
+                    protected IHostOptions getHostOptions() {
+                        return new HostOptions();
                     }
                 };
         // Reset default settings
-        mOptionSetter = new OptionSetter(mPreparer);
         mTmpDir = FileUtil.createTempDir("tmp");
         mBuildInfo = new DeviceBuildInfo("0", "");
         mBuildInfo.setBuildFlavor("flavor");
diff --git a/javatests/com/android/tradefed/targetprep/GsiDeviceFlashPreparerTest.java b/javatests/com/android/tradefed/targetprep/GsiDeviceFlashPreparerTest.java
index bccf68d..b68b7eb 100644
--- a/javatests/com/android/tradefed/targetprep/GsiDeviceFlashPreparerTest.java
+++ b/javatests/com/android/tradefed/targetprep/GsiDeviceFlashPreparerTest.java
@@ -23,11 +23,11 @@
 import com.android.tradefed.command.remote.DeviceDescriptor;
 import com.android.tradefed.device.DeviceAllocationState;
 import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.config.OptionSetter;
-import com.android.tradefed.device.IDeviceManager;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.device.ITestDevice.RecoveryMode;
 import com.android.tradefed.device.TestDeviceOptions;
+import com.android.tradefed.host.HostOptions;
+import com.android.tradefed.host.IHostOptions;
 import com.android.tradefed.invoker.IInvocationContext;
 import com.android.tradefed.invoker.InvocationContext;
 import com.android.tradefed.invoker.TestInformation;
@@ -47,18 +47,15 @@
 import java.io.File;
 import java.util.List;
 
-/** Unit tests for {@link GsiDevicePreparer}. */
+/** Unit tests for {@link GsiDeviceFlashPreparer}. */
 @RunWith(JUnit4.class)
 public class GsiDeviceFlashPreparerTest {
 
-    private IDeviceManager mMockDeviceManager;
-    private IDeviceFlasher mMockFlasher;
     private GsiDeviceFlashPreparer mPreparer;
     private ITestDevice mMockDevice;
     private IDeviceBuildInfo mBuildInfo;
     private File mTmpDir;
     private TestInformation mTestInfo;
-    private OptionSetter mOptionSetter;
     private CommandResult mSuccessResult;
     private CommandResult mFailureResult;
     private IRunUtil mMockRunUtil;
@@ -76,7 +73,6 @@
                         "unknown",
                         "unknown",
                         "unknown");
-        mMockDeviceManager = EasyMock.createMock(IDeviceManager.class);
         mMockDevice = EasyMock.createMock(ITestDevice.class);
         EasyMock.expect(mMockDevice.getSerialNumber()).andStubReturn("serial_1");
         EasyMock.expect(mMockDevice.getDeviceDescriptor()).andStubReturn(mDeviceDescriptor);
@@ -90,12 +86,11 @@
                     }
 
                     @Override
-                    IDeviceManager getDeviceManager() {
-                        return mMockDeviceManager;
+                    protected IHostOptions getHostOptions() {
+                        return new HostOptions();
                     }
                 };
         // Reset default settings
-        mOptionSetter = new OptionSetter(mPreparer);
         mTmpDir = FileUtil.createTempDir("tmp");
         mBuildInfo = new DeviceBuildInfo("0", "");
         mBuildInfo.setBuildFlavor("flavor");
diff --git a/javatests/com/android/tradefed/targetprep/RunHostCommandTargetPreparerTest.java b/javatests/com/android/tradefed/targetprep/RunHostCommandTargetPreparerTest.java
index b654c97..15665e1 100644
--- a/javatests/com/android/tradefed/targetprep/RunHostCommandTargetPreparerTest.java
+++ b/javatests/com/android/tradefed/targetprep/RunHostCommandTargetPreparerTest.java
@@ -25,14 +25,15 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
-import com.android.tradefed.build.BuildInfo;
-import com.android.tradefed.util.FileUtil;
 
+import com.android.tradefed.build.BuildInfo;
 import com.android.tradefed.config.OptionSetter;
-import com.android.tradefed.device.IDeviceManager;
+import com.android.tradefed.host.IHostOptions;
+import com.android.tradefed.host.IHostOptions.PermitLimitType;
 import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.util.CommandResult;
 import com.android.tradefed.util.CommandStatus;
+import com.android.tradefed.util.FileUtil;
 import com.android.tradefed.util.IRunUtil;
 
 import org.junit.Before;
@@ -46,8 +47,8 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
-import java.io.OutputStream;
 import java.io.File;
+import java.io.OutputStream;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
@@ -67,7 +68,7 @@
 
     @Mock private RunHostCommandTargetPreparer.BgCommandLog mBgCommandLog;
     @Mock private IRunUtil mRunUtil;
-    @Mock private IDeviceManager mDeviceManager;
+    @Mock private IHostOptions mHostOptions;
     private RunHostCommandTargetPreparer mPreparer;
 
     @Before
@@ -80,8 +81,8 @@
                     }
 
                     @Override
-                    IDeviceManager getDeviceManager() {
-                        return mDeviceManager;
+                    IHostOptions getHostOptions() {
+                        return mHostOptions;
                     }
 
                     @Override
@@ -106,8 +107,8 @@
         verify(mRunUtil).runTimedCmd(eq(10L), eq("command"), eq("argument"), eq(DEVICE_SERIAL));
 
         // No flashing permit taken/returned by default
-        verify(mDeviceManager, never()).takeFlashingPermit();
-        verify(mDeviceManager, never()).returnFlashingPermit();
+        verify(mHostOptions, never()).takePermit(PermitLimitType.CONCURRENT_FLASHER);
+        verify(mHostOptions, never()).returnPermit(PermitLimitType.CONCURRENT_FLASHER);
     }
 
     @Test
@@ -149,11 +150,11 @@
 
         // Verify command ran with flashing permit
         mPreparer.setUp(mTestInfo);
-        InOrder inOrder = inOrder(mRunUtil, mDeviceManager);
-        inOrder.verify(mDeviceManager).takeFlashingPermit();
+        InOrder inOrder = inOrder(mRunUtil, mHostOptions);
+        inOrder.verify(mHostOptions).takePermit(PermitLimitType.CONCURRENT_FLASHER);
         inOrder.verify(mRunUtil)
                 .runTimedCmd(anyLong(), eq("command"), eq("argument"), eq(DEVICE_SERIAL));
-        inOrder.verify(mDeviceManager).returnFlashingPermit();
+        inOrder.verify(mHostOptions).returnPermit(PermitLimitType.CONCURRENT_FLASHER);
     }
 
     @Test
@@ -170,8 +171,8 @@
         verify(mRunUtil).runTimedCmd(eq(10L), eq("command"), eq("argument"), eq(DEVICE_SERIAL));
 
         // No flashing permit taken/returned by default
-        verify(mDeviceManager, never()).takeFlashingPermit();
-        verify(mDeviceManager, never()).returnFlashingPermit();
+        verify(mHostOptions, never()).takePermit(PermitLimitType.CONCURRENT_FLASHER);
+        verify(mHostOptions, never()).returnPermit(PermitLimitType.CONCURRENT_FLASHER);
     }
 
     @Test
@@ -197,11 +198,11 @@
 
         // Verify command ran with flashing permit
         mPreparer.tearDown(mTestInfo, null);
-        InOrder inOrder = inOrder(mRunUtil, mDeviceManager);
-        inOrder.verify(mDeviceManager).takeFlashingPermit();
+        InOrder inOrder = inOrder(mRunUtil, mHostOptions);
+        inOrder.verify(mHostOptions).takePermit(PermitLimitType.CONCURRENT_FLASHER);
         inOrder.verify(mRunUtil)
                 .runTimedCmd(anyLong(), eq("command"), eq("argument"), eq(DEVICE_SERIAL));
-        inOrder.verify(mDeviceManager).returnFlashingPermit();
+        inOrder.verify(mHostOptions).returnPermit(PermitLimitType.CONCURRENT_FLASHER);
     }
 
     @Test
@@ -245,8 +246,8 @@
                 eq(file1.getAbsolutePath()), eq(file2.getAbsolutePath()));
 
         // No flashing permit taken/returned by default
-        verify(mDeviceManager, never()).takeFlashingPermit();
-        verify(mDeviceManager, never()).returnFlashingPermit();
+        verify(mHostOptions, never()).takePermit(PermitLimitType.CONCURRENT_FLASHER);
+        verify(mHostOptions, never()).returnPermit(PermitLimitType.CONCURRENT_FLASHER);
 
         FileUtil.recursiveDelete(tmpDir);
     }
@@ -268,7 +269,7 @@
                 eq("$EXTRA_FILE(test1)"), eq("$EXTRA_FILE(test2)"));
 
         // No flashing permit taken/returned by default
-        verify(mDeviceManager, never()).takeFlashingPermit();
-        verify(mDeviceManager, never()).returnFlashingPermit();
+        verify(mHostOptions, never()).takePermit(PermitLimitType.CONCURRENT_FLASHER);
+        verify(mHostOptions, never()).returnPermit(PermitLimitType.CONCURRENT_FLASHER);
     }
 }
diff --git a/javatests/com/android/tradefed/targetprep/RunHostScriptTargetPreparerTest.java b/javatests/com/android/tradefed/targetprep/RunHostScriptTargetPreparerTest.java
index 236498a..2c246bc 100644
--- a/javatests/com/android/tradefed/targetprep/RunHostScriptTargetPreparerTest.java
+++ b/javatests/com/android/tradefed/targetprep/RunHostScriptTargetPreparerTest.java
@@ -29,6 +29,8 @@
 import com.android.tradefed.config.ConfigurationException;
 import com.android.tradefed.config.OptionSetter;
 import com.android.tradefed.device.IDeviceManager;
+import com.android.tradefed.host.IHostOptions;
+import com.android.tradefed.host.IHostOptions.PermitLimitType;
 import com.android.tradefed.invoker.ExecutionFiles.FilesKey;
 import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.util.CommandResult;
@@ -65,6 +67,7 @@
     private TestInformation mTestInfo;
 
     @Mock private IRunUtil mRunUtil;
+    @Mock private IHostOptions mHostOptions;
     @Mock private IDeviceManager mDeviceManager;
     private RunHostScriptTargetPreparer mPreparer;
     private OptionSetter mOptionSetter;
@@ -82,6 +85,11 @@
                     }
 
                     @Override
+                    IHostOptions getHostOptions() {
+                        return mHostOptions;
+                    }
+
+                    @Override
                     IDeviceManager getDeviceManager() {
                         return mDeviceManager;
                     }
@@ -120,8 +128,8 @@
         // Verify that script is executable
         assertTrue(mScriptFile.canExecute());
         // No flashing permit taken/returned by default
-        verify(mDeviceManager, never()).takeFlashingPermit();
-        verify(mDeviceManager, never()).returnFlashingPermit();
+        verify(mHostOptions, never()).takePermit(PermitLimitType.CONCURRENT_FLASHER);
+        verify(mHostOptions, never()).returnPermit(PermitLimitType.CONCURRENT_FLASHER);
     }
 
     @Test
@@ -181,9 +189,9 @@
         mOptionSetter.setOptionValue("use-flashing-permit", "true");
         // Verify script executed with flashing permit
         mPreparer.setUp(mTestInfo);
-        InOrder inOrder = inOrder(mRunUtil, mDeviceManager);
-        inOrder.verify(mDeviceManager).takeFlashingPermit();
+        InOrder inOrder = inOrder(mRunUtil, mHostOptions);
+        inOrder.verify(mHostOptions).takePermit(PermitLimitType.CONCURRENT_FLASHER);
         inOrder.verify(mRunUtil).runTimedCmd(anyLong(), eq(mScriptFile.getAbsolutePath()));
-        inOrder.verify(mDeviceManager).returnFlashingPermit();
+        inOrder.verify(mHostOptions).returnPermit(PermitLimitType.CONCURRENT_FLASHER);
     }
 }
diff --git a/javatests/com/android/tradefed/targetprep/RunOnSecondaryUserTargetPreparerTest.java b/javatests/com/android/tradefed/targetprep/RunOnSecondaryUserTargetPreparerTest.java
index 3f3347e..76764a7 100644
--- a/javatests/com/android/tradefed/targetprep/RunOnSecondaryUserTargetPreparerTest.java
+++ b/javatests/com/android/tradefed/targetprep/RunOnSecondaryUserTargetPreparerTest.java
@@ -73,6 +73,7 @@
 
         when(mTestInfo.getDevice().getMaxNumberOfUsersSupported()).thenReturn(2);
         when(mTestInfo.getDevice().listUsers()).thenReturn(userIds);
+        when(mTestInfo.getDevice().getApiLevel()).thenReturn(30);
     }
 
     @Test
@@ -88,6 +89,20 @@
     }
 
     @Test
+    public void setUp_oldVersion_createsStartsAndSwitchesToSecondaryUserWithoutWait()
+            throws Exception {
+        when(mTestInfo.getDevice().createUser(any())).thenReturn(2);
+        when(mTestInfo.getDevice().getCurrentUser()).thenReturn(0);
+        when(mTestInfo.getDevice().getApiLevel()).thenReturn(28);
+
+        mPreparer.setUp(mTestInfo);
+
+        verify(mTestInfo.getDevice()).createUser("secondary");
+        verify(mTestInfo.getDevice()).startUser(2, /* waitFlag= */ false);
+        verify(mTestInfo.getDevice()).switchUser(2);
+    }
+
+    @Test
     public void setUp_secondaryUserAlreadyExists_doesNotCreateSecondaryUser() throws Exception {
         Map<Integer, UserInfo> userInfos = new HashMap<>();
         userInfos.put(2, new UserInfo(2, "secondary", /* flag= */ 0, /* isRunning= */ true));
diff --git a/javatests/com/android/tradefed/targetprep/RunOnWorkProfileTargetPreparerTest.java b/javatests/com/android/tradefed/targetprep/RunOnWorkProfileTargetPreparerTest.java
index 459615b..8e8a5a2 100644
--- a/javatests/com/android/tradefed/targetprep/RunOnWorkProfileTargetPreparerTest.java
+++ b/javatests/com/android/tradefed/targetprep/RunOnWorkProfileTargetPreparerTest.java
@@ -22,6 +22,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static junit.framework.Assert.fail;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.never;
@@ -62,6 +64,26 @@
     private RunOnWorkProfileTargetPreparer mPreparer;
     private OptionSetter mOptionSetter;
 
+    private static final String DEVICE_OWNER_COMPONENT_NAME =
+            "com.android.dpcpackage/com.android.Receiver";
+    private static final int DEVICE_OWNER_USER = 0;
+    private static final String DUMPSYS_WITH_DEVICE_OWNER =
+            "Current Device Policy Manager state:\n"
+                    + "  Immutable state:\n"
+                    + "    mHasFeature=true\n"
+                    + "    mIsWatch=false\n"
+                    + "    mIsAutomotive=false\n"
+                    + "    mHasTelephonyFeature=true\n"
+                    + "    mSafetyChecker=null\n"
+                    + "  Device Owner:\n"
+                    + "    admin=ComponentInfo{com.android.dpcpackage/com.android.Receiver}\n"
+                    + "    name=DO\n"
+                    + "    package=com.android.dpcpackage\n"
+                    + "    isOrganizationOwnedDevice=true\n"
+                    + "    User ID: 0\n"
+                    + "\n"
+                    + "  Profile Owner (User 49):";
+
     @Before
     public void setUp() throws Exception {
         mPreparer = new RunOnWorkProfileTargetPreparer();
@@ -74,6 +96,8 @@
         when(mTestInfo.getDevice().hasFeature("android.software.managed_users")).thenReturn(true);
         when(mTestInfo.getDevice().getMaxNumberOfUsersSupported()).thenReturn(2);
         when(mTestInfo.getDevice().listUsers()).thenReturn(userIds);
+        when(mTestInfo.getDevice().getApiLevel()).thenReturn(30);
+        when(mTestInfo.getDevice().executeShellCommand("dumpsys device_policy")).thenReturn("");
     }
 
     @Test
@@ -89,6 +113,57 @@
     }
 
     @Test
+    public void setUp_oldVersion_createsAndStartsWorkProfileWithoutWait() throws Exception {
+        String expectedCreateUserCommand = "pm create-user --profileOf 0 --managed work";
+        when(mTestInfo.getDevice().executeShellCommand(expectedCreateUserCommand))
+                .thenReturn(CREATED_USER_10_MESSAGE);
+        when(mTestInfo.getDevice().getApiLevel()).thenReturn(28);
+
+        mPreparer.setUp(mTestInfo);
+
+        verify(mTestInfo.getDevice()).executeShellCommand(expectedCreateUserCommand);
+        verify(mTestInfo.getDevice()).startUser(10, /* waitFlag= */ false);
+    }
+
+    @Test
+    public void setup_hasDeviceOwner_removesDeviceOwner() throws Exception {
+        String expectedCreateUserCommand = "pm create-user --profileOf 0 --managed work";
+        String expectedRemoveDeviceOwnerCommand =
+                "dpm remove-active-admin --user 0 " + DEVICE_OWNER_COMPONENT_NAME;
+        when(mTestInfo.getDevice().executeShellCommand(expectedCreateUserCommand))
+                .thenReturn(CREATED_USER_10_MESSAGE);
+        when(mTestInfo.getDevice().executeShellCommand("dumpsys device_policy"))
+                .thenReturn(DUMPSYS_WITH_DEVICE_OWNER);
+        when(mTestInfo.getDevice().executeShellCommand(expectedRemoveDeviceOwnerCommand))
+                .thenReturn("Success: done");
+
+        mPreparer.setUp(mTestInfo);
+
+        verify(mTestInfo.getDevice()).executeShellCommand(expectedRemoveDeviceOwnerCommand);
+    }
+
+    @Test
+    public void setup_hasDeviceOwner_errorWhenRemovingDeviceOwner_throwsException()
+            throws Exception {
+        String expectedCreateUserCommand = "pm create-user --profileOf 0 --managed work";
+        String expectedRemoveDeviceOwnerCommand =
+                "dpm remove-active-admin --user 0 " + DEVICE_OWNER_COMPONENT_NAME;
+        when(mTestInfo.getDevice().executeShellCommand(expectedCreateUserCommand))
+                .thenReturn(CREATED_USER_10_MESSAGE);
+        when(mTestInfo.getDevice().executeShellCommand("dumpsys device_policy"))
+                .thenReturn(DUMPSYS_WITH_DEVICE_OWNER);
+        when(mTestInfo.getDevice().executeShellCommand(expectedRemoveDeviceOwnerCommand))
+                .thenReturn("Error: could not remove");
+
+        try {
+            mPreparer.setUp(mTestInfo);
+            fail();
+        } catch (IllegalStateException expected) {
+
+        }
+    }
+
+    @Test
     public void setUp_workProfileAlreadyExists_doesNotCreateWorkProfile() throws Exception {
         Map<Integer, UserInfo> userInfos = new HashMap<>();
         userInfos.put(
@@ -106,6 +181,26 @@
     }
 
     @Test
+    public void setUp_workProfileAlreadyExists_hasDeviceOwner_doesNotRemoveDeviceOwner()
+            throws Exception {
+        Map<Integer, UserInfo> userInfos = new HashMap<>();
+        userInfos.put(
+                10,
+                new UserInfo(
+                        10,
+                        "work",
+                        /* flag= */ UserInfo.FLAG_MANAGED_PROFILE,
+                        /* isRunning= */ true));
+        when(mTestInfo.getDevice().getUserInfos()).thenReturn(userInfos);
+        when(mTestInfo.getDevice().executeShellCommand("dumpsys device_policy"))
+                .thenReturn(DUMPSYS_WITH_DEVICE_OWNER);
+
+        mPreparer.setUp(mTestInfo);
+
+        verify(mTestInfo.getDevice(), never()).executeShellCommand(any());
+    }
+
+    @Test
     public void setUp_nonZeroCurrentUser_createsWorkProfileForCorrectUser() throws Exception {
         when(mTestInfo.getDevice().getCurrentUser()).thenReturn(1);
         String expectedCreateUserCommand = "pm create-user --profileOf 1 --managed work";
@@ -229,6 +324,25 @@
     }
 
     @Test
+    public void teardown_didRemoveDeviceOwner_setsDeviceOwner() throws Exception {
+        String expectedCreateUserCommand = "pm create-user --profileOf 0 --managed work";
+        String expectedRemoveDeviceOwnerCommand =
+                "dpm remove-active-admin --user 0 " + DEVICE_OWNER_COMPONENT_NAME;
+        when(mTestInfo.getDevice().executeShellCommand(expectedCreateUserCommand))
+                .thenReturn(CREATED_USER_10_MESSAGE);
+        when(mTestInfo.getDevice().executeShellCommand("dumpsys device_policy"))
+                .thenReturn(DUMPSYS_WITH_DEVICE_OWNER);
+        when(mTestInfo.getDevice().executeShellCommand(expectedRemoveDeviceOwnerCommand))
+                .thenReturn("Success: done");
+        mPreparer.setUp(mTestInfo);
+
+        mPreparer.tearDown(mTestInfo, /* throwable= */ null);
+
+        verify(mTestInfo.getDevice())
+                .setDeviceOwner(DEVICE_OWNER_COMPONENT_NAME, /* userId= */ DEVICE_OWNER_USER);
+    }
+
+    @Test
     public void setUp_doesNotSupportManagedUsers_doesNotChangeTestUser() throws Exception {
         when(mTestInfo.getDevice().hasFeature("android.software.managed_users")).thenReturn(false);
 
diff --git a/javatests/com/android/tradefed/targetprep/TestAppInstallSetupTest.java b/javatests/com/android/tradefed/targetprep/TestAppInstallSetupTest.java
index 70be61b..1a2ad12 100644
--- a/javatests/com/android/tradefed/targetprep/TestAppInstallSetupTest.java
+++ b/javatests/com/android/tradefed/targetprep/TestAppInstallSetupTest.java
@@ -23,14 +23,14 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.easymock.EasyMock.anyBoolean;
-import static org.easymock.EasyMock.anyObject;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-
+import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import com.android.incfs.install.IncrementalInstallSession;
 import com.android.incfs.install.IncrementalInstallSession.Builder;
@@ -50,13 +50,14 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 
-import org.easymock.EasyMock;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mock;
 import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 
 import java.io.File;
 import java.io.IOException;
@@ -84,8 +85,8 @@
     private AaptParser mMockAaptParser;
     private TestAppInstallSetup mPrep;
     private TestInformation mTestInfo;
-    private IDeviceBuildInfo mMockBuildInfo;
-    private ITestDevice mMockTestDevice;
+    @Mock IDeviceBuildInfo mMockBuildInfo;
+    @Mock ITestDevice mMockTestDevice;
     private IncrementalInstallSession.Builder mMockIncrementalInstallSessionBuilder;
     private IncrementalInstallSession mMockIncrementalInstallSession;
     private File mTestDir;
@@ -96,6 +97,8 @@
 
     @Before
     public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
         mTestDir = FileUtil.createTempDir("TestAppSetupTest");
         mBuildTestDir = FileUtil.createTempDir("TestAppBuildTestDir");
         mTemporaryFolder = FileUtil.createTempDir("TestAppInstallSetupTest-tmp");
@@ -143,15 +146,14 @@
         mTestSplitApkFiles.add(fakeApk);
         mTestSplitApkFiles.add(fakeApk2);
 
-        mMockBuildInfo = EasyMock.createMock(IDeviceBuildInfo.class);
         mMockAaptParser = Mockito.mock(AaptParser.class);
-        mMockTestDevice = EasyMock.createMock(ITestDevice.class);
+
         mMockIncrementalInstallSessionBuilder =
                 Mockito.mock(IncrementalInstallSession.Builder.class);
         mMockIncrementalInstallSession = Mockito.mock(IncrementalInstallSession.class);
-        EasyMock.expect(mMockTestDevice.getSerialNumber()).andStubReturn(SERIAL);
-        EasyMock.expect(mMockTestDevice.getDeviceDescriptor()).andStubReturn(null);
-        EasyMock.expect(mMockTestDevice.isAppEnumerationSupported()).andStubReturn(false);
+        when(mMockTestDevice.getSerialNumber()).thenReturn(SERIAL);
+        when(mMockTestDevice.getDeviceDescriptor()).thenReturn(null);
+        when(mMockTestDevice.isAppEnumerationSupported()).thenReturn(false);
         IInvocationContext context = new InvocationContext();
         context.addAllocatedDevice("device", mMockTestDevice);
         context.addDeviceBuildInfo("device", mMockBuildInfo);
@@ -167,15 +169,14 @@
 
     @Test
     public void testSetupAndTeardown() throws Exception {
-        EasyMock.expect(mMockTestDevice.installPackage(EasyMock.eq(fakeApk), EasyMock.eq(true)))
-                .andReturn(null);
-        EasyMock.expect(
-                        mMockTestDevice.installPackages(
-                                EasyMock.eq(mTestSplitApkFiles), EasyMock.eq(true)))
-                .andReturn(null);
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
+        when(mMockTestDevice.installPackage(Mockito.eq(fakeApk), Mockito.eq(true)))
+                .thenReturn(null);
+        when(mMockTestDevice.installPackages(Mockito.eq(mTestSplitApkFiles), Mockito.eq(true)))
+                .thenReturn(null);
+
         mPrep.setUp(mTestInfo);
-        EasyMock.verify(mMockBuildInfo, mMockTestDevice);
+        verify(mMockTestDevice, atLeastOnce())
+                .installPackages(Mockito.eq(mTestSplitApkFiles), Mockito.eq(true));
     }
 
     @Test
@@ -197,24 +198,24 @@
         mSetter = new OptionSetter(mPrep);
         mSetter.setOptionValue("cleanup-apks", "true");
         mSetter.setOptionValue("test-file-name", APK_NAME);
-        EasyMock.expect(mMockTestDevice.installPackage(EasyMock.eq(fakeApk), EasyMock.eq(true)))
-                .andReturn(null);
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
+        when(mMockTestDevice.installPackage(Mockito.eq(fakeApk), Mockito.eq(true)))
+                .thenReturn(null);
+
         mPrep.setUp(mTestInfo);
-        EasyMock.verify(mMockBuildInfo, mMockTestDevice);
+        verify(mMockTestDevice, atLeastOnce())
+                .installPackage(Mockito.eq(fakeApk), Mockito.eq(true));
     }
 
     @Test
     public void testSetupAndTeardown_install_packages_only() throws Exception {
         mPrep.clearTestFile();
         mSetter.setOptionValue("cleanup-apks", "true");
-        EasyMock.expect(
-                        mMockTestDevice.installPackages(
-                                EasyMock.eq(mTestSplitApkFiles), EasyMock.eq(true)))
-                .andReturn(null);
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
+        when(mMockTestDevice.installPackages(Mockito.eq(mTestSplitApkFiles), Mockito.eq(true)))
+                .thenReturn(null);
+
         mPrep.setUp(mTestInfo);
-        EasyMock.verify(mMockBuildInfo, mMockTestDevice);
+        verify(mMockTestDevice, atLeastOnce())
+                .installPackages(Mockito.eq(mTestSplitApkFiles), Mockito.eq(true));
     }
 
     @Test
@@ -239,32 +240,30 @@
         mSetter.setOptionValue("test-file-name", APK_NAME);
         mTestInfo.properties().put(RUN_TESTS_AS_USER_KEY, Integer.toString(userId));
 
-        EasyMock.expect(
-                        mMockTestDevice.installPackageForUser(
-                                EasyMock.eq(fakeApk), EasyMock.eq(true), EasyMock.eq(userId)))
-                .andReturn(null);
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
+        when(mMockTestDevice.installPackageForUser(
+                        Mockito.eq(fakeApk), Mockito.eq(true), Mockito.eq(userId)))
+                .thenReturn(null);
+
         mPrep.setUp(mTestInfo);
-        EasyMock.verify(mMockBuildInfo, mMockTestDevice);
+        verify(mMockTestDevice, atLeastOnce())
+                .installPackageForUser(Mockito.eq(fakeApk), Mockito.eq(true), Mockito.eq(userId));
     }
 
     @Test
     public void testSetup_instantMode() throws Exception {
         OptionSetter setter = new OptionSetter(mPrep);
         setter.setOptionValue("instant-mode", "true");
-        EasyMock.expect(
-                        mMockTestDevice.installPackage(
-                                EasyMock.eq(fakeApk), EasyMock.eq(true), EasyMock.eq("--instant")))
-                .andReturn(null);
-        EasyMock.expect(
-                        mMockTestDevice.installPackages(
-                                EasyMock.eq(mTestSplitApkFiles),
-                                EasyMock.eq(true),
-                                EasyMock.eq("--instant")))
-                .andReturn(null);
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
+        when(mMockTestDevice.installPackage(
+                        Mockito.eq(fakeApk), Mockito.eq(true), Mockito.eq("--instant")))
+                .thenReturn(null);
+        when(mMockTestDevice.installPackages(
+                        Mockito.eq(mTestSplitApkFiles), Mockito.eq(true), Mockito.eq("--instant")))
+                .thenReturn(null);
+
         mPrep.setUp(mTestInfo);
-        EasyMock.verify(mMockBuildInfo, mMockTestDevice);
+        verify(mMockTestDevice, atLeastOnce())
+                .installPackages(
+                        Mockito.eq(mTestSplitApkFiles), Mockito.eq(true), Mockito.eq("--instant"));
     }
 
     /**
@@ -276,23 +275,19 @@
         // Install the apk twice
         mSetter.setOptionValue("test-file-name", APK_NAME);
         mPrep.setAbi(new Abi("arm32", "32"));
-        EasyMock.expect(mMockTestDevice.getApiLevel()).andReturn(25);
-        EasyMock.expect(
-                        mMockTestDevice.installPackage(
-                                EasyMock.eq(fakeApk),
-                                EasyMock.eq(true),
-                                EasyMock.eq("--abi arm32")))
-                .andReturn(null)
-                .times(2);
-        EasyMock.expect(
-                        mMockTestDevice.installPackages(
-                                EasyMock.eq(mTestSplitApkFiles),
-                                EasyMock.eq(true),
-                                EasyMock.eq("--abi arm32")))
-                .andReturn(null);
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
+        when(mMockTestDevice.getApiLevel()).thenReturn(25);
+        when(mMockTestDevice.installPackage(
+                        Mockito.eq(fakeApk), Mockito.eq(true), Mockito.eq("--abi arm32")))
+                .thenReturn(null);
+        when(mMockTestDevice.installPackages(
+                        Mockito.eq(mTestSplitApkFiles),
+                        Mockito.eq(true),
+                        Mockito.eq("--abi arm32")))
+                .thenReturn(null);
+
         mPrep.setUp(mTestInfo);
-        EasyMock.verify(mMockBuildInfo, mMockTestDevice);
+        verify(mMockTestDevice, times(2))
+                .installPackage(Mockito.eq(fakeApk), Mockito.eq(true), Mockito.eq("--abi arm32"));
     }
 
     /**
@@ -304,45 +299,48 @@
         OptionSetter setter = new OptionSetter(mPrep);
         setter.setOptionValue("instant-mode", "true");
         setter.setOptionValue("force-install-mode", "FULL");
-        EasyMock.expect(mMockTestDevice.installPackage(EasyMock.eq(fakeApk), EasyMock.eq(true)))
-                .andReturn(null);
-        EasyMock.expect(
-                        mMockTestDevice.installPackages(
-                                EasyMock.eq(mTestSplitApkFiles), EasyMock.eq(true)))
-                .andReturn(null);
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
+        when(mMockTestDevice.installPackage(Mockito.eq(fakeApk), Mockito.eq(true)))
+                .thenReturn(null);
+        when(mMockTestDevice.installPackages(Mockito.eq(mTestSplitApkFiles), Mockito.eq(true)))
+                .thenReturn(null);
+
         mPrep.setUp(mTestInfo);
-        EasyMock.verify(mMockBuildInfo, mMockTestDevice);
+        verify(mMockTestDevice, atLeastOnce())
+                .installPackages(Mockito.eq(mTestSplitApkFiles), Mockito.eq(true));
     }
 
     @Test
     public void testSetup_forceQueryable() throws Exception {
-        EasyMock.expect(mMockTestDevice.isAppEnumerationSupported()).andReturn(true);
-        EasyMock.expect(mMockTestDevice.installPackage(
-                EasyMock.eq(fakeApk), EasyMock.eq(true), EasyMock.eq("--force-queryable")))
-                .andReturn(null);
-        EasyMock.expect(
-                mMockTestDevice.installPackages(
-                        EasyMock.eq(mTestSplitApkFiles), EasyMock.eq(true),
-                        EasyMock.eq("--force-queryable")))
-                .andReturn(null);
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
+        when(mMockTestDevice.isAppEnumerationSupported()).thenReturn(true);
+        when(mMockTestDevice.installPackage(
+                        Mockito.eq(fakeApk), Mockito.eq(true), Mockito.eq("--force-queryable")))
+                .thenReturn(null);
+        when(mMockTestDevice.installPackages(
+                        Mockito.eq(mTestSplitApkFiles),
+                        Mockito.eq(true),
+                        Mockito.eq("--force-queryable")))
+                .thenReturn(null);
+
         mPrep.setUp(mTestInfo);
-        EasyMock.verify(mMockBuildInfo, mMockTestDevice);
+        verify(mMockTestDevice, atLeastOnce())
+                .installPackages(
+                        Mockito.eq(mTestSplitApkFiles),
+                        Mockito.eq(true),
+                        Mockito.eq("--force-queryable"));
     }
 
     @Test
     public void testSetup_forceQueryableIsFalse() throws Exception {
-        EasyMock.expect(mMockTestDevice.isAppEnumerationSupported()).andStubReturn(true);
-        EasyMock.expect(mMockTestDevice.installPackage(
-                EasyMock.eq(fakeApk), EasyMock.eq(true))).andReturn(null);
-        EasyMock.expect(
-                mMockTestDevice.installPackages(
-                        EasyMock.eq(mTestSplitApkFiles), EasyMock.eq(true))).andReturn(null);
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
+        when(mMockTestDevice.isAppEnumerationSupported()).thenReturn(true);
+        when(mMockTestDevice.installPackage(Mockito.eq(fakeApk), Mockito.eq(true)))
+                .thenReturn(null);
+        when(mMockTestDevice.installPackages(Mockito.eq(mTestSplitApkFiles), Mockito.eq(true)))
+                .thenReturn(null);
+
         mPrep.setForceQueryable(false);
         mPrep.setUp(mTestInfo);
-        EasyMock.verify(mMockBuildInfo, mMockTestDevice);
+        verify(mMockTestDevice, atLeastOnce())
+                .installPackages(Mockito.eq(mTestSplitApkFiles), Mockito.eq(true));
     }
 
     /**
@@ -394,9 +392,8 @@
         setter.setOptionValue("incremental", "true");
         setter.setOptionValue("test-file-name", APK_NAME);
 
-        EasyMock.replay(mMockTestDevice, mMockBuildInfo);
         mPrep.setUp(mTestInfo);
-        EasyMock.verify(mMockTestDevice, mMockBuildInfo);
+
         Mockito.verify(mMockIncrementalInstallSessionBuilder)
                 .addApk(fakeApk.toPath(), fakeApkSignature.toPath());
     }
@@ -447,7 +444,6 @@
         setter.setOptionValue("incremental", "true");
         setter.setOptionValue("test-file-name", APK_NAME);
 
-        EasyMock.replay(mMockTestDevice, mMockBuildInfo);
         try {
             mPrep.setUp(mTestInfo);
             fail("Expected TargetSetupError");
@@ -455,7 +451,6 @@
             assertThat(e).hasMessageThat().contains(APK_NAME);
             assertThat(e).hasMessageThat().contains(failure);
         }
-        EasyMock.verify(mMockTestDevice, mMockBuildInfo);
     }
 
     /**
@@ -502,18 +497,17 @@
         setter.setOptionValue("incremental", "true");
         setter.setOptionValue("test-file-name", APK_NAME);
 
-        EasyMock.replay(mMockTestDevice, mMockBuildInfo);
         mPrep.setUp(mTestInfo);
-        EasyMock.verify(mMockTestDevice, mMockBuildInfo);
+
         Mockito.verify(mMockIncrementalInstallSessionBuilder).build();
     }
 
     @Test
     public void testInstallFailure() throws Exception {
         final String failure = "INSTALL_PARSE_FAILED_MANIFEST_MALFORMED";
-        EasyMock.expect(mMockTestDevice.installPackage(EasyMock.eq(fakeApk), EasyMock.eq(true)))
-                .andReturn(failure);
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
+        when(mMockTestDevice.installPackage(Mockito.eq(fakeApk), Mockito.eq(true)))
+                .thenReturn(failure);
+
         try {
             mPrep.setUp(mTestInfo);
             fail("Expected TargetSetupError");
@@ -523,29 +517,25 @@
             assertThat(e).hasMessageThat().contains(SERIAL);
             assertThat(e).hasMessageThat().contains(failure);
         }
-        EasyMock.verify(mMockBuildInfo, mMockTestDevice);
     }
 
     @Test
     public void testInstallFailedUpdateIncompatible() throws Exception {
         final String failure = "INSTALL_FAILED_UPDATE_INCOMPATIBLE";
-        EasyMock.expect(mMockTestDevice.installPackage(EasyMock.eq(fakeApk), EasyMock.eq(true)))
-                .andReturn(failure);
-        EasyMock.expect(mMockTestDevice.uninstallPackage(PACKAGE_NAME)).andReturn(null);
-        EasyMock.expect(mMockTestDevice.installPackage(EasyMock.eq(fakeApk), EasyMock.eq(true)))
-                .andReturn(null);
-        EasyMock.expect(
-                        mMockTestDevice.installPackages(
-                                EasyMock.eq(mTestSplitApkFiles), EasyMock.eq(true)))
-                .andReturn(failure);
-        EasyMock.expect(mMockTestDevice.uninstallPackage(PACKAGE_NAME)).andReturn(null);
-        EasyMock.expect(
-                        mMockTestDevice.installPackages(
-                                EasyMock.eq(mTestSplitApkFiles), EasyMock.eq(true)))
-                .andReturn(null);
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
+        when(mMockTestDevice.installPackage(Mockito.eq(fakeApk), Mockito.eq(true)))
+                .thenReturn(failure);
+        when(mMockTestDevice.uninstallPackage(PACKAGE_NAME)).thenReturn(null);
+        when(mMockTestDevice.installPackage(Mockito.eq(fakeApk), Mockito.eq(true)))
+                .thenReturn(null);
+        when(mMockTestDevice.installPackages(Mockito.eq(mTestSplitApkFiles), Mockito.eq(true)))
+                .thenReturn(failure);
+        when(mMockTestDevice.uninstallPackage(PACKAGE_NAME)).thenReturn(null);
+        when(mMockTestDevice.installPackages(Mockito.eq(mTestSplitApkFiles), Mockito.eq(true)))
+                .thenReturn(null);
+
         mPrep.setUp(mTestInfo);
-        EasyMock.verify(mMockBuildInfo, mMockTestDevice);
+        verify(mMockTestDevice, atLeastOnce())
+                .installPackages(Mockito.eq(mTestSplitApkFiles), Mockito.eq(true));
     }
 
     /**
@@ -555,14 +545,13 @@
     @Test
     public void testMissingApk() throws Exception {
         fakeApk = null; // Apk doesn't exist
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
+
         try {
             mPrep.setUp(mTestInfo);
             fail("TestAppInstallSetup#setUp() did not raise TargetSetupError with missing apk.");
         } catch (TargetSetupError e) {
             assertTrue(e.getMessage().contains("not found"));
         }
-        EasyMock.verify(mMockBuildInfo, mMockTestDevice);
     }
 
     /**
@@ -572,14 +561,13 @@
     @Test
     public void testUnreadableApk() throws Exception {
         fakeApk.delete(); // Apk cannot be read
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
+
         try {
             mPrep.setUp(mTestInfo);
             fail("TestAppInstallSetup#setUp() did not raise TargetSetupError with unreadable apk.");
         } catch (TargetSetupError e) {
             assertTrue(e.getMessage().contains("not read"));
         }
-        EasyMock.verify(mMockBuildInfo, mMockTestDevice);
     }
 
     /**
@@ -591,9 +579,8 @@
         fakeApk = null; // Apk doesn't exist
         mPrep.clearSplitApkFileNames();
         mSetter.setOptionValue("throw-if-not-found", "false");
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
+
         mPrep.setUp(mTestInfo);
-        EasyMock.verify(mMockBuildInfo, mMockTestDevice);
     }
 
     /**
@@ -605,9 +592,8 @@
         fakeApk.delete(); // Apk cannot be read
         mPrep.clearSplitApkFileNames();
         mSetter.setOptionValue("throw-if-not-found", "false");
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
+
         mPrep.setUp(mTestInfo);
-        EasyMock.verify(mMockBuildInfo, mMockTestDevice);
     }
 
     /**
@@ -630,17 +616,16 @@
         setter.setOptionValue("install-arg", "-d");
         setter.setOptionValue("test-file-name", APK_NAME);
 
-        EasyMock.expect(mMockTestDevice.getDeviceDescriptor()).andStubReturn(null);
-        EasyMock.expect(mMockBuildInfo.getTestsDir()).andStubReturn(mBuildTestDir);
+        when(mMockTestDevice.getDeviceDescriptor()).thenReturn(null);
+        when(mMockBuildInfo.getTestsDir()).thenReturn(mBuildTestDir);
 
-        EasyMock.expect(
-                        mMockTestDevice.installPackage(
-                                EasyMock.eq(fakeApk), EasyMock.anyBoolean(), EasyMock.eq("-d")))
-                .andReturn(null);
+        when(mMockTestDevice.installPackage(
+                        Mockito.eq(fakeApk), Mockito.anyBoolean(), Mockito.eq("-d")))
+                .thenReturn(null);
 
-        EasyMock.replay(mMockTestDevice, mMockBuildInfo);
         mPrep.setUp(mTestInfo);
-        EasyMock.verify(mMockTestDevice, mMockBuildInfo);
+        verify(mMockTestDevice, atLeastOnce())
+                .installPackage(Mockito.eq(fakeApk), Mockito.anyBoolean(), Mockito.eq("-d"));
     }
 
     /**
@@ -661,19 +646,16 @@
         setter.setOptionValue("install-arg", "-d");
         setter.setOptionValue("test-file-name", APK_NAME);
 
-        EasyMock.expect(mMockTestDevice.getDeviceDescriptor()).andStubReturn(null);
-        EasyMock.expect(mMockBuildInfo.getTestsDir()).andStubReturn(mBuildTestDir);
+        when(mMockTestDevice.getDeviceDescriptor()).thenReturn(null);
+        when(mMockBuildInfo.getTestsDir()).thenReturn(mBuildTestDir);
 
-        EasyMock.expect(
-                        mMockTestDevice.installPackage(
-                                EasyMock.eq(mFakeBuildApk),
-                                EasyMock.anyBoolean(),
-                                EasyMock.eq("-d")))
-                .andReturn(null);
+        when(mMockTestDevice.installPackage(
+                        Mockito.eq(mFakeBuildApk), Mockito.anyBoolean(), Mockito.eq("-d")))
+                .thenReturn(null);
 
-        EasyMock.replay(mMockTestDevice, mMockBuildInfo);
         mPrep.setUp(mTestInfo);
-        EasyMock.verify(mMockTestDevice, mMockBuildInfo);
+        verify(mMockTestDevice, atLeastOnce())
+                .installPackage(Mockito.eq(mFakeBuildApk), Mockito.anyBoolean(), Mockito.eq("-d"));
     }
 
     @Test
@@ -821,7 +803,7 @@
         files.add(fakeApk);
         OptionSetter setter = new OptionSetter(mPrep);
         setter.setOptionValue(CHECK_MIN_SDK_OPTION, "true");
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
+
         try {
             mPrep.resolveApkFiles(mTestInfo, files);
             fail("Should have thrown an exception");
@@ -830,7 +812,6 @@
                     String.format("Failed to extract info from `%s` using aapt", fakeApk.getName()),
                     expected.getMessage());
         } finally {
-            EasyMock.verify(mMockBuildInfo, mMockTestDevice);
         }
     }
 
@@ -854,17 +835,15 @@
         files.add(fakeApk);
         OptionSetter setter = new OptionSetter(mPrep);
         setter.setOptionValue(CHECK_MIN_SDK_OPTION, "true");
-        EasyMock.expect(mMockTestDevice.getSerialNumber()).andStubReturn(SERIAL);
-        EasyMock.expect(mMockTestDevice.getApiLevel()).andReturn(21).times(2);
+        when(mMockTestDevice.getSerialNumber()).thenReturn(SERIAL);
+        when(mMockTestDevice.getApiLevel()).thenReturn(21);
         doReturn(22).when(mMockAaptParser).getSdkVersion();
 
         Map<File, String> expected = new LinkedHashMap<>();
 
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
-
         Map<File, String> result = mPrep.resolveApkFiles(mTestInfo, files);
 
-        EasyMock.verify(mMockBuildInfo, mMockTestDevice);
+        verify(mMockTestDevice, times(2)).getApiLevel();
         Mockito.verify(mMockAaptParser, times(2)).getSdkVersion();
         assertEquals(expected, result);
     }
@@ -889,19 +868,17 @@
         files.add(fakeApk);
         OptionSetter setter = new OptionSetter(mPrep);
         setter.setOptionValue(CHECK_MIN_SDK_OPTION, "true");
-        EasyMock.expect(mMockTestDevice.getSerialNumber()).andStubReturn(SERIAL);
-        EasyMock.expect(mMockTestDevice.getApiLevel()).andReturn(23);
+        when(mMockTestDevice.getSerialNumber()).thenReturn(SERIAL);
+        when(mMockTestDevice.getApiLevel()).thenReturn(23);
         doReturn(22).when(mMockAaptParser).getSdkVersion();
 
         Map<File, String> expected = new LinkedHashMap<>();
         expected.put(fakeApk, "fakePackageName");
 
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
-
         Map<File, String> result = mPrep.resolveApkFiles(mTestInfo, files);
 
         Mockito.verify(mMockAaptParser).getSdkVersion();
-        EasyMock.verify(mMockBuildInfo, mMockTestDevice);
+
         assertEquals(result, expected);
     }
 
@@ -933,24 +910,22 @@
             throws TargetSetupError, DeviceNotAvailableException, BuildError {
         ImmutableSet.Builder<Set<File>> installs = ImmutableSet.builder();
 
-        EasyMock.expect(mMockTestDevice.installPackage(anyObject(), anyBoolean()))
-                .andStubAnswer(
-                        () -> {
-                            File apkFile = (File) EasyMock.getCurrentArguments()[0];
+        when(mMockTestDevice.installPackage(Mockito.any(), Mockito.anyBoolean()))
+                .thenAnswer(
+                        invocation -> {
+                            File apkFile = (File) invocation.getArguments()[0];
                             installs.add(ImmutableSet.of(apkFile));
                             return null;
                         });
 
-        EasyMock.expect(mMockTestDevice.installPackages(anyObject(), anyBoolean()))
-                .andStubAnswer(
-                        () -> {
-                            List<File> apkFiles = (List<File>) EasyMock.getCurrentArguments()[0];
+        when(mMockTestDevice.installPackages(Mockito.any(), Mockito.anyBoolean()))
+                .thenAnswer(
+                        invocation -> {
+                            List<File> apkFiles = (List<File>) invocation.getArguments()[0];
                             installs.add(ImmutableSet.copyOf(apkFiles));
                             return null;
                         });
 
-        EasyMock.replay(mMockBuildInfo, mMockTestDevice);
-
         preparer.setUp(mTestInfo);
 
         return installs.build();
diff --git a/javatests/com/android/tradefed/testtype/ArtRunTestTest.java b/javatests/com/android/tradefed/testtype/ArtRunTestTest.java
index 9f90365..6d62c5d 100644
--- a/javatests/com/android/tradefed/testtype/ArtRunTestTest.java
+++ b/javatests/com/android/tradefed/testtype/ArtRunTestTest.java
@@ -17,6 +17,10 @@
 package com.android.tradefed.testtype;
 
 import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import com.android.tradefed.config.ConfigurationException;
 import com.android.tradefed.config.OptionSetter;
@@ -32,27 +36,27 @@
 import com.android.tradefed.util.CommandStatus;
 import com.android.tradefed.util.FileUtil;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.concurrent.TimeUnit;
 
-import org.easymock.EasyMock;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
 /** Unit tests for {@link ArtRunTest}. */
 @RunWith(JUnit4.class)
 public class ArtRunTestTest {
 
-    private ITestInvocationListener mMockInvocationListener;
-    private IAbi mMockAbi;
-    private ITestDevice mMockITestDevice;
+    @Mock ITestInvocationListener mMockInvocationListener;
+    @Mock IAbi mMockAbi;
+    @Mock ITestDevice mMockITestDevice;
 
     private ArtRunTest mArtRunTest;
     private OptionSetter mSetter;
@@ -66,9 +70,9 @@
 
     @Before
     public void setUp() throws ConfigurationException, IOException {
-        mMockInvocationListener = EasyMock.createMock(ITestInvocationListener.class);
-        mMockAbi = EasyMock.createMock(IAbi.class);
-        mMockITestDevice = EasyMock.createMock(ITestDevice.class);
+        mMockInvocationListener = mock(ITestInvocationListener.class);
+        mMockAbi = mock(IAbi.class);
+        mMockITestDevice = mock(ITestDevice.class);
         mArtRunTest = new ArtRunTest();
         mArtRunTest.setAbi(mMockAbi);
         mSetter = new OptionSetter(mArtRunTest);
@@ -114,16 +118,6 @@
         return result;
     }
 
-    /** Helper that replays all mocks. */
-    private void replayMocks() {
-        EasyMock.replay(mMockInvocationListener, mMockAbi, mMockITestDevice);
-    }
-
-    /** Helper that verifies all mocks. */
-    private void verifyMocks() {
-        EasyMock.verify(mMockInvocationListener, mMockAbi, mMockITestDevice);
-    }
-
     /** Test the behavior of the run method when the `run-test-name` option is not set. */
     @Test
     public void testRunSingleTest_unsetRunTestNameOption()
@@ -131,14 +125,12 @@
         final String classpath = "/data/local/tmp/test/test.jar";
         mSetter.setOptionValue("classpath", classpath);
 
-        replayMocks();
         try {
             mArtRunTest.run(mTestInfo, mMockInvocationListener);
             fail("An exception should have been thrown.");
         } catch (IllegalArgumentException e) {
             // Expected.
         }
-        verifyMocks();
     }
 
     /** Test the behavior of the run method when the `classpath` option is not set. */
@@ -150,14 +142,12 @@
         createExpectedStdoutFile(runTestName);
         createExpectedStderrFile(runTestName);
 
-        replayMocks();
         try {
             mArtRunTest.run(mTestInfo, mMockInvocationListener);
             fail("An exception should have been thrown.");
         } catch (IllegalArgumentException e) {
             // Expected.
         }
-        verifyMocks();
     }
 
     /** Helper containing testing logic for a (single) test expected to run (and succeed). */
@@ -169,31 +159,28 @@
         mSetter.setOptionValue("classpath", classpath);
 
         // Pre-test checks.
-        EasyMock.expect(mMockAbi.getName()).andReturn("abi");
-        EasyMock.expect(mMockITestDevice.getSerialNumber()).andReturn("");
+        when(mMockAbi.getName()).thenReturn("abi");
+        when(mMockITestDevice.getSerialNumber()).thenReturn("");
         String runName = "ArtRunTest_abi";
         // Beginning of test.
-        mMockInvocationListener.testRunStarted(runName, 1);
+
         TestDescription testId = new TestDescription(runName, runTestName);
-        mMockInvocationListener.testStarted(testId);
+
         String cmd = String.format("dalvikvm64 -classpath %s Main", classpath);
         // Test execution.
         CommandResult result = createMockCommandResult("output\n", "no error\n", /* exitCode */ 0);
-        EasyMock.expect(
-                        mMockITestDevice.executeShellV2Command(
-                                cmd, 60000L, TimeUnit.MILLISECONDS, 0))
-                .andReturn(result);
+        when(mMockITestDevice.executeShellV2Command(cmd, 60000L, TimeUnit.MILLISECONDS, 0))
+                .thenReturn(result);
         // End of test.
-        mMockInvocationListener.testEnded(
-                EasyMock.eq(testId), (HashMap<String, Metric>) EasyMock.anyObject());
-        mMockInvocationListener.testRunEnded(
-                EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
-
-        replayMocks();
 
         mArtRunTest.run(mTestInfo, mMockInvocationListener);
 
-        verifyMocks();
+        verify(mMockInvocationListener).testRunStarted(runName, 1);
+        verify(mMockInvocationListener).testStarted(testId);
+        verify(mMockInvocationListener)
+                .testEnded(eq(testId), (HashMap<String, Metric>) Mockito.any());
+        verify(mMockInvocationListener)
+                .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
     }
 
     /** Helper containing testing logic for a (single) test expected not to run. */
@@ -204,12 +191,10 @@
         createExpectedStderrFile(runTestName);
         mSetter.setOptionValue("classpath", classpath);
 
-        EasyMock.expect(mMockAbi.getName()).andReturn("abi");
-        replayMocks();
+        when(mMockAbi.getName()).thenReturn("abi");
 
         mArtRunTest.run(mTestInfo, mMockInvocationListener);
-
-        verifyMocks();
+        verify(mMockAbi).getName();
     }
 
     /** Test the run method for a (single) test. */
@@ -237,31 +222,28 @@
         mSetter.setOptionValue("classpath", classpath);
 
         // Pre-test checks.
-        EasyMock.expect(mMockAbi.getName()).andReturn("abi");
-        EasyMock.expect(mMockITestDevice.getSerialNumber()).andReturn("");
+        when(mMockAbi.getName()).thenReturn("abi");
+        when(mMockITestDevice.getSerialNumber()).thenReturn("");
         String runName = "ArtRunTest_abi";
         // Beginning of test.
-        mMockInvocationListener.testRunStarted(runName, 1);
+
         TestDescription testId = new TestDescription(runName, runTestName);
-        mMockInvocationListener.testStarted(testId);
+
         String cmd = String.format("dalvikvm64 -classpath %s Main", classpath);
         // Test execution.
         CommandResult result = createMockCommandResult("output\n", "no error\n", /* exitCode */ 1);
-        EasyMock.expect(
-                        mMockITestDevice.executeShellV2Command(
-                                cmd, 60000L, TimeUnit.MILLISECONDS, 0))
-                .andReturn(result);
-        mMockInvocationListener.testFailed(testId, "Test `test` exited with code 1");
-        mMockInvocationListener.testEnded(
-                EasyMock.eq(testId), (HashMap<String, Metric>) EasyMock.anyObject());
-        mMockInvocationListener.testRunEnded(
-                EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
-
-        replayMocks();
+        when(mMockITestDevice.executeShellV2Command(cmd, 60000L, TimeUnit.MILLISECONDS, 0))
+                .thenReturn(result);
 
         mArtRunTest.run(mTestInfo, mMockInvocationListener);
 
-        verifyMocks();
+        verify(mMockInvocationListener).testRunStarted(runName, 1);
+        verify(mMockInvocationListener).testStarted(testId);
+        verify(mMockInvocationListener).testFailed(testId, "Test `test` exited with code 1");
+        verify(mMockInvocationListener)
+                .testEnded(eq(testId), (HashMap<String, Metric>) Mockito.any());
+        verify(mMockInvocationListener)
+                .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
     }
 
     /**
@@ -279,21 +261,19 @@
         mSetter.setOptionValue("classpath", classpath);
 
         // Pre-test checks.
-        EasyMock.expect(mMockAbi.getName()).andReturn("abi");
-        EasyMock.expect(mMockITestDevice.getSerialNumber()).andReturn("");
+        when(mMockAbi.getName()).thenReturn("abi");
+        when(mMockITestDevice.getSerialNumber()).thenReturn("");
         String runName = "ArtRunTest_abi";
         // Beginning of test.
-        mMockInvocationListener.testRunStarted(runName, 1);
+
         TestDescription testId = new TestDescription(runName, runTestName);
-        mMockInvocationListener.testStarted(testId);
+
         String cmd = String.format("dalvikvm64 -classpath %s Main", classpath);
         // Test execution.
         CommandResult result =
                 createMockCommandResult("unexpected\n", "no error\n", /* exitCode */ 0);
-        EasyMock.expect(
-                        mMockITestDevice.executeShellV2Command(
-                                cmd, 60000L, TimeUnit.MILLISECONDS, 0))
-                .andReturn(result);
+        when(mMockITestDevice.executeShellV2Command(cmd, 60000L, TimeUnit.MILLISECONDS, 0))
+                .thenReturn(result);
         // End of test.
         String errorMessage =
                 "The actual standard output does not match the expected standard output"
@@ -303,17 +283,16 @@
                         + "@@ -1,1 +1,1 @@\n"
                         + "-output\n"
                         + "+unexpected\n";
-        mMockInvocationListener.testFailed(testId, errorMessage);
-        mMockInvocationListener.testEnded(
-                EasyMock.eq(testId), (HashMap<String, Metric>) EasyMock.anyObject());
-        mMockInvocationListener.testRunEnded(
-                EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
-
-        replayMocks();
 
         mArtRunTest.run(mTestInfo, mMockInvocationListener);
 
-        verifyMocks();
+        verify(mMockInvocationListener).testRunStarted(runName, 1);
+        verify(mMockInvocationListener).testStarted(testId);
+        verify(mMockInvocationListener).testFailed(testId, errorMessage);
+        verify(mMockInvocationListener)
+                .testEnded(eq(testId), (HashMap<String, Metric>) Mockito.any());
+        verify(mMockInvocationListener)
+                .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
     }
 
     /**
@@ -331,21 +310,19 @@
         mSetter.setOptionValue("classpath", classpath);
 
         // Pre-test checks.
-        EasyMock.expect(mMockAbi.getName()).andReturn("abi");
-        EasyMock.expect(mMockITestDevice.getSerialNumber()).andReturn("");
+        when(mMockAbi.getName()).thenReturn("abi");
+        when(mMockITestDevice.getSerialNumber()).thenReturn("");
         String runName = "ArtRunTest_abi";
         // Beginning of test.
-        mMockInvocationListener.testRunStarted(runName, 1);
+
         TestDescription testId = new TestDescription(runName, runTestName);
-        mMockInvocationListener.testStarted(testId);
+
         String cmd = String.format("dalvikvm64 -classpath %s Main", classpath);
         // Test execution.
         CommandResult result =
                 createMockCommandResult("output\n", "unexpected error\n", /* exitCode */ 0);
-        EasyMock.expect(
-                        mMockITestDevice.executeShellV2Command(
-                                cmd, 60000L, TimeUnit.MILLISECONDS, 0))
-                .andReturn(result);
+        when(mMockITestDevice.executeShellV2Command(cmd, 60000L, TimeUnit.MILLISECONDS, 0))
+                .thenReturn(result);
         // End of test.
         String errorMessage =
                 "The actual standard error does not match the expected standard error"
@@ -355,17 +332,16 @@
                         + "@@ -1,1 +1,1 @@\n"
                         + "-no error\n"
                         + "+unexpected error\n";
-        mMockInvocationListener.testFailed(testId, errorMessage);
-        mMockInvocationListener.testEnded(
-                EasyMock.eq(testId), (HashMap<String, Metric>) EasyMock.anyObject());
-        mMockInvocationListener.testRunEnded(
-                EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
-
-        replayMocks();
 
         mArtRunTest.run(mTestInfo, mMockInvocationListener);
 
-        verifyMocks();
+        verify(mMockInvocationListener).testRunStarted(runName, 1);
+        verify(mMockInvocationListener).testStarted(testId);
+        verify(mMockInvocationListener).testFailed(testId, errorMessage);
+        verify(mMockInvocationListener)
+                .testEnded(eq(testId), (HashMap<String, Metric>) Mockito.any());
+        verify(mMockInvocationListener)
+                .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
     }
 
     /**
@@ -383,21 +359,19 @@
         mSetter.setOptionValue("classpath", classpath);
 
         // Pre-test checks.
-        EasyMock.expect(mMockAbi.getName()).andReturn("abi");
-        EasyMock.expect(mMockITestDevice.getSerialNumber()).andReturn("");
+        when(mMockAbi.getName()).thenReturn("abi");
+        when(mMockITestDevice.getSerialNumber()).thenReturn("");
         String runName = "ArtRunTest_abi";
         // Beginning of test.
-        mMockInvocationListener.testRunStarted(runName, 1);
+
         TestDescription testId = new TestDescription(runName, runTestName);
-        mMockInvocationListener.testStarted(testId);
+
         String cmd = String.format("dalvikvm64 -classpath %s Main", classpath);
         // Test execution.
         CommandResult result =
                 createMockCommandResult("unexpected\n", "unexpected error\n", /* exitCode */ 2);
-        EasyMock.expect(
-                        mMockITestDevice.executeShellV2Command(
-                                cmd, 60000L, TimeUnit.MILLISECONDS, 0))
-                .andReturn(result);
+        when(mMockITestDevice.executeShellV2Command(cmd, 60000L, TimeUnit.MILLISECONDS, 0))
+                .thenReturn(result);
         // End of test.
         String errorMessage =
                 "Test `test` exited with code 2\n"
@@ -416,17 +390,16 @@
                         + "@@ -1,1 +1,1 @@\n"
                         + "-no error\n"
                         + "+unexpected error\n";
-        mMockInvocationListener.testFailed(testId, errorMessage);
-        mMockInvocationListener.testEnded(
-                EasyMock.eq(testId), (HashMap<String, Metric>) EasyMock.anyObject());
-        mMockInvocationListener.testRunEnded(
-                EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
-
-        replayMocks();
 
         mArtRunTest.run(mTestInfo, mMockInvocationListener);
 
-        verifyMocks();
+        verify(mMockInvocationListener).testRunStarted(runName, 1);
+        verify(mMockInvocationListener).testStarted(testId);
+        verify(mMockInvocationListener).testFailed(testId, errorMessage);
+        verify(mMockInvocationListener)
+                .testEnded(eq(testId), (HashMap<String, Metric>) Mockito.any());
+        verify(mMockInvocationListener)
+                .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
     }
 
     /** Test the run method for a (single) test contained in an include filter. */
diff --git a/javatests/com/android/tradefed/testtype/DeviceTestCaseTest.java b/javatests/com/android/tradefed/testtype/DeviceTestCaseTest.java
index 1f634a1..6298acb 100644
--- a/javatests/com/android/tradefed/testtype/DeviceTestCaseTest.java
+++ b/javatests/com/android/tradefed/testtype/DeviceTestCaseTest.java
@@ -17,6 +17,9 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.invoker.TestInformation;
@@ -25,14 +28,12 @@
 import com.android.tradefed.result.TestDescription;
 import com.android.tradefed.util.proto.TfMetricProtoUtil;
 
-import junit.framework.TestCase;
-
-import org.easymock.Capture;
-import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -50,6 +51,7 @@
             // test adding a metric during the test.
             addTestMetric("test", "value");
         }
+
         public void test2() {}
     }
 
@@ -58,6 +60,7 @@
 
         @MyAnnotation1
         public void test1() {}
+
         @MyAnnotation2
         public void test2() {}
     }
@@ -76,19 +79,13 @@
         public void test2() {}
     }
 
-    /**
-     * Simple Annotation class for testing
-     */
+    /** Simple Annotation class for testing */
     @Retention(RetentionPolicy.RUNTIME)
-    public @interface MyAnnotation1 {
-    }
+    public @interface MyAnnotation1 {}
 
-    /**
-     * Simple Annotation class for testing
-     */
+    /** Simple Annotation class for testing */
     @Retention(RetentionPolicy.RUNTIME)
-    public @interface MyAnnotation2 {
-    }
+    public @interface MyAnnotation2 {}
 
     public static class MockAbortTest extends DeviceTestCase {
 
@@ -112,21 +109,22 @@
     public void testRun_suite() throws Exception {
         MockTest test = new MockTest();
 
-        ITestInvocationListener listener = EasyMock.createMock(ITestInvocationListener.class);
-        listener.testRunStarted(MockTest.class.getName(), 2);
+        ITestInvocationListener listener = mock(ITestInvocationListener.class);
+
         final TestDescription test1 = new TestDescription(MockTest.class.getName(), "test1");
         final TestDescription test2 = new TestDescription(MockTest.class.getName(), "test2");
-        listener.testStarted(test1);
+
         Map<String, String> metrics = new HashMap<>();
         metrics.put("test", "value");
-        listener.testEnded(test1, TfMetricProtoUtil.upgradeConvert(metrics));
-        listener.testStarted(test2);
-        listener.testEnded(test2, new HashMap<String, Metric>());
-        listener.testRunEnded(EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
-        EasyMock.replay(listener);
 
         test.run(mTestInfo, listener);
-        EasyMock.verify(listener);
+
+        verify(listener).testRunStarted(MockTest.class.getName(), 2);
+        verify(listener).testStarted(test1);
+        verify(listener).testEnded(test1, TfMetricProtoUtil.upgradeConvert(metrics));
+        verify(listener).testStarted(test2);
+        verify(listener).testEnded(test2, new HashMap<String, Metric>());
+        verify(listener).testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
     }
 
     /**
@@ -137,18 +135,19 @@
     public void testRun_includeFilter() throws Exception {
         MockTest test = new MockTest();
         test.addIncludeFilter("com.android.tradefed.testtype.DeviceTestCaseTest$MockTest#test1");
-        ITestInvocationListener listener = EasyMock.createMock(ITestInvocationListener.class);
-        listener.testRunStarted(MockTest.class.getName(), 1);
+        ITestInvocationListener listener = mock(ITestInvocationListener.class);
+
         final TestDescription test1 = new TestDescription(MockTest.class.getName(), "test1");
-        listener.testStarted(test1);
+
         Map<String, String> metrics = new HashMap<>();
         metrics.put("test", "value");
-        listener.testEnded(test1, TfMetricProtoUtil.upgradeConvert(metrics));
-        listener.testRunEnded(EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
-        EasyMock.replay(listener);
 
         test.run(mTestInfo, listener);
-        EasyMock.verify(listener);
+
+        verify(listener).testRunStarted(MockTest.class.getName(), 1);
+        verify(listener).testStarted(test1);
+        verify(listener).testEnded(test1, TfMetricProtoUtil.upgradeConvert(metrics));
+        verify(listener).testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
     }
 
     /**
@@ -159,16 +158,16 @@
     public void testRun_excludeFilter() throws Exception {
         MockTest test = new MockTest();
         test.addExcludeFilter("com.android.tradefed.testtype.DeviceTestCaseTest$MockTest#test1");
-        ITestInvocationListener listener = EasyMock.createMock(ITestInvocationListener.class);
-        listener.testRunStarted(MockTest.class.getName(), 1);
+        ITestInvocationListener listener = mock(ITestInvocationListener.class);
+
         final TestDescription test2 = new TestDescription(MockTest.class.getName(), "test2");
-        listener.testStarted(test2);
-        listener.testEnded(test2, new HashMap<String, Metric>());
-        listener.testRunEnded(EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
-        EasyMock.replay(listener);
 
         test.run(mTestInfo, listener);
-        EasyMock.verify(listener);
+
+        verify(listener).testRunStarted(MockTest.class.getName(), 1);
+        verify(listener).testStarted(test2);
+        verify(listener).testEnded(test2, new HashMap<String, Metric>());
+        verify(listener).testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
     }
 
     /**
@@ -178,42 +177,38 @@
     @Test
     public void testRun_includeAnnotationFiltering() throws Exception {
         MockAnnotatedTest test = new MockAnnotatedTest();
-        test.addIncludeAnnotation(
-                "com.android.tradefed.testtype.DeviceTestCaseTest$MyAnnotation1");
+        test.addIncludeAnnotation("com.android.tradefed.testtype.DeviceTestCaseTest$MyAnnotation1");
         test.addExcludeAnnotation("com.android.tradefed.testtype.DeviceTestCaseTest$MyAnnotation2");
-        ITestInvocationListener listener = EasyMock.createMock(ITestInvocationListener.class);
-        listener.testRunStarted(MockAnnotatedTest.class.getName(), 1);
+        ITestInvocationListener listener = mock(ITestInvocationListener.class);
+
         final TestDescription test1 =
                 new TestDescription(MockAnnotatedTest.class.getName(), "test1");
-        listener.testStarted(test1);
-        listener.testEnded(test1, new HashMap<String, Metric>());
-        listener.testRunEnded(EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
-        EasyMock.replay(listener);
 
         test.run(mTestInfo, listener);
-        EasyMock.verify(listener);
+
+        verify(listener).testRunStarted(MockAnnotatedTest.class.getName(), 1);
+        verify(listener).testStarted(test1);
+        verify(listener).testEnded(test1, new HashMap<String, Metric>());
+        verify(listener).testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
     }
 
     /** Verify that we properly carry the annotations of the methods. */
     @Test
     public void testRun_checkAnnotation() throws Exception {
         MockAnnotatedTest test = new MockAnnotatedTest();
-        ITestInvocationListener listener = EasyMock.createMock(ITestInvocationListener.class);
-        listener.testRunStarted(MockAnnotatedTest.class.getName(), 2);
-        Capture<TestDescription> capture = new Capture<>();
-        listener.testStarted(EasyMock.capture(capture));
-        listener.testEnded(
-                EasyMock.capture(capture), EasyMock.<HashMap<String, Metric>>anyObject());
-        listener.testStarted(EasyMock.capture(capture));
-        listener.testEnded(
-                EasyMock.capture(capture), EasyMock.<HashMap<String, Metric>>anyObject());
-        listener.testRunEnded(EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
-        EasyMock.replay(listener);
+        ITestInvocationListener listener = mock(ITestInvocationListener.class);
+
+        ArgumentCaptor<TestDescription> capture = ArgumentCaptor.forClass(TestDescription.class);
 
         test.run(mTestInfo, listener);
-        EasyMock.verify(listener);
 
-        List<TestDescription> descriptions = capture.getValues();
+        verify(listener).testRunStarted(MockAnnotatedTest.class.getName(), 2);
+        verify(listener, times(2)).testStarted(capture.capture());
+        verify(listener, times(2))
+                .testEnded(capture.capture(), Mockito.<HashMap<String, Metric>>any());
+        verify(listener).testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
+
+        List<TestDescription> descriptions = capture.getAllValues();
         // Ensure we properly capture the annotations for both methods.
         for (TestDescription desc : descriptions) {
             assertFalse(desc.getAnnotations().isEmpty());
@@ -227,19 +222,18 @@
     @Test
     public void testRun_excludeAnnotationFiltering() throws Exception {
         MockAnnotatedTest test = new MockAnnotatedTest();
-        test.addExcludeAnnotation(
-                "com.android.tradefed.testtype.DeviceTestCaseTest$MyAnnotation2");
-        ITestInvocationListener listener = EasyMock.createMock(ITestInvocationListener.class);
-        listener.testRunStarted(MockAnnotatedTest.class.getName(), 1);
+        test.addExcludeAnnotation("com.android.tradefed.testtype.DeviceTestCaseTest$MyAnnotation2");
+        ITestInvocationListener listener = mock(ITestInvocationListener.class);
+
         final TestDescription test1 =
                 new TestDescription(MockAnnotatedTest.class.getName(), "test1");
-        listener.testStarted(test1);
-        listener.testEnded(test1, new HashMap<String, Metric>());
-        listener.testRunEnded(EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
-        EasyMock.replay(listener);
 
         test.run(mTestInfo, listener);
-        EasyMock.verify(listener);
+
+        verify(listener).testRunStarted(MockAnnotatedTest.class.getName(), 1);
+        verify(listener).testStarted(test1);
+        verify(listener).testEnded(test1, new HashMap<String, Metric>());
+        verify(listener).testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
     }
 
     /** Regression test to verify a single test can still be run. */
@@ -248,18 +242,19 @@
         MockTest test = new MockTest();
         test.setName("test1");
 
-        ITestInvocationListener listener = EasyMock.createMock(ITestInvocationListener.class);
-        listener.testRunStarted(MockTest.class.getName(), 1);
+        ITestInvocationListener listener = mock(ITestInvocationListener.class);
+
         final TestDescription test1 = new TestDescription(MockTest.class.getName(), "test1");
-        listener.testStarted(test1);
+
         Map<String, String> metrics = new HashMap<>();
         metrics.put("test", "value");
-        listener.testEnded(test1, TfMetricProtoUtil.upgradeConvert(metrics));
-        listener.testRunEnded(EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
-        EasyMock.replay(listener);
 
         test.run(mTestInfo, listener);
-        EasyMock.verify(listener);
+
+        verify(listener).testRunStarted(MockTest.class.getName(), 1);
+        verify(listener).testStarted(test1);
+        verify(listener).testEnded(test1, TfMetricProtoUtil.upgradeConvert(metrics));
+        verify(listener).testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
     }
 
     /** Verify that a device not available exception is thrown up. */
@@ -267,24 +262,23 @@
     public void testRun_deviceNotAvail() {
         MockAbortTest test = new MockAbortTest();
         // create a mock ITestInvocationListener, because results are easier to verify
-        ITestInvocationListener listener = EasyMock.createMock(ITestInvocationListener.class);
+        ITestInvocationListener listener = mock(ITestInvocationListener.class);
 
         final TestDescription test1 = new TestDescription(MockAbortTest.class.getName(), "test1");
-        listener.testRunStarted(MockAbortTest.class.getName(), 1);
-        listener.testStarted(test1);
-        listener.testFailed(EasyMock.eq(test1),
-                EasyMock.contains(MockAbortTest.EXCEP_MSG));
-        listener.testEnded(test1, new HashMap<String, Metric>());
-        listener.testRunFailed(EasyMock.contains(MockAbortTest.EXCEP_MSG));
-        listener.testRunEnded(EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
-        EasyMock.replay(listener);
+
         try {
             test.run(mTestInfo, listener);
             fail("DeviceNotAvailableException not thrown");
         } catch (DeviceNotAvailableException e) {
             // expected
         }
-        EasyMock.verify(listener);
+
+        verify(listener).testRunStarted(MockAbortTest.class.getName(), 1);
+        verify(listener).testStarted(test1);
+        verify(listener).testFailed(Mockito.eq(test1), Mockito.contains(MockAbortTest.EXCEP_MSG));
+        verify(listener).testEnded(test1, new HashMap<String, Metric>());
+        verify(listener).testRunFailed(Mockito.contains(MockAbortTest.EXCEP_MSG));
+        verify(listener).testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
     }
 
     /**
@@ -293,18 +287,16 @@
      */
     @Test
     public void testRun_testcaseCollectMode() throws Exception {
-        ITestInvocationListener listener = EasyMock.createMock(ITestInvocationListener.class);
+        ITestInvocationListener listener = mock(ITestInvocationListener.class);
         MockTest test = new MockTest();
         test.setCollectTestsOnly(true);
-        listener.testRunStarted((String)EasyMock.anyObject(), EasyMock.eq(2));
-        listener.testStarted(EasyMock.anyObject());
-        listener.testEnded(EasyMock.anyObject(), EasyMock.<HashMap<String, Metric>>anyObject());
-        listener.testStarted(EasyMock.anyObject());
-        listener.testEnded(EasyMock.anyObject(), EasyMock.<HashMap<String, Metric>>anyObject());
-        listener.testRunEnded(EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
-        EasyMock.replay(listener);
+
         test.run(mTestInfo, listener);
-        EasyMock.verify(listener);
+
+        verify(listener).testRunStarted((String) Mockito.any(), Mockito.eq(2));
+        verify(listener, times(2)).testStarted(Mockito.any());
+        verify(listener, times(2)).testEnded(Mockito.any(), Mockito.<HashMap<String, Metric>>any());
+        verify(listener).testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
     }
 
     /**
@@ -313,17 +305,17 @@
      */
     @Test
     public void testRun_testcaseCollectMode_singleMethod() throws Exception {
-        ITestInvocationListener listener = EasyMock.createMock(ITestInvocationListener.class);
+        ITestInvocationListener listener = mock(ITestInvocationListener.class);
         MockTest test = new MockTest();
         test.setName("test1");
         test.setCollectTestsOnly(true);
-        listener.testRunStarted((String)EasyMock.anyObject(), EasyMock.eq(1));
-        listener.testStarted(EasyMock.anyObject());
-        listener.testEnded(EasyMock.anyObject(), EasyMock.<HashMap<String, Metric>>anyObject());
-        listener.testRunEnded(EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
-        EasyMock.replay(listener);
+
         test.run(mTestInfo, listener);
-        EasyMock.verify(listener);
+
+        verify(listener).testRunStarted((String) Mockito.any(), Mockito.eq(1));
+        verify(listener).testStarted(Mockito.any());
+        verify(listener).testEnded(Mockito.any(), Mockito.<HashMap<String, Metric>>any());
+        verify(listener).testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
     }
 
     /**
@@ -333,19 +325,18 @@
     @Test
     public void testRun_duplicateName() throws Exception {
         DuplicateTest test = new DuplicateTest();
-        ITestInvocationListener listener = EasyMock.createMock(ITestInvocationListener.class);
+        ITestInvocationListener listener = mock(ITestInvocationListener.class);
 
-        listener.testRunStarted(DuplicateTest.class.getName(), 2);
         final TestDescription test1 = new TestDescription(DuplicateTest.class.getName(), "test1");
         final TestDescription test2 = new TestDescription(DuplicateTest.class.getName(), "test2");
-        listener.testStarted(test1);
-        listener.testEnded(test1, new HashMap<String, Metric>());
-        listener.testStarted(test2);
-        listener.testEnded(test2, new HashMap<String, Metric>());
-        listener.testRunEnded(EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
-        EasyMock.replay(listener);
 
         test.run(mTestInfo, listener);
-        EasyMock.verify(listener);
+
+        verify(listener).testRunStarted(DuplicateTest.class.getName(), 2);
+        verify(listener).testStarted(test1);
+        verify(listener).testEnded(test1, new HashMap<String, Metric>());
+        verify(listener).testStarted(test2);
+        verify(listener).testEnded(test2, new HashMap<String, Metric>());
+        verify(listener).testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
     }
 }
diff --git a/javatests/com/android/tradefed/testtype/DeviceTestSuiteTest.java b/javatests/com/android/tradefed/testtype/DeviceTestSuiteTest.java
index 94436fd..1c5efcc 100644
--- a/javatests/com/android/tradefed/testtype/DeviceTestSuiteTest.java
+++ b/javatests/com/android/tradefed/testtype/DeviceTestSuiteTest.java
@@ -16,6 +16,8 @@
 package com.android.tradefed.testtype;
 
 import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.invoker.TestInformation;
@@ -24,11 +26,11 @@
 import com.android.tradefed.result.TestDescription;
 import com.android.tradefed.util.proto.TfMetricProtoUtil;
 
-import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mockito;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -43,6 +45,7 @@
             // Metrics are also available for test within Suite
             addTestMetric("key1", "metric1");
         }
+
         public void test2() {}
     }
 
@@ -69,21 +72,22 @@
         DeviceTestSuite suite = new DeviceTestSuite();
         suite.addTestSuite(MockTest.class);
 
-        ITestInvocationListener listener = EasyMock.createMock(ITestInvocationListener.class);
-        listener.testRunStarted(DeviceTestSuite.class.getName(), 2);
+        ITestInvocationListener listener = mock(ITestInvocationListener.class);
+
         final TestDescription test1 = new TestDescription(MockTest.class.getName(), "test1");
         final TestDescription test2 = new TestDescription(MockTest.class.getName(), "test2");
-        listener.testStarted(test1);
+
         Map<String, String> metrics = new HashMap<>();
         metrics.put("key1", "metric1");
-        listener.testEnded(test1, TfMetricProtoUtil.upgradeConvert(metrics));
-        listener.testStarted(test2);
-        listener.testEnded(test2, new HashMap<String, Metric>());
-        listener.testRunEnded(EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
-        EasyMock.replay(listener);
 
         suite.run(mTestInfo, listener);
-        EasyMock.verify(listener);
+
+        verify(listener).testRunStarted(DeviceTestSuite.class.getName(), 2);
+        verify(listener).testStarted(test1);
+        verify(listener).testEnded(test1, TfMetricProtoUtil.upgradeConvert(metrics));
+        verify(listener).testStarted(test2);
+        verify(listener).testEnded(test2, new HashMap<String, Metric>());
+        verify(listener).testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
     }
 
     /** Verify that a device not available exception is thrown up. */
@@ -93,23 +97,22 @@
         suite.addTestSuite(MockAbortTest.class);
 
         // create a mock ITestInvocationListener, because results are easier to verify
-        ITestInvocationListener listener = EasyMock.createMock(ITestInvocationListener.class);
+        ITestInvocationListener listener = mock(ITestInvocationListener.class);
 
         final TestDescription test1 = new TestDescription(MockAbortTest.class.getName(), "test1");
-        listener.testRunStarted(DeviceTestSuite.class.getName(), 1);
-        listener.testStarted(test1);
-        listener.testFailed(EasyMock.eq(test1),
-                EasyMock.contains(MockAbortTest.EXCEP_MSG));
-        listener.testEnded(test1, new HashMap<String, Metric>());
-        listener.testRunFailed(EasyMock.contains(MockAbortTest.EXCEP_MSG));
-        listener.testRunEnded(EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
-        EasyMock.replay(listener);
+
         try {
             suite.run(mTestInfo, listener);
             fail("DeviceNotAvailableException not thrown");
         } catch (DeviceNotAvailableException e) {
             // expected
         }
-        EasyMock.verify(listener);
+
+        verify(listener).testRunStarted(DeviceTestSuite.class.getName(), 1);
+        verify(listener).testStarted(test1);
+        verify(listener).testFailed(Mockito.eq(test1), Mockito.contains(MockAbortTest.EXCEP_MSG));
+        verify(listener).testEnded(test1, new HashMap<String, Metric>());
+        verify(listener).testRunFailed(Mockito.contains(MockAbortTest.EXCEP_MSG));
+        verify(listener).testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
     }
 }
diff --git a/javatests/com/android/tradefed/testtype/GTestBaseTest.java b/javatests/com/android/tradefed/testtype/GTestBaseTest.java
index 9acb692..ea2f22a 100644
--- a/javatests/com/android/tradefed/testtype/GTestBaseTest.java
+++ b/javatests/com/android/tradefed/testtype/GTestBaseTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
 
 import com.android.ddmlib.IShellOutputReceiver;
 import com.android.tradefed.config.ConfigurationException;
@@ -28,7 +29,6 @@
 import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.result.ITestInvocationListener;
 
-import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -130,8 +130,7 @@
         gTestBase.addExcludeFilter("test1.filter3");
         gTestBase.addExcludeFilter("test1.filter4");
         mSetter.setOptionValue("prepend-filename", "true");
-        ITestInvocationListener listener = EasyMock.createNiceMock(ITestInvocationListener.class);
-        EasyMock.replay(listener);
+        ITestInvocationListener listener = mock(ITestInvocationListener.class);
 
         gTestBase.createResultParser("test1", listener);
 
@@ -139,8 +138,6 @@
         assertEquals(
                 String.format("--gtest_filter=%s-%s", "filter1:filter2", "filter3:filter4"),
                 filters);
-
-        EasyMock.verify(listener);
     }
 
     /** Test the return instance type of createResultParser. */
@@ -148,8 +145,7 @@
     public void testCreateResultParser() throws ConfigurationException {
         GTestBase gTestBase = new GTestBaseImpl();
         mSetter = new OptionSetter(gTestBase);
-        ITestInvocationListener listener = EasyMock.createNiceMock(ITestInvocationListener.class);
-        EasyMock.replay(listener);
+        ITestInvocationListener listener = mock(ITestInvocationListener.class);
 
         IShellOutputReceiver receiver = gTestBase.createResultParser("test1", listener);
         assertTrue(receiver instanceof GTestResultParser);
@@ -157,8 +153,6 @@
         mSetter.setOptionValue("collect-tests-only", "true");
         receiver = gTestBase.createResultParser("test1", listener);
         assertTrue(receiver instanceof GTestListTestParser);
-
-        EasyMock.verify(listener);
     }
 
     /**
diff --git a/javatests/com/android/tradefed/testtype/GTestXmlResultParserTest.java b/javatests/com/android/tradefed/testtype/GTestXmlResultParserTest.java
index 3f81f23..b1a36e8 100644
--- a/javatests/com/android/tradefed/testtype/GTestXmlResultParserTest.java
+++ b/javatests/com/android/tradefed/testtype/GTestXmlResultParserTest.java
@@ -15,6 +15,10 @@
  */
 package com.android.tradefed.testtype;
 
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
 import com.android.tradefed.device.CollectingOutputReceiver;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
@@ -22,10 +26,10 @@
 import com.android.tradefed.result.TestDescription;
 import com.android.tradefed.util.FileUtil;
 
-import org.easymock.EasyMock;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mockito;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -56,9 +60,11 @@
         File res = null;
         FileOutputStream out = null;
         try {
-            gtest_output = getClass().getResourceAsStream(File.separator +
-                    TEST_TYPE_DIR + File.separator + filename);
-            res = FileUtil.createTempFile("unit_gtest_", ".xml") ;
+            gtest_output =
+                    getClass()
+                            .getResourceAsStream(
+                                    File.separator + TEST_TYPE_DIR + File.separator + filename);
+            res = FileUtil.createTempFile("unit_gtest_", ".xml");
             out = new FileOutputStream(res);
             byte[] buffer = new byte[1024];
             int byteRead;
@@ -66,8 +72,7 @@
                 out.write(buffer, 0, byteRead);
             }
             out.close();
-        }
-        catch (NullPointerException | IOException e) {
+        } catch (NullPointerException | IOException e) {
             CLog.e("Gest output file does not exist: " + filename);
         }
         return res;
@@ -77,33 +82,27 @@
     @SuppressWarnings("unchecked")
     @Test
     public void testParseSimpleFile() throws Exception {
-        File contents =  readInFile(GTEST_OUTPUT_FILE_1);
+        File contents = readInFile(GTEST_OUTPUT_FILE_1);
         TestDescription firstInFile = new TestDescription("InteropTest", "test_lookup_hit");
         try {
-            ITestInvocationListener mockRunListener =
-                    EasyMock.createMock(ITestInvocationListener.class);
-            mockRunListener.testRunStarted(TEST_MODULE_NAME, 6);
-            mockRunListener.testStarted(EasyMock.eq(firstInFile), EasyMock.anyLong());
-            mockRunListener.testEnded(
-                    EasyMock.eq(firstInFile),
-                    EasyMock.anyLong(),
-                    (HashMap<String, Metric>) EasyMock.anyObject());
-            // 5 more passing test cases in this run
-            for (int i = 0; i < 5; ++i) {
-                mockRunListener.testStarted(
-                        (TestDescription) EasyMock.anyObject(), EasyMock.anyLong());
-                mockRunListener.testEnded(
-                        (TestDescription) EasyMock.anyObject(),
-                        EasyMock.anyLong(),
-                        (HashMap<String, Metric>) EasyMock.anyObject());
-            }
-            mockRunListener.testRunEnded(
-                    EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
-            EasyMock.replay(mockRunListener);
+            ITestInvocationListener mockRunListener = mock(ITestInvocationListener.class);
+
             GTestXmlResultParser resultParser =
                     new GTestXmlResultParser(TEST_MODULE_NAME, mockRunListener);
             resultParser.parseResult(contents, null);
-            EasyMock.verify(mockRunListener);
+
+            verify(mockRunListener).testRunStarted(TEST_MODULE_NAME, 6);
+            verify(mockRunListener).testStarted(Mockito.eq(firstInFile), Mockito.anyLong());
+            // +5 more passing test cases in this run
+            verify(mockRunListener, times(6))
+                    .testStarted((TestDescription) Mockito.any(), Mockito.anyLong());
+            verify(mockRunListener, times(6))
+                    .testEnded(
+                            (TestDescription) Mockito.any(),
+                            Mockito.anyLong(),
+                            (HashMap<String, Metric>) Mockito.any());
+            verify(mockRunListener)
+                    .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
         } finally {
             FileUtil.deleteFile(contents);
         }
@@ -113,27 +112,25 @@
     @SuppressWarnings("unchecked")
     @Test
     public void testParseLargerFile() throws Exception {
-        File contents =  readInFile(GTEST_OUTPUT_FILE_2);
+        File contents = readInFile(GTEST_OUTPUT_FILE_2);
         try {
-            ITestInvocationListener mockRunListener =
-                    EasyMock.createMock(ITestInvocationListener.class);
-            mockRunListener.testRunStarted(TEST_MODULE_NAME, 84);
-            // 84 passing test cases in this run
-            for (int i=0; i<84; ++i) {
-                mockRunListener.testStarted(
-                        (TestDescription) EasyMock.anyObject(), EasyMock.anyLong());
-                mockRunListener.testEnded(
-                        (TestDescription) EasyMock.anyObject(),
-                        EasyMock.anyLong(),
-                        (HashMap<String, Metric>) EasyMock.anyObject());
-            }
-            mockRunListener.testRunEnded(
-                    EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
-            EasyMock.replay(mockRunListener);
+            ITestInvocationListener mockRunListener = mock(ITestInvocationListener.class);
+
             GTestXmlResultParser resultParser =
                     new GTestXmlResultParser(TEST_MODULE_NAME, mockRunListener);
             resultParser.parseResult(contents, null);
-            EasyMock.verify(mockRunListener);
+
+            verify(mockRunListener).testRunStarted(TEST_MODULE_NAME, 84);
+            // 84 passing test cases in this run
+            verify(mockRunListener, times(84))
+                    .testStarted((TestDescription) Mockito.any(), Mockito.anyLong());
+            verify(mockRunListener, times(84))
+                    .testEnded(
+                            (TestDescription) Mockito.any(),
+                            Mockito.anyLong(),
+                            (HashMap<String, Metric>) Mockito.any());
+            verify(mockRunListener)
+                    .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
         } finally {
             FileUtil.deleteFile(contents);
         }
@@ -145,35 +142,27 @@
     public void testParseWithFailures() throws Exception {
         String expectedMessage = "Message\nFailed";
 
-        File contents =  readInFile(GTEST_OUTPUT_FILE_3);
+        File contents = readInFile(GTEST_OUTPUT_FILE_3);
         try {
-            ITestInvocationListener mockRunListener =
-                    EasyMock.createMock(ITestInvocationListener.class);
-            mockRunListener.testRunStarted(TEST_MODULE_NAME, 7);
-            // 6 passing test cases in this run
-            for (int i=0; i<6; ++i) {
-                mockRunListener.testStarted(
-                        (TestDescription) EasyMock.anyObject(), EasyMock.anyLong());
-                mockRunListener.testEnded(
-                        (TestDescription) EasyMock.anyObject(),
-                        EasyMock.anyLong(),
-                        (HashMap<String, Metric>) EasyMock.anyObject());
-            }
-            // 1 failed test
-            mockRunListener.testStarted((TestDescription) EasyMock.anyObject(), EasyMock.anyLong());
-            mockRunListener.testFailed(
-                    (TestDescription) EasyMock.anyObject(), EasyMock.eq(expectedMessage));
-            mockRunListener.testEnded(
-                    (TestDescription) EasyMock.anyObject(),
-                    EasyMock.anyLong(),
-                    (HashMap<String, Metric>) EasyMock.anyObject());
-            mockRunListener.testRunEnded(
-                    EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
-            EasyMock.replay(mockRunListener);
+            ITestInvocationListener mockRunListener = mock(ITestInvocationListener.class);
+
             GTestXmlResultParser resultParser =
                     new GTestXmlResultParser(TEST_MODULE_NAME, mockRunListener);
             resultParser.parseResult(contents, null);
-            EasyMock.verify(mockRunListener);
+
+            verify(mockRunListener).testRunStarted(TEST_MODULE_NAME, 7);
+            // 6 passing tests and 1 failed test.
+            verify(mockRunListener, times(7))
+                    .testStarted((TestDescription) Mockito.any(), Mockito.anyLong());
+            verify(mockRunListener, times(7))
+                    .testEnded(
+                            (TestDescription) Mockito.any(),
+                            Mockito.anyLong(),
+                            (HashMap<String, Metric>) Mockito.any());
+            verify(mockRunListener)
+                    .testFailed((TestDescription) Mockito.any(), Mockito.eq(expectedMessage));
+            verify(mockRunListener)
+                    .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
         } finally {
             FileUtil.deleteFile(contents);
         }
@@ -187,17 +176,16 @@
 
         File contents = FileUtil.createTempFile("test", ".xml");
         try {
-            ITestInvocationListener mockRunListener =
-                    EasyMock.createMock(ITestInvocationListener.class);
-            mockRunListener.testRunStarted(TEST_MODULE_NAME, 0);
-            mockRunListener.testRunFailed(expected);
-            mockRunListener.testRunEnded(
-                    EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
-            EasyMock.replay(mockRunListener);
+            ITestInvocationListener mockRunListener = mock(ITestInvocationListener.class);
+
             GTestXmlResultParser resultParser =
                     new GTestXmlResultParser(TEST_MODULE_NAME, mockRunListener);
             resultParser.parseResult(contents, null);
-            EasyMock.verify(mockRunListener);
+
+            verify(mockRunListener).testRunStarted(TEST_MODULE_NAME, 0);
+            verify(mockRunListener).testRunFailed(expected);
+            verify(mockRunListener)
+                    .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
         } finally {
             FileUtil.deleteFile(contents);
         }
@@ -208,28 +196,26 @@
     @Test
     public void testParseUnexpectedNumberTest() throws Exception {
         String expected = "Test run incomplete. Expected 7 tests, received 6";
-        File contents =  readInFile(GTEST_OUTPUT_FILE_4);
+        File contents = readInFile(GTEST_OUTPUT_FILE_4);
         try {
-            ITestInvocationListener mockRunListener =
-                    EasyMock.createMock(ITestInvocationListener.class);
-            mockRunListener.testRunStarted(TEST_MODULE_NAME, 7);
-            // 6 passing test cases in this run
-            for (int i=0; i<6; ++i) {
-                mockRunListener.testStarted(
-                        (TestDescription) EasyMock.anyObject(), EasyMock.anyLong());
-                mockRunListener.testEnded(
-                        (TestDescription) EasyMock.anyObject(),
-                        EasyMock.anyLong(),
-                        (HashMap<String, Metric>) EasyMock.anyObject());
-            }
-            mockRunListener.testRunFailed(expected);
-            mockRunListener.testRunEnded(
-                    EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
-            EasyMock.replay(mockRunListener);
+            ITestInvocationListener mockRunListener = mock(ITestInvocationListener.class);
+
             GTestXmlResultParser resultParser =
                     new GTestXmlResultParser(TEST_MODULE_NAME, mockRunListener);
             resultParser.parseResult(contents, null);
-            EasyMock.verify(mockRunListener);
+
+            verify(mockRunListener).testRunStarted(TEST_MODULE_NAME, 7);
+            // 6 passing test cases in this run
+            verify(mockRunListener, times(6))
+                    .testStarted((TestDescription) Mockito.any(), Mockito.anyLong());
+            verify(mockRunListener, times(6))
+                    .testEnded(
+                            (TestDescription) Mockito.any(),
+                            Mockito.anyLong(),
+                            (HashMap<String, Metric>) Mockito.any());
+            verify(mockRunListener).testRunFailed(expected);
+            verify(mockRunListener)
+                    .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
         } finally {
             FileUtil.deleteFile(contents);
         }
@@ -243,28 +229,25 @@
     @Test
     public void testParseSimpleFile_badXmltag() throws Exception {
         String expected = "Test run incomplete. Expected 6 tests, received 3";
-        File contents =  readInFile(GTEST_OUTPUT_FILE_5);
+        File contents = readInFile(GTEST_OUTPUT_FILE_5);
         try {
-            ITestInvocationListener mockRunListener =
-                    EasyMock.createMock(ITestInvocationListener.class);
-            mockRunListener.testRunStarted(TEST_MODULE_NAME, 6);
-            // 6 passing test cases in this run
-            for (int i=0; i<3; ++i) {
-                mockRunListener.testStarted(
-                        (TestDescription) EasyMock.anyObject(), EasyMock.anyLong());
-                mockRunListener.testEnded(
-                        (TestDescription) EasyMock.anyObject(),
-                        EasyMock.anyLong(),
-                        (HashMap<String, Metric>) EasyMock.anyObject());
-            }
-            mockRunListener.testRunFailed(expected);
-            mockRunListener.testRunEnded(
-                    EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
-            EasyMock.replay(mockRunListener);
+            ITestInvocationListener mockRunListener = mock(ITestInvocationListener.class);
+
             GTestXmlResultParser resultParser =
                     new GTestXmlResultParser(TEST_MODULE_NAME, mockRunListener);
             resultParser.parseResult(contents, null);
-            EasyMock.verify(mockRunListener);
+
+            verify(mockRunListener).testRunStarted(TEST_MODULE_NAME, 6);
+            verify(mockRunListener, times(3))
+                    .testStarted((TestDescription) Mockito.any(), Mockito.anyLong());
+            verify(mockRunListener, times(3))
+                    .testEnded(
+                            (TestDescription) Mockito.any(),
+                            Mockito.anyLong(),
+                            (HashMap<String, Metric>) Mockito.any());
+            verify(mockRunListener).testRunFailed(expected);
+            verify(mockRunListener)
+                    .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
         } finally {
             FileUtil.deleteFile(contents);
         }
@@ -275,28 +258,28 @@
     @Test
     public void testParseWithEmptyFile_AdditionalOutput() throws Exception {
         final String exec_log = "EXECUTION LOG";
-        CollectingOutputReceiver fake = new CollectingOutputReceiver() {
-            @Override
-            public String getOutput() {
-                return exec_log;
-            }
-        };
-        String expected = "Failed to get an xml output from tests, it probably crashed\nlogs:\n"
-                + exec_log;
+        CollectingOutputReceiver fake =
+                new CollectingOutputReceiver() {
+                    @Override
+                    public String getOutput() {
+                        return exec_log;
+                    }
+                };
+        String expected =
+                "Failed to get an xml output from tests, it probably crashed\nlogs:\n" + exec_log;
 
         File contents = FileUtil.createTempFile("test", ".xml");
         try {
-            ITestInvocationListener mockRunListener =
-                    EasyMock.createMock(ITestInvocationListener.class);
-            mockRunListener.testRunStarted(TEST_MODULE_NAME, 0);
-            mockRunListener.testRunFailed(expected);
-            mockRunListener.testRunEnded(
-                    EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
-            EasyMock.replay(mockRunListener);
+            ITestInvocationListener mockRunListener = mock(ITestInvocationListener.class);
+
             GTestXmlResultParser resultParser =
                     new GTestXmlResultParser(TEST_MODULE_NAME, mockRunListener);
             resultParser.parseResult(contents, fake);
-            EasyMock.verify(mockRunListener);
+
+            verify(mockRunListener).testRunStarted(TEST_MODULE_NAME, 0);
+            verify(mockRunListener).testRunFailed(expected);
+            verify(mockRunListener)
+                    .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
         } finally {
             FileUtil.deleteFile(contents);
         }
@@ -309,33 +292,29 @@
         File contents = readInFile(GTEST_OUTPUT_FILE_6);
         TestDescription firstInFile = new TestDescription("InteropTest", "test_lookup_hit");
         try {
-            ITestInvocationListener mockRunListener =
-                    EasyMock.createMock(ITestInvocationListener.class);
-            mockRunListener.testRunStarted(TEST_MODULE_NAME, 6);
-            mockRunListener.testStarted(EasyMock.eq(firstInFile), EasyMock.anyLong());
-            mockRunListener.testEnded(
-                    EasyMock.eq(firstInFile),
-                    EasyMock.anyLong(),
-                    (HashMap<String, Metric>) EasyMock.anyObject());
-            // 5 more passing test cases in this run
-            for (int i = 0; i < 5; ++i) {
-                mockRunListener.testStarted(
-                        (TestDescription) EasyMock.anyObject(), EasyMock.anyLong());
-                if (i == 1) {
-                    mockRunListener.testIgnored((TestDescription) EasyMock.anyObject());
-                }
-                mockRunListener.testEnded(
-                        (TestDescription) EasyMock.anyObject(),
-                        EasyMock.anyLong(),
-                        (HashMap<String, Metric>) EasyMock.anyObject());
-            }
-            mockRunListener.testRunEnded(
-                    EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject());
-            EasyMock.replay(mockRunListener);
+            ITestInvocationListener mockRunListener = mock(ITestInvocationListener.class);
+
             GTestXmlResultParser resultParser =
                     new GTestXmlResultParser(TEST_MODULE_NAME, mockRunListener);
             resultParser.parseResult(contents, null);
-            EasyMock.verify(mockRunListener);
+
+            verify(mockRunListener).testRunStarted(TEST_MODULE_NAME, 6);
+            verify(mockRunListener).testStarted(Mockito.eq(firstInFile), Mockito.anyLong());
+            verify(mockRunListener)
+                    .testEnded(
+                            Mockito.eq(firstInFile),
+                            Mockito.anyLong(),
+                            (HashMap<String, Metric>) Mockito.any());
+            verify(mockRunListener, times(6))
+                    .testStarted((TestDescription) Mockito.any(), Mockito.anyLong());
+            verify(mockRunListener).testIgnored((TestDescription) Mockito.any());
+            verify(mockRunListener, times(6))
+                    .testEnded(
+                            (TestDescription) Mockito.any(),
+                            Mockito.anyLong(),
+                            (HashMap<String, Metric>) Mockito.any());
+            verify(mockRunListener)
+                    .testRunEnded(Mockito.anyLong(), (HashMap<String, Metric>) Mockito.any());
         } finally {
             FileUtil.deleteFile(contents);
         }
diff --git a/javatests/com/android/tradefed/testtype/NativeBenchmarkTestTest.java b/javatests/com/android/tradefed/testtype/NativeBenchmarkTestTest.java
index 44bb752..e0e4ebc 100644
--- a/javatests/com/android/tradefed/testtype/NativeBenchmarkTestTest.java
+++ b/javatests/com/android/tradefed/testtype/NativeBenchmarkTestTest.java
@@ -17,6 +17,14 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import com.android.ddmlib.FileListingService;
 import com.android.tradefed.config.OptionSetter;
@@ -27,11 +35,13 @@
 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
 import com.android.tradefed.result.ITestInvocationListener;
 
-import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 
 import java.util.HashMap;
 import java.util.concurrent.TimeUnit;
@@ -41,38 +51,27 @@
 public class NativeBenchmarkTestTest {
 
     private NativeBenchmarkTest mBenchmark;
-    private ITestInvocationListener mListener;
-    private ITestDevice mDevice;
+    @Mock ITestInvocationListener mListener;
+    @Mock ITestDevice mDevice;
     private TestInformation mTestInfo;
 
     @Before
     public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
         mBenchmark = new NativeBenchmarkTest();
-        mListener = EasyMock.createMock(ITestInvocationListener.class);
-        mDevice = EasyMock.createMock(ITestDevice.class);
-        EasyMock.expect(mDevice.getSerialNumber()).andStubReturn("SERIAL");
+
+        when(mDevice.getSerialNumber()).thenReturn("SERIAL");
         mTestInfo = TestInformation.newBuilder().build();
     }
 
-    private void replayMocks(Object... mocks) {
-        EasyMock.replay(mListener, mDevice);
-        EasyMock.replay(mocks);
-    }
-
-    private void verifyMocks(Object... mocks) {
-        EasyMock.verify(mListener, mDevice);
-        EasyMock.verify(mocks);
-    }
-
     @Test
     public void testRun_noDevice() throws DeviceNotAvailableException {
         try {
-            replayMocks();
             mBenchmark.run(mTestInfo, mListener);
             fail("An exception should have been thrown");
         } catch (IllegalArgumentException expected) {
             assertEquals("Device has not been set", expected.getMessage());
-            verifyMocks();
         }
     }
 
@@ -87,18 +86,22 @@
         OptionSetter setter = new OptionSetter(mBenchmark);
         setter.setOptionValue("benchmark-module-name", "TEST");
         String res = mBenchmark.getTestPath();
-        String expected = String.format("%s%s%s", NativeBenchmarkTest.DEFAULT_TEST_PATH,
-                FileListingService.FILE_SEPARATOR, "TEST");
+        String expected =
+                String.format(
+                        "%s%s%s",
+                        NativeBenchmarkTest.DEFAULT_TEST_PATH,
+                        FileListingService.FILE_SEPARATOR,
+                        "TEST");
         assertEquals(expected, res);
     }
 
     @Test
     public void testRun_noFileEntry() throws DeviceNotAvailableException {
         mBenchmark.setDevice(mDevice);
-        EasyMock.expect(mDevice.getFileEntry((String) EasyMock.anyObject())).andReturn(null);
-        replayMocks();
+        when(mDevice.getFileEntry(any(String.class))).thenReturn(null);
+
         mBenchmark.run(mTestInfo, mListener);
-        verifyMocks();
+        verify(mDevice).getFileEntry(any(String.class));
     }
 
     @Test
@@ -117,17 +120,23 @@
         mBenchmark.setDevice(mDevice);
         OptionSetter setter = new OptionSetter(mBenchmark);
         setter.setOptionValue("max-cpu-freq", "true");
-        IFileEntry fakeEntry = EasyMock.createMock(IFileEntry.class);
-        EasyMock.expect(mDevice.getFileEntry((String) EasyMock.anyObject())).andReturn(fakeEntry);
-        EasyMock.expect(mDevice.executeShellCommand(EasyMock.eq("cat "
-                + "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq > "
-                + "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq"))).andReturn("");
-        EasyMock.expect(mDevice.executeShellCommand(EasyMock.eq("cat "
-                + "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq > "
-                + "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq"))).andReturn("");
-        replayMocks(fakeEntry);
+        IFileEntry fakeEntry = mock(IFileEntry.class);
+        when(mDevice.getFileEntry(any(String.class))).thenReturn(fakeEntry);
+        when(mDevice.executeShellCommand(
+                        eq(
+                                "cat "
+                                        + "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq > "
+                                        + "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq")))
+                .thenReturn("");
+        when(mDevice.executeShellCommand(
+                        eq(
+                                "cat "
+                                        + "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq > "
+                                        + "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq")))
+                .thenReturn("");
+
         mBenchmark.run(mTestInfo, mListener);
-        verifyMocks(fakeEntry);
+        verify(mDevice, times(2)).executeShellCommand(any(String.class));
     }
 
     @Test
@@ -135,23 +144,22 @@
         final String fakeRunName = "RUN_NAME";
         final String fakeFullPath = "/path/" + fakeRunName;
         mBenchmark.setDevice(mDevice);
-        IFileEntry fakeEntry = EasyMock.createMock(IFileEntry.class);
-        EasyMock.expect(fakeEntry.isDirectory()).andReturn(false);
-        EasyMock.expect(fakeEntry.getName()).andStubReturn(fakeRunName);
-        EasyMock.expect(fakeEntry.getFullEscapedPath()).andReturn(fakeFullPath);
-        EasyMock.expect(mDevice.getFileEntry((String) EasyMock.anyObject())).andReturn(fakeEntry);
-        EasyMock.expect(mDevice.executeShellCommand(EasyMock.eq("chmod 755 " + fakeFullPath)))
-                .andReturn("");
-        mDevice.executeShellCommand(EasyMock.eq(fakeFullPath + " -n 1000 -d 0.000000 -c 1 -s 1"),
-                EasyMock.anyObject(), EasyMock.anyLong(), EasyMock.eq(TimeUnit.MILLISECONDS),
-                EasyMock.eq(0));
-        EasyMock.expectLastCall();
-        mListener.testRunStarted(EasyMock.eq(fakeRunName), EasyMock.anyInt());
-        EasyMock.expectLastCall();
-        mListener.testRunEnded(EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
-        EasyMock.expectLastCall();
-        replayMocks(fakeEntry);
+        IFileEntry fakeEntry = mock(IFileEntry.class);
+        when(fakeEntry.isDirectory()).thenReturn(false);
+        when(fakeEntry.getName()).thenReturn(fakeRunName);
+        when(fakeEntry.getFullEscapedPath()).thenReturn(fakeFullPath);
+        when(mDevice.getFileEntry(any(String.class))).thenReturn(fakeEntry);
+        when(mDevice.executeShellCommand(eq("chmod 755 " + fakeFullPath))).thenReturn("");
+
         mBenchmark.run(mTestInfo, mListener);
-        verifyMocks(fakeEntry);
+        verify(mDevice, times(1))
+                .executeShellCommand(
+                        eq(fakeFullPath + " -n 1000 -d 0.000000 -c 1 -s 1"),
+                        any(),
+                        anyLong(),
+                        eq(TimeUnit.MILLISECONDS),
+                        eq(0));
+        verify(mListener, times(1)).testRunStarted(eq(fakeRunName), anyInt());
+        verify(mListener, times(1)).testRunEnded(anyLong(), Mockito.<HashMap<String, Metric>>any());
     }
 }
diff --git a/javatests/com/android/tradefed/testtype/TfTestLauncherTest.java b/javatests/com/android/tradefed/testtype/TfTestLauncherTest.java
index 95048e8..cdb5e56 100644
--- a/javatests/com/android/tradefed/testtype/TfTestLauncherTest.java
+++ b/javatests/com/android/tradefed/testtype/TfTestLauncherTest.java
@@ -16,6 +16,9 @@
 package com.android.tradefed.testtype;
 
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import com.android.tradefed.build.IFolderBuildInfo;
 import com.android.tradefed.command.CommandOptions;
@@ -39,12 +42,13 @@
 import com.android.tradefed.util.IRunUtil.EnvPriority;
 import com.android.tradefed.util.SystemUtil.EnvVariable;
 
-import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mock;
 import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -62,18 +66,15 @@
     private static final String SUB_GLOBAL_CONFIG = "FAKE_GLOBAL_CONFIG";
 
     private TfTestLauncher mTfTestLauncher;
-    private ITestInvocationListener mMockListener;
-    private IRunUtil mMockRunUtil;
-    private IFolderBuildInfo mMockBuildInfo;
-    private IConfiguration mMockConfig;
+    @Mock ITestInvocationListener mMockListener;
+    @Mock IRunUtil mMockRunUtil;
+    @Mock IFolderBuildInfo mMockBuildInfo;
+    @Mock IConfiguration mMockConfig;
     private TestInformation mTestInfo;
 
     @Before
     public void setUp() throws Exception {
-        mMockListener = EasyMock.createMock(ITestInvocationListener.class);
-        mMockRunUtil = EasyMock.createMock(IRunUtil.class);
-        mMockBuildInfo = EasyMock.createMock(IFolderBuildInfo.class);
-        mMockConfig = EasyMock.createMock(IConfiguration.class);
+        MockitoAnnotations.initMocks(this);
 
         mTfTestLauncher = new TfTestLauncher();
         mTfTestLauncher.setRunUtil(mMockRunUtil);
@@ -85,7 +86,7 @@
         context.addDeviceBuildInfo("device", mMockBuildInfo);
         mTestInfo = TestInformation.newBuilder().setInvocationContext(context).build();
 
-        EasyMock.expect(mMockConfig.getCommandOptions()).andStubReturn(new CommandOptions());
+        when(mMockConfig.getCommandOptions()).thenReturn(new CommandOptions());
 
         OptionSetter setter = new OptionSetter(mTfTestLauncher);
         setter.setOptionValue("config-name", CONFIG_NAME);
@@ -96,144 +97,148 @@
     @Test
     public void testRun() throws DeviceNotAvailableException {
         CommandResult cr = new CommandResult(CommandStatus.SUCCESS);
-        EasyMock.expect(
-                        mMockRunUtil.runTimedCmd(
-                                EasyMock.anyLong(),
-                                (FileOutputStream) EasyMock.anyObject(),
-                                (FileOutputStream) EasyMock.anyObject(),
-                                EasyMock.endsWith("/java"),
-                                (String) EasyMock.anyObject(),
-                                EasyMock.eq("--add-opens=java.base/java.nio=ALL-UNNAMED"),
-                                EasyMock.eq(
-                                        "--add-opens=java.base/sun.reflect.annotation=ALL-UNNAMED"),
-                                EasyMock.eq("--add-opens=java.base/java.io=ALL-UNNAMED"),
-                                EasyMock.eq("-cp"),
-                                (String) EasyMock.anyObject(),
-                                EasyMock.eq("com.android.tradefed.command.CommandRunner"),
-                                EasyMock.eq(CONFIG_NAME),
-                                EasyMock.eq("-n"),
-                                EasyMock.eq("--test-tag"),
-                                EasyMock.eq(TEST_TAG),
-                                EasyMock.eq("--build-id"),
-                                EasyMock.eq(BUILD_ID),
-                                EasyMock.eq("--branch"),
-                                EasyMock.eq(BUILD_BRANCH),
-                                EasyMock.eq("--build-flavor"),
-                                EasyMock.eq(BUILD_FLAVOR),
-                                EasyMock.eq("--" + CommandOptions.INVOCATION_DATA),
-                                EasyMock.eq(SubprocessTfLauncher.SUBPROCESS_TAG_NAME),
-                                EasyMock.eq("true"),
-                                EasyMock.eq("--subprocess-report-file"),
-                                (String) EasyMock.anyObject()))
-                .andReturn(cr);
+        when(mMockRunUtil.runTimedCmd(
+                        Mockito.anyLong(),
+                        (FileOutputStream) Mockito.any(),
+                        (FileOutputStream) Mockito.any(),
+                        Mockito.endsWith("/java"),
+                        (String) Mockito.any(),
+                        Mockito.eq("--add-opens=java.base/java.nio=ALL-UNNAMED"),
+                        Mockito.eq("--add-opens=java.base/sun.reflect.annotation=ALL-UNNAMED"),
+                        Mockito.eq("--add-opens=java.base/java.io=ALL-UNNAMED"),
+                        Mockito.eq("-cp"),
+                        (String) Mockito.any(),
+                        Mockito.eq("com.android.tradefed.command.CommandRunner"),
+                        Mockito.eq(CONFIG_NAME),
+                        Mockito.eq("-n"),
+                        Mockito.eq("--test-tag"),
+                        Mockito.eq(TEST_TAG),
+                        Mockito.eq("--build-id"),
+                        Mockito.eq(BUILD_ID),
+                        Mockito.eq("--branch"),
+                        Mockito.eq(BUILD_BRANCH),
+                        Mockito.eq("--build-flavor"),
+                        Mockito.eq(BUILD_FLAVOR),
+                        Mockito.eq("--" + CommandOptions.INVOCATION_DATA),
+                        Mockito.eq(SubprocessTfLauncher.SUBPROCESS_TAG_NAME),
+                        Mockito.eq("true"),
+                        Mockito.eq("--subprocess-report-file"),
+                        (String) Mockito.any()))
+                .thenReturn(cr);
 
-        mMockRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE);
-        mMockRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_SERVER_CONFIG_VARIABLE);
-        mMockRunUtil.unsetEnvVariable(SubprocessTfLauncher.ANDROID_SERIAL_VAR);
-        for (String variable : AutomatedReporters.REPORTER_MAPPING) {
-            mMockRunUtil.unsetEnvVariable(variable);
-        }
-        mMockRunUtil.unsetEnvVariable(EnvVariable.ANDROID_HOST_OUT_TESTCASES.name());
-        mMockRunUtil.unsetEnvVariable(EnvVariable.ANDROID_TARGET_OUT_TESTCASES.name());
-        mMockRunUtil.setEnvVariablePriority(EnvPriority.SET);
-        mMockRunUtil.setEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE, SUB_GLOBAL_CONFIG);
+        when(mMockBuildInfo.getTestTag()).thenReturn(TEST_TAG);
+        when(mMockBuildInfo.getBuildBranch()).thenReturn(BUILD_BRANCH);
+        when(mMockBuildInfo.getBuildFlavor()).thenReturn(BUILD_FLAVOR);
 
-        EasyMock.expect(mMockBuildInfo.getTestTag()).andReturn(TEST_TAG);
-        EasyMock.expect(mMockBuildInfo.getBuildBranch()).andReturn(BUILD_BRANCH).times(3);
-        EasyMock.expect(mMockBuildInfo.getBuildFlavor()).andReturn(BUILD_FLAVOR).times(2);
+        when(mMockBuildInfo.getRootDir()).thenReturn(new File(""));
+        when(mMockBuildInfo.getBuildId()).thenReturn(BUILD_ID);
 
-        EasyMock.expect(mMockBuildInfo.getRootDir()).andReturn(new File(""));
-        EasyMock.expect(mMockBuildInfo.getBuildId()).andReturn(BUILD_ID).times(3);
-        mMockBuildInfo.addBuildAttribute(SubprocessTfLauncher.PARENT_PROC_TAG_NAME, "true");
-
-        mMockListener.testLog((String)EasyMock.anyObject(), (LogDataType)EasyMock.anyObject(),
-                (FileInputStreamSource)EasyMock.anyObject());
-        EasyMock.expectLastCall().times(3);
-
-        mMockListener.testRunStarted("temporaryFiles", 1);
-        mMockListener.testRunStarted("StdErr", 1);
-        for (int i = 0; i < 2; i++) {
-            mMockListener.testStarted((TestDescription) EasyMock.anyObject());
-            mMockListener.testEnded(
-                    (TestDescription) EasyMock.anyObject(),
-                    EasyMock.eq(new HashMap<String, Metric>()));
-            mMockListener.testRunEnded(0, new HashMap<String, Metric>());
-        }
-        mMockListener.testRunStarted("elapsed-time", 1);
-        mMockListener.testStarted(EasyMock.anyObject());
-        mMockListener.testEnded(
-                EasyMock.anyObject(), EasyMock.<HashMap<String, Metric>>anyObject());
-        mMockListener.testRunEnded(
-                EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
-
-        EasyMock.replay(mMockBuildInfo, mMockRunUtil, mMockListener, mMockConfig);
         mTfTestLauncher.run(mTestInfo, mMockListener);
-        EasyMock.verify(mMockBuildInfo, mMockRunUtil, mMockListener, mMockConfig);
+        verify(mMockListener, times(3))
+                .testLog(
+                        (String) Mockito.any(),
+                        (LogDataType) Mockito.any(),
+                        (FileInputStreamSource) Mockito.any());
+        verify(mMockBuildInfo, times(3)).getBuildBranch();
+        verify(mMockBuildInfo, times(2)).getBuildFlavor();
+        verify(mMockBuildInfo, times(3)).getBuildId();
+        verify(mMockRunUtil).unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE);
+        verify(mMockRunUtil)
+                .unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_SERVER_CONFIG_VARIABLE);
+        verify(mMockRunUtil).unsetEnvVariable(SubprocessTfLauncher.ANDROID_SERIAL_VAR);
+        for (String variable : AutomatedReporters.REPORTER_MAPPING) {
+            verify(mMockRunUtil).unsetEnvVariable(variable);
+        }
+        verify(mMockRunUtil).unsetEnvVariable(EnvVariable.ANDROID_HOST_OUT_TESTCASES.name());
+        verify(mMockRunUtil).unsetEnvVariable(EnvVariable.ANDROID_TARGET_OUT_TESTCASES.name());
+        verify(mMockRunUtil).setEnvVariablePriority(EnvPriority.SET);
+        verify(mMockRunUtil)
+                .setEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE, SUB_GLOBAL_CONFIG);
+        verify(mMockBuildInfo).addBuildAttribute(SubprocessTfLauncher.PARENT_PROC_TAG_NAME, "true");
+        verify(mMockListener).testRunStarted("temporaryFiles", 1);
+        verify(mMockListener).testRunStarted("StdErr", 1);
+        verify(mMockListener, times(3)).testStarted((TestDescription) Mockito.any());
+        verify(mMockListener, times(2))
+                .testEnded(
+                        (TestDescription) Mockito.any(), Mockito.eq(new HashMap<String, Metric>()));
+        verify(mMockListener, times(2)).testRunEnded(0, new HashMap<String, Metric>());
+        verify(mMockListener).testRunStarted("elapsed-time", 1);
+        verify(mMockListener, times(3))
+                .testEnded(Mockito.any(), Mockito.<HashMap<String, Metric>>any());
+        verify(mMockListener, times(3))
+                .testRunEnded(Mockito.anyLong(), Mockito.<HashMap<String, Metric>>any());
     }
 
-    /**
-     * Test {@link TfTestLauncher#testTmpDirClean(File, ITestInvocationListener)}
-     */
+    /** Test {@link TfTestLauncher#testTmpDirClean(File, ITestInvocationListener)} */
     @Test
     public void testTestTmpDirClean_success() {
-        mMockListener.testRunStarted("temporaryFiles", 1);
-        mMockListener.testStarted((TestDescription) EasyMock.anyObject());
-        mMockListener.testEnded(
-                (TestDescription) EasyMock.anyObject(), EasyMock.eq(new HashMap<String, Metric>()));
-        mMockListener.testRunEnded(0, new HashMap<String, Metric>());
+
         File tmpDir = Mockito.mock(File.class);
         Mockito.when(tmpDir.list())
-                .thenReturn(new String[] {"inv_123", "tradefed_global_log_123", "lc_cache",
-                        "stage-android-build-api"});
-        EasyMock.replay(mMockListener);
+                .thenReturn(
+                        new String[] {
+                            "inv_123",
+                            "tradefed_global_log_123",
+                            "lc_cache",
+                            "stage-android-build-api"
+                        });
+
         mTfTestLauncher.testTmpDirClean(tmpDir, mMockListener);
-        EasyMock.verify(mMockListener);
+
+        verify(mMockListener).testRunStarted("temporaryFiles", 1);
+        verify(mMockListener).testStarted((TestDescription) Mockito.any());
+        verify(mMockListener)
+                .testEnded(
+                        (TestDescription) Mockito.any(), Mockito.eq(new HashMap<String, Metric>()));
+        verify(mMockListener).testRunEnded(0, new HashMap<String, Metric>());
     }
 
     /**
      * Test {@link TfTestLauncher#testTmpDirClean(File, ITestInvocationListener)}
      *
-     * Test should fail if there are extra files do not match expected pattern.
+     * <p>Test should fail if there are extra files do not match expected pattern.
      */
     @Test
     public void testTestTmpDirClean_failExtraFile() {
         mTfTestLauncher.setBuild(mMockBuildInfo);
-        EasyMock.expect(mMockBuildInfo.getBuildBranch()).andReturn(BUILD_BRANCH).times(1);
-        mMockListener.testRunStarted("temporaryFiles", 1);
-        mMockListener.testStarted((TestDescription) EasyMock.anyObject());
-        mMockListener.testFailed(
-                (TestDescription) EasyMock.anyObject(), (String) EasyMock.anyObject());
-        mMockListener.testEnded(
-                (TestDescription) EasyMock.anyObject(), EasyMock.eq(new HashMap<String, Metric>()));
-        mMockListener.testRunEnded(0, new HashMap<String, Metric>());
+        when(mMockBuildInfo.getBuildBranch()).thenReturn(BUILD_BRANCH);
+
         File tmpDir = Mockito.mock(File.class);
         Mockito.when(tmpDir.list()).thenReturn(new String[] {"extra_file"});
-        EasyMock.replay(mMockListener, mMockBuildInfo);
+
         mTfTestLauncher.testTmpDirClean(tmpDir, mMockListener);
-        EasyMock.verify(mMockListener, mMockBuildInfo);
+        verify(mMockBuildInfo, times(1)).getBuildBranch();
+        verify(mMockListener).testRunStarted("temporaryFiles", 1);
+        verify(mMockListener).testStarted((TestDescription) Mockito.any());
+        verify(mMockListener).testFailed((TestDescription) Mockito.any(), (String) Mockito.any());
+        verify(mMockListener)
+                .testEnded(
+                        (TestDescription) Mockito.any(), Mockito.eq(new HashMap<String, Metric>()));
+        verify(mMockListener).testRunEnded(0, new HashMap<String, Metric>());
     }
 
     /**
      * Test {@link TfTestLauncher#testTmpDirClean(File, ITestInvocationListener)}
      *
-     * Test should fail if there are multiple files matching an expected pattern.
+     * <p>Test should fail if there are multiple files matching an expected pattern.
      */
     @Test
     public void testTestTmpDirClean_failMultipleFiles() {
         mTfTestLauncher.setBuild(mMockBuildInfo);
-        EasyMock.expect(mMockBuildInfo.getBuildBranch()).andReturn(BUILD_BRANCH).times(1);
-        mMockListener.testRunStarted("temporaryFiles", 1);
-        mMockListener.testStarted((TestDescription) EasyMock.anyObject());
-        mMockListener.testFailed(
-                (TestDescription) EasyMock.anyObject(), (String) EasyMock.anyObject());
-        mMockListener.testEnded(
-                (TestDescription) EasyMock.anyObject(), EasyMock.eq(new HashMap<String, Metric>()));
-        mMockListener.testRunEnded(0, new HashMap<String, Metric>());
+        when(mMockBuildInfo.getBuildBranch()).thenReturn(BUILD_BRANCH);
+
         File tmpDir = Mockito.mock(File.class);
         Mockito.when(tmpDir.list()).thenReturn(new String[] {"inv_1", "inv_2"});
-        EasyMock.replay(mMockListener, mMockBuildInfo);
+
         mTfTestLauncher.testTmpDirClean(tmpDir, mMockListener);
-        EasyMock.verify(mMockListener, mMockBuildInfo);
+        verify(mMockBuildInfo, times(1)).getBuildBranch();
+        verify(mMockListener).testRunStarted("temporaryFiles", 1);
+        verify(mMockListener).testStarted((TestDescription) Mockito.any());
+        verify(mMockListener).testFailed((TestDescription) Mockito.any(), (String) Mockito.any());
+        verify(mMockListener)
+                .testEnded(
+                        (TestDescription) Mockito.any(), Mockito.eq(new HashMap<String, Metric>()));
+        verify(mMockListener).testRunEnded(0, new HashMap<String, Metric>());
     }
 
     /** Test that when code coverage option is on, we add the javaagent to the java arguments. */
@@ -244,25 +249,29 @@
         setter.setOptionValue("include-coverage", "com.android.tradefed*");
         setter.setOptionValue("include-coverage", "com.google.android.tradefed*");
         setter.setOptionValue("exclude-coverage", "com.test*");
-        EasyMock.expect(mMockBuildInfo.getRootDir()).andReturn(new File(""));
-        EasyMock.expect(mMockBuildInfo.getTestTag()).andReturn(TEST_TAG);
-        EasyMock.expect(mMockBuildInfo.getBuildBranch()).andReturn(BUILD_BRANCH).times(2);
-        EasyMock.expect(mMockBuildInfo.getBuildFlavor()).andReturn(BUILD_FLAVOR).times(2);
-        EasyMock.expect(mMockBuildInfo.getBuildId()).andReturn(BUILD_ID).times(2);
-        mMockRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE);
-        mMockRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_SERVER_CONFIG_VARIABLE);
-        mMockRunUtil.unsetEnvVariable(SubprocessTfLauncher.ANDROID_SERIAL_VAR);
-        for (String variable : AutomatedReporters.REPORTER_MAPPING) {
-            mMockRunUtil.unsetEnvVariable(variable);
-        }
-        mMockRunUtil.unsetEnvVariable(EnvVariable.ANDROID_HOST_OUT_TESTCASES.name());
-        mMockRunUtil.unsetEnvVariable(EnvVariable.ANDROID_TARGET_OUT_TESTCASES.name());
-        mMockRunUtil.setEnvVariablePriority(EnvPriority.SET);
-        mMockRunUtil.setEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE, SUB_GLOBAL_CONFIG);
-        EasyMock.replay(mMockBuildInfo, mMockRunUtil, mMockListener, mMockConfig);
+        when(mMockBuildInfo.getRootDir()).thenReturn(new File(""));
+        when(mMockBuildInfo.getTestTag()).thenReturn(TEST_TAG);
+        when(mMockBuildInfo.getBuildBranch()).thenReturn(BUILD_BRANCH);
+        when(mMockBuildInfo.getBuildFlavor()).thenReturn(BUILD_FLAVOR);
+        when(mMockBuildInfo.getBuildId()).thenReturn(BUILD_ID);
+
         try {
             mTfTestLauncher.preRun();
-            EasyMock.verify(mMockBuildInfo, mMockRunUtil, mMockListener);
+            verify(mMockBuildInfo, times(2)).getBuildBranch();
+            verify(mMockBuildInfo, times(2)).getBuildFlavor();
+            verify(mMockBuildInfo, times(2)).getBuildId();
+            verify(mMockRunUtil).unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE);
+            verify(mMockRunUtil)
+                    .unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_SERVER_CONFIG_VARIABLE);
+            verify(mMockRunUtil).unsetEnvVariable(SubprocessTfLauncher.ANDROID_SERIAL_VAR);
+            for (String variable : AutomatedReporters.REPORTER_MAPPING) {
+                verify(mMockRunUtil).unsetEnvVariable(variable);
+            }
+            verify(mMockRunUtil).unsetEnvVariable(EnvVariable.ANDROID_HOST_OUT_TESTCASES.name());
+            verify(mMockRunUtil).unsetEnvVariable(EnvVariable.ANDROID_TARGET_OUT_TESTCASES.name());
+            verify(mMockRunUtil).setEnvVariablePriority(EnvPriority.SET);
+            verify(mMockRunUtil)
+                    .setEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE, SUB_GLOBAL_CONFIG);
             assertTrue(mTfTestLauncher.mCmdArgs.get(2).startsWith("-javaagent:"));
             assertTrue(
                     mTfTestLauncher
@@ -275,6 +284,5 @@
             FileUtil.recursiveDelete(mTfTestLauncher.mTmpDir);
             mTfTestLauncher.cleanTmpFile();
         }
-        EasyMock.verify(mMockBuildInfo, mMockRunUtil, mMockListener, mMockConfig);
     }
 }
diff --git a/javatests/com/android/tradefed/testtype/rust/RustTestResultParserTest.java b/javatests/com/android/tradefed/testtype/rust/RustTestResultParserTest.java
index f0d16f0..c8553a6 100644
--- a/javatests/com/android/tradefed/testtype/rust/RustTestResultParserTest.java
+++ b/javatests/com/android/tradefed/testtype/rust/RustTestResultParserTest.java
@@ -15,22 +15,23 @@
  */
 package com.android.tradefed.testtype.rust;
 
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 
 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
 import com.android.tradefed.result.ITestInvocationListener;
 import com.android.tradefed.result.TestDescription;
 import com.android.tradefed.util.ArrayUtil;
 
-import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 
 import java.util.Arrays;
 import java.util.HashMap;
@@ -40,11 +41,12 @@
 public class RustTestResultParserTest extends RustParserTestBase {
 
     private RustTestResultParser mParser;
-    private ITestInvocationListener mMockListener;
+    @Mock ITestInvocationListener mMockListener;
 
     @Before
     public void setUp() throws Exception {
-        mMockListener = createMock(ITestInvocationListener.class);
+        MockitoAnnotations.initMocks(this);
+
         mParser = new RustTestResultParser(ArrayUtil.list(mMockListener), "test");
     }
 
@@ -151,63 +153,57 @@
     public void testParseRealOutput() {
         String[] contents = readInFile(RUST_OUTPUT_FILE_1);
 
-        for (int i = 0; i < 10; i++) {
-            mMockListener.testStarted(EasyMock.anyObject());
-            mMockListener.testEnded(
-                    EasyMock.anyObject(), EasyMock.<HashMap<String, Metric>>anyObject());
-        }
-
-        replay(mMockListener);
         mParser.processNewLines(contents);
         mParser.done();
-        verify(mMockListener);
+
+        verify(mMockListener, times(10)).testStarted(Mockito.any());
+        verify(mMockListener, times(10))
+                .testEnded(Mockito.any(), Mockito.<HashMap<String, Metric>>any());
     }
 
     @Test
     public void testParseRealOutput2() {
         String[] contents = readInFile(RUST_OUTPUT_FILE_2);
-        for (int i = 0; i < 23; i++) {
-            mMockListener.testStarted(EasyMock.anyObject());
-            mMockListener.testEnded(
-                    EasyMock.anyObject(), EasyMock.<HashMap<String, Metric>>anyObject());
-        }
         String identsTrace =
                 String.join(
                         "\n",
                         "thread 'idents' panicked at 'assertion failed: `(left == right)`",
                         "  left: `\"_\"`,",
                         " right: `\"_abc\"`', external/rust/crates/proc-macro2/tests/test.rs:13:5");
-        mMockListener.testFailed(
-                EasyMock.eq(new TestDescription("test", "idents")), EasyMock.eq(identsTrace));
+
         String literalStringTrace =
                 String.join(
                         "\n",
                         "thread 'literal_string' panicked at 'assertion failed: `(left == right)`",
                         "  left: `\"\\\"didn\\'t\\\"\"`,",
                         " right: `\"fake\"`', external/rust/crates/proc-macro2/tests/test.rs:86:5");
-        mMockListener.testFailed(
-                EasyMock.eq(new TestDescription("test", "literal_string")),
-                EasyMock.eq(literalStringTrace));
-        replay(mMockListener);
+
         mParser.processNewLines(contents);
         mParser.done();
-        verify(mMockListener);
+
+        verify(mMockListener, times(23)).testStarted(Mockito.any());
+        verify(mMockListener, times(23))
+                .testEnded(Mockito.any(), Mockito.<HashMap<String, Metric>>any());
+        verify(mMockListener)
+                .testFailed(
+                        Mockito.eq(new TestDescription("test", "idents")), Mockito.eq(identsTrace));
+        verify(mMockListener)
+                .testFailed(
+                        Mockito.eq(new TestDescription("test", "literal_string")),
+                        Mockito.eq(literalStringTrace));
     }
 
     @Test
     public void testParseRealOutput3() {
         String[] contents = readInFile(RUST_OUTPUT_FILE_3);
-        for (int i = 0; i < 1; i++) {
-            mMockListener.testStarted(EasyMock.anyObject());
-            mMockListener.testEnded(
-                    EasyMock.anyObject(), EasyMock.<HashMap<String, Metric>>anyObject());
-        }
-        mMockListener.testIgnored(
-                EasyMock.eq(new TestDescription("test", "make_sure_no_proc_macro")));
-        replay(mMockListener);
+
         mParser.processNewLines(contents);
         mParser.done();
-        verify(mMockListener);
+
+        verify(mMockListener).testStarted(Mockito.any());
+        verify(mMockListener).testEnded(Mockito.any(), Mockito.<HashMap<String, Metric>>any());
+        verify(mMockListener)
+                .testIgnored(Mockito.eq(new TestDescription("test", "make_sure_no_proc_macro")));
     }
 
     /**
@@ -217,47 +213,45 @@
     @Test
     public void testParsePartialOutput() {
         String[] contents = readInFile(RUST_OUTPUT_FILE_1);
-        for (int i = 0; i < 10; i++) {
-            mMockListener.testStarted(EasyMock.anyObject());
-            mMockListener.testEnded(
-                    EasyMock.anyObject(), EasyMock.<HashMap<String, Metric>>anyObject());
-        }
-        replay(mMockListener);
+
         mParser.processNewLines(Arrays.copyOfRange(contents, 0, 4));
         mParser.processNewLines(Arrays.copyOfRange(contents, 4, 7));
         mParser.processNewLines(Arrays.copyOfRange(contents, 4, contents.length));
         mParser.done();
-        verify(mMockListener);
+
+        verify(mMockListener, times(10)).testStarted(Mockito.any());
+        verify(mMockListener, times(10))
+                .testEnded(Mockito.any(), Mockito.<HashMap<String, Metric>>any());
     }
 
     @Test
     public void testParseLinkError() {
         String[] contents = readInFile(RUST_OUTPUT_FILE_4);
-        mMockListener.testRunFailed(
-                EasyMock.eq(
-                        "test did not report any run:\n"
-                            + "CANNOT LINK EXECUTABLE"
-                            + " \"/data/local/tmp/keystore2_test/x86_64/keystore2_test\": library"
-                            + " \"libkeystore2_crypto.so\" not found: needed by main executable"));
-        replay(mMockListener);
+
         mParser.processNewLines(contents);
         mParser.done();
-        verify(mMockListener);
+
+        verify(mMockListener)
+                .testRunFailed(
+                        Mockito.eq(
+                                "test did not report any run:\n"
+                                    + "CANNOT LINK EXECUTABLE"
+                                    + " \"/data/local/tmp/keystore2_test/x86_64/keystore2_test\":"
+                                    + " library \"libkeystore2_crypto.so\" not found: needed by"
+                                    + " main executable"));
     }
 
     @Test
     public void testParseTimeout() {
         String[] contents = readInFile(RUST_OUTPUT_FILE_5);
-        for (int i = 0; i < 9; i++) {
-            mMockListener.testStarted(EasyMock.anyObject());
-            mMockListener.testEnded(
-                    EasyMock.anyObject(), EasyMock.<HashMap<String, Metric>>anyObject());
-        }
-        mMockListener.testRunFailed(
-                EasyMock.eq("Test run incomplete. Started 10 tests, finished 9"));
-        replay(mMockListener);
+
         mParser.processNewLines(contents);
         mParser.done();
-        verify(mMockListener);
+
+        verify(mMockListener, times(9)).testStarted(Mockito.any());
+        verify(mMockListener, times(9))
+                .testEnded(Mockito.any(), Mockito.<HashMap<String, Metric>>any());
+        verify(mMockListener)
+                .testRunFailed(Mockito.eq("Test run incomplete. Started 10 tests, finished 9"));
     }
 }
diff --git a/javatests/com/android/tradefed/testtype/suite/BaseTestSuiteTest.java b/javatests/com/android/tradefed/testtype/suite/BaseTestSuiteTest.java
index ec437c7..ee14ac1 100644
--- a/javatests/com/android/tradefed/testtype/suite/BaseTestSuiteTest.java
+++ b/javatests/com/android/tradefed/testtype/suite/BaseTestSuiteTest.java
@@ -331,9 +331,11 @@
             fail("Should have thrown exception");
         } catch (HarnessRuntimeException ex) {
             assertEquals(
-                    "Include filter '{arm64-v8a Doesntexist=[Doesntexist], armeabi-v7a "
-                            + "Doesntexist=[Doesntexist]}' was specified but resulted in "
-                            + "an empty test set.",
+                    "Include filter '{arm64-v8a Doesntexist=[Doesntexist], "
+                            + "armeabi-v7a Doesntexist=[Doesntexist], arm64-v8a suite/stub1=[], "
+                            + "armeabi-v7a suite/stub1=[], arm64-v8a suite/stub2=[], "
+                            + "armeabi-v7a suite/stub2=[]}' was specified but "
+                            + "resulted in an empty test set.",
                     ex.getMessage());
         }
     }
diff --git a/javatests/com/android/tradefed/testtype/suite/RemoteTestTimeOutEnforcerTest.java b/javatests/com/android/tradefed/testtype/suite/RemoteTestTimeOutEnforcerTest.java
index 8ca098b..46e929e 100644
--- a/javatests/com/android/tradefed/testtype/suite/RemoteTestTimeOutEnforcerTest.java
+++ b/javatests/com/android/tradefed/testtype/suite/RemoteTestTimeOutEnforcerTest.java
@@ -19,23 +19,24 @@
 import static junit.framework.TestCase.assertNull;
 import static junit.framework.TestCase.assertTrue;
 
+import static org.mockito.Mockito.mock;
+
 import com.android.tradefed.config.ConfigurationDescriptor;
 import com.android.tradefed.invoker.InvocationContext;
 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
 import com.android.tradefed.result.ITestInvocationListener;
-
 import com.android.tradefed.testtype.IRemoteTest;
 import com.android.tradefed.testtype.StubTest;
-import java.time.Duration;
-import org.easymock.EasyMock;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
-
-import java.util.HashMap;
 import org.mockito.Mockito;
 
+import java.time.Duration;
+import java.util.HashMap;
+
 /** Unit tests for {@link RemoteTestTimeOutEnforcer}. */
 @RunWith(JUnit4.class)
 public class RemoteTestTimeOutEnforcerTest {
@@ -52,7 +53,7 @@
 
     @Before
     public void setUp() {
-        mListener = new ModuleListener(EasyMock.createMock(ITestInvocationListener.class));
+        mListener = new ModuleListener(mock(ITestInvocationListener.class));
         mIRemoteTest = new StubTest();
         mConfigurationDescriptor = new ConfigurationDescriptor();
         mModuleDefinition = Mockito.mock(ModuleDefinition.class);
@@ -61,24 +62,25 @@
                 Integer.toString(mIRemoteTest.hashCode()), mTestMappingPath);
         mModuleInvocationContext.setConfigurationDescriptor(mConfigurationDescriptor);
         Mockito.when(mModuleDefinition.getId()).thenReturn(mModuleName);
-        Mockito.when(mModuleDefinition.getModuleInvocationContext()).thenReturn(
-                mModuleInvocationContext);
-        mEnforcer = new RemoteTestTimeOutEnforcer(
-                mListener, mModuleDefinition, mIRemoteTest, mTimeout);
+        Mockito.when(mModuleDefinition.getModuleInvocationContext())
+                .thenReturn(mModuleInvocationContext);
+        mEnforcer =
+                new RemoteTestTimeOutEnforcer(mListener, mModuleDefinition, mIRemoteTest, mTimeout);
     }
 
     @Test
     public void testTimeout() {
         mEnforcer.testRunEnded(200000L, new HashMap<String, Metric>());
         assertTrue(
-                mListener.getCurrentRunResults().getRunFailureDescription().getErrorMessage()
-                        .contains(String.format(
-                                "%s defined in [%s] took 200 seconds while timeout is %s seconds",
-                                mModuleName,
-                                mTestMappingPath,
-                                mTimeout.getSeconds())
-                        )
-        );
+                mListener
+                        .getCurrentRunResults()
+                        .getRunFailureDescription()
+                        .getErrorMessage()
+                        .contains(
+                                String.format(
+                                        "%s defined in [%s] took 200 seconds while timeout is %s"
+                                                + " seconds",
+                                        mModuleName, mTestMappingPath, mTimeout.getSeconds())));
         assertFalse(mListener.getCurrentRunResults().getRunFailureDescription().isRetriable());
     }
 
diff --git a/javatests/com/android/tradefed/testtype/suite/module/ArchModuleControllerTest.java b/javatests/com/android/tradefed/testtype/suite/module/ArchModuleControllerTest.java
index 816259b..1b13d00 100644
--- a/javatests/com/android/tradefed/testtype/suite/module/ArchModuleControllerTest.java
+++ b/javatests/com/android/tradefed/testtype/suite/module/ArchModuleControllerTest.java
@@ -17,7 +17,6 @@
 
 import static org.junit.Assert.assertEquals;
 
-import com.android.ddmlib.IDevice;
 import com.android.tradefed.config.ConfigurationDef;
 import com.android.tradefed.config.ConfigurationException;
 import com.android.tradefed.config.OptionSetter;
@@ -27,35 +26,35 @@
 import com.android.tradefed.invoker.InvocationContext;
 import com.android.tradefed.testtype.suite.ModuleDefinition;
 import com.android.tradefed.testtype.suite.module.IModuleController.RunStrategy;
-import org.easymock.EasyMock;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 /** Unit tests for {@link ArchModuleController}. */
 @RunWith(JUnit4.class)
 public class ArchModuleControllerTest {
     private ArchModuleController mController;
     private IInvocationContext mContext;
-    private ITestDevice mMockDevice;
-    private IDevice mMockIDevice;
+    @Mock ITestDevice mMockDevice;
 
     @Before
     public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
         mController = new ArchModuleController();
-        mMockDevice = EasyMock.createMock(ITestDevice.class);
         mContext = new InvocationContext();
         mContext.addInvocationAttribute(ModuleDefinition.MODULE_NAME, "module1");
         mContext.addAllocatedDevice(ConfigurationDef.DEFAULT_DEVICE_NAME, mMockDevice);
-        mMockIDevice = EasyMock.createMock(IDevice.class);
     }
 
     @Test
     public void testMatchesArch() throws DeviceNotAvailableException, ConfigurationException {
         mContext.addInvocationAttribute(ModuleDefinition.MODULE_ABI, "arm64-v8a");
-        EasyMock.expect(mMockDevice.getIDevice()).andReturn(mMockIDevice).times(2);
-        EasyMock.replay(mMockDevice);
+
         OptionSetter setter = new OptionSetter(mController);
         setter.setOptionValue("arch", "arm64");
         setter.setOptionValue("arch", "x86_64");
@@ -65,8 +64,7 @@
     @Test
     public void testMismatchesArch() throws DeviceNotAvailableException, ConfigurationException {
         mContext.addInvocationAttribute(ModuleDefinition.MODULE_ABI, "arm64-v8a");
-        EasyMock.expect(mMockDevice.getIDevice()).andReturn(mMockIDevice).times(2);
-        EasyMock.replay(mMockDevice);
+
         OptionSetter setter = new OptionSetter(mController);
         setter.setOptionValue("arch", "arm");
         setter.setOptionValue("arch", "x86");
diff --git a/javatests/com/android/tradefed/testtype/suite/module/MainlineTestModuleControllerTest.java b/javatests/com/android/tradefed/testtype/suite/module/MainlineTestModuleControllerTest.java
index 039d60f..e9dc97d 100644
--- a/javatests/com/android/tradefed/testtype/suite/module/MainlineTestModuleControllerTest.java
+++ b/javatests/com/android/tradefed/testtype/suite/module/MainlineTestModuleControllerTest.java
@@ -16,6 +16,7 @@
 package com.android.tradefed.testtype.suite.module;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
 
 import com.android.ddmlib.IDevice;
 import com.android.tradefed.config.ConfigurationDef;
@@ -29,33 +30,35 @@
 import com.android.tradefed.testtype.suite.ModuleDefinition;
 import com.android.tradefed.testtype.suite.module.IModuleController.RunStrategy;
 
-import java.util.HashSet;
-import java.util.Set;
-import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.HashSet;
+import java.util.Set;
 
 /** Unit tests for {@link MainlineTestModuleController}. */
 @RunWith(JUnit4.class)
 public class MainlineTestModuleControllerTest {
     private MainlineTestModuleController mController;
     private IInvocationContext mContext;
-    private ITestDevice mMockDevice;
-    private IDevice mMockIDevice;
+    @Mock ITestDevice mMockDevice;
+    @Mock IDevice mMockIDevice;
     private ApexInfo mFakeApexInfo;
     private Set<ApexInfo> mFakeApexes;
 
     @Before
     public void setUp() throws ConfigurationException {
+        MockitoAnnotations.initMocks(this);
+
         mController = new MainlineTestModuleController();
-        mMockDevice = EasyMock.createMock(ITestDevice.class);
         mContext = new InvocationContext();
         mContext.addAllocatedDevice(ConfigurationDef.DEFAULT_DEVICE_NAME, mMockDevice);
         mContext.addInvocationAttribute(ModuleDefinition.MODULE_ABI, "arm64-v8a");
         mContext.addInvocationAttribute(ModuleDefinition.MODULE_NAME, "module1");
-        mMockIDevice = EasyMock.createMock(IDevice.class);
         mFakeApexes = new HashSet<ITestDevice.ApexInfo>();
     }
 
@@ -67,11 +70,10 @@
         setter.setOptionValue("mainline-module-package-name", "com.google.android.fakeapex");
         mFakeApexInfo = new ApexInfo("com.google.android.fakeapex", 1, "fakeDir");
         mFakeApexes.add(mFakeApexInfo);
-        EasyMock.expect(mMockDevice.getIDevice()).andReturn(mMockIDevice);
-        EasyMock.expect(mMockDevice.getActiveApexes()).andReturn(mFakeApexes);
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getIDevice()).thenReturn(mMockIDevice);
+        when(mMockDevice.getActiveApexes()).thenReturn(mFakeApexes);
+
         assertEquals(RunStrategy.RUN, mController.shouldRunModule(mContext));
-        EasyMock.verify(mMockDevice);
     }
 
     /** Test mainline module is not installed and test should not run. */
@@ -83,11 +85,10 @@
         setter.setOptionValue("mainline-module-package-name", "com.google.android.fakeapex");
         ApexInfo fakeApexInfo = new ApexInfo("com.google.android.fake1apex", 1, "fakeDir");
         mFakeApexes.add(fakeApexInfo);
-        EasyMock.expect(mMockDevice.getIDevice()).andReturn(mMockIDevice);
-        EasyMock.expect(mMockDevice.getActiveApexes()).andReturn(mFakeApexes);
-        EasyMock.replay(mMockDevice);
+        when(mMockDevice.getIDevice()).thenReturn(mMockIDevice);
+        when(mMockDevice.getActiveApexes()).thenReturn(mFakeApexes);
+
         assertEquals(RunStrategy.FULL_MODULE_BYPASS, mController.shouldRunModule(mContext));
-        EasyMock.verify(mMockDevice);
     }
 
     /** Test {@link MainlineTestModuleController} is disabled and test should run anyway. */
@@ -96,9 +97,8 @@
             throws DeviceNotAvailableException, ConfigurationException {
         OptionSetter setter = new OptionSetter(mController);
         setter.setOptionValue("enable", "false");
-        EasyMock.replay(mMockDevice);
+
         assertEquals(RunStrategy.RUN, mController.shouldRunModule(mContext));
-        EasyMock.verify(mMockDevice);
     }
 
     /** Test {@link MainlineTestModuleController} is enabled but no mainline module specified. */
@@ -107,8 +107,7 @@
             throws DeviceNotAvailableException, ConfigurationException {
         OptionSetter setter = new OptionSetter(mController);
         setter.setOptionValue("enable", "true");
-        EasyMock.replay(mMockDevice);
+
         assertEquals(RunStrategy.RUN, mController.shouldRunModule(mContext));
-        EasyMock.verify(mMockDevice);
     }
 }
diff --git a/javatests/com/android/tradefed/testtype/suite/params/ModuleParametersHelperTest.java b/javatests/com/android/tradefed/testtype/suite/params/ModuleParametersHelperTest.java
index 664fe03..0ef4671 100644
--- a/javatests/com/android/tradefed/testtype/suite/params/ModuleParametersHelperTest.java
+++ b/javatests/com/android/tradefed/testtype/suite/params/ModuleParametersHelperTest.java
@@ -15,13 +15,16 @@
  */
 package com.android.tradefed.testtype.suite.params;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
-import java.util.Set;
+import java.util.Map;
 
 /** Unit tests for {@link ModuleParametersHelper}. */
 @RunWith(JUnit4.class)
@@ -38,60 +41,60 @@
                 continue;
             }
 
-            IModuleParameter handler =
-                    ModuleParametersHelper.getParameterHandler(param, /* withOptional= */ true);
+            Map<ModuleParameters, IModuleParameterHandler> handler =
+                    ModuleParametersHelper.resolveParam(param, /* withOptional= */ true);
             assertNotNull(handler);
         }
     }
 
     private boolean isGroupParameter(ModuleParameters param) {
-        Set<ModuleParameters> resolvedParams =
+        Map<ModuleParameters, IModuleParameterHandler> resolvedParams =
                 ModuleParametersHelper.resolveParam(param, /* withOptional= */ true);
 
         if (resolvedParams.size() != 1) {
             return true;
         }
 
-        return resolvedParams.iterator().next() != param;
+        return resolvedParams.keySet().iterator().next() != param;
     }
 
     @Test
     public void resolveParam_notGroupParam_returnsSetOfSameParam() {
-        Set<ModuleParameters> resolvedParams =
+        Map<ModuleParameters, IModuleParameterHandler> resolvedParams =
                 ModuleParametersHelper.resolveParam(
                         ModuleParameters.INSTANT_APP, /* withOptional= */ true);
 
         assertEquals(resolvedParams.size(), 1);
-        assertEquals(resolvedParams.iterator().next(), ModuleParameters.INSTANT_APP);
+        assertEquals(resolvedParams.keySet().iterator().next(), ModuleParameters.INSTANT_APP);
     }
 
     @Test
     public void resolveParam_groupParam_returnsSetOfMultipleParams() {
-        Set<ModuleParameters> resolvedParams =
+        Map<ModuleParameters, IModuleParameterHandler> resolvedParams =
                 ModuleParametersHelper.resolveParam(
                         ModuleParameters.MULTIUSER, /* withOptional= */ true);
 
         assertNotEquals(resolvedParams.size(), 1);
-        assertFalse(resolvedParams.contains(ModuleParameters.MULTIUSER));
+        assertFalse(resolvedParams.keySet().contains(ModuleParameters.MULTIUSER));
     }
 
     @Test
     public void resolveParamString_notGroupParam_returnsSetOfSameParam() {
-        Set<ModuleParameters> resolvedParams =
+        Map<ModuleParameters, IModuleParameterHandler> resolvedParams =
                 ModuleParametersHelper.resolveParam(
                         ModuleParameters.INSTANT_APP.toString(), /* withOptional= */ true);
 
         assertEquals(resolvedParams.size(), 1);
-        assertEquals(resolvedParams.iterator().next(), ModuleParameters.INSTANT_APP);
+        assertEquals(resolvedParams.keySet().iterator().next(), ModuleParameters.INSTANT_APP);
     }
 
     @Test
     public void resolveParamString_groupParam_returnsSetOfMultipleParams() {
-        Set<ModuleParameters> resolvedParams =
+        Map<ModuleParameters, IModuleParameterHandler> resolvedParams =
                 ModuleParametersHelper.resolveParam(
                         ModuleParameters.MULTIUSER.toString(), /* withOptional= */ true);
 
         assertNotEquals(resolvedParams.size(), 1);
-        assertFalse(resolvedParams.contains(ModuleParameters.MULTIUSER));
+        assertFalse(resolvedParams.keySet().contains(ModuleParameters.MULTIUSER));
     }
 }
diff --git a/javatests/com/android/tradefed/testtype/suite/retry/ResultsPlayerTest.java b/javatests/com/android/tradefed/testtype/suite/retry/ResultsPlayerTest.java
index eda01e0..656cf75 100644
--- a/javatests/com/android/tradefed/testtype/suite/retry/ResultsPlayerTest.java
+++ b/javatests/com/android/tradefed/testtype/suite/retry/ResultsPlayerTest.java
@@ -15,6 +15,10 @@
  */
 package com.android.tradefed.testtype.suite.retry;
 
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import com.android.ddmlib.IDevice;
 import com.android.ddmlib.Log.LogLevel;
 import com.android.ddmlib.testrunner.TestResult.TestStatus;
@@ -32,11 +36,14 @@
 import com.android.tradefed.result.TestResult;
 import com.android.tradefed.result.TestRunResult;
 
-import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 
 import java.util.AbstractMap.SimpleEntry;
 import java.util.HashMap;
@@ -46,24 +53,22 @@
 @RunWith(JUnit4.class)
 public class ResultsPlayerTest {
     private ResultsPlayer mPlayer;
-    private ITestInvocationListener mMockListener;
+    @Mock ITestInvocationListener mMockListener;
     private IInvocationContext mContext;
     private TestInformation mTestInfo;
-    private ITestDevice mMockDevice;
-    private IDevice mMockIDevice;
-    private IConfiguration mMockConfig;
-    private ILeveledLogOutput mMockLogOutput;
+    @Mock ITestDevice mMockDevice;
+    @Mock IDevice mMockIDevice;
+    @Mock IConfiguration mMockConfig;
+    @Mock ILeveledLogOutput mMockLogOutput;
 
     @Before
     public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
         mContext = new InvocationContext();
-        mMockListener = EasyMock.createStrictMock(ITestInvocationListener.class);
-        mMockDevice = EasyMock.createMock(ITestDevice.class);
-        mMockIDevice = EasyMock.createMock(IDevice.class);
-        mMockConfig = EasyMock.createMock(IConfiguration.class);
-        mMockLogOutput = EasyMock.createMock(ILeveledLogOutput.class);
-        EasyMock.expect(mMockConfig.getLogOutput()).andStubReturn(mMockLogOutput);
-        EasyMock.expect(mMockLogOutput.getLogLevel()).andReturn(LogLevel.VERBOSE);
+
+        when(mMockConfig.getLogOutput()).thenReturn(mMockLogOutput);
+        when(mMockLogOutput.getLogLevel()).thenReturn(LogLevel.VERBOSE);
         mMockLogOutput.setLogLevel(LogLevel.WARN);
         mMockLogOutput.setLogLevel(LogLevel.VERBOSE);
         mTestInfo = TestInformation.newBuilder().setInvocationContext(mContext).build();
@@ -72,9 +77,7 @@
         mPlayer.setConfiguration(mMockConfig);
         mContext.addAllocatedDevice(ConfigurationDef.DEFAULT_DEVICE_NAME, mMockDevice);
 
-        EasyMock.expect(mMockDevice.getIDevice()).andReturn(mMockIDevice);
-        mMockDevice.waitForDeviceAvailable();
-        EasyMock.expectLastCall();
+        when(mMockDevice.getIDevice()).thenReturn(mMockIDevice);
     }
 
     /** Test that the replay of a full test run is properly working. */
@@ -82,24 +85,44 @@
     public void testReplay() throws DeviceNotAvailableException {
         mPlayer.addToReplay(null, createTestRunResult("run1", 2, 1), null);
 
-        // Verify Mock
-        mMockListener.testRunStarted("run1", 2);
         TestDescription test = new TestDescription("test.class", "method0");
-        mMockListener.testStarted(EasyMock.eq(test), EasyMock.anyLong());
-        mMockListener.testEnded(
-                EasyMock.eq(test), EasyMock.anyLong(), EasyMock.eq(new HashMap<String, Metric>()));
         TestDescription testFail = new TestDescription("test.class", "fail0");
-        mMockListener.testStarted(EasyMock.eq(testFail), EasyMock.anyLong());
-        mMockListener.testFailed(testFail, "fail0");
-        mMockListener.testEnded(
-                EasyMock.eq(testFail),
-                EasyMock.anyLong(),
-                EasyMock.eq(new HashMap<String, Metric>()));
-        mMockListener.testRunEnded(500L, new HashMap<String, Metric>());
 
-        EasyMock.replay(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
         mPlayer.run(mTestInfo, mMockListener);
-        EasyMock.verify(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
+
+        InOrder inOrder = Mockito.inOrder(mMockListener);
+        inOrder.verify(mMockListener).testRunStarted("run1", 2);
+        inOrder.verify(mMockListener).testStarted(Mockito.eq(test), Mockito.anyLong());
+        inOrder.verify(mMockListener)
+                .testEnded(
+                        Mockito.eq(test),
+                        Mockito.anyLong(),
+                        Mockito.eq(new HashMap<String, Metric>()));
+        inOrder.verify(mMockListener).testStarted(Mockito.eq(testFail), Mockito.anyLong());
+        inOrder.verify(mMockListener).testFailed(testFail, "fail0");
+        inOrder.verify(mMockListener)
+                .testEnded(
+                        Mockito.eq(testFail),
+                        Mockito.anyLong(),
+                        Mockito.eq(new HashMap<String, Metric>()));
+        inOrder.verify(mMockListener).testRunEnded(500L, new HashMap<String, Metric>());
+
+        verify(mMockDevice, times(1)).waitForDeviceAvailable();
+        verify(mMockListener).testRunStarted("run1", 2);
+        verify(mMockListener).testStarted(Mockito.eq(test), Mockito.anyLong());
+        verify(mMockListener)
+                .testEnded(
+                        Mockito.eq(test),
+                        Mockito.anyLong(),
+                        Mockito.eq(new HashMap<String, Metric>()));
+        verify(mMockListener).testStarted(Mockito.eq(testFail), Mockito.anyLong());
+        verify(mMockListener).testFailed(testFail, "fail0");
+        verify(mMockListener)
+                .testEnded(
+                        Mockito.eq(testFail),
+                        Mockito.anyLong(),
+                        Mockito.eq(new HashMap<String, Metric>()));
+        verify(mMockListener).testRunEnded(500L, new HashMap<String, Metric>());
     }
 
     /** Test that when replaying a module we properly replay all the results. */
@@ -110,42 +133,35 @@
         IInvocationContext module2 = new InvocationContext();
         mPlayer.addToReplay(module2, createTestRunResult("run2", 2, 1), null);
 
-        // Verify Mock
-        mMockListener.testModuleStarted(module1);
-        mMockListener.testRunStarted("run1", 2);
         TestDescription test = new TestDescription("test.class", "method0");
-        mMockListener.testStarted(EasyMock.eq(test), EasyMock.anyLong());
-        mMockListener.testEnded(
-                EasyMock.eq(test), EasyMock.anyLong(), EasyMock.eq(new HashMap<String, Metric>()));
         TestDescription testFail = new TestDescription("test.class", "fail0");
-        mMockListener.testStarted(EasyMock.eq(testFail), EasyMock.anyLong());
-        mMockListener.testFailed(testFail, "fail0");
-        mMockListener.testEnded(
-                EasyMock.eq(testFail),
-                EasyMock.anyLong(),
-                EasyMock.eq(new HashMap<String, Metric>()));
-        mMockListener.testRunEnded(500L, new HashMap<String, Metric>());
-        mMockListener.testModuleEnded();
-        // Second module
-        mMockListener.testModuleStarted(module2);
-        mMockListener.testRunStarted("run2", 2);
-        test = new TestDescription("test.class", "method0");
-        mMockListener.testStarted(EasyMock.eq(test), EasyMock.anyLong());
-        mMockListener.testEnded(
-                EasyMock.eq(test), EasyMock.anyLong(), EasyMock.eq(new HashMap<String, Metric>()));
-        testFail = new TestDescription("test.class", "fail0");
-        mMockListener.testStarted(EasyMock.eq(testFail), EasyMock.anyLong());
-        mMockListener.testFailed(testFail, "fail0");
-        mMockListener.testEnded(
-                EasyMock.eq(testFail),
-                EasyMock.anyLong(),
-                EasyMock.eq(new HashMap<String, Metric>()));
-        mMockListener.testRunEnded(500L, new HashMap<String, Metric>());
-        mMockListener.testModuleEnded();
 
-        EasyMock.replay(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
+        test = new TestDescription("test.class", "method0");
+        testFail = new TestDescription("test.class", "fail0");
+
         mPlayer.run(mTestInfo, mMockListener);
-        EasyMock.verify(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
+
+        verify(mMockDevice, times(1)).waitForDeviceAvailable();
+        verify(mMockListener).testModuleStarted(module1);
+        verify(mMockListener).testRunStarted("run1", 2);
+        verify(mMockListener, times(2)).testStarted(Mockito.eq(test), Mockito.anyLong());
+        verify(mMockListener, times(2))
+                .testEnded(
+                        Mockito.eq(test),
+                        Mockito.anyLong(),
+                        Mockito.eq(new HashMap<String, Metric>()));
+        verify(mMockListener, times(2)).testStarted(Mockito.eq(testFail), Mockito.anyLong());
+        verify(mMockListener, times(2)).testFailed(testFail, "fail0");
+        verify(mMockListener, times(2))
+                .testEnded(
+                        Mockito.eq(testFail),
+                        Mockito.anyLong(),
+                        Mockito.eq(new HashMap<String, Metric>()));
+        verify(mMockListener, times(2)).testRunEnded(500L, new HashMap<String, Metric>());
+        verify(mMockListener, times(2)).testModuleEnded();
+        // Second module
+        verify(mMockListener).testModuleStarted(module2);
+        verify(mMockListener).testRunStarted("run2", 2);
     }
 
     /** Test that the replay of a single requested test case is working. */
@@ -161,18 +177,19 @@
         Entry<TestDescription, TestResult> entry = new SimpleEntry<>(test, result);
         mPlayer.addToReplay(null, createTestRunResult("run1", 2, 1), entry);
 
-        // Verify Mock
-        mMockListener.testRunStarted("run1", 1);
-        // Only the provided test is re-run
-        mMockListener.testStarted(EasyMock.eq(test), EasyMock.anyLong());
-        mMockListener.testAssumptionFailure(test, "assertionfailure");
-        mMockListener.testEnded(
-                EasyMock.eq(test), EasyMock.anyLong(), EasyMock.eq(new HashMap<String, Metric>()));
-        mMockListener.testRunEnded(500L, new HashMap<String, Metric>());
-
-        EasyMock.replay(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
         mPlayer.run(mTestInfo, mMockListener);
-        EasyMock.verify(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
+
+        verify(mMockDevice, times(1)).waitForDeviceAvailable();
+        verify(mMockListener).testRunStarted("run1", 1);
+        // Only the provided test is re-run
+        verify(mMockListener).testStarted(Mockito.eq(test), Mockito.anyLong());
+        verify(mMockListener).testAssumptionFailure(test, "assertionfailure");
+        verify(mMockListener)
+                .testEnded(
+                        Mockito.eq(test),
+                        Mockito.anyLong(),
+                        Mockito.eq(new HashMap<String, Metric>()));
+        verify(mMockListener).testRunEnded(500L, new HashMap<String, Metric>());
     }
 
     /** Test requesting several tests to re-run. */
@@ -198,24 +215,26 @@
         Entry<TestDescription, TestResult> entry2 = new SimpleEntry<>(test2, result2);
         mPlayer.addToReplay(null, runResult, entry2);
 
-        // Verify Mock
-        mMockListener.testRunStarted("run1", 2);
-        // Only the provided test is re-run
-        mMockListener.testStarted(EasyMock.eq(test), EasyMock.anyLong());
-        mMockListener.testAssumptionFailure(test, "assertionfailure");
-        mMockListener.testEnded(
-                EasyMock.eq(test), EasyMock.anyLong(), EasyMock.eq(new HashMap<String, Metric>()));
-
-        mMockListener.testStarted(EasyMock.eq(test2), EasyMock.anyLong());
-        mMockListener.testFailed(test2, "fail0");
-        mMockListener.testEnded(
-                EasyMock.eq(test2), EasyMock.anyLong(), EasyMock.eq(new HashMap<String, Metric>()));
-
-        mMockListener.testRunEnded(500L, new HashMap<String, Metric>());
-
-        EasyMock.replay(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
         mPlayer.run(mTestInfo, mMockListener);
-        EasyMock.verify(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
+
+        verify(mMockDevice, times(1)).waitForDeviceAvailable();
+        verify(mMockListener).testRunStarted("run1", 2);
+        // Only the provided test is re-run
+        verify(mMockListener).testStarted(Mockito.eq(test), Mockito.anyLong());
+        verify(mMockListener).testAssumptionFailure(test, "assertionfailure");
+        verify(mMockListener)
+                .testEnded(
+                        Mockito.eq(test),
+                        Mockito.anyLong(),
+                        Mockito.eq(new HashMap<String, Metric>()));
+        verify(mMockListener).testStarted(Mockito.eq(test2), Mockito.anyLong());
+        verify(mMockListener).testFailed(test2, "fail0");
+        verify(mMockListener)
+                .testEnded(
+                        Mockito.eq(test2),
+                        Mockito.anyLong(),
+                        Mockito.eq(new HashMap<String, Metric>()));
+        verify(mMockListener).testRunEnded(500L, new HashMap<String, Metric>());
     }
 
     private TestRunResult createTestRunResult(String runName, int testCount, int failCount) {
diff --git a/javatests/com/android/tradefed/util/FuseUtilTest.java b/javatests/com/android/tradefed/util/FuseUtilTest.java
index b16fddf..aa3aa33 100644
--- a/javatests/com/android/tradefed/util/FuseUtilTest.java
+++ b/javatests/com/android/tradefed/util/FuseUtilTest.java
@@ -47,42 +47,34 @@
     @Test
     public void testCanMountZip() {
         mFuseUtil.resetCanMountZip();
-        Mockito.when(
-                        mRunUtil.runTimedCmd(
-                                Mockito.anyLong(), Mockito.anyString(), Mockito.anyString()))
+        Mockito.when(mRunUtil.runTimedCmd(Mockito.anyLong(), Mockito.<String>any()))
                 .thenReturn(new CommandResult(CommandStatus.SUCCESS))
                 .thenReturn(new CommandResult(CommandStatus.SUCCESS));
 
         Assert.assertTrue(mFuseUtil.canMountZip());
 
-        Mockito.verify(mRunUtil).runTimedCmd(FuseUtil.FUSE_ZIP_TIMEOUT_MILLIS, "test", "/dev/fuse");
+        Mockito.verify(mRunUtil)
+                .runTimedCmd(FuseUtil.FUSE_ZIP_TIMEOUT_MILLIS, "test", "-c", "/dev/fuse");
         Mockito.verify(mRunUtil).runTimedCmd(FuseUtil.FUSE_ZIP_TIMEOUT_MILLIS, "fuse-zip", "-h");
     }
 
     @Test
     public void testCanMountZip_unsupported() {
         mFuseUtil.resetCanMountZip();
-        Mockito.when(
-                        mRunUtil.runTimedCmd(
-                                Mockito.anyLong(), Mockito.anyString(), Mockito.anyString()))
+        Mockito.when(mRunUtil.runTimedCmd(Mockito.anyLong(), Mockito.<String>any()))
                 .thenReturn(new CommandResult(CommandStatus.SUCCESS))
                 .thenReturn(new CommandResult(CommandStatus.FAILED));
 
         Assert.assertFalse(mFuseUtil.canMountZip());
 
-        Mockito.verify(mRunUtil).runTimedCmd(FuseUtil.FUSE_ZIP_TIMEOUT_MILLIS, "test", "/dev/fuse");
+        Mockito.verify(mRunUtil)
+                .runTimedCmd(FuseUtil.FUSE_ZIP_TIMEOUT_MILLIS, "test", "-c", "/dev/fuse");
         Mockito.verify(mRunUtil).runTimedCmd(FuseUtil.FUSE_ZIP_TIMEOUT_MILLIS, "fuse-zip", "-h");
     }
 
     @Test
     public void testMountZip() {
-        Mockito.when(
-                        mRunUtil.runTimedCmd(
-                                Mockito.anyLong(),
-                                Mockito.anyString(),
-                                Mockito.anyString(),
-                                Mockito.anyString(),
-                                Mockito.anyString()))
+        Mockito.when(mRunUtil.runTimedCmd(Mockito.anyLong(), Mockito.<String>any()))
                 .thenReturn(new CommandResult(CommandStatus.SUCCESS));
         File zipFile = new File("/path/to/zip");
         File mountDir = new File("/path/to/mount");
@@ -100,12 +92,7 @@
 
     @Test
     public void testUnmountZip() {
-        Mockito.when(
-                        mRunUtil.runTimedCmd(
-                                Mockito.anyLong(),
-                                Mockito.anyString(),
-                                Mockito.anyString(),
-                                Mockito.anyString()))
+        Mockito.when(mRunUtil.runTimedCmd(Mockito.anyLong(), Mockito.<String>any()))
                 .thenReturn(new CommandResult(CommandStatus.SUCCESS));
         File mountDir = new File("/path/to/mount");
 
diff --git a/javatests/com/android/tradefed/util/NativeCodeCoverageFlusherTest.java b/javatests/com/android/tradefed/util/NativeCodeCoverageFlusherTest.java
index 6c2ff47..2c96887 100644
--- a/javatests/com/android/tradefed/util/NativeCodeCoverageFlusherTest.java
+++ b/javatests/com/android/tradefed/util/NativeCodeCoverageFlusherTest.java
@@ -62,7 +62,7 @@
         doReturn(true).when(mMockDevice).isAdbRoot();
 
         CommandResult result = new CommandResult(CommandStatus.SUCCESS);
-        result.setStdout("ffffffffffff\n");
+        result.setStdout("1000000000\n");
         result.setExitCode(0);
 
         when(mMockDevice.executeShellV2Command(anyString())).thenReturn(result);
@@ -97,7 +97,7 @@
         doReturn(true).when(mMockDevice).isAdbRoot();
 
         CommandResult result = new CommandResult(CommandStatus.SUCCESS);
-        result.setStdout("ffffffffffff\n");
+        result.setStdout("1000000000\n");
         result.setExitCode(0);
 
         when(mMockDevice.executeShellV2Command(anyString())).thenReturn(result);
@@ -117,7 +117,7 @@
         doReturn(true).when(mMockDevice).isAdbRoot();
 
         CommandResult result = new CommandResult(CommandStatus.SUCCESS);
-        result.setStdout("ffffffffffff\n");
+        result.setStdout("1000000000\n");
         result.setExitCode(0);
 
         when(mMockDevice.executeShellV2Command(anyString())).thenReturn(result);
@@ -190,11 +190,11 @@
         doReturn(true).when(mMockDevice).isAdbRoot();
 
         CommandResult resultNotHandled = new CommandResult(CommandStatus.SUCCESS);
-        resultNotHandled.setStdout("0000000000\n");
+        resultNotHandled.setStdout("8000000000000000\n");
         resultNotHandled.setExitCode(0);
 
         CommandResult resultHandled = new CommandResult(CommandStatus.SUCCESS);
-        resultHandled.setStdout("ffffffffffff\n");
+        resultHandled.setStdout("1000000000\n");
         resultHandled.setExitCode(0);
 
         CommandResult resultEmpty = new CommandResult(CommandStatus.SUCCESS);
diff --git a/src/com/android/tradefed/cluster/ClusterCommandScheduler.java b/src/com/android/tradefed/cluster/ClusterCommandScheduler.java
index 1800df6..fa3b6b6 100644
--- a/src/com/android/tradefed/cluster/ClusterCommandScheduler.java
+++ b/src/com/android/tradefed/cluster/ClusterCommandScheduler.java
@@ -34,6 +34,7 @@
 import com.android.tradefed.device.battery.IBatteryInfo;
 import com.android.tradefed.device.battery.IBatteryInfo.BatteryState;
 import com.android.tradefed.error.IHarnessException;
+import com.android.tradefed.host.IHostOptions.PermitLimitType;
 import com.android.tradefed.invoker.IInvocationContext;
 import com.android.tradefed.invoker.InvocationContext;
 import com.android.tradefed.invoker.logger.InvocationMetricLogger.InvocationMetricKey;
@@ -579,7 +580,8 @@
 
         boolean checkFlashingPermitsLease = options.checkFlashingPermitsOnLease();
         if (checkFlashingPermitsLease) {
-            availableFlashingPermits = getDeviceManager().getAvailableFlashingPermits();
+            availableFlashingPermits = getHostOptions()
+                    .getAvailablePermits(PermitLimitType.CONCURRENT_FLASHER);
             CLog.i("available flasher permits %d", availableFlashingPermits);
         }
         return availableFlashingPermits;
diff --git a/src/com/android/tradefed/command/CommandOptions.java b/src/com/android/tradefed/command/CommandOptions.java
index 66fbd00..6c01f3d 100644
--- a/src/com/android/tradefed/command/CommandOptions.java
+++ b/src/com/android/tradefed/command/CommandOptions.java
@@ -249,7 +249,7 @@
     @Option(
             name = "filter-previous-passed",
             description = "Feature flag to test filtering previously passed tests.")
-    private boolean mTestFilterPassed = false;
+    private boolean mTestFilterPassed = true;
 
     @Option(
             name = "report-invocation-complete-logs",
diff --git a/src/com/android/tradefed/command/CommandScheduler.java b/src/com/android/tradefed/command/CommandScheduler.java
index 18c0ca4..b12c554 100644
--- a/src/com/android/tradefed/command/CommandScheduler.java
+++ b/src/com/android/tradefed/command/CommandScheduler.java
@@ -58,6 +58,7 @@
 import com.android.tradefed.device.NoDeviceException;
 import com.android.tradefed.device.StubDevice;
 import com.android.tradefed.device.TestDeviceState;
+import com.android.tradefed.host.IHostOptions;
 import com.android.tradefed.invoker.IInvocationContext;
 import com.android.tradefed.invoker.IRescheduler;
 import com.android.tradefed.invoker.ITestInvocation;
@@ -1006,14 +1007,18 @@
         return GlobalConfiguration.getDeviceManagerInstance();
     }
 
-     /**
-      * Factory method for getting a reference to the {@link IHostMonitor}
-      *
-      * @return the {@link IHostMonitor} to use
-      */
-     List<IHostMonitor> getHostMonitor() {
-         return GlobalConfiguration.getHostMonitorInstances();
-     }
+    protected IHostOptions getHostOptions() {
+        return GlobalConfiguration.getInstance().getHostOptions();
+    }
+
+    /**
+     * Factory method for getting a reference to the {@link IHostMonitor}
+     *
+     * @return the {@link IHostMonitor} to use
+     */
+    List<IHostMonitor> getHostMonitor() {
+        return GlobalConfiguration.getHostMonitorInstances();
+    }
 
     /**
      * Factory method for getting a reference to the {@link IConfigurationFactory}
diff --git a/src/com/android/tradefed/command/Console.java b/src/com/android/tradefed/command/Console.java
index 96c43e8..fe5f35b 100644
--- a/src/com/android/tradefed/command/Console.java
+++ b/src/com/android/tradefed/command/Console.java
@@ -1224,6 +1224,8 @@
         console.setDaemon(true);
 
         GlobalConfiguration.getInstance().getCommandScheduler().setClearcutClient(client);
+        // Initialize the locks for the TF session
+        GlobalConfiguration.getInstance().getHostOptions().initConcurrentLocks();
 
         console.start();
 
diff --git a/src/com/android/tradefed/config/filter/OptionFetcher.java b/src/com/android/tradefed/config/filter/OptionFetcher.java
index 7ae95ec..fd91ae9 100644
--- a/src/com/android/tradefed/config/filter/OptionFetcher.java
+++ b/src/com/android/tradefed/config/filter/OptionFetcher.java
@@ -40,7 +40,6 @@
      * Set of options that should align with the parent process.
      */
     private static final Set<String> OPTION_TO_FETCH = ImmutableSet.of(
-            "filter-previous-passed",
             "retry-isolation-grade"
             );
 
diff --git a/src/com/android/tradefed/device/DeviceManager.java b/src/com/android/tradefed/device/DeviceManager.java
index 7196c1f..ea90332 100644
--- a/src/com/android/tradefed/device/DeviceManager.java
+++ b/src/com/android/tradefed/device/DeviceManager.java
@@ -66,7 +66,6 @@
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Pattern;
 
@@ -115,15 +114,6 @@
      */
     private static final String DEVICE_LIST_PATTERN = ".*\n(%s)\\s+(device|offline|recovery).*";
 
-    private Semaphore mConcurrentFlashLock = null;
-
-    /**
-     * This serves both as an indication of whether the flash lock should be used, and as an
-     * indicator of whether or not the flash lock has been initialized -- if this is true
-     * and {@code mConcurrentFlashLock} is {@code null}, then it has not yet been initialized.
-     */
-    private Boolean mShouldCheckFlashLock = true;
-
     protected DeviceMonitorMultiplexer mDvcMon = new DeviceMonitorMultiplexer();
     private Boolean mDvcMonRunning = false;
 
@@ -1591,86 +1581,6 @@
         return mFastbootFile.getAbsolutePath();
     }
 
-    /**
-     * Set the state of the concurrent flash limit implementation
-     *
-     * Exposed for unit testing
-     */
-    void setConcurrentFlashSettings(Semaphore flashLock, boolean shouldCheck) {
-        synchronized (mShouldCheckFlashLock) {
-            mConcurrentFlashLock = flashLock;
-            mShouldCheckFlashLock = shouldCheck;
-        }
-    }
-
-    Semaphore getConcurrentFlashLock() {
-        return mConcurrentFlashLock;
-    }
-
-    /** Initialize the concurrent flash lock semaphore **/
-    private void initConcurrentFlashLock() {
-        if (!mShouldCheckFlashLock) return;
-        // The logic below is to avoid multi-thread race conditions while initializing
-        // mConcurrentFlashLock when we hit this condition.
-        if (mConcurrentFlashLock == null) {
-            // null with mShouldCheckFlashLock == true means initialization hasn't been done yet
-            synchronized(mShouldCheckFlashLock) {
-                // Check all state again, since another thread might have gotten here first
-                if (!mShouldCheckFlashLock) return;
-
-                IHostOptions hostOptions = getHostOptions();
-                Integer concurrentFlashingLimit = hostOptions.getConcurrentFlasherLimit();
-
-                if (concurrentFlashingLimit == null) {
-                    mShouldCheckFlashLock = false;
-                    return;
-                }
-
-                if (mConcurrentFlashLock == null) {
-                    mConcurrentFlashLock = new Semaphore(concurrentFlashingLimit, true /* fair */);
-                }
-            }
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public int getAvailableFlashingPermits() {
-        initConcurrentFlashLock();
-        if (mConcurrentFlashLock != null) {
-            return mConcurrentFlashLock.availablePermits();
-        }
-        IHostOptions hostOptions = getHostOptions();
-        if (hostOptions.getConcurrentFlasherLimit() != null) {
-            return hostOptions.getConcurrentFlasherLimit();
-        }
-        return Integer.MAX_VALUE;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public void takeFlashingPermit() {
-        initConcurrentFlashLock();
-        if (!mShouldCheckFlashLock) return;
-
-        IHostOptions hostOptions = getHostOptions();
-        Integer concurrentFlashingLimit = hostOptions.getConcurrentFlasherLimit();
-        CLog.i(
-                "Requesting a flashing permit out of the max limit of %s. Current queue "
-                        + "length: %s",
-                concurrentFlashingLimit,
-                mConcurrentFlashLock.getQueueLength());
-        mConcurrentFlashLock.acquireUninterruptibly();
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public void returnFlashingPermit() {
-        if (mConcurrentFlashLock != null) {
-            mConcurrentFlashLock.release();
-        }
-    }
-
     /** {@inheritDoc} */
     @Override
     public String getAdbVersion() {
diff --git a/src/com/android/tradefed/device/IDeviceManager.java b/src/com/android/tradefed/device/IDeviceManager.java
index 6308de7..2ea66b7 100644
--- a/src/com/android/tradefed/device/IDeviceManager.java
+++ b/src/com/android/tradefed/device/IDeviceManager.java
@@ -289,24 +289,6 @@
      */
     public boolean waitForFirstDeviceAdded(long timeout);
 
-    /**
-     * Get the number of available flashing permits
-     *
-     * @return Number of available flashing permits or Integer.MAX_VALUE if not available.
-     */
-    public int getAvailableFlashingPermits();
-
-    /**
-     * Request permission to flash.  If the number of concurrent flashers is limited, this will
-     * wait in line in order to remain under the flash limit count.
-     */
-    public void takeFlashingPermit();
-
-    /**
-     * Restore a flashing permit that we acquired previously
-     */
-    public void returnFlashingPermit();
-
     /** Get the adb version currently in use by the device manager. */
     public String getAdbVersion();
 
diff --git a/src/com/android/tradefed/invoker/DeviceUnavailableMonitor.java b/src/com/android/tradefed/invoker/DeviceUnavailableMonitor.java
index 5e416a2..233fa27 100644
--- a/src/com/android/tradefed/invoker/DeviceUnavailableMonitor.java
+++ b/src/com/android/tradefed/invoker/DeviceUnavailableMonitor.java
@@ -43,53 +43,57 @@
 
     @Override
     public void testRunFailed(FailureDescription failure) {
-        analyzeFailure(failure);
+        if (mUnavailableException != null || mInvocationFailed) {
+            return;
+        }
+        mUnavailableException = analyzeFailure(failure);
     }
 
     @Override
     public void testFailed(TestDescription test, FailureDescription failure) {
-        analyzeFailure(failure);
+        if (mUnavailableException != null || mInvocationFailed) {
+            return;
+        }
+        mUnavailableException = analyzeFailure(failure);
     }
 
     @Override
     public void invocationFailed(FailureDescription failure) {
-        // Clear the tracking, let the invocation failure be evaluated
-        mUnavailableException = null;
         mInvocationFailed = true;
+        if (mUnavailableException != null) {
+          return;
+        }
+        mUnavailableException = analyzeFailure(failure);
     }
 
     @Override
     public void invocationFailed(Throwable cause) {
-        // Clear the tracking, let the invocation failure be evaluated
-        mUnavailableException = null;
         mInvocationFailed = true;
     }
 
     /** Returns the exception if any was captured. */
     public DeviceNotAvailableException getUnavailableException() {
+        if (mInvocationFailed) {
+            return null;
+        }
         return mUnavailableException;
     }
 
-    private void analyzeFailure(FailureDescription failure) {
-        if (mUnavailableException != null || mInvocationFailed) {
-            return;
-        }
+    private DeviceNotAvailableException analyzeFailure(FailureDescription failure) {
         if (failure.getCause() != null
                 && failure.getCause() instanceof DeviceNotAvailableException) {
-            mUnavailableException = (DeviceNotAvailableException) failure.getCause();
+            return (DeviceNotAvailableException) failure.getCause();
         } else if (failure.getFailureStatus() != null
                 && FailureStatus.LOST_SYSTEM_UNDER_TEST.equals(failure.getFailureStatus())) {
-            mUnavailableException =
-                    new DeviceNotAvailableException(failure.getErrorMessage(), mSerial);
+            return new DeviceNotAvailableException(failure.getErrorMessage(), mSerial);
         } else if (failure.getErrorIdentifier() != null) {
             if (DeviceErrorIdentifier.DEVICE_UNAVAILABLE.equals(failure.getErrorIdentifier())) {
-                mUnavailableException =
-                        new DeviceNotAvailableException(failure.getErrorMessage(), mSerial);
+                return new DeviceNotAvailableException(failure.getErrorMessage(), mSerial);
             } else if (DeviceErrorIdentifier.DEVICE_UNRESPONSIVE.equals(
                     failure.getErrorIdentifier())) {
-                mUnavailableException =
-                        new DeviceUnresponsiveException(failure.getErrorMessage(), mSerial);
+                return new DeviceUnresponsiveException(failure.getErrorMessage(), mSerial);
             }
         }
+        return null;
     }
 }
diff --git a/src/com/android/tradefed/invoker/TestInvocation.java b/src/com/android/tradefed/invoker/TestInvocation.java
index 62a642e..2d68fb9 100644
--- a/src/com/android/tradefed/invoker/TestInvocation.java
+++ b/src/com/android/tradefed/invoker/TestInvocation.java
@@ -348,6 +348,8 @@
                         for (ITestDevice device : context.getDevices()) {
                             Callable<Boolean> callableTask =
                                     () -> {
+                                        CLog.d("Start taking bugreport on '%s'",
+                                                device.getSerialNumber());
                                         takeBugreport(device, listener, reportName);
                                         return true;
                                     };
@@ -367,7 +369,13 @@
             }
             // Save the device executeShellCommand logs
             logExecuteShellCommand(context.getDevices(), listener);
-
+            if (exception == null) {
+                exception = mUnavailableMonitor.getUnavailableException();
+                if (exception != null) {
+                    CLog.e("Found a test level only device unavailable exception:");
+                    CLog.e(exception);
+                }
+            }
             mStatus = "tearing down";
             try {
                 invocationPath.doTeardown(testInfo, config, listener, exception);
@@ -394,13 +402,6 @@
             // Track the timestamp when we are done with devices
             addInvocationMetric(
                     InvocationMetricKey.DEVICE_DONE_TIMESTAMP, System.currentTimeMillis());
-            if (exception == null) {
-                exception = mUnavailableMonitor.getUnavailableException();
-                if (exception != null) {
-                    CLog.e("Found a test level only device unavailable exception:");
-                    CLog.e(exception);
-                }
-            }
             Map<ITestDevice, FreeDeviceState> devicesStates =
                     handleAndLogReleaseState(context, exception, tearDownException);
             if (config.getCommandOptions().earlyDeviceRelease()) {
@@ -578,7 +579,9 @@
             return;
         }
         // logBugreport will report a regular bugreport if bugreportz is not supported.
+        RecoveryMode recovery = device.getRecoveryMode();
         try {
+            device.setRecoveryMode(RecoveryMode.NONE);
             boolean res =
                     device.logBugreport(
                             String.format("%s_%s", bugreportName, device.getSerialNumber()),
@@ -589,6 +592,8 @@
         } catch (RuntimeException e) {
             CLog.e("Harness Exception while collecting bugreport");
             CLog.e(e);
+        } finally {
+            device.setRecoveryMode(recovery);
         }
     }
 
diff --git a/src/com/android/tradefed/invoker/shard/ShardHelper.java b/src/com/android/tradefed/invoker/shard/ShardHelper.java
index 0978839..5ebc1e3 100644
--- a/src/com/android/tradefed/invoker/shard/ShardHelper.java
+++ b/src/com/android/tradefed/invoker/shard/ShardHelper.java
@@ -36,6 +36,7 @@
 import com.android.tradefed.result.ITestInvocationListener;
 import com.android.tradefed.result.ITestLoggerReceiver;
 import com.android.tradefed.retry.IRetryDecision;
+import com.android.tradefed.service.TradefedFeatureServer;
 import com.android.tradefed.suite.checker.ISystemStatusChecker;
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.IDeviceTest;
@@ -267,6 +268,9 @@
             deepCopy.getCommandOptions().setShardCount(null);
             deepCopy.getConfigurationDescription()
                     .addMetadata(ConfigurationDescriptor.LOCAL_SHARDED_KEY, "true");
+            // Remove parent shard server reference from the copy.
+            deepCopy.getConfigurationDescription().removeMetadata(
+                    TradefedFeatureServer.SERVER_REFERENCE);
             return deepCopy;
         } catch (ConfigurationException e) {
             throw new RuntimeException(
diff --git a/src/com/android/tradefed/result/DeviceUnavailEmailResultReporter.java b/src/com/android/tradefed/result/DeviceUnavailEmailResultReporter.java
deleted file mode 100644
index 074d81c..0000000
--- a/src/com/android/tradefed/result/DeviceUnavailEmailResultReporter.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.tradefed.result;
-
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.config.OptionClass;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil.CLog;
-
-import com.google.common.annotations.VisibleForTesting;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-
-
-/**
- * An {@link EmailResultReporter} that will send email when invocation fails due to a device not
- * available exception.
- */
-@OptionClass(alias = "device-unavail-email")
-public class DeviceUnavailEmailResultReporter extends EmailResultReporter {
-
-    @Override
-    protected boolean shouldSendMessage() {
-        return getInvocationException() instanceof DeviceNotAvailableException;
-    }
-
-    @Override
-    protected String generateEmailSubject() {
-        StringBuilder subj = new StringBuilder();
-        subj.append("Device unavailable ");
-        for (IBuildInfo build : getInvocationContext().getBuildInfos()) {
-            subj.append(build.toString());
-        }
-        subj.append(" ");
-        subj.append(String.format("hostname %s", getHostname()));
-
-        // Sample email subject: Device unavailable: mantaray-user JDQ39
-        // 015d172c980c2208 atl-034.mtv.corp.google.com
-        return subj.toString();
-    }
-
-    /**
-     * Fetch the hostname and returns it, or returns "Unknown" if an error occurs.
-     */
-    @VisibleForTesting
-    String getHostname() {
-        try {
-            return InetAddress.getLocalHost().getHostName();
-        } catch (UnknownHostException e) {
-            CLog.e(e);
-            return "Unknown";
-        }
-    }
-}
diff --git a/src/com/android/tradefed/result/EmailResultReporter.java b/src/com/android/tradefed/result/EmailResultReporter.java
deleted file mode 100644
index bbf3bca..0000000
--- a/src/com/android/tradefed/result/EmailResultReporter.java
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * Copyright (C) 2010 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 com.android.tradefed.result;
-
-import com.android.ddmlib.testrunner.TestResult.TestStatus;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.config.Option.Importance;
-import com.android.tradefed.config.OptionClass;
-import com.android.tradefed.invoker.IInvocationContext;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.targetprep.BuildError;
-import com.android.tradefed.util.Email;
-import com.android.tradefed.util.IEmail;
-import com.android.tradefed.util.IEmail.Message;
-import com.android.tradefed.util.StreamUtil;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A simple result reporter base class that sends emails for test results.<br>
- * Subclasses should determine whether an email needs to be sent, and can
- * override other behavior.
- */
-@OptionClass(alias = "email")
-public class EmailResultReporter extends CollectingTestListener implements
-        ITestSummaryListener {
-    private static final String DEFAULT_SUBJECT_TAG = "Tradefed";
-    private static final String TEST_FAILURE_STATUS = "FAILED";
-
-    @Option(name = "sender", description = "The envelope-sender address to use for the messages.",
-            importance = Importance.IF_UNSET)
-    private String mSender = null;
-
-    @Option(name = "destination", description = "One or more destination addresses.",
-            importance = Importance.IF_UNSET)
-    private Collection<String> mDestinations = new HashSet<String>();
-
-    @Option(name = "subject-tag",
-            description = "The tag to be added to the beginning of the email subject.")
-    private String mSubjectTag = DEFAULT_SUBJECT_TAG;
-
-    @Option(name = "include-test-failures", description = "If there are some test failures, "
-            + "this option allows to add them to the email body."
-            + "To be used with care, as it could be pretty big with traces.")
-    private boolean mIncludeTestFailures = false;
-
-    private List<TestSummary> mSummaries = null;
-    private Throwable mInvocationThrowable = null;
-    private IEmail mMailer;
-    private boolean mHtml;
-
-    /**
-     * Create a {@link EmailResultReporter}
-     */
-    public EmailResultReporter() {
-        this(new Email());
-    }
-
-    /**
-     * Create a {@link EmailResultReporter} with a custom {@link IEmail} instance to use.
-     * <p/>
-     * Exposed for unit testing.
-     *
-     * @param mailer the {@link IEmail} instance to use.
-     */
-    protected EmailResultReporter(IEmail mailer) {
-        mMailer = mailer;
-    }
-
-    /**
-     * Adds an email destination address.
-     *
-     * @param dest
-     */
-    public void addDestination(String dest) {
-        mDestinations.add(dest);
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void putSummary(List<TestSummary> summaries) {
-        mSummaries = summaries;
-    }
-
-    /**
-     * Allow subclasses to get at the summaries we've received
-     */
-    protected List<TestSummary> fetchSummaries() {
-        return mSummaries;
-    }
-
-    /**
-     * A method, meant to be overridden, which should do whatever filtering is decided and determine
-     * whether a notification email should be sent for the test results.  Presumably, would consider
-     * how many (if any) tests failed, prior failures of the same tests, etc.
-     *
-     * @return {@code true} if a notification email should be sent, {@code false} if not
-     */
-    protected boolean shouldSendMessage() {
-        return true;
-    }
-
-    /**
-     * A method to generate the subject for email reports. Will not be called if
-     * {@link #shouldSendMessage()} returns {@code false}.
-     * <p />
-     * Sample email subjects:
-     * <ul>
-     *   <li>"Tradefed result for powerChromeFullSitesLocal on mantaray-user git_jb-mr1.1-release
-     *       JDQ39: FAILED"</li>
-     *   <li>"Tradefed result for Monkey on build 25: FAILED"</li>
-     * </ul>
-     *
-     * @return A {@link String} containing the subject to use for an email
-     *         report
-     */
-    protected String generateEmailSubject() {
-        final IInvocationContext context = getInvocationContext();
-        final StringBuilder subj = new StringBuilder(mSubjectTag);
-
-        subj.append(" result for ");
-
-        if (!appendUnlessNull(subj, context.getTestTag())) {
-            subj.append("(unknown suite)");
-        }
-
-        subj.append(" on ");
-        for (IBuildInfo build : context.getBuildInfos()) {
-            subj.append(build.toString());
-        }
-
-        subj.append(": ");
-        subj.append(getInvocationOrTestStatus());
-        return subj.toString();
-    }
-
-    /**
-     * Appends {@code str + " "} to {@code builder} IFF {@code str} is not null.
-     * @return {@code true} if str is not null, {@code false} if str is null.
-     */
-    private boolean appendUnlessNull(StringBuilder builder, String str) {
-        if (str == null) {
-            return false;
-        } else {
-            builder.append(str);
-            builder.append(" ");
-            return true;
-        }
-    }
-
-    protected String getInvocationOrTestStatus() {
-        InvocationStatus invStatus = getInvocationStatus();
-        // if invocation status is not success, report invocation status
-        if (!InvocationStatus.SUCCESS.equals(invStatus)) {
-            // special-case invocation failure and report as "ERROR" to avoid confusion with
-            // test failures
-            if (InvocationStatus.FAILED.equals(invStatus)) {
-                return "ERROR";
-            }
-            return invStatus.toString();
-        }
-        if (hasFailedTests()) {
-            return TEST_FAILURE_STATUS;
-        }
-        return invStatus.toString(); // should be success at this point
-    }
-
-    /**
-     * Returns the {@link InvocationStatus}
-     */
-    protected InvocationStatus getInvocationStatus() {
-        if (mInvocationThrowable == null) {
-            return InvocationStatus.SUCCESS;
-        } else if (mInvocationThrowable instanceof BuildError) {
-            return InvocationStatus.BUILD_ERROR;
-        } else {
-            return InvocationStatus.FAILED;
-        }
-    }
-
-    /**
-     * Returns the {@link Throwable} passed via {@link #invocationFailed(Throwable)}.
-     */
-    protected Throwable getInvocationException() {
-        return mInvocationThrowable;
-    }
-
-    /**
-     * A method to generate the body for email reports.  Will not be called if
-     * {@link #shouldSendMessage()} returns {@code false}.
-     *
-     * @return A {@link String} containing the body to use for an email report
-     */
-    protected String generateEmailBody() {
-        StringBuilder bodyBuilder = new StringBuilder();
-
-        for (IBuildInfo build : getInvocationContext().getBuildInfos()) {
-            bodyBuilder.append(String.format("Device %s:\n", build.getDeviceSerial()));
-            for (Map.Entry<String, String> buildAttr : build.getBuildAttributes().entrySet()) {
-                bodyBuilder.append(buildAttr.getKey());
-                bodyBuilder.append(": ");
-                bodyBuilder.append(buildAttr.getValue());
-                bodyBuilder.append("\n");
-            }
-        }
-        bodyBuilder.append("host: ");
-        try {
-            bodyBuilder.append(InetAddress.getLocalHost().getHostName());
-        } catch (UnknownHostException e) {
-            bodyBuilder.append("unknown");
-            CLog.e(e);
-        }
-        bodyBuilder.append("\n\n");
-
-        if (mInvocationThrowable != null) {
-            bodyBuilder.append("Invocation failed: ");
-            bodyBuilder.append(StreamUtil.getStackTrace(mInvocationThrowable));
-            bodyBuilder.append("\n");
-        }
-        bodyBuilder.append(String.format("Test results:  %d passed, %d failed\n\n",
-                getNumTestsInState(TestStatus.PASSED), getNumAllFailedTests()));
-
-        // During a Test Failure, the current run results will not appear in getRunResults()
-        // This may be fairly big and we are not sure of email body max size, so limiting usage
-        // with the option.
-        if (hasFailedTests() && mIncludeTestFailures) {
-            TestRunResult res = getCurrentRunResults();
-            for (TestDescription tid : res.getTestResults().keySet()) {
-                TestResult tr = res.getTestResults().get(tid);
-                if (TestStatus.FAILURE.equals(tr.getStatus())) {
-                    bodyBuilder.append(String.format("Test Identifier: %s\nStack: %s", tid,
-                            tr.getStackTrace()));
-                    bodyBuilder.append("\n");
-                }
-            }
-        }
-        bodyBuilder.append("\n");
-
-        if (mSummaries != null) {
-            for (TestSummary summary : mSummaries) {
-                bodyBuilder.append("Invocation summary report: ");
-                bodyBuilder.append(summary.getSummary().getString());
-                if (!summary.getKvEntries().isEmpty()) {
-                    bodyBuilder.append("\".\nSummary key-value dump:\n");
-                    bodyBuilder.append(summary.getKvEntries().toString());
-                }
-            }
-        }
-        return bodyBuilder.toString();
-    }
-
-    /**
-     * A method to set a flag indicating that the email body is in HTML rather than plain text
-     *
-     * This method must be called before the email body is generated
-     *
-     * @param html true if the body is html
-     */
-    protected void setHtml(boolean html) {
-        mHtml = html;
-    }
-
-    protected boolean isHtml() {
-        return mHtml;
-    }
-
-    @Override
-    public void invocationFailed(Throwable t) {
-        mInvocationThrowable = t;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void invocationEnded(long elapsedTime) {
-        super.invocationEnded(elapsedTime);
-        if (!shouldSendMessage()) {
-            return;
-        }
-
-        if (mDestinations.isEmpty()) {
-            CLog.i("No destinations set, not sending any emails");
-            return;
-        }
-
-        Message msg = new Message();
-        msg.setSender(mSender);
-        msg.setSubject(generateEmailSubject());
-        msg.setBody(generateEmailBody());
-        msg.setHtml(isHtml());
-        Iterator<String> toAddress = mDestinations.iterator();
-        while (toAddress.hasNext()) {
-            msg.addTo(toAddress.next());
-        }
-
-        try {
-            mMailer.send(msg);
-        } catch (IllegalArgumentException e) {
-            CLog.e("Failed to send email");
-            CLog.e(e);
-        } catch (IOException e) {
-            CLog.e("Failed to send email");
-            CLog.e(e);
-        }
-    }
-}
diff --git a/src/com/android/tradefed/result/FailureEmailResultReporter.java b/src/com/android/tradefed/result/FailureEmailResultReporter.java
deleted file mode 100644
index 120af09..0000000
--- a/src/com/android/tradefed/result/FailureEmailResultReporter.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2011 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 com.android.tradefed.result;
-
-import com.android.tradefed.config.OptionClass;
-import com.android.tradefed.util.Email;
-import com.android.tradefed.util.IEmail;
-
-/**
- * An {@link EmailResultReporter} that sends notifications if either a test failure or invocation
- * failure occurred.
- */
-@OptionClass(alias = "failure-email")
-public class FailureEmailResultReporter extends EmailResultReporter {
-
-    /**
-     * Default constructor
-     */
-    public FailureEmailResultReporter() {
-        this(new Email());
-    }
-
-    /**
-     * Create a {@link FailureEmailResultReporter} with a custom {@link IEmail} instance to use.
-     * <p/>
-     * Exposed for unit testing.
-     *
-     * @param mailer the {@link IEmail} instance to use.
-     */
-    protected FailureEmailResultReporter(IEmail mailer) {
-        super(mailer);
-    }
-
-    /**
-     * Send a message if there was a failure.
-     *
-     * @return {@code true} if the InvocationStatus is not {@link InvocationStatus#SUCCESS} or
-     * if {@link #hasFailedTests()} is true, {@code false} otherwise.
-     */
-    @Override
-    protected boolean shouldSendMessage() {
-        return !getInvocationStatus().equals(InvocationStatus.SUCCESS) || hasFailedTests();
-    }
-}
diff --git a/src/com/android/tradefed/result/InvocationFailureEmailResultReporter.java b/src/com/android/tradefed/result/InvocationFailureEmailResultReporter.java
deleted file mode 100644
index 59931e4..0000000
--- a/src/com/android/tradefed/result/InvocationFailureEmailResultReporter.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.tradefed.result;
-
-import com.android.tradefed.config.OptionClass;
-import com.android.tradefed.util.Email;
-import com.android.tradefed.util.IEmail;
-
-/**
- * An {@link EmailResultReporter} that can also restrict notifications to just invocation failures.
- */
-@OptionClass(alias = "invocation-failure-email")
-public class InvocationFailureEmailResultReporter extends EmailResultReporter {
-
-    private boolean mDisabled = false;
-
-    /**
-     * Default constructor
-     */
-    public InvocationFailureEmailResultReporter() {
-        this(new Email());
-    }
-
-    /**
-     * Create a {@link InvocationFailureEmailResultReporter} with a custom {@link IEmail} instance
-     * to use.
-     * <p/>
-     * Exposed for unit testing.
-     *
-     * @param mailer the {@link IEmail} instance to use.
-     */
-    protected InvocationFailureEmailResultReporter(IEmail mailer) {
-        super(mailer);
-    }
-
-    /**
-     * Send a message if there was an invocation failure.
-     *
-     * @return {@code true} if the InvocationStatus is not {@link InvocationStatus#SUCCESS}, or
-     * {@code false} if it is.
-     */
-    @Override
-    protected boolean shouldSendMessage() {
-        if (mDisabled) {
-            // Inhibit the failure from sending emails if we are shutting down TF.
-            return false;
-        }
-        return !getInvocationStatus().equals(InvocationStatus.SUCCESS);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void invocationInterrupted() {
-        mDisabled = true;
-    }
-}
diff --git a/src/com/android/tradefed/result/TestFailureEmailResultReporter.java b/src/com/android/tradefed/result/TestFailureEmailResultReporter.java
deleted file mode 100644
index 1d83ba9..0000000
--- a/src/com/android/tradefed/result/TestFailureEmailResultReporter.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.tradefed.result;
-
-import com.android.tradefed.config.OptionClass;
-import com.android.tradefed.util.Email;
-import com.android.tradefed.util.IEmail;
-
-/**
- * An {@link EmailResultReporter} that can also restrict notifications to just test failures.
- */
-@OptionClass(alias = "test-failure-email")
-public class TestFailureEmailResultReporter extends EmailResultReporter {
-
-    /**
-     * Default constructor
-     */
-    public TestFailureEmailResultReporter() {
-        this(new Email());
-    }
-
-    /**
-     * Create a {@link TestFailureEmailResultReporter} with a custom {@link IEmail} instance to use.
-     * <p/>
-     * Exposed for unit testing.
-     *
-     * @param mailer the {@link IEmail} instance to use.
-     */
-    protected TestFailureEmailResultReporter(IEmail mailer) {
-        super(mailer);
-    }
-
-    /**
-     * Send a message if there was an invocation failure.
-     *
-     * @return the return value of {@link #hasFailedTests()}.
-     */
-    @Override
-    protected boolean shouldSendMessage() {
-        return hasFailedTests();
-    }
-}
diff --git a/src/com/android/tradefed/targetprep/DeviceCleaner.java b/src/com/android/tradefed/targetprep/DeviceCleaner.java
index 9a34f35..b0eb115 100644
--- a/src/com/android/tradefed/targetprep/DeviceCleaner.java
+++ b/src/com/android/tradefed/targetprep/DeviceCleaner.java
@@ -19,7 +19,6 @@
 import com.android.tradefed.config.Option;
 import com.android.tradefed.config.OptionClass;
 import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.DeviceUnresponsiveException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.device.TestDeviceState;
 import com.android.tradefed.invoker.TestInformation;
@@ -78,16 +77,15 @@
 
     @Override
     public void tearDown(TestInformation testInfo, Throwable e) throws DeviceNotAvailableException {
-        if (e instanceof DeviceFailedToBootError) {
-            CLog.w("boot failure: attempting to stop runtime instead of cleanup");
-            try {
-                testInfo.getDevice().executeShellCommand("stop");
-            } catch (DeviceUnresponsiveException due) {
-                CLog.w("boot failure: ignored DeviceUnresponsiveException during forced cleanup");
-            }
-        } else {
-            clean(testInfo.getDevice());
+        if (e instanceof DeviceNotAvailableException) {
+            CLog.w("Skipping device clean up due to device unavailable.");
+            return;
         }
+        if (e instanceof DeviceFailedToBootError) {
+            CLog.w("Skipping device clean up due to boot failure.");
+            return;
+        }
+        clean(testInfo.getDevice());
     }
 
     /**
diff --git a/src/com/android/tradefed/targetprep/DeviceFlashPreparer.java b/src/com/android/tradefed/targetprep/DeviceFlashPreparer.java
index 865c27b..6a56871 100644
--- a/src/com/android/tradefed/targetprep/DeviceFlashPreparer.java
+++ b/src/com/android/tradefed/targetprep/DeviceFlashPreparer.java
@@ -23,12 +23,12 @@
 import com.android.tradefed.config.Option;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.DeviceUnresponsiveException;
-import com.android.tradefed.device.IDeviceManager;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.device.ITestDevice.RecoveryMode;
 import com.android.tradefed.device.NullDevice;
 import com.android.tradefed.error.HarnessRuntimeException;
 import com.android.tradefed.host.IHostOptions;
+import com.android.tradefed.host.IHostOptions.PermitLimitType;
 import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.invoker.logger.InvocationMetricLogger;
 import com.android.tradefed.invoker.logger.InvocationMetricLogger.InvocationMetricKey;
@@ -161,17 +161,6 @@
     }
 
     /**
-     * Getg a reference to the {@link IDeviceManager}
-     *
-     * Exposed for unit testing
-     *
-     * @return the {@link IDeviceManager} to use
-     */
-    IDeviceManager getDeviceManager() {
-        return GlobalConfiguration.getDeviceManagerInstance();
-    }
-
-    /**
      * Gets the {@link IHostOptions} instance to use.
      * <p/>
      * Exposed for unit testing
@@ -211,7 +200,6 @@
         }
         // don't allow interruptions during flashing operations.
         getRunUtil().allowInterrupt(false);
-        IDeviceManager deviceManager = getDeviceManager();
         long queueTime = -1;
         long flashingTime = -1;
         long start = -1;
@@ -223,7 +211,7 @@
             // only surround fastboot related operations with flashing permit restriction
             try {
                 start = System.currentTimeMillis();
-                deviceManager.takeFlashingPermit();
+                getHostOptions().takePermit(PermitLimitType.CONCURRENT_FLASHER);
                 queueTime = System.currentTimeMillis() - start;
                 CLog.v(
                         "Flashing permit obtained after %ds",
@@ -247,7 +235,7 @@
                 flasher.flash(device, deviceBuild);
             } finally {
                 flashingTime = System.currentTimeMillis() - start;
-                deviceManager.returnFlashingPermit();
+                getHostOptions().returnPermit(PermitLimitType.CONCURRENT_FLASHER);
                 // report flashing status
                 CommandStatus status = flasher.getSystemFlashingStatus();
                 if (status == null) {
diff --git a/src/com/android/tradefed/targetprep/DeviceUpdateTargetPreparer.java b/src/com/android/tradefed/targetprep/DeviceUpdateTargetPreparer.java
index 3218365..55f2439 100644
--- a/src/com/android/tradefed/targetprep/DeviceUpdateTargetPreparer.java
+++ b/src/com/android/tradefed/targetprep/DeviceUpdateTargetPreparer.java
@@ -20,9 +20,10 @@
 import com.android.tradefed.config.Option;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.DeviceUnresponsiveException;
-import com.android.tradefed.device.IDeviceManager;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.device.ITestDevice.RecoveryMode;
+import com.android.tradefed.host.IHostOptions;
+import com.android.tradefed.host.IHostOptions.PermitLimitType;
 import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.result.error.DeviceErrorIdentifier;
@@ -72,8 +73,8 @@
         preUpdateActions(deviceUpdateImage, device);
         // flashing concurrency control
         long start = System.currentTimeMillis();
-        IDeviceManager deviceManager = GlobalConfiguration.getDeviceManagerInstance();
-        deviceManager.takeFlashingPermit();
+        IHostOptions hostOptions = GlobalConfiguration.getInstance().getHostOptions();
+        hostOptions.takePermit(PermitLimitType.CONCURRENT_FLASHER);
         CLog.v(
                 "Flashing permit obtained after %ds",
                 TimeUnit.MILLISECONDS.toSeconds((System.currentTimeMillis() - start)));
@@ -83,7 +84,7 @@
             CLog.v(
                     "Flashing finished after %ds",
                     TimeUnit.MILLISECONDS.toSeconds((System.currentTimeMillis() - start)));
-            deviceManager.returnFlashingPermit();
+            hostOptions.returnPermit(PermitLimitType.CONCURRENT_FLASHER);
         }
         postUpdateActions(deviceUpdateImage, device);
         CLog.i(
diff --git a/src/com/android/tradefed/targetprep/GkiDeviceFlashPreparer.java b/src/com/android/tradefed/targetprep/GkiDeviceFlashPreparer.java
index 20e6393..c61dfeb 100644
--- a/src/com/android/tradefed/targetprep/GkiDeviceFlashPreparer.java
+++ b/src/com/android/tradefed/targetprep/GkiDeviceFlashPreparer.java
@@ -21,9 +21,10 @@
 import com.android.tradefed.config.OptionClass;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.DeviceUnresponsiveException;
-import com.android.tradefed.device.IDeviceManager;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.device.ITestDevice.RecoveryMode;
+import com.android.tradefed.host.IHostOptions;
+import com.android.tradefed.host.IHostOptions.PermitLimitType;
 import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.result.error.DeviceErrorIdentifier;
@@ -157,13 +158,13 @@
     }
 
     /**
-     * Get a reference to the {@link IDeviceManager}
+     * Get a reference to the {@link IHostOptions}
      *
-     * @return the {@link IDeviceManager} to use
+     * @return the {@link IHostOptions} to use
      */
     @VisibleForTesting
-    IDeviceManager getDeviceManager() {
-        return GlobalConfiguration.getDeviceManagerInstance();
+    protected IHostOptions getHostOptions() {
+        return GlobalConfiguration.getInstance().getHostOptions();
     }
 
     /**
@@ -186,10 +187,9 @@
      */
     private void flashGki(ITestDevice device, IBuildInfo buildInfo, File tmpDir)
             throws TargetSetupError, DeviceNotAvailableException {
-        IDeviceManager deviceManager = getDeviceManager();
         device.rebootIntoBootloader();
         long start = System.currentTimeMillis();
-        deviceManager.takeFlashingPermit();
+        getHostOptions().takePermit(PermitLimitType.CONCURRENT_FLASHER);
         CLog.v(
                 "Flashing permit obtained after %ds",
                 TimeUnit.MILLISECONDS.toSeconds((System.currentTimeMillis() - start)));
@@ -220,7 +220,7 @@
                 executeFastbootCmd(device, "-w");
             }
         } finally {
-            deviceManager.returnFlashingPermit();
+            getHostOptions().returnPermit(PermitLimitType.CONCURRENT_FLASHER);
             // Allow interruption at the end no matter what.
             getRunUtil().allowInterrupt(true);
             CLog.v(
diff --git a/src/com/android/tradefed/targetprep/GsiDeviceFlashPreparer.java b/src/com/android/tradefed/targetprep/GsiDeviceFlashPreparer.java
index 5d9f224..609758b 100644
--- a/src/com/android/tradefed/targetprep/GsiDeviceFlashPreparer.java
+++ b/src/com/android/tradefed/targetprep/GsiDeviceFlashPreparer.java
@@ -21,9 +21,10 @@
 import com.android.tradefed.config.OptionClass;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.DeviceUnresponsiveException;
-import com.android.tradefed.device.IDeviceManager;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.device.ITestDevice.RecoveryMode;
+import com.android.tradefed.host.IHostOptions;
+import com.android.tradefed.host.IHostOptions.PermitLimitType;
 import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.result.error.DeviceErrorIdentifier;
@@ -156,13 +157,13 @@
     }
 
     /**
-     * Get a reference to the {@link IDeviceManager}
+     * Get a reference to the {@link IHostOptions}
      *
-     * @return the {@link IDeviceManager} to use
+     * @return the {@link IHostOptions} to use
      */
     @VisibleForTesting
-    IDeviceManager getDeviceManager() {
-        return GlobalConfiguration.getDeviceManagerInstance();
+    protected IHostOptions getHostOptions() {
+        return GlobalConfiguration.getInstance().getHostOptions();
     }
 
     /**
@@ -184,7 +185,6 @@
      */
     private void flashGsi(ITestDevice device, IBuildInfo buildInfo)
             throws TargetSetupError, DeviceNotAvailableException {
-        IDeviceManager deviceManager = getDeviceManager();
         device.waitForDeviceOnline();
         // After Android 10, system parition and product partion are moved to dynamic partitions
         // https://source.android.com/devices/tech/ota/dynamic_partitions/implement?hl=en
@@ -194,7 +194,7 @@
         }
         device.rebootIntoBootloader();
         long start = System.currentTimeMillis();
-        deviceManager.takeFlashingPermit();
+        getHostOptions().takePermit(PermitLimitType.CONCURRENT_FLASHER);
         CLog.v(
                 "Flashing permit obtained after %ds",
                 TimeUnit.MILLISECONDS.toSeconds((System.currentTimeMillis() - start)));
@@ -233,7 +233,7 @@
                 executeFastbootCmd(device, "flash", "boot", mBootImg.getAbsolutePath());
             }
         } finally {
-            deviceManager.returnFlashingPermit();
+            getHostOptions().returnPermit(PermitLimitType.CONCURRENT_FLASHER);
             // Allow interruption at the end no matter what.
             getRunUtil().allowInterrupt(true);
             CLog.v(
diff --git a/src/com/android/tradefed/targetprep/InstallApexModuleTargetPreparer.java b/src/com/android/tradefed/targetprep/InstallApexModuleTargetPreparer.java
index 7d42bbe..6d00a27 100644
--- a/src/com/android/tradefed/targetprep/InstallApexModuleTargetPreparer.java
+++ b/src/com/android/tradefed/targetprep/InstallApexModuleTargetPreparer.java
@@ -82,7 +82,7 @@
     @Option(name = "bundletool-file-name", description = "The file name of the bundletool jar.")
     private String mBundletoolFilename;
 
-    @Option(name = "train-path", description = "The absoulte path of the train folder.")
+    @Option(name = "train-path", description = "The absolute path of the train folder.")
     private File mTrainFolderPath;
 
     @Option(
diff --git a/src/com/android/tradefed/targetprep/RunOnSecondaryUserTargetPreparer.java b/src/com/android/tradefed/targetprep/RunOnSecondaryUserTargetPreparer.java
index dd116b9..3847358 100644
--- a/src/com/android/tradefed/targetprep/RunOnSecondaryUserTargetPreparer.java
+++ b/src/com/android/tradefed/targetprep/RunOnSecondaryUserTargetPreparer.java
@@ -93,7 +93,10 @@
             userIdToDelete = secondaryUserId;
         }
 
-        testInfo.getDevice().startUser(secondaryUserId, /* waitFlag= */ true);
+        // The wait flag is only supported on Android 29+
+        testInfo.getDevice()
+                .startUser(
+                        secondaryUserId, /* waitFlag= */ testInfo.getDevice().getApiLevel() >= 29);
 
         originalUserId = testInfo.getDevice().getCurrentUser();
 
diff --git a/src/com/android/tradefed/targetprep/RunOnWorkProfileTargetPreparer.java b/src/com/android/tradefed/targetprep/RunOnWorkProfileTargetPreparer.java
index e6a0f11..9e019ca 100644
--- a/src/com/android/tradefed/targetprep/RunOnWorkProfileTargetPreparer.java
+++ b/src/com/android/tradefed/targetprep/RunOnWorkProfileTargetPreparer.java
@@ -16,6 +16,7 @@
 
 package com.android.tradefed.targetprep;
 
+import com.android.ddmlib.Log;
 import com.android.tradefed.config.ConfigurationException;
 import com.android.tradefed.config.IConfiguration;
 import com.android.tradefed.config.IConfigurationReceiver;
@@ -50,6 +51,8 @@
 public class RunOnWorkProfileTargetPreparer extends BaseTargetPreparer
         implements IConfigurationReceiver {
 
+    private static final String LOG_TAG = "RunOnWorkProfileTargetPreparer";
+
     @VisibleForTesting static final String RUN_TESTS_AS_USER_KEY = "RUN_TESTS_AS_USER";
 
     @VisibleForTesting static final String TEST_PACKAGE_NAME_OPTION = "test-package-name";
@@ -58,7 +61,18 @@
 
     private IConfiguration mConfiguration;
 
-    private int userIdToDelete = -1;
+    private int mUserIdToDelete = -1;
+    private DeviceOwner mDeviceOwnerToSet = null;
+
+    private static class DeviceOwner {
+        final String componentName;
+        final int userId;
+
+        DeviceOwner(String componentName, int userId) {
+            this.componentName = componentName;
+            this.userId = userId;
+        }
+    }
 
     @Option(
             name = TEST_PACKAGE_NAME_OPTION,
@@ -93,11 +107,23 @@
                 return;
             }
 
+            mDeviceOwnerToSet = getDeviceOwner(testInfo.getDevice());
+
+            if (mDeviceOwnerToSet != null) {
+                Log.d(
+                        LOG_TAG,
+                        "Work profiles cannot be created after device owner is set. Attempting to"
+                                + " remove device owner");
+                removeDeviceOwner(testInfo.getDevice(), mDeviceOwnerToSet);
+            }
+
             workProfileId = createWorkProfile(testInfo.getDevice());
-            userIdToDelete = workProfileId;
+            mUserIdToDelete = workProfileId;
         }
 
-        testInfo.getDevice().startUser(workProfileId, /* waitFlag= */ true);
+        // The wait flag is only supported on Android 29+
+        testInfo.getDevice()
+                .startUser(workProfileId, /* waitFlag= */ testInfo.getDevice().getApiLevel() >= 29);
 
         for (String pkg : mTestPackages) {
             testInfo.getDevice()
@@ -120,18 +146,27 @@
     /** Creates a work profile and returns the new user ID. */
     private static int createWorkProfile(ITestDevice device) throws DeviceNotAvailableException {
         int parentProfile = device.getCurrentUser();
-        final String createUserOutput =
-                device.executeShellCommand(
-                        "pm create-user --profileOf " + parentProfile + " --managed work");
-        final int profileId = Integer.parseInt(createUserOutput.split(" id ")[1].trim());
-        return profileId;
+        String command = "pm create-user --profileOf " + parentProfile + " --managed work";
+        final String createUserOutput = device.executeShellCommand(command);
+
+        try {
+            return Integer.parseInt(createUserOutput.split(" id ")[1].trim());
+        } catch (RuntimeException e) {
+            throwCommandError("Error creating work profile", command, createUserOutput, e);
+            return -1; // Never reached as showCommandError throws an exception
+        }
     }
 
     @Override
     public void tearDown(TestInformation testInfo, Throwable e) throws DeviceNotAvailableException {
         testInfo.properties().remove(RUN_TESTS_AS_USER_KEY);
-        if (userIdToDelete != -1) {
-            testInfo.getDevice().removeUser(userIdToDelete);
+        if (mUserIdToDelete != -1) {
+            testInfo.getDevice().removeUser(mUserIdToDelete);
+        }
+
+        if (mDeviceOwnerToSet != null) {
+            testInfo.getDevice()
+                    .setDeviceOwner(mDeviceOwnerToSet.componentName, mDeviceOwnerToSet.userId);
         }
     }
 
@@ -175,4 +210,51 @@
             throws DeviceNotAvailableException {
         return device.listUsers().size() + numberOfUsers <= device.getMaxNumberOfUsersSupported();
     }
+
+    private DeviceOwner getDeviceOwner(ITestDevice device) throws DeviceNotAvailableException {
+        String command = "dumpsys device_policy";
+        String dumpsysOutput = device.executeShellCommand(command);
+
+        if (!dumpsysOutput.contains("Device Owner:")) {
+            return null;
+        }
+
+        try {
+            String deviceOwnerOnwards = dumpsysOutput.split("Device Owner:", 2)[1];
+            String componentName =
+                    deviceOwnerOnwards.split("ComponentInfo\\{", 2)[1].split("}", 2)[0];
+            int userId =
+                    Integer.parseInt(
+                            deviceOwnerOnwards.split("User ID: ", 2)[1].split("\n", 2)[0].trim());
+            return new DeviceOwner(componentName, userId);
+        } catch (RuntimeException e) {
+            throwCommandError("Error reading device owner information", command, dumpsysOutput, e);
+            return null; // Never reached as showCommandError throws an exception
+        }
+    }
+
+    private void removeDeviceOwner(ITestDevice device, DeviceOwner deviceOwner)
+            throws DeviceNotAvailableException {
+        String command =
+                "dpm remove-active-admin --user "
+                        + deviceOwner.userId
+                        + " "
+                        + deviceOwner.componentName;
+
+        String commandOutput = device.executeShellCommand(command);
+        if (!commandOutput.startsWith("Success")) {
+            throwCommandError("Error removing device owner", command, commandOutput);
+        }
+    }
+
+    private static void throwCommandError(String error, String command, String commandOutput) {
+        throwCommandError(error, command, commandOutput, /* exception= */ null);
+    }
+
+    private static void throwCommandError(
+            String error, String command, String commandOutput, Exception exception) {
+        throw new IllegalStateException(
+                error + ". Command was '" + command + "', output was '" + commandOutput + "'",
+                exception);
+    }
 }
diff --git a/src/com/android/tradefed/targetprep/suite/FoldableModePreparer.java b/src/com/android/tradefed/targetprep/suite/FoldableModePreparer.java
new file mode 100644
index 0000000..6834925
--- /dev/null
+++ b/src/com/android/tradefed/targetprep/suite/FoldableModePreparer.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 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 com.android.tradefed.targetprep.suite;
+
+import com.android.tradefed.config.Option;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.error.HarnessRuntimeException;
+import com.android.tradefed.invoker.TestInformation;
+import com.android.tradefed.result.error.DeviceErrorIdentifier;
+import com.android.tradefed.targetprep.BaseTargetPreparer;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.TargetSetupError;
+import com.android.tradefed.util.CommandResult;
+import com.android.tradefed.util.CommandStatus;
+
+/**
+ * A target preparer that can switch the foldable state of a device.
+ */
+public class FoldableModePreparer extends BaseTargetPreparer {
+
+    @Option(name = "foldable-state-identifier", description = "The integer state identifier of the foldable mode.")
+    private Long mStateIdentifier = null;
+
+    public FoldableModePreparer() {}
+
+    public FoldableModePreparer(long stateIdentifier) {
+        mStateIdentifier = stateIdentifier;
+    }
+
+    @Override
+    public void setUp(TestInformation testInformation)
+            throws TargetSetupError, BuildError, DeviceNotAvailableException {
+        if (mStateIdentifier == null) {
+            return;
+        }
+        CommandResult result = testInformation.getDevice().executeShellV2Command(
+                String.format("cmd device_state state %s", mStateIdentifier));
+        if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
+            throw new TargetSetupError(
+                    String.format("Could not set device_state %s. stderr: %s",
+                            mStateIdentifier, result.getStderr()),
+                    testInformation.getDevice().getDeviceDescriptor(),
+                    DeviceErrorIdentifier.DEVICE_UNEXPECTED_RESPONSE);
+        }
+    }
+
+    @Override
+    public void tearDown(TestInformation testInformation, Throwable e)
+            throws DeviceNotAvailableException {
+        if (mStateIdentifier == null) {
+            return;
+        }
+        CommandResult result = testInformation.getDevice().executeShellV2Command(
+                "cmd device_state state reset");
+        if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
+            throw new HarnessRuntimeException(
+                    String.format("Could not reset device_state. stderr: %s", result.getStderr()),
+                    DeviceErrorIdentifier.DEVICE_UNEXPECTED_RESPONSE);
+        }
+    }
+}
diff --git a/src/com/android/tradefed/testtype/suite/BaseTestSuite.java b/src/com/android/tradefed/testtype/suite/BaseTestSuite.java
index 3ff633f..c4d1da9 100644
--- a/src/com/android/tradefed/testtype/suite/BaseTestSuite.java
+++ b/src/com/android/tradefed/testtype/suite/BaseTestSuite.java
@@ -31,7 +31,7 @@
 import com.android.tradefed.testtype.IRemoteTest;
 import com.android.tradefed.testtype.ITestFileFilterReceiver;
 import com.android.tradefed.testtype.ITestFilterReceiver;
-import com.android.tradefed.testtype.suite.params.IModuleParameter;
+import com.android.tradefed.testtype.suite.params.IModuleParameterHandler;
 import com.android.tradefed.testtype.suite.params.ModuleParameters;
 import com.android.tradefed.testtype.suite.params.ModuleParametersHelper;
 import com.android.tradefed.testtype.suite.params.NegativeHandler;
@@ -49,6 +49,7 @@
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 
 /** A Test for running Compatibility Test Suite with new suite system. */
@@ -244,10 +245,10 @@
             SuiteModuleLoader.addFilters(mIncludeFilters, mIncludeFiltersParsed, mAbis);
             SuiteModuleLoader.addFilters(mExcludeFilters, mExcludeFiltersParsed, mAbis);
 
-            String includeFilter = mIncludeFiltersParsed.toString();
+            String includeFilters = "";
             if (mIncludeFiltersParsed.size() > MAX_FILTER_DISPLAY) {
                 if (isSplitting()) {
-                    includeFilter = includeFilter.substring(0, 100) + "...";
+                    includeFilters = "Includes: <too long to display>";
                 } else {
                     File suiteIncludeFilters = null;
                     try {
@@ -258,7 +259,8 @@
                                 suiteIncludeFilters,
                                 suiteIncludeFilters.getName(),
                                 LogDataType.TEXT);
-                        includeFilter = String.format("See %s", suiteIncludeFilters.getName());
+                        includeFilters =
+                                String.format("Includes: See %s", suiteIncludeFilters.getName());
                     } catch (IOException e) {
                         CLog.e(e);
                     } finally {
@@ -267,10 +269,10 @@
                 }
             }
 
-            String excludeFilter = mExcludeFiltersParsed.toString();
+            String excludeFilters = "";
             if (mExcludeFiltersParsed.size() > MAX_FILTER_DISPLAY) {
                 if (isSplitting()) {
-                    excludeFilter = excludeFilter.substring(0, 100) + "...";
+                    excludeFilters = "Excludes: <too long to display>";
                 } else {
                     File suiteExcludeFilters = null;
                     try {
@@ -281,7 +283,8 @@
                                 suiteExcludeFilters,
                                 suiteExcludeFilters.getName(),
                                 LogDataType.TEXT);
-                        excludeFilter = String.format("See %s", suiteExcludeFilters.getName());
+                        excludeFilters =
+                                String.format("Excludes: See %s", suiteExcludeFilters.getName());
                     } catch (IOException e) {
                         CLog.e(e);
                     } finally {
@@ -292,8 +295,8 @@
 
             CLog.d(
                     "Initializing ModuleRepo\nABIs:%s\n"
-                            + "Test Args:%s\nModule Args:%s\nIncludes:%s\nExcludes:%s",
-                            mAbis, mTestArgs, mModuleArgs, includeFilter, excludeFilter);
+                            + "Test Args:%s\nModule Args:%s\n%s\n%s",
+                            mAbis, mTestArgs, mModuleArgs, includeFilters, excludeFilters);
 
             mModuleRepo =
                     createModuleLoader(
@@ -351,7 +354,7 @@
                         String.format(
                                 "Include filter '%s' was specified"
                                         + " but resulted in an empty test set.",
-                                includeFilter),
+                                        mIncludeFiltersParsed.toString()),
                         InfraErrorIdentifier.OPTION_CONFIGURATION_ERROR);
             }
             return loadedTests;
@@ -538,21 +541,24 @@
             // Create the matching filters for the parameterized version of it if needed.
             if (mEnableParameter) {
                 for (ModuleParameters param : ModuleParameters.values()) {
-                    IModuleParameter moduleParam =
-                            ModuleParametersHelper.getParameterHandler(
-                                    param, mEnableOptionalParameter);
-                    if (moduleParam == null) {
+                    Map<ModuleParameters, IModuleParameterHandler> moduleParamExpanded =
+                            ModuleParametersHelper.resolveParam(param, mEnableOptionalParameter);
+                    if (moduleParamExpanded == null) {
                         continue;
                     }
-                    if (moduleParam instanceof NegativeHandler) {
-                        continue;
+                    for (Entry<ModuleParameters, IModuleParameterHandler> moduleParam :
+                            moduleParamExpanded.entrySet()) {
+                        if (moduleParam.getValue() instanceof NegativeHandler) {
+                            continue;
+                        }
+                        String paramModuleName =
+                                String.format(
+                                        "%s[%s]", moduleName,
+                                        moduleParam.getValue().getParameterIdentifier());
+                        mIncludeFilters.add(
+                                new SuiteTestFilter(getRequestedAbi(), paramModuleName, mTestName)
+                                        .toString());
                     }
-                    String paramModuleName =
-                            String.format(
-                                    "%s[%s]", moduleName, moduleParam.getParameterIdentifier());
-                    mIncludeFilters.add(
-                            new SuiteTestFilter(getRequestedAbi(), paramModuleName, mTestName)
-                                    .toString());
                 }
             }
         }
diff --git a/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java b/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java
index c3d78b4..ef47c10 100644
--- a/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java
+++ b/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java
@@ -33,7 +33,7 @@
 import com.android.tradefed.testtype.IRemoteTest;
 import com.android.tradefed.testtype.ITestFileFilterReceiver;
 import com.android.tradefed.testtype.ITestFilterReceiver;
-import com.android.tradefed.testtype.suite.params.IModuleParameter;
+import com.android.tradefed.testtype.suite.params.IModuleParameterHandler;
 import com.android.tradefed.testtype.suite.params.MainlineModuleHandler;
 import com.android.tradefed.testtype.suite.params.ModuleParameters;
 import com.android.tradefed.testtype.suite.params.ModuleParametersHelper;
@@ -60,6 +60,7 @@
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -259,21 +260,15 @@
             boolean primaryAbi = true;
             boolean shouldCreateMultiAbi = true;
             // If a particular parameter was requested to be run, find it.
-            Set<IModuleParameter> mForcedParameters = null;
+            Set<IModuleParameterHandler> mForcedParameters = null;
             Set<Class<?>> mForcedParameterClasses = null;
             if (mForcedModuleParameter != null) {
                 mForcedParameters = new HashSet<>();
-                Set<ModuleParameters> moduleParameters =
+                Map<ModuleParameters, IModuleParameterHandler> moduleParameters =
                         ModuleParametersHelper.resolveParam(
                                 mForcedModuleParameter, mAllowOptionalParameterizedModules);
-
-                for (ModuleParameters moduleParam : moduleParameters) {
-                    mForcedParameters.add(
-                            ModuleParametersHelper.getParameterHandler(
-                                    moduleParam, mAllowOptionalParameterizedModules));
-                }
                 mForcedParameterClasses = new HashSet<>();
-                for (IModuleParameter parameter : mForcedParameters) {
+                for (IModuleParameterHandler parameter : moduleParameters.values()) {
                     mForcedParameterClasses.add(parameter.getClass());
                 }
             }
@@ -312,7 +307,7 @@
                 }
 
                 boolean skipCreatingBaseConfig = false;
-                List<IModuleParameter> params = null;
+                List<IModuleParameterHandler> params = null;
                 List<String> mainlineParams = new ArrayList<>();
                 try {
                     params = getModuleParameters(name, config);
@@ -348,7 +343,7 @@
                     shouldCreateMultiAbi = shouldCreateMultiAbiForBase(params);
 
                     // If we find any parameterized combination.
-                    for (IModuleParameter param : params) {
+                    for (IModuleParameterHandler param : params) {
                         if (param instanceof NegativeHandler) {
                             if (mForcedParameters != null
                                     && !mForcedParameterClasses.contains(param.getClass())) {
@@ -516,7 +511,7 @@
             String baseModuleId,
             String parameterModuleId,
             String nameWithParam,
-            Set<IModuleParameter> forcedModuleParameters) {
+            Set<IModuleParameterHandler> forcedModuleParameters) {
         // Explicitly excluded
         LinkedHashSet<SuiteTestFilter> excluded = getFilterList(mExcludeFilters, parameterModuleId);
         LinkedHashSet<SuiteTestFilter> excludedParam = getFilterList(mExcludeFilters, nameWithParam);
@@ -665,10 +660,10 @@
         }
     }
 
-    /** Gets the list of {@link IModuleParameter}s associated with a module. */
-    private List<IModuleParameter> getModuleParameters(String moduleName, IConfiguration config)
+    /** Gets the list of {@link IModuleParameterHandler}s associated with a module. */
+    private List<IModuleParameterHandler> getModuleParameters(String moduleName, IConfiguration config)
             throws ConfigurationException {
-        List<IModuleParameter> params = new ArrayList<>();
+        List<IModuleParameterHandler> params = new ArrayList<>();
         Set<String> processedParameterArgs = new HashSet<>();
         // Track family of the parameters to make sure we have no duplicate.
         Map<String, ModuleParameters> duplicateModule = new LinkedHashMap<>();
@@ -683,7 +678,7 @@
         for (ModuleParameters moduleParameters : mExcludedModuleParameters) {
             expandedExcludedModuleParameters.addAll(
                     ModuleParametersHelper.resolveParam(
-                            moduleParameters, mAllowOptionalParameterizedModules));
+                            moduleParameters, mAllowOptionalParameterizedModules).keySet());
         }
 
         for (String p : parameters) {
@@ -691,10 +686,11 @@
                 // Avoid processing the same parameter twice
                 continue;
             }
-            Set<ModuleParameters> suiteParams =
+            Map<ModuleParameters, IModuleParameterHandler> suiteParams =
                     ModuleParametersHelper.resolveParam(
                             p.toUpperCase(), mAllowOptionalParameterizedModules);
-            for (ModuleParameters suiteParam : suiteParams) {
+            for (Entry<ModuleParameters, IModuleParameterHandler>  suiteParamEntry : suiteParams.entrySet()) {
+                ModuleParameters suiteParam = suiteParamEntry.getKey();
                 String family = suiteParam.getFamily();
                 if (duplicateModule.containsKey(family)) {
                     // Duplicate family members are not accepted.
@@ -712,13 +708,7 @@
                     continue;
                 }
 
-                IModuleParameter handler =
-                        ModuleParametersHelper.getParameterHandler(
-                                suiteParam, /* optionalParams */
-                                mAllowOptionalParameterizedModules);
-                if (handler != null) {
-                    params.add(handler);
-                }
+                params.add(suiteParamEntry.getValue());
             }
         }
         return params;
@@ -864,8 +854,8 @@
 
 
     /** Whether or not the base configuration should be created for all abis or not. */
-    private boolean shouldCreateMultiAbiForBase(List<IModuleParameter> params) {
-        for (IModuleParameter param : params) {
+    private boolean shouldCreateMultiAbiForBase(List<IModuleParameterHandler> params) {
+        for (IModuleParameterHandler param : params) {
             if (param instanceof NotMultiAbiHandler) {
                 return false;
             }
diff --git a/src/com/android/tradefed/testtype/suite/params/FoldableHandler.java b/src/com/android/tradefed/testtype/suite/params/FoldableHandler.java
new file mode 100644
index 0000000..dd333fc
--- /dev/null
+++ b/src/com/android/tradefed/testtype/suite/params/FoldableHandler.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 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 com.android.tradefed.testtype.suite.params;
+
+import com.android.tradefed.config.IConfiguration;
+import com.android.tradefed.config.IDeviceConfiguration;
+import com.android.tradefed.targetprep.ITargetPreparer;
+import com.android.tradefed.targetprep.suite.FoldableModePreparer;
+
+import java.util.List;
+
+/**
+ * Generic foldable handler that can take the foldable parameters to create a specialized module.
+ */
+public class FoldableHandler implements IModuleParameterHandler {
+
+    private final String mStateName;
+    private final long mIdentifier;
+
+    public FoldableHandler(String stateName, long identifier) {
+        mStateName = stateName;
+        mIdentifier = identifier;
+    }
+
+    @Override
+    public String getParameterIdentifier() {
+        return mStateName;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void addParameterSpecificConfig(IConfiguration moduleConfiguration) {
+        for (IDeviceConfiguration deviceConfig : moduleConfiguration.getDeviceConfig()) {
+            List<ITargetPreparer> preparers = deviceConfig.getTargetPreparers();
+            // The last things module will do is switch to the foldable mode
+            preparers.add(new FoldableModePreparer(mIdentifier));
+        }
+    }
+
+    @Override
+    public void applySetup(IConfiguration moduleConfiguration) {
+        // Empty on purpose currently. If needed set the annotation filters.
+    }
+}
diff --git a/src/com/android/tradefed/testtype/suite/params/IModuleParameter.java b/src/com/android/tradefed/testtype/suite/params/IModuleParameterHandler.java
similarity index 96%
rename from src/com/android/tradefed/testtype/suite/params/IModuleParameter.java
rename to src/com/android/tradefed/testtype/suite/params/IModuleParameterHandler.java
index a694de9..0345c3c 100644
--- a/src/com/android/tradefed/testtype/suite/params/IModuleParameter.java
+++ b/src/com/android/tradefed/testtype/suite/params/IModuleParameterHandler.java
@@ -18,7 +18,7 @@
 import com.android.tradefed.config.IConfiguration;
 
 /** The interface for parameters of suites modules. */
-public interface IModuleParameter {
+public interface IModuleParameterHandler {
 
     /** Returns the name the parameterized module will be identified as. */
     public String getParameterIdentifier();
diff --git a/src/com/android/tradefed/testtype/suite/params/InstantAppHandler.java b/src/com/android/tradefed/testtype/suite/params/InstantAppHandler.java
index 60f985f..c999870 100644
--- a/src/com/android/tradefed/testtype/suite/params/InstantAppHandler.java
+++ b/src/com/android/tradefed/testtype/suite/params/InstantAppHandler.java
@@ -26,7 +26,7 @@
 import java.util.Set;
 
 /** Handler for {@link ModuleParameters#INSTANT_APP}. */
-public class InstantAppHandler implements IModuleParameter {
+public class InstantAppHandler implements IModuleParameterHandler {
 
     /** {@inheritDoc} */
     @Override
diff --git a/src/com/android/tradefed/testtype/suite/params/ModuleParametersHelper.java b/src/com/android/tradefed/testtype/suite/params/ModuleParametersHelper.java
index a51f459..37d98d1 100644
--- a/src/com/android/tradefed/testtype/suite/params/ModuleParametersHelper.java
+++ b/src/com/android/tradefed/testtype/suite/params/ModuleParametersHelper.java
@@ -19,14 +19,13 @@
 import com.android.tradefed.testtype.suite.params.multiuser.RunOnWorkProfileParameterHandler;
 
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
-/** Helper to get the {@link IModuleParameter} associated with the parameter. */
+/** Helper to get the {@link IModuleParameterHandler} associated with the parameter. */
 public class ModuleParametersHelper {
 
-    private static Map<ModuleParameters, IModuleParameter> sHandlerMap = new HashMap<>();
+    private static Map<ModuleParameters, IModuleParameterHandler> sHandlerMap = new HashMap<>();
 
     static {
         sHandlerMap.put(ModuleParameters.INSTANT_APP, new InstantAppHandler());
@@ -57,7 +56,7 @@
      * set of parameterization that is less commonly requested to run. They could be upgraded to
      * main parameters in the future by moving them above.
      */
-    private static Map<ModuleParameters, IModuleParameter> sOptionalHandlerMap = new HashMap<>();
+    private static Map<ModuleParameters, IModuleParameterHandler> sOptionalHandlerMap = new HashMap<>();
 
     static {
         sOptionalHandlerMap.put(ModuleParameters.SECONDARY_USER, new SecondaryUserHandler());
@@ -70,25 +69,12 @@
     }
 
     /**
-     * Returns the {@link IModuleParameter} associated with the requested parameter.
-     *
-     * @param withOptional Whether or not to also check optional params.
-     */
-    public static IModuleParameter getParameterHandler(
-            ModuleParameters param, boolean withOptional) {
-        IModuleParameter value = sHandlerMap.get(param);
-        if (value == null && withOptional) {
-            return sOptionalHandlerMap.get(param);
-        }
-        return value;
-    }
-
-    /**
      * Resolve a {@link ModuleParameters} from its {@link String} representation.
      *
      * @see #resolveParam(ModuleParameters, boolean)
      */
-    public static Set<ModuleParameters> resolveParam(String param, boolean withOptional) {
+    public static Map<ModuleParameters, IModuleParameterHandler> resolveParam(
+            String param, boolean withOptional) {
         return resolveParam(ModuleParameters.valueOf(param.toUpperCase()), withOptional);
     }
 
@@ -104,19 +90,40 @@
      *
      * @param withOptional Whether or not to also check optional param groups.
      */
-    public static Set<ModuleParameters> resolveParam(ModuleParameters param, boolean withOptional) {
+    public static Map<ModuleParameters, IModuleParameterHandler> resolveParam(
+            ModuleParameters param, boolean withOptional) {
         Set<ModuleParameters> mappedParams = sGroupMap.get(param);
         if (mappedParams == null && withOptional) {
             mappedParams = sOptionalGroupMap.get(param);
         }
-        if (mappedParams != null) {
-            Set<ModuleParameters> resolvedParams = new HashSet<>();
-            for (ModuleParameters moduleParameters : mappedParams) {
-                resolvedParams.addAll(resolveParam(moduleParameters, withOptional));
+        if (mappedParams == null) {
+            IModuleParameterHandler handler = getParameterHandler(param, withOptional);
+            if (handler == null) {
+                // If the handler is not supported yet (for example, optional params) skip the
+                // param.
+                return new HashMap<>();
             }
-            return resolvedParams;
+            return Map.of(param, getParameterHandler(param, withOptional));
         }
+        // If the parameter is a group, expand it.
+        Map<ModuleParameters, IModuleParameterHandler> resolvedParams = new HashMap<>();
+        for (ModuleParameters moduleParameters : mappedParams) {
+            resolvedParams.put(moduleParameters, sHandlerMap.get(moduleParameters));
+        }
+        return resolvedParams;
+    }
 
-        return Set.of(param);
+    /**
+     * Returns the {@link IModuleParameterHandler} associated with the requested parameter.
+     *
+     * @param withOptional Whether or not to also check optional params.
+     */
+    private static IModuleParameterHandler getParameterHandler(
+            ModuleParameters param, boolean withOptional) {
+        IModuleParameterHandler value = sHandlerMap.get(param);
+        if (value == null && withOptional) {
+            return sOptionalHandlerMap.get(param);
+        }
+        return value;
     }
 }
diff --git a/src/com/android/tradefed/testtype/suite/params/NegativeHandler.java b/src/com/android/tradefed/testtype/suite/params/NegativeHandler.java
index e142f2d..2c3d59e 100644
--- a/src/com/android/tradefed/testtype/suite/params/NegativeHandler.java
+++ b/src/com/android/tradefed/testtype/suite/params/NegativeHandler.java
@@ -21,7 +21,7 @@
  * Handler that specify that nothing should be done and the parameter should not create any extra
  * module.
  */
-public class NegativeHandler implements IModuleParameter {
+public class NegativeHandler implements IModuleParameterHandler {
 
     @Override
     public String getParameterIdentifier() {
diff --git a/src/com/android/tradefed/testtype/suite/params/SecondaryUserHandler.java b/src/com/android/tradefed/testtype/suite/params/SecondaryUserHandler.java
index 85d5f49..7684b1b 100644
--- a/src/com/android/tradefed/testtype/suite/params/SecondaryUserHandler.java
+++ b/src/com/android/tradefed/testtype/suite/params/SecondaryUserHandler.java
@@ -28,7 +28,7 @@
 import java.util.Set;
 
 /** Handler for {@link ModuleParameters#SECONDARY_USER}. */
-public class SecondaryUserHandler implements IModuleParameter {
+public class SecondaryUserHandler implements IModuleParameterHandler {
     @Override
     public String getParameterIdentifier() {
         return "secondary_user";
diff --git a/src/com/android/tradefed/testtype/suite/params/multiuser/RunOnSecondaryUserParameterHandler.java b/src/com/android/tradefed/testtype/suite/params/multiuser/RunOnSecondaryUserParameterHandler.java
index 5e6e4ca..fbcea90 100644
--- a/src/com/android/tradefed/testtype/suite/params/multiuser/RunOnSecondaryUserParameterHandler.java
+++ b/src/com/android/tradefed/testtype/suite/params/multiuser/RunOnSecondaryUserParameterHandler.java
@@ -22,13 +22,13 @@
 import com.android.tradefed.targetprep.RunOnSecondaryUserTargetPreparer;
 import com.android.tradefed.testtype.IRemoteTest;
 import com.android.tradefed.testtype.ITestAnnotationFilterReceiver;
-import com.android.tradefed.testtype.suite.params.IModuleParameter;
+import com.android.tradefed.testtype.suite.params.IModuleParameterHandler;
 
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
-public class RunOnSecondaryUserParameterHandler implements IModuleParameter {
+public class RunOnSecondaryUserParameterHandler implements IModuleParameterHandler {
 
     private static final String REQUIRE_RUN_ON_SECONDARY_USER_NAME =
             "com.android.bedstead.harrier.annotations.RequireRunOnSecondaryUser";
diff --git a/src/com/android/tradefed/testtype/suite/params/multiuser/RunOnWorkProfileParameterHandler.java b/src/com/android/tradefed/testtype/suite/params/multiuser/RunOnWorkProfileParameterHandler.java
index a406d92..93a71af 100644
--- a/src/com/android/tradefed/testtype/suite/params/multiuser/RunOnWorkProfileParameterHandler.java
+++ b/src/com/android/tradefed/testtype/suite/params/multiuser/RunOnWorkProfileParameterHandler.java
@@ -22,13 +22,13 @@
 import com.android.tradefed.targetprep.RunOnWorkProfileTargetPreparer;
 import com.android.tradefed.testtype.IRemoteTest;
 import com.android.tradefed.testtype.ITestAnnotationFilterReceiver;
-import com.android.tradefed.testtype.suite.params.IModuleParameter;
+import com.android.tradefed.testtype.suite.params.IModuleParameterHandler;
 
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
-public class RunOnWorkProfileParameterHandler implements IModuleParameter {
+public class RunOnWorkProfileParameterHandler implements IModuleParameterHandler {
 
     private static final String REQUIRE_RUN_ON_WORK_PROFILE_NAME =
             "com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile";
diff --git a/src/com/android/tradefed/util/NativeCodeCoverageFlusher.java b/src/com/android/tradefed/util/NativeCodeCoverageFlusher.java
index 204b399..004723a 100644
--- a/src/com/android/tradefed/util/NativeCodeCoverageFlusher.java
+++ b/src/com/android/tradefed/util/NativeCodeCoverageFlusher.java
@@ -34,7 +34,7 @@
 
     private static final String EXTRACT_SIGCGT_FORMAT =
             "cat /proc/%d/status | grep SigCgt | awk '{ print $2 }'";
-    private static final long SIGNAL_37_BIT = 1 << (37 - 1);
+    private static final long SIGNAL_37_BIT = 1L << (37 - 1);
     private static final String COVERAGE_FLUSH_COMMAND_FORMAT = "kill -37 %s";
     private static final String CLEAR_CLANG_COVERAGE_FILES =
             "find /data/misc/trace -name '*.profraw' -delete";
diff --git a/src/com/android/tradefed/util/executor/ParallelDeviceExecutor.java b/src/com/android/tradefed/util/executor/ParallelDeviceExecutor.java
index 7a94bf5..9dfc8f0 100644
--- a/src/com/android/tradefed/util/executor/ParallelDeviceExecutor.java
+++ b/src/com/android/tradefed/util/executor/ParallelDeviceExecutor.java
@@ -78,7 +78,7 @@
             CLog.e(e);
             mErrors.add(e);
         } finally {
-            executor.shutdown();
+            executor.shutdownNow();
         }
         return results;
     }
diff --git a/test_framework/com/android/tradefed/targetprep/RunHostCommandTargetPreparer.java b/test_framework/com/android/tradefed/targetprep/RunHostCommandTargetPreparer.java
index e2692b6..aea713e 100644
--- a/test_framework/com/android/tradefed/targetprep/RunHostCommandTargetPreparer.java
+++ b/test_framework/com/android/tradefed/targetprep/RunHostCommandTargetPreparer.java
@@ -16,12 +16,14 @@
 
 package com.android.tradefed.targetprep;
 
+import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.config.GlobalConfiguration;
 import com.android.tradefed.config.Option;
 import com.android.tradefed.config.OptionClass;
 import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.IDeviceManager;
 import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.host.IHostOptions;
+import com.android.tradefed.host.IHostOptions.PermitLimitType;
 import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.log.ITestLogger;
 import com.android.tradefed.log.LogUtil.CLog;
@@ -33,7 +35,6 @@
 import com.android.tradefed.util.FileUtil;
 import com.android.tradefed.util.IRunUtil;
 import com.android.tradefed.util.RunUtil;
-import com.android.tradefed.build.IBuildInfo;
 
 import com.google.common.annotations.VisibleForTesting;
 
@@ -45,8 +46,8 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.regex.Pattern;
 import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /** Target preparer to run arbitrary host commands before and after running the test. */
 @OptionClass(alias = "run-host-command")
@@ -164,12 +165,12 @@
         replaceExtraFile(mSetUpCommands, buildInfo);
         try {
             if (mUseFlashingPermit) {
-                getDeviceManager().takeFlashingPermit();
+                getHostOptions().takePermit(PermitLimitType.CONCURRENT_FLASHER);
             }
             runCommandList(mSetUpCommands, device);
         } finally {
             if (mUseFlashingPermit) {
-                getDeviceManager().returnFlashingPermit();
+                getHostOptions().returnPermit(PermitLimitType.CONCURRENT_FLASHER);
             }
         }
 
@@ -191,14 +192,14 @@
         replaceExtraFile(mTearDownCommands, testInfo.getBuildInfo());
         try {
             if (mUseFlashingPermit) {
-                getDeviceManager().takeFlashingPermit();
+                getHostOptions().takePermit(PermitLimitType.CONCURRENT_FLASHER);
             }
             runCommandList(mTearDownCommands, device);
         } catch (TargetSetupError tse) {
             CLog.e(tse);
         } finally {
             if (mUseFlashingPermit) {
-                getDeviceManager().returnFlashingPermit();
+                getHostOptions().returnPermit(PermitLimitType.CONCURRENT_FLASHER);
             }
         }
 
@@ -337,10 +338,10 @@
         return mRunUtil;
     }
 
-    /** @return {@link IDeviceManager} instance used for flashing permits */
+    /** @return {@link IHostOptions} instance used for flashing permits */
     @VisibleForTesting
-    IDeviceManager getDeviceManager() {
-        return GlobalConfiguration.getDeviceManagerInstance();
+    IHostOptions getHostOptions() {
+        return GlobalConfiguration.getInstance().getHostOptions();
     }
 
     /**
diff --git a/test_framework/com/android/tradefed/targetprep/RunHostScriptTargetPreparer.java b/test_framework/com/android/tradefed/targetprep/RunHostScriptTargetPreparer.java
index 06fec43..85da2d6 100644
--- a/test_framework/com/android/tradefed/targetprep/RunHostScriptTargetPreparer.java
+++ b/test_framework/com/android/tradefed/targetprep/RunHostScriptTargetPreparer.java
@@ -22,6 +22,8 @@
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.IDeviceManager;
 import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.host.IHostOptions;
+import com.android.tradefed.host.IHostOptions.PermitLimitType;
 import com.android.tradefed.invoker.ExecutionFiles.FilesKey;
 import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.log.LogUtil.CLog;
@@ -89,12 +91,12 @@
 
         try {
             if (mUseFlashingPermit) {
-                getDeviceManager().takeFlashingPermit();
+                getHostOptions().takePermit(PermitLimitType.CONCURRENT_FLASHER);
             }
             executeScript(scriptFile, device);
         } finally {
             if (mUseFlashingPermit) {
-                getDeviceManager().returnFlashingPermit();
+                getHostOptions().returnPermit(PermitLimitType.CONCURRENT_FLASHER);
             }
         }
     }
@@ -114,6 +116,12 @@
         return GlobalConfiguration.getDeviceManagerInstance();
     }
 
+    /** @return {@link IHostOptions} instance used for flashing permits */
+    @VisibleForTesting
+    IHostOptions getHostOptions() {
+        return GlobalConfiguration.getInstance().getHostOptions();
+    }
+
     /** Find the script file to execute. */
     @Nullable
     private File findScriptFile(TestInformation testInfo) {
diff --git a/test_framework/com/android/tradefed/testtype/IsolatedHostTest.java b/test_framework/com/android/tradefed/testtype/IsolatedHostTest.java
index 8c44b00..581b26a 100644
--- a/test_framework/com/android/tradefed/testtype/IsolatedHostTest.java
+++ b/test_framework/com/android/tradefed/testtype/IsolatedHostTest.java
@@ -23,6 +23,7 @@
 import com.android.tradefed.config.Option.Importance;
 import com.android.tradefed.config.OptionClass;
 import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.error.HarnessRuntimeException;
 import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.invoker.logger.CurrentInvocation;
 import com.android.tradefed.isolation.FilterSpec;
@@ -38,6 +39,7 @@
 import com.android.tradefed.result.ITestInvocationListener;
 import com.android.tradefed.result.LogDataType;
 import com.android.tradefed.result.TestDescription;
+import com.android.tradefed.result.error.InfraErrorIdentifier;
 import com.android.tradefed.result.proto.TestRecordProto.FailureStatus;
 import com.android.tradefed.util.FileUtil;
 import com.android.tradefed.util.RunUtil;
@@ -154,7 +156,7 @@
             description =
                     "The android-all resource jar to be used, e.g."
                             + " 'android-all-R-robolectric-r0.jar'")
-    private String mAndroidAllName = "android-all-S-robolectric-r0.jar";
+    private String mAndroidAllName = "android-all-T-robolectric-r0.jar";
 
     @Option(
             name = TestTimeoutEnforcer.TEST_CASE_TIMEOUT_OPTION,
@@ -380,8 +382,9 @@
                 // This is contingent on the current android-all version.
                 File androidAllJar = FileUtil.findFile(testDir, mAndroidAllName);
                 if (androidAllJar == null) {
-                    throw new RuntimeException(
-                            "Could not find android-all jar needed for test execution.");
+                    throw new HarnessRuntimeException(
+                            "Could not find android-all jar needed for test execution.",
+                            InfraErrorIdentifier.ARTIFACT_NOT_FOUND);
                 }
                 paths.add(androidAllJar.getAbsolutePath());
             }