Make mobile-install wait for debugger

--
PiperOrigin-RevId: 150372383
MOS_MIGRATED_REVID=150372383
diff --git a/site/versions/master/docs/bazel-user-manual.html b/site/versions/master/docs/bazel-user-manual.html
index 89417ea..f1be716 100644
--- a/site/versions/master/docs/bazel-user-manual.html
+++ b/site/versions/master/docs/bazel-user-manual.html
@@ -3134,12 +3134,23 @@
   Starts the app in a clean state after installing. Equivalent to
   <code>--start=COLD</code>.
 </p>
-<h4 id='flag--start'><code class='flag'>--start (NO|COLD|WARM)</code></h4>
+<h4 id='flag--debug_app'><code class='flag'>--debug_app</code></h4>
 <p>
-  How the app should be started after installing it. Set to <code>WARM</code> to
-  preserve and restore application state on incremental installs. Set to
-  <code>COLD</code> to start the app from a clean state after install. Defaults
-  <code>NO</code> which does not start the app.
+  Waits for debugger to be attached before starting the app in a clean state after installing.
+  Equivalent to <code>--start=DEBUG</code>.
+</p>
+<h4 id='flag--start'><code class='flag'>--start=<i>start_type</i></code></h4>
+<p>
+  How the app should be started after installing it. Supported <i>start_type</i>s are:
+  <ul>
+    <li><code>NO</code> Does not start the app. This is the default.</li>
+    <li><code>COLD</code> Starts the app from a clean state after install.</li>
+    <li><code>WARM</code> Preserves and restores the application state on incremental installs.</li>
+    <li><code>DEBUG</code> Waits for the debugger before starting the app in a clean state after install.</li>
+  </ul>
+  Note that if more than one of <code class='flag'>--start=<i>start_type</i></code>,
+  <code class='flag'>--start_app</code> or
+  <code class='flag'>--debug_app</code> is set, the last value will be used.
 </p>
 <h4 id='flag--adb'><code class='flag'>--adb <var>path</var></code></h4>
 <p>
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/WriteAdbArgsAction.java b/src/main/java/com/google/devtools/build/lib/rules/android/WriteAdbArgsAction.java
index 6ddf13d..19a4509 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/WriteAdbArgsAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/WriteAdbArgsAction.java
@@ -83,6 +83,13 @@
         help = "Whether to start the app after installing it.",
         expansion = {"--start=COLD"})
     public Void startApp;
+
+    @Option(name = "debug_app",
+        category = "mobile_install",
+        defaultValue = "null",
+        help = "Whether to wait for the debugger before starting the app.",
+        expansion = {"--start=DEBUG"})
+    public Void debugApp;
   }
 
   public WriteAdbArgsAction(ActionOwner owner, Artifact outputFile) {
@@ -163,7 +170,9 @@
      * The app will save its state before installing, and be restored from that state after
      * installing.
      */
-    WARM
+    WARM,
+    /** The app will wait for debugger to attach before restarting from clean state after install */
+    DEBUG
   }
 
   /** Converter for the --start option. */
diff --git a/tools/android/incremental_install.py b/tools/android/incremental_install.py
index bef9246..b02d722 100644
--- a/tools/android/incremental_install.py
+++ b/tools/android/incremental_install.py
@@ -46,10 +46,11 @@
                       "The number of instances of adb to use in parallel to "
                       "update files on the device",
                       lower_bound=1)
-gflags.DEFINE_enum("start", "no", ["no", "cold", "warm"], "Whether/how to "
-                   "start the app after installing it. 'cold' and 'warm' will "
-                   "both cause the app to be started, 'warm' will start it "
-                   "with previously saved application state.")
+gflags.DEFINE_enum("start", "no", ["no", "cold", "warm", "debug"],
+                   "Whether/how to start the app after installing it. 'cold' "
+                   "and 'warm' will both cause the app to be started, 'warm' "
+                   "will start it with previously saved application state, "
+                   "'debug' will wait for the debugger before a clean start.")
 gflags.DEFINE_boolean("start_app", False, "Deprecated, use 'start'.")
 gflags.DEFINE_string("user_home_dir", None, "Path to the user's home directory")
 gflags.DEFINE_string("flagfile", None,
@@ -275,8 +276,12 @@
     self._Shell("input keyevent KEYCODE_APP_SWITCH")
     self._Shell("am kill %s" % package)
 
-  def StartApp(self, package):
+  def StartApp(self, package, start_type):
     """Starts the app with the given package."""
+    if start_type == "debug":
+      self._Shell("am set-debug-app -w --persistent %s" % package)
+    else:
+      self._Shell("am clear-debug-app %s" % package)
     self._Shell("monkey -p %s -c android.intent.category.LAUNCHER 1" % package)
 
   def _Shell(self, cmd):
@@ -722,9 +727,9 @@
         else:
           adb.StopApp(app_package)
 
-    if start_type in ["cold", "warm"]:
+    if start_type in ["cold", "warm", "debug"]:
       logging.info("Starting application %s", app_package)
-      adb.StartApp(app_package)
+      adb.StartApp(app_package, start_type)
 
     with file(output_marker, "w") as _:
       pass
diff --git a/tools/android/incremental_install_test.py b/tools/android/incremental_install_test.py
index 64b31eb..46ceb3e 100644
--- a/tools/android/incremental_install_test.py
+++ b/tools/android/incremental_install_test.py
@@ -531,6 +531,25 @@
     self.assertTrue(("monkey -p %s -c android.intent.category.LAUNCHER 1" %
                      self._APP_PACKAGE) in self._mock_adb.shell_cmdlns)
 
+  def testDebugStart(self):
+    self._CreateZip()
+
+    with open("dex1", "w") as f:
+      f.write("content3")
+
+    self._CreateLocalManifest(
+        "zip1 zp1 ip1 0",
+        "zip1 zp2 ip2 0",
+        "dex1 - ip3 0")
+
+    self._CallIncrementalInstall(incremental=False, start_type="debug")
+    enable_debug_cmd = ("am set-debug-app -w --persistent %s" %
+                        self._APP_PACKAGE)
+    start_app_cmd = ("monkey -p %s -c android.intent.category.LAUNCHER 1" %
+                     self._APP_PACKAGE)
+    self.assertTrue(enable_debug_cmd in self._mock_adb.shell_cmdlns)
+    self.assertTrue(start_app_cmd in self._mock_adb.shell_cmdlns)
+
   def testColdStop(self):
     self._CreateRemoteManifest(
         "zip1 zp1 ip1 0",