public void killApp() throws Exception {
    // try to kill just by calling exit
    try {
      Client.getInstance().map("java.lang.System", "exit", 0);
    } catch (Exception e) {
      // this will actually throw an exception since it doesnt get a response from this command
    }

    // shut down the thread
    if (ap != null) {
      ap.close();
      ap.interrupt();
      ap = null;
    }

    // wait for the server to be dead
    for (int x = 0; x < 10; x++) {
      // try to make a query.. if it doesnt work then sleep
      TestLogger.get().info("Trying to see if server is still available..");

      if (!Client.getInstance().isListening()) break;

      if (x == 9) throw new Exception("Server is still available, but should not be");

      Thread.sleep(2000);
    }
  }
  public void startApp() throws Exception {
    ap = new AppThread();
    ap.start();

    for (int x = 0; x < 10; x++) {
      // try to make a query.. if it doesnt work then sleep
      TestLogger.get().info("Trying to ping test server..");
      if (Client.getInstance().isListening()) break;

      if (x == 9) throw new Exception("Could not contact test server");

      Thread.sleep(5000);
    }
  }
  // This is called in the failure method override above
  public void tearDown() throws Exception {
    try {
      EmSingleton.get().close();
      killApp();

      // clear stale ADB ports
      Utils.clearStaleADBTunnels("ROBO");

      // stop logcat
      TestLogger.get().info("Stopping logcat");
      logcatLogger.stopLogListener();
      logcatLogger = null;

      // store logs
      Device.storeLogs("adb_robo.log", "robo.log");

      // stop EventManager
      EmSingleton.release();
    } catch (Exception e) {

    } finally {
      DebugBridge.destroy();
    }
  }
  /**
   * This is the generic test setup function
   *
   * @param relaunch - true if this is an app relaunch
   * @param clearAppData - true if you want app data cleared, false otherwise
   */
  public void setUp(String testName, Boolean relaunch, Boolean clearAppData) throws Exception {
    if (!relaunch) {
      logger.info("Starting test {}", testName);
      Device.setupLogDirectories(testName);

      // clear stale ports
      Utils.clearStaleADBTunnels("ROBO");

      // find a useable port
      PortSingleton.getInstance().setPort(Utils.getFreePort());

      // create adb tunnel
      Utils.addADBTunnelWithPIDFile("ROBO", PortSingleton.getInstance().getPort());
    }

    // see if a server is already listening
    boolean clientWasListening = false;
    if (Client.getInstance().isListening()) {
      clientWasListening = true;
    }

    if (clearAppData) {
      // clear app data - this has the side effect of killing a running app
      // TODO: this only works on 2.3+.. need a solution for 2.1+
      Device.clearAppData(app_package);
    }

    // wait for the client to stop listening if it was previously listening
    if (clientWasListening) {
      // wait for the server to be dead
      for (int x = 0; x < 10; x++) {
        // try to make a query.. if it doesnt work then sleep
        TestLogger.get().info("Trying to see if server is still available..");

        if (!Client.getInstance().isListening()) break;

        if (x == 9) throw new Exception("Server is still available, but should not be");

        Thread.sleep(2000);
      }
    }

    if (!relaunch) {
      TestLogger.get().info("Starting logcat");
      if (logcatLogger == null) {
        logcatLogger =
            new LogcatLogger(
                System.getProperty("java.io.tmpdir") + File.separator + "adb_robo.log");
      }
      logcatLogger.startLogListener();

      // set up event manager
      EmSingleton.get().clearEvents();
    }

    // starting test runner
    TestLogger.get().info("Starting RC Runner");

    // start app
    startApp();
  }