/** {@inheritDoc} */
  @Override
  public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
    Assert.assertNotNull(mTestDevice);

    mAppListPath =
        new File(mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE), APP_LIST_FILE)
            .getAbsolutePath();
    mAppOutputPath =
        new File(mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE), APP_OUTPUT_FILE)
            .getAbsolutePath();

    setupAppInfos();

    // Setup the device
    mTestDevice.executeShellCommand(String.format("rm %s %s", mAppListPath, mAppOutputPath));
    mTestDevice.pushString(generateAppList(), mAppListPath);
    mTestDevice.executeShellCommand(String.format("chmod 750 %s", APP_LAUNCH));

    // Sleep 30 seconds to let device settle.
    RunUtil.getDefault().sleep(30 * 1000);

    // Run the test
    String output = mTestDevice.executeShellCommand(APP_LAUNCH);

    CLog.d("App launch output: %s", output);
    logOutputFile(listener);
  }
 /**
  * Wipes the device's external memory of test collateral from prior runs.
  *
  * @throws DeviceNotAvailableException If the device is unavailable or something happened while
  *     deleting files
  */
 private void preTestSetup() throws DeviceNotAvailableException {
   String extStore = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
   mUrlsFilePath = String.format("%s/%s", extStore, URLS_FILE_NAME);
   mStatusFilePath = String.format("%s/%s", extStore, STATUS_FILE_NAME);
   if (!mTestDevice.doesFileExist(mUrlsFilePath)) {
     throw new RuntimeException("missing URL list file at: " + mUrlsFilePath);
   }
   mTestDevice.executeShellCommand("rm " + mStatusFilePath);
 }
 /** {@inheritDoc} */
 @Override
 public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e)
     throws DeviceNotAvailableException {
   for (String cmd : mTeardownCommands) {
     // If the command had any output, the executeShellCommand method will log it at the
     // VERBOSE level; so no need to do any logging from here.
     CLog.d("About to run tearDown command on device %s: %s", device.getSerialNumber(), cmd);
     device.executeShellCommand(cmd);
   }
 }
  private boolean runCapture(int themeId, int layoutId, String imageName) throws Exception {
    final StringBuilder sb = new StringBuilder(START_CMD);
    sb.append(String.format(INTENT_INTEGER_EXTRA, EXTRA_THEME, themeId));
    sb.append(String.format(INTENT_INTEGER_EXTRA, EXTRA_LAYOUT, layoutId));
    sb.append(String.format(INTENT_INTEGER_EXTRA, EXTRA_TIMEOUT, CAPTURE_TIMEOUT));
    final String startCommand = sb.toString();
    // Clear logcat
    mDevice.executeAdbCommand("logcat", "-c");
    // Stop any existing instances
    mDevice.executeShellCommand(STOP_CMD);
    // Start activity
    mDevice.executeShellCommand(startCommand);

    boolean success = false;
    boolean waiting = true;
    while (waiting) {
      // Dump logcat.
      final String logs =
          mDevice.executeAdbCommand("logcat", "-v", "brief", "-d", CLASS + ":I", "*:S");
      // Search for string.
      final Scanner in = new Scanner(logs);
      while (in.hasNextLine()) {
        final String line = in.nextLine();
        if (line.startsWith("I/" + CLASS)) {
          final String[] lineSplit = line.split(":");
          final String s = lineSplit[1].trim();
          final String imageNameGenerated = lineSplit[2].trim();
          if (s.equals("OKAY") && imageNameGenerated.equals(imageName)) {
            success = true;
            waiting = false;
          } else if (s.equals("ERROR") && imageNameGenerated.equals(imageName)) {
            success = false;
            waiting = false;
          }
        }
      }
      in.close();
    }

    return success;
  }
  @TimeoutReq(minutes = 60)
  public void testHoloThemes() throws Exception {
    if (checkHardwareTypeSkipTest(mDevice.executeShellCommand(HARDWARE_TYPE_CMD).trim())) {
      Log.logAndDisplay(LogLevel.INFO, TAG, "Skipped HoloThemes test for watch and TV");
      return;
    }

    if (mReferences.isEmpty()) {
      Log.logAndDisplay(LogLevel.INFO, TAG, "Skipped HoloThemes test due to no reference images");
      return;
    }

    int numTasks = 0;
    for (int i = 0; i < NUM_THEMES; i++) {
      final String themeName = THEMES[i];
      for (int j = 0; j < NUM_LAYOUTS; j++) {
        final String name = String.format("%s_%s", themeName, LAYOUTS[j]);
        if (runCapture(i, j, name)) {
          final File ref = mReferences.get(name + ".png");
          if (!ref.exists()) {
            Log.logAndDisplay(
                LogLevel.INFO,
                TAG,
                "Skipping theme test due to missing reference for reference image " + name);
            continue;
          }
          mCompletionService.submit(new ComparisonTask(mDevice, ref, name));
          numTasks++;
        } else {
          Log.logAndDisplay(LogLevel.ERROR, TAG, "Capture failed: " + name);
        }
      }
    }
    int failures = 0;
    for (int i = 0; i < numTasks; i++) {
      failures += mCompletionService.take().get() ? 0 : 1;
    }
    assertTrue(failures + " failures in theme test", failures == 0);
  }
 /** Clean up the tmp output file from previous test runs */
 private void cleanOutputFile() throws DeviceNotAvailableException {
   mTestDevice.executeShellCommand(String.format("rm ${EXTERNAL_STORAGE}/%s", OUTPUT_PATH));
   if (mLogBtsnoop) {
     mTestDevice.executeShellCommand(String.format("rm ${EXTERNAL_STORAGE}/%s", BTSNOOP_LOG_FILE));
   }
 }
 /** Clean up output files from the last test run */
 private void cleanOutputFiles() throws DeviceNotAvailableException {
   CLog.d("Remove output file: %s", mOutputFile);
   mTestDevice.executeShellCommand(String.format("rm %s", mOutputFile));
 }