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()