From d148b0151854cd0db25b813c28a09db6c355a943 Mon Sep 17 00:00:00 2001 From: "cjhopman@chromium.org" Date: Fri, 19 Apr 2013 09:16:13 +0000 Subject: [Android] Use a script on the device for creating library symlinks On new versions of Android, re-installing an APK creates a new /lib/ folder for native libraries. This means we need to recreate all the symlinks in that directory (not just the ones that have changed). To make all these links quickly, it should run as a single adb command. To make that simple, we first create a simple script that, when run, creates all the symlinks for an APK. Then, after any install, we send a single adb command to run that script. This also requires that the apk_install script only triggers its dependents when it actually installs an apk. BUG=158821 Review URL: https://chromiumcodereview.appspot.com/14017010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@195124 0039d316-1c4b-4281-b951-d872f2087c98 --- build/android/gyp/apk_install.py | 8 ++- build/android/gyp/create_device_library_links.py | 77 +++++++++++++++--------- 2 files changed, 55 insertions(+), 30 deletions(-) (limited to 'build/android/gyp') diff --git a/build/android/gyp/apk_install.py b/build/android/gyp/apk_install.py index 8f1e69b..8cd1a60 100755 --- a/build/android/gyp/apk_install.py +++ b/build/android/gyp/apk_install.py @@ -27,6 +27,8 @@ def main(argv): help='Path to Android SDK tools.') parser.add_option('--apk-path', help='Path to .apk to install.') + parser.add_option('--install-record', + help='Path to install record (touched only when APK is installed).') parser.add_option('--stamp', help='Path to touch on success.') options, _ = parser.parse_args() @@ -37,10 +39,14 @@ def main(argv): 'install', '-r', options.apk_path] + def Install(): + build_utils.CheckCallDie(install_cmd) + build_utils.Touch(options.install_record) + serial_number = android_commands.AndroidCommands().Adb().GetSerialNumber() record_path = '%s.%s.md5.stamp' % (options.apk_path, serial_number) md5_check.CallAndRecordIfStale( - lambda: build_utils.CheckCallDie(install_cmd), + Install, record_path=record_path, input_paths=[options.apk_path], input_strings=install_cmd) diff --git a/build/android/gyp/create_device_library_links.py b/build/android/gyp/create_device_library_links.py index 48aa61e..5b8ee2b 100755 --- a/build/android/gyp/create_device_library_links.py +++ b/build/android/gyp/create_device_library_links.py @@ -25,57 +25,76 @@ sys.path.append(BUILD_ANDROID_DIR) from pylib import android_commands from pylib.utils import apk_helper +def RunShellCommand(adb, cmd): + output = adb.RunShellCommand(cmd) -def RunLinkCommand(adb, target, link): - cmd = ( - 'rm ' + link + ' > /dev/null 2>&1 \n' - 'ln -s ' + target + ' ' + link + '\n' - ) - result = adb.RunShellCommand(cmd) - - if result: + if output: raise Exception( - 'Unexpected output creating links on device.\n' + - '\n'.join(result)) + 'Unexpected output running command: ' + cmd + '\n' + + '\n'.join(output)) -def CreateLinks(options): +def CreateSymlinkScript(options): libraries = build_utils.ReadJson(options.libraries_json) - apk_package = apk_helper.GetPackageName(options.apk) - adb = android_commands.AndroidCommands() - serial_number = adb.Adb().GetSerialNumber() + link_cmd = ( + 'rm $APK_LIBRARIES_DIR/%(lib_basename)s > /dev/null 2>&1 \n' + 'ln -s $STRIPPED_LIBRARIES_DIR/%(lib_basename)s ' + '$APK_LIBRARIES_DIR/%(lib_basename)s \n' + ) + + script = '#!/bin/sh \n' + for lib in libraries: - host_path = os.path.join(options.libraries_dir, lib) - def CreateLink(): - link = '/data/data/' + apk_package + '/lib/' + lib - target = options.target_dir + '/' + lib - RunLinkCommand(adb, target, link) + script += link_cmd % { 'lib_basename': lib } + + with open(options.script_host_path, 'w') as scriptfile: + scriptfile.write(script) + - record_path = '%s.%s.link.md5.stamp' % (host_path, serial_number) - md5_check.CallAndRecordIfStale( - CreateLink, - record_path=record_path, - input_paths=[host_path]) +def TriggerSymlinkScript(options): + apk_package = apk_helper.GetPackageName(options.apk) + apk_libraries_dir = '/data/data/%s/lib' % apk_package + + adb = android_commands.AndroidCommands() + device_dir = os.path.dirname(options.script_device_path) + mkdir_cmd = ('if [ ! -e %(dir)s ]; then mkdir %(dir)s; fi ' % + { 'dir': device_dir }) + RunShellCommand(adb, mkdir_cmd) + adb.PushIfNeeded(options.script_host_path, options.script_device_path) + + trigger_cmd = ( + 'APK_LIBRARIES_DIR=%(apk_libraries_dir)s; ' + 'STRIPPED_LIBRARIES_DIR=%(target_dir)s; ' + '. %(script_device_path)s' + ) % { + 'apk_libraries_dir': apk_libraries_dir, + 'target_dir': options.target_dir, + 'script_device_path': options.script_device_path + } + RunShellCommand(adb, trigger_cmd) def main(argv): parser = optparse.OptionParser() parser.add_option('--apk', help='Path to the apk.') + parser.add_option('--script-host-path', + help='Path on the host for the symlink script.') + parser.add_option('--script-device-path', + help='Path on the device to push the created symlink script.') parser.add_option('--libraries-json', help='Path to the json list of native libraries.') parser.add_option('--target-dir', help='Device directory that contains the target libraries for symlinks.') - parser.add_option('--libraries-dir', - help='Directory that contains stripped libraries ' - '(used to determine if a library has changed since last push).') parser.add_option('--stamp', help='Path to touch on success.') options, _ = parser.parse_args() - required_options = ['apk', 'libraries_json', 'target_dir', 'libraries_dir'] + required_options = ['apk', 'libraries_json', 'script_host_path', + 'script_device_path', 'target_dir'] build_utils.CheckOptions(options, parser, required=required_options) - CreateLinks(options) + CreateSymlinkScript(options) + TriggerSymlinkScript(options) if options.stamp: build_utils.Touch(options.stamp) -- cgit v1.1