1# Copyright 2013 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""The android specific platform implementation module.""" 6 7import os 8import subprocess 9 10import cr 11 12# This is the set of environment variables that are not automatically 13# copied back from the envsetup shell 14_IGNORE_ENV = [ 15 'SHLVL', # Because it's nothing to do with envsetup 16 'GYP_GENERATOR_FLAGS', # because we set them in they gyp handler 17 'GYP_GENERATORS', # because we set them in they gyp handler 18 'PATH', # Because it gets a special merge handler 19 'GYP_DEFINES', # Because it gets a special merge handler 20] 21 22 23class AndroidPlatform(cr.Platform): 24 """The implementation of Platform for the android target.""" 25 26 ACTIVE = cr.Config.From( 27 CR_ENVSETUP=os.path.join('{CR_SRC}', 'build', 'android', 'envsetup.sh'), 28 CR_ADB=os.path.join('{CR_SRC}', 'third_party', 'android_tools', 'sdk', 29 'platform-tools', 'adb'), 30 CR_TARGET_SUFFIX='_apk', 31 CR_BINARY=os.path.join('{CR_BUILD_DIR}', 'apks', '{CR_TARGET_NAME}.apk'), 32 CR_ACTION='android.intent.action.VIEW', 33 CR_PACKAGE='com.google.android.apps.{CR_TARGET}', 34 CR_PROCESS='{CR_PACKAGE}', 35 CR_ACTIVITY='.Main', 36 CR_INTENT='{CR_PACKAGE}/{CR_ACTIVITY}', 37 CR_TEST_RUNNER=os.path.join( 38 '{CR_SRC}', 'build', 'android', 'test_runner.py'), 39 CR_ADB_GDB=os.path.join('{CR_SRC}', 'build', 'android', 'adb_gdb'), 40 CR_DEFAULT_TARGET='chrome_shell', 41 GYP_DEF_OS='android' 42 ) 43 44 def __init__(self): 45 super(AndroidPlatform, self).__init__() 46 self._env = cr.Config('android-env', literal=True, export=True) 47 self.detected_config.AddChild(self._env) 48 self._env_ready = False 49 self._env_paths = [] 50 51 @property 52 def priority(self): 53 return super(AndroidPlatform, self).priority + 1 54 55 def Prepare(self): 56 """Override Prepare from cr.Platform.""" 57 super(AndroidPlatform, self).Prepare() 58 try: 59 # capture the result of env setup if we have not already done so 60 if not self._env_ready: 61 # See what the env would be without env setup 62 before = cr.context.exported 63 # Run env setup and capture/parse its output 64 envsetup = 'source {CR_ENVSETUP}' 65 output = cr.Host.CaptureShell(envsetup + ' > /dev/null && env') 66 env_setup = cr.Config('envsetup', literal=True, export=True) 67 for line in output.split('\n'): 68 (key, op, value) = line.partition('=') 69 if op: 70 key = key.strip() 71 if key not in _IGNORE_ENV: 72 env_setup[key] = env_setup.ParseValue(value.strip()) 73 if key == 'PATH': 74 self._env_paths = value.strip().split(os.path.pathsep) 75 items = env_setup.exported.items() 76 if not items: 77 # Because of the way envsetup is run, the exit code does not make it 78 # back to us. Instead, we assume if we got no environment at all, it 79 # must have failed. 80 print 'Envsetup failed!' 81 exit(1) 82 # Find all the things that envsetup changed 83 for key, value in env_setup.exported.items(): 84 if str(value) != str(before.get(key, None)): 85 self._env[key] = value 86 self._env_ready = True 87 except subprocess.CalledProcessError, e: 88 exit(e.returncode) 89 90 @property 91 def paths(self): 92 return self._env_paths 93 94 95class AndroidInitHook(cr.InitHook): 96 """Android output directory init hook. 97 98 This makes sure that your client is android capable when you try 99 to make and android output directory. 100 """ 101 102 @property 103 def enabled(self): 104 return cr.AndroidPlatform.GetInstance().is_active 105 106 def Run(self, old_version, config): 107 _ = old_version, config # unused 108 # Check we are an android capable client 109 target_os = cr.context.gclient.get('target_os', []) 110 if 'android' in target_os: 111 return 112 url = cr.context.gclient.get('solutions', [{}])[0].get('url') 113 if (url.startswith('https://chrome-internal.googlesource.com/') and 114 url.endswith('/internal/apps.git')): 115 return 116 print 'This client is not android capable.' 117 print 'It can be made capable by adding android to the target_os list' 118 print 'in the .gclient file, and then syncing again.' 119 if not cr.Host.YesNo('Would you like to upgrade this client?'): 120 print 'Abandoning the creation of and android output directory.' 121 exit(1) 122 target_os.append('android') 123 cr.context.gclient['target_os'] = target_os 124 cr.base.client.WriteGClient() 125 print 'Client updated.' 126 print 'You may need to sync before an output directory can be made.' 127 if cr.Host.YesNo('Would you like to sync this client now?'): 128 cr.SyncCommand.Sync(["--nohooks"]) 129 130