def _InitializeRamdisk()

in tools/android/emulator/emulated_device.py [0:0]


  def _InitializeRamdisk(self, system_image_dir, modified_ramdisk_path):
    """Pushes the boot properties to RAM Disk."""

    if modified_ramdisk_path:
      # Ramdisk is already initialized. Jus copy the file.
      logging.info(
          'Using pre initialized ramdisk.img: %s', modified_ramdisk_path)
      shutil.copy2(modified_ramdisk_path, self._RamdiskFile())
      return

    base_ramdisk = os.path.join(system_image_dir, 'ramdisk.img')
    ramdisk_dir = self._TempDir('ramdisk_repack')
    exploded_temp = os.path.join(ramdisk_dir, 'tmp')
    os.makedirs(exploded_temp)

    gunzip_proc = subprocess.Popen(
        ['gunzip', '-f', '-c', base_ramdisk],
        stdout=subprocess.PIPE)
    extract_cpio_proc = subprocess.Popen(
        ['cpio', '--extract'],
        cwd=exploded_temp,
        stdin=gunzip_proc.stdout,
        stdout=open('/dev/null'))
    gunzip_proc.stdout.close()
    extract_cpio_proc.wait()
    gunzip_proc.wait()

    set_props_in_init = True
    if os.path.exists(os.path.join(exploded_temp, 'default.prop')):
      set_props_in_init = False
      properties = '#\n# MOBILE_NINJAS_PROPERTIES\n#\n'
      for prop in self._metadata_pb.boot_property:
        properties += '%s=%s\n' % (prop.name, prop.value)
      properties += '#\n# MOBILE_NINJAS_RUNTIME_PROPERTIES\n#\n'
      for prop in self._RuntimeProperties():
        properties += '%s=%s\n' % (prop.name, prop.value)
      properties += '#\n# MOBILE_NINJAS_PROPERTIES_END\n#\n\n'
      with open(os.path.join(exploded_temp, 'default.prop'), 'r+') as prop_file:
        properties += prop_file.read()
        prop_file.seek(0)
        prop_file.write(properties)

    with open(os.path.join(exploded_temp, 'init.rc'), 'r+') as init_rc:
      in_adbd = False
      # note: do not use for line in init_rc. it reads large buffers
      # of init.rc into memory (updating file position). this makes
      # it hard for us to write back to the file into the correct
      # position once we encounter adbd's disabled line.
      line = init_rc.readline()
      while line:
        if not in_adbd:
          if line.startswith('service adbd'):
            in_adbd = True
        else:
          if self._metadata_pb.with_patched_adbd and ('disable' in line
                                                      or 'seclabel' in line):
            # I would _LOVE_ to have the seclabels checked on adbd.
            #
            # However I would love to reliably connect to adbd from multiple
            # adb servers even more.
            #
            # Post KitKat adbd stopped allowing multiple adb servers to talk
            # to it. So on post KitKat devices, we have to push an old (read
            # good, working, useful) version of adbd onto the emulator. This
            # version of adbd may not be compatible with the selinux policy
            # enforced on adbd. Therefore we disable that singular policy.
            #
            # TL;DR;. Given the fact that we have 4 choices:
            #
            # #1 use a broken adbd
            # #2 replace adbd with a working one and disable SELinux entirely
            # #3 replace adbd with a working one and disable the adbd seclabel
            # #4 fix adbd
            #
            # 4 is the most desirable - but outside our scope - 3 seems the
            # least harmful and most effective.
            #
            # I just want to freaking copy some bytes and exec a few shell
            # commands, is that so wrong? :)

            init_rc.seek(- len(line), 1)
            # comment it out!
            init_rc.write('#')
            init_rc.readline()
          else:
            if line.startswith('service ') or line.startswith('on '):
              in_adbd = False
        line = init_rc.readline()

      # at end of file.
      init_rc.write('\n')

      init_rc.write(
          'service g3_monitor /system/bin/app_process /system/bin com.google.'
          'android.apps.common.testing.services.activitycontroller.'
          'ActivityControllerMain\n')
      init_rc.write('    setenv CLASSPATH /g3_activity_controller.jar\n')
      init_rc.write('    disabled\n')  # property triggers will start us.
      init_rc.write('    user system\n')
      init_rc.write('    group system\n')

      # trigger as soon as service manager is ready.
      init_rc.write('\n')
      init_rc.write('on property:init.svc.servicemanager=running\n')
      init_rc.write('    start g3_monitor\n')

      # if zygote dies or restarts, we should restart so we can connect to the
      # new system server.
      init_rc.write('\n')
      init_rc.write('on service-exited-zygote\n')
      init_rc.write('    stop g3_monitor\n')
      init_rc.write('    start g3_monitor\n')
      init_rc.write('\n')

      # In this stanza we're setting up pipe_traversal for shell / push
      # and pull commands, it connects thru qemu-pipes to a suite of
      # sockets beneath $EMULATOR_CWD/sockets
      init_rc.write('service pipe_traverse /sbin/pipe_traversal ')
      init_rc.write('--action=emu-service\n')
      init_rc.write('    user root\n')
      init_rc.write('    group root\n')
      if self.GetApiVersion() >= 23:
        init_rc.write('    seclabel u:r:shell:s0\n')
      init_rc.write('\n')

      # Set up pipe_traversal to allow guest to connect to its own
      # Android telnet console. Also, apparently service names have a
      # maximum length of 16 characters.
      init_rc.write('service tn_pipe_traverse /sbin/pipe_traversal ')
      init_rc.write('--action=raw ')
      init_rc.write(
          '--external_addr=tcp-listen::%d ' % _DEFAULT_QEMU_TELNET_PORT)
      init_rc.write('--relay_addr=qemu-pipe:pipe:unix:sockets/qemu.mgmt ')
      init_rc.write('--frame_relay\n')
      init_rc.write('    user root\n')
      init_rc.write('    group root\n')
      if self.GetApiVersion() >= 23:
        init_rc.write('    seclabel u:r:shell:s0\n')
      init_rc.write('\n')

      init_rc.write('service waterfall /sbin/waterfall ')
      init_rc.write('    user root\n')
      init_rc.write('    group root\n')
      if self.GetApiVersion() >= 23:
        init_rc.write('    seclabel u:r:shell:s0\n')
      init_rc.write('\n')

      init_rc.write('on boot\n')
      init_rc.write('   start pipe_traverse\n')
      init_rc.write('   start tn_pipe_traverse\n')
      init_rc.write('   start waterfall\n')
      init_rc.write('   setprop ro.test_harness '
                    '${ro.kernel.enable_test_harness}\n')
      # if ro.kernel.enable_test_harness is not set, default to 1
      init_rc.write('   setprop ro.test_harness 1\n')
      init_rc.write('\n')

      if set_props_in_init:
        # System properties are loaded in post-fs. We want our read-only
        # properties to be set first (see e.g. b/70277971), so use early-fs.
        init_rc.write('on early-fs\n')
        for prop in self._metadata_pb.boot_property:
          init_rc.write('   setprop %s %s\n' %
                        (prop.name, self._EscapeInitToken(prop.value)))
        for prop in self._RuntimeProperties():
          init_rc.write('   setprop %s %s\n' %
                        (prop.name, self._EscapeInitToken(prop.value)))
        init_rc.write('\n')

    arch = self._metadata_pb.emulator_architecture
    pipe_traversal_path = os.path.join(exploded_temp, 'sbin', 'pipe_traversal')
    shutil.copy2(
        resources.GetResourceFilename(
            'android_test_support/'
            'tools/android/emulator/daemon/%s/pipe_traversal' % arch),
        pipe_traversal_path)
    os.chmod(pipe_traversal_path, stat.S_IRWXU)

    waterfall_path = os.path.join(exploded_temp, 'sbin', 'waterfall')
    shutil.copy2(
        resources.GetResourceFilename(
            'android_test_support/'
            'tools/android/emulator/daemon/%s/waterfall' % arch),
        waterfall_path)
    os.chmod(pipe_traversal_path, stat.S_IRWXU)

    # FYI: /sbin is only readable by root, so we put g3_activity_controller.jar
    # in / since it is run by the system user.
    shutil.copy2(
        resources.GetResourceFilename(
            'android_test_support/'
            'tools/android/emulator/daemon/g3_activity_controller.jar'),
        os.path.join(exploded_temp, 'g3_activity_controller.jar'))

    os.chmod(os.path.join(exploded_temp, 'g3_activity_controller.jar'),
             stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)


    if self._metadata_pb.with_patched_adbd:
      # hrm I wonder how borked ADBD is on this device.
      # oh well!!!
      resource_adb_path = os.path.join(
          'android_test_support', 'tools', 'android', 'emulator', 'daemon',
          self._metadata_pb.emulator_architecture, 'adbd')
      adbd_ramdisk_path = os.path.join(exploded_temp, 'sbin', 'adbd')
      with open(adbd_ramdisk_path, 'w+') as ramdisk_adbd:
        with contextlib.closing(
            resources.GetResourceAsFile(resource_adb_path)) as resource_adbd:
          adbd_bytes = resource_adbd.read()
          ramdisk_adbd.write(adbd_bytes)
          ramdisk_adbd.flush()
    find_proc = subprocess.Popen(
        ['find', '.', '-mindepth', '1', '-printf', '%P\n'],
        cwd=exploded_temp,
        stdout=subprocess.PIPE)
    create_cpio_proc = subprocess.Popen(
        ['cpio', '--create', '--format', 'newc', '--owner', '0:0'],
        cwd=exploded_temp,
        stdin=find_proc.stdout,
        stdout=subprocess.PIPE)
    gzip_proc = subprocess.Popen(
        ['gzip', '-c'],
        stdin=create_cpio_proc.stdout,
        stdout=open(self._RamdiskFile(), 'w+'))
    find_proc.stdout.close()
    create_cpio_proc.stdout.close()
    gzip_proc.wait()
    create_cpio_proc.wait()
    find_proc.wait()