Add option to start goofy_device on boot

With this, we can control whether to run goofy host and/or goofy_device
on boot through tag files. The tag files will be initially set/unset by
finalize_bundle and may be changed during runtime if needed by the
factory flow.

BUG=chrome-os-partner:30202
TEST=Set goofy_device tag file and check goofy_device is running

Change-Id: Ibb0d01b8b832b12d664eda3cc6918fdd05038caf
Signed-off-by: Vic Yang <victoryang@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/206912
Reviewed-by: Peter Ammon <pca@google.com>
diff --git a/py/toolkit/installer.py b/py/toolkit/installer.py
index 166c427..2445acd 100755
--- a/py/toolkit/installer.py
+++ b/py/toolkit/installer.py
@@ -92,7 +92,8 @@
   # Whether to sudo when rsyncing; set to False for testing.
   _sudo = True
 
-  def __init__(self, src, dest, no_enable, system_root='/'):
+  def __init__(self, src, dest, no_enable, enable_host,
+               enable_device, system_root='/'):
     self._src = src
     self._system_root = system_root
     if dest == self._system_root:
@@ -133,6 +134,14 @@
     self._no_enable = no_enable
     self._tag_file = os.path.join(self._usr_local_dest, 'factory', 'enabled')
 
+    self._enable_host = enable_host
+    self._host_tag_file = os.path.join(self._var_dest, 'factory',
+                                       'state', 'run_goofy_host')
+
+    self._enable_device = enable_device
+    self._device_tag_file = os.path.join(self._var_dest, 'factory',
+                                         'state', 'run_goofy_device')
+
     if (not os.path.exists(self._usr_local_src) or
         not os.path.exists(self._var_src)):
       raise Exception(
@@ -182,6 +191,15 @@
           '***' % self._tag_file)
     return ret
 
+  def _SetTagFile(self, name, path, enabled):
+    """Install or remove a tag file."""
+    if enabled:
+      print '*** Installing %s enabled tag...' % name
+      Spawn(['touch', path], sudo=True, log=True, check_call=True)
+    else:
+      print '*** Removing %s enabled tag...' % name
+      Spawn(['rm', '-f', path], sudo=True, log=True, check_call=True)
+
   def Install(self):
     print '*** Installing factory toolkit...'
     for src, dest in ((self._usr_local_src, self._usr_local_dest),
@@ -201,12 +219,9 @@
       Spawn(['rsync', '-a', '--force', src + '/', dest],
             sudo=self._sudo, log=True, check_output=True)
 
-    if self._no_enable:
-      print '*** Removing factory enabled tag...'
-      Spawn(['rm', '-f', self._tag_file], sudo=True, log=True, check_call=True)
-    else:
-      print '*** Installing factory enabled tag...'
-      Spawn(['touch', self._tag_file], sudo=True, log=True, check_call=True)
+    self._SetTagFile('factory', self._tag_file, not self._no_enable)
+    self._SetTagFile('host', self._host_tag_file, self._enable_host)
+    self._SetTagFile('device', self._device_tag_file, self._enable_device)
 
     print '*** Installation completed.'
 
@@ -280,6 +295,21 @@
       help="Pack the files into a new factory toolkit")
   parser.add_argument('--repack', metavar='UNPACKED_TOOLKIT',
       help="Repack from previously unpacked toolkit")
+
+  parser.add_argument('--enable-host', dest='enable_host',
+      action='store_true',
+      help="Run goofy host on startup")
+  parser.add_argument('--no-enable-host', dest='enable_host',
+      action='store_false', help=argparse.SUPPRESS)
+  parser.set_defaults(enable_host=True)
+
+  parser.add_argument('--enable-device', dest='enable_device',
+      action='store_true',
+      help="Run goofy_device on startup")
+  parser.add_argument('--no-enable-device', dest='enable_device',
+      action='store_false', help=argparse.SUPPRESS)
+  parser.set_defaults(enable_device=False)
+
   args = parser.parse_args()
 
   src_root = factory.FACTORY_PATH
@@ -321,7 +351,8 @@
 
   with (MountPartition(args.dest, 1, rw=True) if patch_test_image
         else DummyContext(args.dest)) as dest:
-    installer = FactoryToolkitInstaller(src_root, dest, args.no_enable)
+    installer = FactoryToolkitInstaller(
+        src_root, dest, args.no_enable, args.enable_host, args.enable_device)
 
     print installer.WarningMessage(args.dest if patch_test_image else None)