1*c2e18aaaSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*c2e18aaaSAndroid Build Coastguard Worker# 3*c2e18aaaSAndroid Build Coastguard Worker# Copyright 2020 - The Android Open Source Project 4*c2e18aaaSAndroid Build Coastguard Worker# 5*c2e18aaaSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*c2e18aaaSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*c2e18aaaSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*c2e18aaaSAndroid Build Coastguard Worker# 9*c2e18aaaSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*c2e18aaaSAndroid Build Coastguard Worker# 11*c2e18aaaSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*c2e18aaaSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*c2e18aaaSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*c2e18aaaSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*c2e18aaaSAndroid Build Coastguard Worker# limitations under the License. 16*c2e18aaaSAndroid Build Coastguard Worker 17*c2e18aaaSAndroid Build Coastguard Worker"""Configs the jdk.table.xml. 18*c2e18aaaSAndroid Build Coastguard Worker 19*c2e18aaaSAndroid Build Coastguard WorkerIn order to enable the feature "Attach debugger to Android process" in Android 20*c2e18aaaSAndroid Build Coastguard WorkerStudio or IntelliJ, AIDEGen needs the JDK and Android SDK been set up. The class 21*c2e18aaaSAndroid Build Coastguard WorkerJDKTableXML parses the jdk.table.xml to find the existing JDK and Android SDK 22*c2e18aaaSAndroid Build Coastguard Workerinformation. If they do not exist, AIDEGen will create them. 23*c2e18aaaSAndroid Build Coastguard Worker 24*c2e18aaaSAndroid Build Coastguard Worker Usage example: 25*c2e18aaaSAndroid Build Coastguard Worker jdk_table_xml = JDKTableXML(jdk_table_xml_file, 26*c2e18aaaSAndroid Build Coastguard Worker jdk_template, 27*c2e18aaaSAndroid Build Coastguard Worker default_jdk_path, 28*c2e18aaaSAndroid Build Coastguard Worker default_android_sdk_path) 29*c2e18aaaSAndroid Build Coastguard Worker if jdk_table_xml.config_jdk_table_xml(): 30*c2e18aaaSAndroid Build Coastguard Worker android_sdk_version = jdk_table_xml.android_sdk_version 31*c2e18aaaSAndroid Build Coastguard Worker""" 32*c2e18aaaSAndroid Build Coastguard Worker 33*c2e18aaaSAndroid Build Coastguard Workerfrom __future__ import absolute_import 34*c2e18aaaSAndroid Build Coastguard Worker 35*c2e18aaaSAndroid Build Coastguard Workerimport os 36*c2e18aaaSAndroid Build Coastguard Worker 37*c2e18aaaSAndroid Build Coastguard Workerfrom xml.etree import ElementTree 38*c2e18aaaSAndroid Build Coastguard Worker 39*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen import constant 40*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen import templates 41*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import aidegen_metrics 42*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import common_util 43*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import xml_util 44*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.sdk import android_sdk 45*c2e18aaaSAndroid Build Coastguard Worker 46*c2e18aaaSAndroid Build Coastguard Worker 47*c2e18aaaSAndroid Build Coastguard Workerclass JDKTableXML: 48*c2e18aaaSAndroid Build Coastguard Worker """Configs jdk.table.xml for IntelliJ and Android Studio. 49*c2e18aaaSAndroid Build Coastguard Worker 50*c2e18aaaSAndroid Build Coastguard Worker Attributes: 51*c2e18aaaSAndroid Build Coastguard Worker _config_file: The absolute file path of the jdk.table.xml, the file 52*c2e18aaaSAndroid Build Coastguard Worker might not exist. 53*c2e18aaaSAndroid Build Coastguard Worker _jdk_content: A string, the content of the JDK configuration. 54*c2e18aaaSAndroid Build Coastguard Worker _jdk_path: The path of JDK in android project. 55*c2e18aaaSAndroid Build Coastguard Worker _default_android_sdk_path: The default path to the Android SDK. 56*c2e18aaaSAndroid Build Coastguard Worker _platform_version: The version name of the platform, e.g. android-29 57*c2e18aaaSAndroid Build Coastguard Worker _android_sdk_version: The version name of the Android SDK in the 58*c2e18aaaSAndroid Build Coastguard Worker jdk.table.xml, e.g. Android API 29 Platform 59*c2e18aaaSAndroid Build Coastguard Worker _modify_config: A boolean, True to write new content to jdk.table.xml. 60*c2e18aaaSAndroid Build Coastguard Worker _xml: An xml.etree.ElementTree object contains the XML parsing result. 61*c2e18aaaSAndroid Build Coastguard Worker _sdk: An AndroidSDK object to get the Android SDK path and platform 62*c2e18aaaSAndroid Build Coastguard Worker mapping. 63*c2e18aaaSAndroid Build Coastguard Worker """ 64*c2e18aaaSAndroid Build Coastguard Worker _JDK = 'jdk' 65*c2e18aaaSAndroid Build Coastguard Worker _NAME = 'name' 66*c2e18aaaSAndroid Build Coastguard Worker _TYPE = 'type' 67*c2e18aaaSAndroid Build Coastguard Worker _VALUE = 'value' 68*c2e18aaaSAndroid Build Coastguard Worker _SDK = 'sdk' 69*c2e18aaaSAndroid Build Coastguard Worker _HOMEPATH = 'homePath' 70*c2e18aaaSAndroid Build Coastguard Worker _ADDITIONAL = 'additional' 71*c2e18aaaSAndroid Build Coastguard Worker _ANDROID_SDK = 'Android SDK' 72*c2e18aaaSAndroid Build Coastguard Worker _JAVA_SDK = 'JavaSDK' 73*c2e18aaaSAndroid Build Coastguard Worker _JDK_VERSION = 'JDK21' 74*c2e18aaaSAndroid Build Coastguard Worker _APPLICATION = 'application' 75*c2e18aaaSAndroid Build Coastguard Worker _COMPONENT = 'component' 76*c2e18aaaSAndroid Build Coastguard Worker _PROJECTJDKTABLE = 'ProjectJdkTable' 77*c2e18aaaSAndroid Build Coastguard Worker _LAST_TAG_TAIL = '\n ' 78*c2e18aaaSAndroid Build Coastguard Worker _NEW_TAG_TAIL = '\n ' 79*c2e18aaaSAndroid Build Coastguard Worker _ANDROID_SDK_VERSION = 'Android API {CODE_NAME} Platform' 80*c2e18aaaSAndroid Build Coastguard Worker _DEFAULT_JDK_TABLE_XML = os.path.join(common_util.get_android_root_dir(), 81*c2e18aaaSAndroid Build Coastguard Worker constant.AIDEGEN_ROOT_PATH, 82*c2e18aaaSAndroid Build Coastguard Worker 'data', 83*c2e18aaaSAndroid Build Coastguard Worker 'jdk.table.xml') 84*c2e18aaaSAndroid Build Coastguard Worker _ILLEGAL_XML = ('The {XML} is not an useful XML file for IntelliJ. Do you ' 85*c2e18aaaSAndroid Build Coastguard Worker 'agree AIDEGen override it?(y/n)') 86*c2e18aaaSAndroid Build Coastguard Worker _IGNORE_XML_WARNING = ('The {XML} is not an useful XML file for IntelliJ. ' 87*c2e18aaaSAndroid Build Coastguard Worker 'It causes the feature "Attach debugger to Android ' 88*c2e18aaaSAndroid Build Coastguard Worker 'process" to be disabled.') 89*c2e18aaaSAndroid Build Coastguard Worker 90*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, config_file, jdk_content, jdk_path, 91*c2e18aaaSAndroid Build Coastguard Worker default_android_sdk_path): 92*c2e18aaaSAndroid Build Coastguard Worker """JDKTableXML initialize. 93*c2e18aaaSAndroid Build Coastguard Worker 94*c2e18aaaSAndroid Build Coastguard Worker Args: 95*c2e18aaaSAndroid Build Coastguard Worker config_file: The absolute file path of the jdk.table.xml, the file 96*c2e18aaaSAndroid Build Coastguard Worker might not exist. 97*c2e18aaaSAndroid Build Coastguard Worker jdk_content: A string, the content of the JDK configuration. 98*c2e18aaaSAndroid Build Coastguard Worker jdk_path: The path of JDK in android project. 99*c2e18aaaSAndroid Build Coastguard Worker default_android_sdk_path: The default absolute path to the Android 100*c2e18aaaSAndroid Build Coastguard Worker SDK. 101*c2e18aaaSAndroid Build Coastguard Worker """ 102*c2e18aaaSAndroid Build Coastguard Worker self._config_file = config_file 103*c2e18aaaSAndroid Build Coastguard Worker self._jdk_content = jdk_content 104*c2e18aaaSAndroid Build Coastguard Worker self._jdk_path = jdk_path 105*c2e18aaaSAndroid Build Coastguard Worker self._default_android_sdk_path = default_android_sdk_path 106*c2e18aaaSAndroid Build Coastguard Worker self._xml = None 107*c2e18aaaSAndroid Build Coastguard Worker if os.path.exists(config_file): 108*c2e18aaaSAndroid Build Coastguard Worker xml_file = config_file 109*c2e18aaaSAndroid Build Coastguard Worker else: 110*c2e18aaaSAndroid Build Coastguard Worker xml_file = self._DEFAULT_JDK_TABLE_XML 111*c2e18aaaSAndroid Build Coastguard Worker common_util.file_generate(xml_file, templates.JDK_TABLE_XML) 112*c2e18aaaSAndroid Build Coastguard Worker self._xml = xml_util.parse_xml(xml_file) 113*c2e18aaaSAndroid Build Coastguard Worker self._platform_version = None 114*c2e18aaaSAndroid Build Coastguard Worker self._android_sdk_version = None 115*c2e18aaaSAndroid Build Coastguard Worker self._modify_config = False 116*c2e18aaaSAndroid Build Coastguard Worker self._sdk = android_sdk.AndroidSDK() 117*c2e18aaaSAndroid Build Coastguard Worker 118*c2e18aaaSAndroid Build Coastguard Worker @property 119*c2e18aaaSAndroid Build Coastguard Worker def android_sdk_version(self): 120*c2e18aaaSAndroid Build Coastguard Worker """Gets the Android SDK version.""" 121*c2e18aaaSAndroid Build Coastguard Worker return self._android_sdk_version 122*c2e18aaaSAndroid Build Coastguard Worker 123*c2e18aaaSAndroid Build Coastguard Worker def _check_structure(self): 124*c2e18aaaSAndroid Build Coastguard Worker """Checks the XML's structure is correct. 125*c2e18aaaSAndroid Build Coastguard Worker 126*c2e18aaaSAndroid Build Coastguard Worker The content of the XML file should have a root tag as <application> and 127*c2e18aaaSAndroid Build Coastguard Worker a child tag <component> of it. 128*c2e18aaaSAndroid Build Coastguard Worker E.g. 129*c2e18aaaSAndroid Build Coastguard Worker <application> 130*c2e18aaaSAndroid Build Coastguard Worker <component name="ProjectJdkTable"> 131*c2e18aaaSAndroid Build Coastguard Worker ... 132*c2e18aaaSAndroid Build Coastguard Worker </component> 133*c2e18aaaSAndroid Build Coastguard Worker </application> 134*c2e18aaaSAndroid Build Coastguard Worker 135*c2e18aaaSAndroid Build Coastguard Worker Returns: 136*c2e18aaaSAndroid Build Coastguard Worker Boolean: True if the structure is correct, otherwise False. 137*c2e18aaaSAndroid Build Coastguard Worker """ 138*c2e18aaaSAndroid Build Coastguard Worker if (not self._xml or self._xml.getroot().tag != self._APPLICATION 139*c2e18aaaSAndroid Build Coastguard Worker or self._xml.find(self._COMPONENT) is None 140*c2e18aaaSAndroid Build Coastguard Worker or self._xml.find(self._COMPONENT).tag != self._COMPONENT): 141*c2e18aaaSAndroid Build Coastguard Worker return False 142*c2e18aaaSAndroid Build Coastguard Worker return self._xml.find(self._COMPONENT).get( 143*c2e18aaaSAndroid Build Coastguard Worker self._NAME) == self._PROJECTJDKTABLE 144*c2e18aaaSAndroid Build Coastguard Worker 145*c2e18aaaSAndroid Build Coastguard Worker def _override_xml(self): 146*c2e18aaaSAndroid Build Coastguard Worker """Overrides the XML file when it's invalid. 147*c2e18aaaSAndroid Build Coastguard Worker 148*c2e18aaaSAndroid Build Coastguard Worker Returns: 149*c2e18aaaSAndroid Build Coastguard Worker A boolean, True when developers choose to override the XML file, 150*c2e18aaaSAndroid Build Coastguard Worker otherwise False. 151*c2e18aaaSAndroid Build Coastguard Worker """ 152*c2e18aaaSAndroid Build Coastguard Worker input_data = input(self._ILLEGAL_XML.format(XML=self._config_file)) 153*c2e18aaaSAndroid Build Coastguard Worker while input_data not in ('y', 'n'): 154*c2e18aaaSAndroid Build Coastguard Worker input_data = input('Please type y(Yes) or n(No): ') 155*c2e18aaaSAndroid Build Coastguard Worker if input_data == 'y': 156*c2e18aaaSAndroid Build Coastguard Worker # Record the exception about wrong XML format. 157*c2e18aaaSAndroid Build Coastguard Worker if self._xml: 158*c2e18aaaSAndroid Build Coastguard Worker aidegen_metrics.send_exception_metrics( 159*c2e18aaaSAndroid Build Coastguard Worker constant.XML_PARSING_FAILURE, '', 160*c2e18aaaSAndroid Build Coastguard Worker ElementTree.tostring(self._xml.getroot()), '') 161*c2e18aaaSAndroid Build Coastguard Worker self._xml = xml_util.parse_xml(self._DEFAULT_JDK_TABLE_XML) 162*c2e18aaaSAndroid Build Coastguard Worker return True 163*c2e18aaaSAndroid Build Coastguard Worker return False 164*c2e18aaaSAndroid Build Coastguard Worker 165*c2e18aaaSAndroid Build Coastguard Worker def _check_jdk21_in_xml(self): 166*c2e18aaaSAndroid Build Coastguard Worker """Checks if the JDK21 is already set in jdk.table.xml. 167*c2e18aaaSAndroid Build Coastguard Worker 168*c2e18aaaSAndroid Build Coastguard Worker Returns: 169*c2e18aaaSAndroid Build Coastguard Worker Boolean: True if the JDK21 exists else False. 170*c2e18aaaSAndroid Build Coastguard Worker """ 171*c2e18aaaSAndroid Build Coastguard Worker for jdk in self._xml.iter(self._JDK): 172*c2e18aaaSAndroid Build Coastguard Worker _name = jdk.find(self._NAME) 173*c2e18aaaSAndroid Build Coastguard Worker _type = jdk.find(self._TYPE) 174*c2e18aaaSAndroid Build Coastguard Worker if None in (_name, _type): 175*c2e18aaaSAndroid Build Coastguard Worker continue 176*c2e18aaaSAndroid Build Coastguard Worker if (_type.get(self._VALUE) == self._JAVA_SDK 177*c2e18aaaSAndroid Build Coastguard Worker and _name.get(self._VALUE) == self._JDK_VERSION): 178*c2e18aaaSAndroid Build Coastguard Worker return True 179*c2e18aaaSAndroid Build Coastguard Worker return False 180*c2e18aaaSAndroid Build Coastguard Worker 181*c2e18aaaSAndroid Build Coastguard Worker def _check_android_sdk_in_xml(self): 182*c2e18aaaSAndroid Build Coastguard Worker """Checks if the Android SDK is already set in jdk.table.xml. 183*c2e18aaaSAndroid Build Coastguard Worker 184*c2e18aaaSAndroid Build Coastguard Worker If the Android SDK exists in xml, validate the value of Android SDK path 185*c2e18aaaSAndroid Build Coastguard Worker and platform version. 186*c2e18aaaSAndroid Build Coastguard Worker 1. Check if the Android SDK path is valid. 187*c2e18aaaSAndroid Build Coastguard Worker 2. Check if the platform version exists in the Android SDK. 188*c2e18aaaSAndroid Build Coastguard Worker The Android SDK version can be used to generate enable_debugger module 189*c2e18aaaSAndroid Build Coastguard Worker when condition 1 and 2 are true. 190*c2e18aaaSAndroid Build Coastguard Worker 191*c2e18aaaSAndroid Build Coastguard Worker Returns: 192*c2e18aaaSAndroid Build Coastguard Worker Boolean: True if the Android SDK configuration exists, otherwise 193*c2e18aaaSAndroid Build Coastguard Worker False. 194*c2e18aaaSAndroid Build Coastguard Worker """ 195*c2e18aaaSAndroid Build Coastguard Worker for tag in self._xml.iter(self._JDK): 196*c2e18aaaSAndroid Build Coastguard Worker _name = tag.find(self._NAME) 197*c2e18aaaSAndroid Build Coastguard Worker _type = tag.find(self._TYPE) 198*c2e18aaaSAndroid Build Coastguard Worker _homepath = tag.find(self._HOMEPATH) 199*c2e18aaaSAndroid Build Coastguard Worker _additional = tag.find(self._ADDITIONAL) 200*c2e18aaaSAndroid Build Coastguard Worker if None in (_name, _type, _homepath, _additional): 201*c2e18aaaSAndroid Build Coastguard Worker continue 202*c2e18aaaSAndroid Build Coastguard Worker 203*c2e18aaaSAndroid Build Coastguard Worker tag_type = _type.get(self._VALUE) 204*c2e18aaaSAndroid Build Coastguard Worker home_path = _homepath.get(self._VALUE).replace( 205*c2e18aaaSAndroid Build Coastguard Worker constant.USER_HOME, os.path.expanduser('~')) 206*c2e18aaaSAndroid Build Coastguard Worker platform = _additional.get(self._SDK) 207*c2e18aaaSAndroid Build Coastguard Worker if (tag_type != self._ANDROID_SDK 208*c2e18aaaSAndroid Build Coastguard Worker or not self._sdk.is_android_sdk_path(home_path) 209*c2e18aaaSAndroid Build Coastguard Worker or platform not in self._sdk.platform_mapping): 210*c2e18aaaSAndroid Build Coastguard Worker continue 211*c2e18aaaSAndroid Build Coastguard Worker self._android_sdk_version = _name.get(self._VALUE) 212*c2e18aaaSAndroid Build Coastguard Worker self._platform_version = platform 213*c2e18aaaSAndroid Build Coastguard Worker return True 214*c2e18aaaSAndroid Build Coastguard Worker return False 215*c2e18aaaSAndroid Build Coastguard Worker 216*c2e18aaaSAndroid Build Coastguard Worker def _append_config(self, new_config): 217*c2e18aaaSAndroid Build Coastguard Worker """Adds a <jdk> configuration at the last of <component>. 218*c2e18aaaSAndroid Build Coastguard Worker 219*c2e18aaaSAndroid Build Coastguard Worker Args: 220*c2e18aaaSAndroid Build Coastguard Worker new_config: A string of new <jdk> configuration. 221*c2e18aaaSAndroid Build Coastguard Worker """ 222*c2e18aaaSAndroid Build Coastguard Worker node = ElementTree.fromstring(new_config) 223*c2e18aaaSAndroid Build Coastguard Worker node.tail = self._NEW_TAG_TAIL 224*c2e18aaaSAndroid Build Coastguard Worker component = self._xml.getroot().find(self._COMPONENT) 225*c2e18aaaSAndroid Build Coastguard Worker if len(component) > 0: 226*c2e18aaaSAndroid Build Coastguard Worker component[-1].tail = self._LAST_TAG_TAIL 227*c2e18aaaSAndroid Build Coastguard Worker else: 228*c2e18aaaSAndroid Build Coastguard Worker component.text = self._LAST_TAG_TAIL 229*c2e18aaaSAndroid Build Coastguard Worker self._xml.getroot().find(self._COMPONENT).append(node) 230*c2e18aaaSAndroid Build Coastguard Worker 231*c2e18aaaSAndroid Build Coastguard Worker def _generate_jdk_config_string(self): 232*c2e18aaaSAndroid Build Coastguard Worker """Generates the default JDK configuration.""" 233*c2e18aaaSAndroid Build Coastguard Worker if self._check_jdk21_in_xml(): 234*c2e18aaaSAndroid Build Coastguard Worker return 235*c2e18aaaSAndroid Build Coastguard Worker self._append_config(self._jdk_content.format(JDKpath=self._jdk_path)) 236*c2e18aaaSAndroid Build Coastguard Worker self._modify_config = True 237*c2e18aaaSAndroid Build Coastguard Worker 238*c2e18aaaSAndroid Build Coastguard Worker def _generate_sdk_config_string(self): 239*c2e18aaaSAndroid Build Coastguard Worker """Generates Android SDK configuration.""" 240*c2e18aaaSAndroid Build Coastguard Worker if self._check_android_sdk_in_xml(): 241*c2e18aaaSAndroid Build Coastguard Worker return 242*c2e18aaaSAndroid Build Coastguard Worker if self._sdk.path_analysis(self._default_android_sdk_path): 243*c2e18aaaSAndroid Build Coastguard Worker # TODO(b/151582629): Revise the API_LEVEL to CODE_NAME when 244*c2e18aaaSAndroid Build Coastguard Worker # abandoning the sdk_config.py. 245*c2e18aaaSAndroid Build Coastguard Worker self._append_config(templates.ANDROID_SDK_XML.format( 246*c2e18aaaSAndroid Build Coastguard Worker ANDROID_SDK_PATH=self._sdk.android_sdk_path, 247*c2e18aaaSAndroid Build Coastguard Worker FOLDER_NAME=self._sdk.max_folder_name, 248*c2e18aaaSAndroid Build Coastguard Worker CODE_NAME=self._sdk.max_code_name)) 249*c2e18aaaSAndroid Build Coastguard Worker self._android_sdk_version = self._ANDROID_SDK_VERSION.format( 250*c2e18aaaSAndroid Build Coastguard Worker CODE_NAME=self._sdk.max_code_name) 251*c2e18aaaSAndroid Build Coastguard Worker self._modify_config = True 252*c2e18aaaSAndroid Build Coastguard Worker return 253*c2e18aaaSAndroid Build Coastguard Worker # Record the exception about missing Android SDK. 254*c2e18aaaSAndroid Build Coastguard Worker aidegen_metrics.send_exception_metrics( 255*c2e18aaaSAndroid Build Coastguard Worker constant.LOCATE_SDK_PATH_FAILURE, '', 256*c2e18aaaSAndroid Build Coastguard Worker ElementTree.tostring(self._xml.getroot()), '') 257*c2e18aaaSAndroid Build Coastguard Worker 258*c2e18aaaSAndroid Build Coastguard Worker def config_jdk_table_xml(self): 259*c2e18aaaSAndroid Build Coastguard Worker """Configures the jdk.table.xml. 260*c2e18aaaSAndroid Build Coastguard Worker 261*c2e18aaaSAndroid Build Coastguard Worker 1. Generate the JDK21 configuration if it does not exist. 262*c2e18aaaSAndroid Build Coastguard Worker 2. Generate the Android SDK configuration if it does not exist and 263*c2e18aaaSAndroid Build Coastguard Worker save the Android SDK path. 264*c2e18aaaSAndroid Build Coastguard Worker 3. Update the jdk.table.xml if AIDEGen needs to append JDK21 or 265*c2e18aaaSAndroid Build Coastguard Worker Android SDK configuration. 266*c2e18aaaSAndroid Build Coastguard Worker 267*c2e18aaaSAndroid Build Coastguard Worker Returns: 268*c2e18aaaSAndroid Build Coastguard Worker A boolean, True when get the Android SDK version, otherwise False. 269*c2e18aaaSAndroid Build Coastguard Worker """ 270*c2e18aaaSAndroid Build Coastguard Worker if not self._check_structure() and not self._override_xml(): 271*c2e18aaaSAndroid Build Coastguard Worker print(self._IGNORE_XML_WARNING.format(XML=self._config_file)) 272*c2e18aaaSAndroid Build Coastguard Worker return False 273*c2e18aaaSAndroid Build Coastguard Worker self._generate_jdk_config_string() 274*c2e18aaaSAndroid Build Coastguard Worker self._generate_sdk_config_string() 275*c2e18aaaSAndroid Build Coastguard Worker if self._modify_config: 276*c2e18aaaSAndroid Build Coastguard Worker if not os.path.exists(self._config_file): 277*c2e18aaaSAndroid Build Coastguard Worker common_util.file_generate( 278*c2e18aaaSAndroid Build Coastguard Worker self._config_file, templates.JDK_TABLE_XML) 279*c2e18aaaSAndroid Build Coastguard Worker self._xml.write(self._config_file) 280*c2e18aaaSAndroid Build Coastguard Worker return bool(self._android_sdk_version) 281