1#!/usr/bin/env vpython3 2# Copyright 2015 The Chromium Authors 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6"""Utility for reading / writing command-line flag files on device(s).""" 7 8 9import argparse 10import logging 11import sys 12 13import devil_chromium 14 15from devil.android import device_errors 16from devil.android import device_utils 17from devil.android import flag_changer 18from devil.android.tools import script_common 19from devil.utils import cmd_helper 20from devil.utils import logging_common 21 22 23def CheckBuildTypeSupportsFlags(device, command_line_flags_file): 24 is_webview = command_line_flags_file == 'webview-command-line' 25 if device.IsUserBuild() and is_webview: 26 raise device_errors.CommandFailedError( 27 'WebView only respects flags on a userdebug or eng device, yours ' 28 'is a user build.', device) 29 if device.IsUserBuild(): 30 logging.warning( 31 'Your device (%s) is a user build; Chrome may or may not pick up ' 32 'your commandline flags. Check your ' 33 '"command_line_on_non_rooted_enabled" preference, or switch ' 34 'devices.', device) 35 36 37def main(): 38 parser = argparse.ArgumentParser(description=__doc__) 39 parser.usage = '''%(prog)s --name FILENAME [--device SERIAL] [flags...] 40 41No flags: Prints existing command-line file. 42Empty string: Deletes command-line file. 43Otherwise: Writes command-line file. 44 45''' 46 parser.add_argument('--name', required=True, 47 help='Name of file where to store flags on the device.') 48 parser.add_argument('-e', '--executable', dest='executable', default='chrome', 49 help='(deprecated) No longer used.') 50 script_common.AddEnvironmentArguments(parser) 51 script_common.AddDeviceArguments(parser) 52 logging_common.AddLoggingArguments(parser) 53 54 args, remote_args = parser.parse_known_args() 55 devil_chromium.Initialize(adb_path=args.adb_path) 56 logging_common.InitializeLogging(args) 57 58 devices = device_utils.DeviceUtils.HealthyDevices(device_arg=args.devices, 59 default_retries=0) 60 all_devices = device_utils.DeviceUtils.parallel(devices) 61 62 if not remote_args: 63 # No args == do not update, just print flags. 64 remote_args = None 65 action = '' 66 elif len(remote_args) == 1 and not remote_args[0]: 67 # Single empty string arg == delete flags 68 remote_args = [] 69 action = 'Deleted command line file. ' 70 else: 71 if remote_args[0] == '--': 72 remote_args.pop(0) 73 action = 'Wrote command line file. ' 74 75 def update_flags(device): 76 CheckBuildTypeSupportsFlags(device, args.name) 77 changer = flag_changer.FlagChanger(device, args.name) 78 if remote_args is not None: 79 flags = changer.ReplaceFlags(remote_args) 80 else: 81 flags = changer.GetCurrentFlags() 82 return (device, device.build_description, flags) 83 84 updated_values = all_devices.pMap(update_flags).pGet(None) 85 86 print('%sCurrent flags (in %s):' % (action, args.name)) 87 for d, desc, flags in updated_values: 88 if flags: 89 # Shell-quote flags for easy copy/paste as new args on the terminal. 90 quoted_flags = ' '.join(cmd_helper.SingleQuote(f) for f in sorted(flags)) 91 else: 92 quoted_flags = '( empty )' 93 print(' %s (%s): %s' % (d, desc, quoted_flags)) 94 95 return 0 96 97 98if __name__ == '__main__': 99 sys.exit(main()) 100