xref: /aosp_15_r20/prebuilts/sdk/update_prebuilts/update_prebuilts.py (revision 344a7f5ef16c479e7a7f54ee6567a9d112f9e72b)
1*344a7f5eSAndroid Build Coastguard Worker#!/usr/bin/python3
2*344a7f5eSAndroid Build Coastguard Worker
3*344a7f5eSAndroid Build Coastguard Worker"""Updates prebuilt libraries used by Android builds.
4*344a7f5eSAndroid Build Coastguard Worker
5*344a7f5eSAndroid Build Coastguard WorkerFor details on how to use this script, visit go/update-prebuilts.
6*344a7f5eSAndroid Build Coastguard Worker"""
7*344a7f5eSAndroid Build Coastguard Workerimport os
8*344a7f5eSAndroid Build Coastguard Workerimport sys
9*344a7f5eSAndroid Build Coastguard Workerimport zipfile
10*344a7f5eSAndroid Build Coastguard Workerimport re
11*344a7f5eSAndroid Build Coastguard Workerimport argparse
12*344a7f5eSAndroid Build Coastguard Workerimport subprocess
13*344a7f5eSAndroid Build Coastguard Workerimport shlex
14*344a7f5eSAndroid Build Coastguard Workerimport glob
15*344a7f5eSAndroid Build Coastguard Workerimport shutil
16*344a7f5eSAndroid Build Coastguard Worker
17*344a7f5eSAndroid Build Coastguard Worker# Modules not in Android repo. Ok to ignore if they are not really used.
18*344a7f5eSAndroid Build Coastguard Workertry:
19*344a7f5eSAndroid Build Coastguard Worker    import six
20*344a7f5eSAndroid Build Coastguard Workerexcept ImportError:
21*344a7f5eSAndroid Build Coastguard Worker    six = None
22*344a7f5eSAndroid Build Coastguard Worker
23*344a7f5eSAndroid Build Coastguard Workerfrom urllib import request
24*344a7f5eSAndroid Build Coastguard Workerfrom shutil import which
25*344a7f5eSAndroid Build Coastguard Workerfrom distutils.version import LooseVersion
26*344a7f5eSAndroid Build Coastguard Workerfrom pathlib import Path
27*344a7f5eSAndroid Build Coastguard Workerfrom io import StringIO
28*344a7f5eSAndroid Build Coastguard Workerfrom typing import Iterable, Optional
29*344a7f5eSAndroid Build Coastguard Workerimport xml.etree.ElementTree as ET
30*344a7f5eSAndroid Build Coastguard Workerfrom maven import MavenLibraryInfo, GMavenArtifact, maven_path_for_artifact
31*344a7f5eSAndroid Build Coastguard Workerfrom buildserver import fetch_and_extract, extract_artifact, \
32*344a7f5eSAndroid Build Coastguard Worker    parse_build_id, fetch_artifact as buildserver_fetch_artifact, fetch_artifacts as buildserver_fetch_artifacts
33*344a7f5eSAndroid Build Coastguard Workerfrom utils import print_e, append, cp, mv, rm
34*344a7f5eSAndroid Build Coastguard Worker
35*344a7f5eSAndroid Build Coastguard Worker
36*344a7f5eSAndroid Build Coastguard Workercurrent_path = 'current'
37*344a7f5eSAndroid Build Coastguard Workerframework_sdk_target = 'sdk'
38*344a7f5eSAndroid Build Coastguard Workerandroidx_dir = os.path.join(current_path, 'androidx')
39*344a7f5eSAndroid Build Coastguard Workerandroidx_owners = os.path.join(androidx_dir, 'OWNERS')
40*344a7f5eSAndroid Build Coastguard Workerjava_plugins_bp_path = os.path.join(androidx_dir, 'JavaPlugins.bp')
41*344a7f5eSAndroid Build Coastguard Workertest_mapping_file = os.path.join(androidx_dir, 'TEST_MAPPING')
42*344a7f5eSAndroid Build Coastguard Workerdrop_config_toml = os.path.join(androidx_dir, 'drop_config.toml')
43*344a7f5eSAndroid Build Coastguard Workercompose_test_mapping_file = os.path.join(androidx_dir, 'm2repository/androidx/compose/TEST_MAPPING')
44*344a7f5eSAndroid Build Coastguard Workergmaven_dir = os.path.join(current_path, 'gmaven')
45*344a7f5eSAndroid Build Coastguard Workerextras_dir = os.path.join(current_path, 'extras')
46*344a7f5eSAndroid Build Coastguard Workerbuildtools_dir = 'tools'
47*344a7f5eSAndroid Build Coastguard Workerjetifier_dir = os.path.join(buildtools_dir, 'jetifier', 'jetifier-standalone')
48*344a7f5eSAndroid Build Coastguard Workerrepo_root_dir = Path(sys.argv[0]).resolve().parents[3]
49*344a7f5eSAndroid Build Coastguard Workerextension_sdk_finalization_cmd = 'prebuilts/build-tools/path/linux-x86/python3 %s -r "{readme}" {local_mode} -b {bug} -f {extension_version} {build_id}' % (
50*344a7f5eSAndroid Build Coastguard Worker    "packages/modules/common/tools/finalize_sdk.py"
51*344a7f5eSAndroid Build Coastguard Worker)
52*344a7f5eSAndroid Build Coastguard Workertemp_dir = os.path.join(os.getcwd(), 'support_tmp')
53*344a7f5eSAndroid Build Coastguard Workeros.chdir(os.path.dirname(os.path.dirname(os.path.realpath(sys.argv[0]))))
54*344a7f5eSAndroid Build Coastguard Workergit_dir = os.getcwd()
55*344a7f5eSAndroid Build Coastguard Worker
56*344a7f5eSAndroid Build Coastguard Worker# Suffixes used by KMP artifacts. If an artifact in maven_to_make ends with one
57*344a7f5eSAndroid Build Coastguard Worker# of these, it will replace the anchor artifact.
58*344a7f5eSAndroid Build Coastguard Workerkmp_suffixes = ['android','jvm']
59*344a7f5eSAndroid Build Coastguard Worker
60*344a7f5eSAndroid Build Coastguard Worker# Leave map blank to automatically populate name and path:
61*344a7f5eSAndroid Build Coastguard Worker# - Name format is MAVEN.replaceAll(':','_')
62*344a7f5eSAndroid Build Coastguard Worker# - Path format is MAVEN.replaceAll(':','/').replaceAll('.','/')
63*344a7f5eSAndroid Build Coastguard Workermaven_to_make = {
64*344a7f5eSAndroid Build Coastguard Worker    # AndroidX
65*344a7f5eSAndroid Build Coastguard Worker    'androidx.benchmark:benchmark-macro': {},
66*344a7f5eSAndroid Build Coastguard Worker    'androidx.benchmark:benchmark-macro-junit4': {},
67*344a7f5eSAndroid Build Coastguard Worker    'androidx.benchmark:benchmark-common': {},
68*344a7f5eSAndroid Build Coastguard Worker    'androidx.benchmark:benchmark-junit4': {},
69*344a7f5eSAndroid Build Coastguard Worker    'androidx.tracing:tracing': {},
70*344a7f5eSAndroid Build Coastguard Worker    'androidx.tracing:tracing-perfetto': {},
71*344a7f5eSAndroid Build Coastguard Worker    'androidx.tracing:tracing-perfetto-binary': {},
72*344a7f5eSAndroid Build Coastguard Worker    'androidx.tracing:tracing-perfetto-handshake': {},
73*344a7f5eSAndroid Build Coastguard Worker    'androidx.tracing:tracing-perfetto-common': {},
74*344a7f5eSAndroid Build Coastguard Worker    'androidx.tracing:tracing-ktx': {},
75*344a7f5eSAndroid Build Coastguard Worker    'androidx.slice:slice-builders': {},
76*344a7f5eSAndroid Build Coastguard Worker    'androidx.slice:slice-core': {},
77*344a7f5eSAndroid Build Coastguard Worker    'androidx.slice:slice-view': {},
78*344a7f5eSAndroid Build Coastguard Worker    'androidx.remotecallback:remotecallback': {},
79*344a7f5eSAndroid Build Coastguard Worker    'androidx.remotecallback:remotecallback-processor': {
80*344a7f5eSAndroid Build Coastguard Worker        'host': True
81*344a7f5eSAndroid Build Coastguard Worker    },
82*344a7f5eSAndroid Build Coastguard Worker    'androidx.versionedparcelable:versionedparcelable': {},
83*344a7f5eSAndroid Build Coastguard Worker    'androidx.vectordrawable:vectordrawable-animated': {},
84*344a7f5eSAndroid Build Coastguard Worker    'androidx.activity:activity': {},
85*344a7f5eSAndroid Build Coastguard Worker    'androidx.activity:activity-ktx': {},
86*344a7f5eSAndroid Build Coastguard Worker    'androidx.annotation:annotation-jvm': {
87*344a7f5eSAndroid Build Coastguard Worker        'host_and_device': True
88*344a7f5eSAndroid Build Coastguard Worker    },
89*344a7f5eSAndroid Build Coastguard Worker    'androidx.annotation:annotation-experimental': {},
90*344a7f5eSAndroid Build Coastguard Worker    'androidx.asynclayoutinflater:asynclayoutinflater': {},
91*344a7f5eSAndroid Build Coastguard Worker    'androidx.camera:camera-viewfinder':{},
92*344a7f5eSAndroid Build Coastguard Worker    'androidx.camera:camera-camera2' :{},
93*344a7f5eSAndroid Build Coastguard Worker    'androidx.camera:camera-core': {},
94*344a7f5eSAndroid Build Coastguard Worker    'androidx.camera:camera-lifecycle': {},
95*344a7f5eSAndroid Build Coastguard Worker    'androidx.camera:camera-extensions': {},
96*344a7f5eSAndroid Build Coastguard Worker    'androidx.collection:collection-ktx': {},
97*344a7f5eSAndroid Build Coastguard Worker    'androidx.collection:collection-jvm': {},
98*344a7f5eSAndroid Build Coastguard Worker    'androidx.concurrent:concurrent-futures': {},
99*344a7f5eSAndroid Build Coastguard Worker    'androidx.concurrent:concurrent-futures-ktx': {},
100*344a7f5eSAndroid Build Coastguard Worker    'androidx.concurrent:concurrent-listenablefuture-callback': {},
101*344a7f5eSAndroid Build Coastguard Worker    'androidx.concurrent:concurrent-listenablefuture': {},
102*344a7f5eSAndroid Build Coastguard Worker    'androidx.core:core': {},
103*344a7f5eSAndroid Build Coastguard Worker    'androidx.core:core-animation': {},
104*344a7f5eSAndroid Build Coastguard Worker    'androidx.core:core-animation-testing': {},
105*344a7f5eSAndroid Build Coastguard Worker    'androidx.core:core-ktx': {},
106*344a7f5eSAndroid Build Coastguard Worker    'androidx.core.uwb:uwb': {},
107*344a7f5eSAndroid Build Coastguard Worker    'androidx.core.uwb:uwb-rxjava3': {},
108*344a7f5eSAndroid Build Coastguard Worker    'androidx.contentpaging:contentpaging': {},
109*344a7f5eSAndroid Build Coastguard Worker    'androidx.coordinatorlayout:coordinatorlayout': {},
110*344a7f5eSAndroid Build Coastguard Worker    'androidx.datastore:datastore-android': {},
111*344a7f5eSAndroid Build Coastguard Worker    'androidx.datastore:datastore-core-okio-jvm': {},
112*344a7f5eSAndroid Build Coastguard Worker    'androidx.datastore:datastore-core-android': {},
113*344a7f5eSAndroid Build Coastguard Worker    'androidx.datastore:datastore-preferences-android': {},
114*344a7f5eSAndroid Build Coastguard Worker    'androidx.datastore:datastore-preferences-core-jvm': {},
115*344a7f5eSAndroid Build Coastguard Worker    'androidx.datastore:datastore-preferences-rxjava2': {},
116*344a7f5eSAndroid Build Coastguard Worker    'androidx.datastore:datastore-rxjava2': {},
117*344a7f5eSAndroid Build Coastguard Worker    'androidx.legacy:legacy-support-core-ui': {},
118*344a7f5eSAndroid Build Coastguard Worker    'androidx.legacy:legacy-support-core-utils': {},
119*344a7f5eSAndroid Build Coastguard Worker    'androidx.cursoradapter:cursoradapter': {},
120*344a7f5eSAndroid Build Coastguard Worker    'androidx.browser:browser': {},
121*344a7f5eSAndroid Build Coastguard Worker    'androidx.customview:customview': {},
122*344a7f5eSAndroid Build Coastguard Worker    'androidx.customview:customview-poolingcontainer': {},
123*344a7f5eSAndroid Build Coastguard Worker    'androidx.credentials:credentials': {},
124*344a7f5eSAndroid Build Coastguard Worker    'androidx.documentfile:documentfile': {},
125*344a7f5eSAndroid Build Coastguard Worker    'androidx.drawerlayout:drawerlayout': {},
126*344a7f5eSAndroid Build Coastguard Worker    'androidx.dynamicanimation:dynamicanimation': {},
127*344a7f5eSAndroid Build Coastguard Worker    'androidx.emoji:emoji': {},
128*344a7f5eSAndroid Build Coastguard Worker    'androidx.emoji:emoji-appcompat': {},
129*344a7f5eSAndroid Build Coastguard Worker    'androidx.emoji:emoji-bundled': {},
130*344a7f5eSAndroid Build Coastguard Worker    'androidx.emoji2:emoji2': {},
131*344a7f5eSAndroid Build Coastguard Worker    'androidx.emoji2:emoji2-views-helper': {},
132*344a7f5eSAndroid Build Coastguard Worker    'androidx.exifinterface:exifinterface': {},
133*344a7f5eSAndroid Build Coastguard Worker    'androidx.fragment:fragment': {},
134*344a7f5eSAndroid Build Coastguard Worker    'androidx.fragment:fragment-ktx': {},
135*344a7f5eSAndroid Build Coastguard Worker    'androidx.fragment:fragment-testing': {},
136*344a7f5eSAndroid Build Coastguard Worker    'androidx.fragment:fragment-testing-manifest': {},
137*344a7f5eSAndroid Build Coastguard Worker    'androidx.heifwriter:heifwriter': {},
138*344a7f5eSAndroid Build Coastguard Worker    'androidx.health:health-services-client': {},
139*344a7f5eSAndroid Build Coastguard Worker    'androidx.interpolator:interpolator': {},
140*344a7f5eSAndroid Build Coastguard Worker    'androidx.loader:loader': {},
141*344a7f5eSAndroid Build Coastguard Worker    'androidx.media:media': {},
142*344a7f5eSAndroid Build Coastguard Worker    'androidx.media2:media2-player': {},
143*344a7f5eSAndroid Build Coastguard Worker    'androidx.media2:media2-session': {},
144*344a7f5eSAndroid Build Coastguard Worker    'androidx.media2:media2-common': {},
145*344a7f5eSAndroid Build Coastguard Worker    'androidx.media2:media2-exoplayer': {},
146*344a7f5eSAndroid Build Coastguard Worker    'androidx.media2:media2-widget': {},
147*344a7f5eSAndroid Build Coastguard Worker    'androidx.navigation:navigation-common': {},
148*344a7f5eSAndroid Build Coastguard Worker    'androidx.navigation:navigation-common-ktx': {},
149*344a7f5eSAndroid Build Coastguard Worker    'androidx.navigation:navigation-fragment': {},
150*344a7f5eSAndroid Build Coastguard Worker    'androidx.navigation:navigation-fragment-ktx': {},
151*344a7f5eSAndroid Build Coastguard Worker    'androidx.navigation:navigation-runtime': {},
152*344a7f5eSAndroid Build Coastguard Worker    'androidx.navigation:navigation-runtime-ktx': {},
153*344a7f5eSAndroid Build Coastguard Worker    'androidx.navigation:navigation-ui': {},
154*344a7f5eSAndroid Build Coastguard Worker    'androidx.navigation:navigation-ui-ktx': {},
155*344a7f5eSAndroid Build Coastguard Worker    'androidx.percentlayout:percentlayout': {},
156*344a7f5eSAndroid Build Coastguard Worker    'androidx.print:print': {},
157*344a7f5eSAndroid Build Coastguard Worker    'androidx.privacysandbox.ads:ads-adservices': {},
158*344a7f5eSAndroid Build Coastguard Worker    'androidx.privacysandbox.ads:ads-adservices-java': {},
159*344a7f5eSAndroid Build Coastguard Worker    'androidx.privacysandbox.ui:ui-client': {},
160*344a7f5eSAndroid Build Coastguard Worker    'androidx.privacysandbox.ui:ui-provider': {},
161*344a7f5eSAndroid Build Coastguard Worker    'androidx.privacysandbox.ui:ui-core': {},
162*344a7f5eSAndroid Build Coastguard Worker    'androidx.privacysandbox.sdkruntime:sdkruntime-client': {},
163*344a7f5eSAndroid Build Coastguard Worker    'androidx.privacysandbox.sdkruntime:sdkruntime-core': {},
164*344a7f5eSAndroid Build Coastguard Worker    'androidx.privacysandbox.tools:tools': {
165*344a7f5eSAndroid Build Coastguard Worker        'host': True
166*344a7f5eSAndroid Build Coastguard Worker    },
167*344a7f5eSAndroid Build Coastguard Worker    'androidx.privacysandbox.tools:tools-apicompiler': {
168*344a7f5eSAndroid Build Coastguard Worker        'host': True
169*344a7f5eSAndroid Build Coastguard Worker    },
170*344a7f5eSAndroid Build Coastguard Worker    'androidx.privacysandbox.tools:tools-apigenerator': {
171*344a7f5eSAndroid Build Coastguard Worker        'host': True
172*344a7f5eSAndroid Build Coastguard Worker    },
173*344a7f5eSAndroid Build Coastguard Worker    'androidx.privacysandbox.tools:tools-apipackager': {
174*344a7f5eSAndroid Build Coastguard Worker        'host': True
175*344a7f5eSAndroid Build Coastguard Worker    },
176*344a7f5eSAndroid Build Coastguard Worker    'androidx.privacysandbox.tools:tools-core': {
177*344a7f5eSAndroid Build Coastguard Worker        'host': True
178*344a7f5eSAndroid Build Coastguard Worker    },
179*344a7f5eSAndroid Build Coastguard Worker    'androidx.privacysandbox.ui:ui-tests': {},
180*344a7f5eSAndroid Build Coastguard Worker    'androidx.recommendation:recommendation': {},
181*344a7f5eSAndroid Build Coastguard Worker    'androidx.recyclerview:recyclerview-selection': {},
182*344a7f5eSAndroid Build Coastguard Worker    'androidx.savedstate:savedstate': {},
183*344a7f5eSAndroid Build Coastguard Worker    'androidx.savedstate:savedstate-ktx': {},
184*344a7f5eSAndroid Build Coastguard Worker    'androidx.slidingpanelayout:slidingpanelayout': {},
185*344a7f5eSAndroid Build Coastguard Worker    'androidx.swiperefreshlayout:swiperefreshlayout': {},
186*344a7f5eSAndroid Build Coastguard Worker    'androidx.textclassifier:textclassifier': {},
187*344a7f5eSAndroid Build Coastguard Worker    'androidx.transition:transition': {},
188*344a7f5eSAndroid Build Coastguard Worker    'androidx.transition:transition-ktx': {},
189*344a7f5eSAndroid Build Coastguard Worker    'androidx.tvprovider:tvprovider': {},
190*344a7f5eSAndroid Build Coastguard Worker    'androidx.legacy:legacy-support-v13': {},
191*344a7f5eSAndroid Build Coastguard Worker    'androidx.legacy:legacy-preference-v14': {},
192*344a7f5eSAndroid Build Coastguard Worker    'androidx.leanback:leanback': {},
193*344a7f5eSAndroid Build Coastguard Worker    'androidx.leanback:leanback-grid': {},
194*344a7f5eSAndroid Build Coastguard Worker    'androidx.leanback:leanback-preference': {},
195*344a7f5eSAndroid Build Coastguard Worker    'androidx.legacy:legacy-support-v4': {},
196*344a7f5eSAndroid Build Coastguard Worker    'androidx.appcompat:appcompat': {},
197*344a7f5eSAndroid Build Coastguard Worker    'androidx.appcompat:appcompat-resources': {},
198*344a7f5eSAndroid Build Coastguard Worker    'androidx.cardview:cardview': {},
199*344a7f5eSAndroid Build Coastguard Worker    'androidx.gridlayout:gridlayout': {},
200*344a7f5eSAndroid Build Coastguard Worker    'androidx.mediarouter:mediarouter': {},
201*344a7f5eSAndroid Build Coastguard Worker    'androidx.palette:palette': {},
202*344a7f5eSAndroid Build Coastguard Worker    'androidx.preference:preference': {},
203*344a7f5eSAndroid Build Coastguard Worker    'androidx.recyclerview:recyclerview': {},
204*344a7f5eSAndroid Build Coastguard Worker    'androidx.vectordrawable:vectordrawable': {},
205*344a7f5eSAndroid Build Coastguard Worker    'androidx.viewpager:viewpager': {},
206*344a7f5eSAndroid Build Coastguard Worker    'androidx.viewpager2:viewpager2': {},
207*344a7f5eSAndroid Build Coastguard Worker    'androidx.wear:wear': {},
208*344a7f5eSAndroid Build Coastguard Worker    'androidx.wear:wear-ongoing': {},
209*344a7f5eSAndroid Build Coastguard Worker    'androidx.javascriptengine:javascriptengine': {},
210*344a7f5eSAndroid Build Coastguard Worker    'androidx.webkit:webkit': {},
211*344a7f5eSAndroid Build Coastguard Worker    'androidx.biometric:biometric': {},
212*344a7f5eSAndroid Build Coastguard Worker    'androidx.autofill:autofill': {},
213*344a7f5eSAndroid Build Coastguard Worker    'androidx.appsearch:appsearch': {},
214*344a7f5eSAndroid Build Coastguard Worker    'androidx.appsearch:appsearch-builtin-types': {},
215*344a7f5eSAndroid Build Coastguard Worker    'androidx.appsearch:appsearch-compiler': {
216*344a7f5eSAndroid Build Coastguard Worker        'name': 'androidx.appsearch_appsearch-compiler',
217*344a7f5eSAndroid Build Coastguard Worker        'host': True
218*344a7f5eSAndroid Build Coastguard Worker    },
219*344a7f5eSAndroid Build Coastguard Worker    'androidx.appsearch:appsearch-local-storage': {
220*344a7f5eSAndroid Build Coastguard Worker        'name': 'androidx.appsearch_appsearch_local_storage'
221*344a7f5eSAndroid Build Coastguard Worker    },
222*344a7f5eSAndroid Build Coastguard Worker    'androidx.appsearch:appsearch-platform-storage': {},
223*344a7f5eSAndroid Build Coastguard Worker    'androidx.car.app:app': {},
224*344a7f5eSAndroid Build Coastguard Worker    'androidx.car.app:app-automotive': {},
225*344a7f5eSAndroid Build Coastguard Worker    'androidx.car.app:app-testing': {},
226*344a7f5eSAndroid Build Coastguard Worker    'androidx.startup:startup-runtime': {},
227*344a7f5eSAndroid Build Coastguard Worker    'androidx.window:window': {
228*344a7f5eSAndroid Build Coastguard Worker        'optional-uses-libs': {
229*344a7f5eSAndroid Build Coastguard Worker            'androidx.window.extensions',
230*344a7f5eSAndroid Build Coastguard Worker            'androidx.window.sidecar'
231*344a7f5eSAndroid Build Coastguard Worker        }
232*344a7f5eSAndroid Build Coastguard Worker    },
233*344a7f5eSAndroid Build Coastguard Worker    'androidx.window.extensions:extensions': {},
234*344a7f5eSAndroid Build Coastguard Worker    'androidx.window.extensions.core:core': {},
235*344a7f5eSAndroid Build Coastguard Worker    'androidx.window:window-core': {},
236*344a7f5eSAndroid Build Coastguard Worker    'androidx.window:window-java':{},
237*344a7f5eSAndroid Build Coastguard Worker    'androidx.resourceinspection:resourceinspection-annotation': {},
238*344a7f5eSAndroid Build Coastguard Worker    'androidx.profileinstaller:profileinstaller': {},
239*344a7f5eSAndroid Build Coastguard Worker    'androidx.test.uiautomator:uiautomator': {},
240*344a7f5eSAndroid Build Coastguard Worker
241*344a7f5eSAndroid Build Coastguard Worker    # AndroidX for Compose
242*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.compiler:compiler-hosted': {
243*344a7f5eSAndroid Build Coastguard Worker        'host': True
244*344a7f5eSAndroid Build Coastguard Worker    },
245*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.animation:animation-android': {},
246*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.animation:animation-core-android': {},
247*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.animation:animation-graphics-android': {},
248*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.foundation:foundation-android': {},
249*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.foundation:foundation-layout-android': {},
250*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.foundation:foundation-text-android': {},
251*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.material:material-android': {},
252*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.material:material-icons-core-android': {},
253*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.material:material-icons-extended-android': {},
254*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.material:material-ripple-android': {},
255*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.material3:material3-android': {},
256*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.material3:material3-window-size-class-android': {},
257*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.runtime:runtime-android': {},
258*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.runtime:runtime-livedata': {},
259*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.runtime:runtime-saveable-android': {},
260*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.runtime:runtime-tracing': {},
261*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.ui:ui-util-android': {},
262*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.ui:ui-android': {},
263*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.ui:ui-geometry-android': {},
264*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.ui:ui-graphics-android': {},
265*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.ui:ui-test-manifest': {},
266*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.ui:ui-test-android': {},
267*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.ui:ui-test-junit4-android': {},
268*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.ui:ui-text-android': {},
269*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.ui:ui-tooling-android': {},
270*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.ui:ui-tooling-data-android': {},
271*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.ui:ui-tooling-preview-android': {},
272*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.ui:ui-unit-android': {},
273*344a7f5eSAndroid Build Coastguard Worker    'androidx.activity:activity-compose': {},
274*344a7f5eSAndroid Build Coastguard Worker    'androidx.navigation:navigation-compose': { },
275*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle:lifecycle-viewmodel-compose': { },
276*344a7f5eSAndroid Build Coastguard Worker
277*344a7f5eSAndroid Build Coastguard Worker    # Compose for wear
278*344a7f5eSAndroid Build Coastguard Worker    'androidx.wear.compose:compose-material-core': {},
279*344a7f5eSAndroid Build Coastguard Worker    'androidx.wear.compose:compose-foundation': {},
280*344a7f5eSAndroid Build Coastguard Worker    'androidx.wear.compose:compose-material': {},
281*344a7f5eSAndroid Build Coastguard Worker    'androidx.wear.compose:compose-navigation': {},
282*344a7f5eSAndroid Build Coastguard Worker
283*344a7f5eSAndroid Build Coastguard Worker    # AndroidX for Multidex
284*344a7f5eSAndroid Build Coastguard Worker    'androidx.multidex:multidex': {},
285*344a7f5eSAndroid Build Coastguard Worker    'androidx.multidex:multidex-instrumentation': {},
286*344a7f5eSAndroid Build Coastguard Worker
287*344a7f5eSAndroid Build Coastguard Worker    # AndroidX for Constraint Layout
288*344a7f5eSAndroid Build Coastguard Worker    'androidx.constraintlayout:constraintlayout': {
289*344a7f5eSAndroid Build Coastguard Worker        'name': 'androidx-constraintlayout_constraintlayout'
290*344a7f5eSAndroid Build Coastguard Worker    },
291*344a7f5eSAndroid Build Coastguard Worker    'androidx.constraintlayout:constraintlayout-solver': {
292*344a7f5eSAndroid Build Coastguard Worker        'name': 'androidx-constraintlayout_constraintlayout-solver'
293*344a7f5eSAndroid Build Coastguard Worker    },
294*344a7f5eSAndroid Build Coastguard Worker    'androidx.constraintlayout:constraintlayout-core': {},
295*344a7f5eSAndroid Build Coastguard Worker    'androidx.constraintlayout:constraintlayout-compose-android': {},
296*344a7f5eSAndroid Build Coastguard Worker    # AndroidX for Architecture Components
297*344a7f5eSAndroid Build Coastguard Worker    'androidx.arch.core:core-common': {},
298*344a7f5eSAndroid Build Coastguard Worker    'androidx.arch.core:core-runtime': {},
299*344a7f5eSAndroid Build Coastguard Worker    'androidx.arch.core:core-testing': {},
300*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle:lifecycle-common': {},
301*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle:lifecycle-common-java8': {},
302*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle:lifecycle-extensions': {},
303*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle:lifecycle-livedata': {},
304*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle:lifecycle-livedata-ktx': {},
305*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle:lifecycle-livedata-core': {},
306*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle:lifecycle-livedata-core-ktx': {},
307*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle:lifecycle-process': {},
308*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle:lifecycle-runtime': {},
309*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle:lifecycle-runtime-ktx': {},
310*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle:lifecycle-runtime-compose': {},
311*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle:lifecycle-runtime-testing': {},
312*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle:lifecycle-service': {},
313*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle:lifecycle-viewmodel': {},
314*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle:lifecycle-viewmodel-ktx': {},
315*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle:lifecycle-viewmodel-savedstate': {},
316*344a7f5eSAndroid Build Coastguard Worker    'androidx.paging:paging-common-jvm': {},
317*344a7f5eSAndroid Build Coastguard Worker    'androidx.paging:paging-common-ktx': {},
318*344a7f5eSAndroid Build Coastguard Worker    'androidx.paging:paging-guava': {},
319*344a7f5eSAndroid Build Coastguard Worker    'androidx.paging:paging-runtime': {},
320*344a7f5eSAndroid Build Coastguard Worker    'androidx.sqlite:sqlite': {},
321*344a7f5eSAndroid Build Coastguard Worker    'androidx.sqlite:sqlite-framework': {},
322*344a7f5eSAndroid Build Coastguard Worker    'androidx.room:room-common-jvm': {
323*344a7f5eSAndroid Build Coastguard Worker        'host_and_device': True
324*344a7f5eSAndroid Build Coastguard Worker    },
325*344a7f5eSAndroid Build Coastguard Worker    'androidx.room:room-compiler': {
326*344a7f5eSAndroid Build Coastguard Worker        'host': True,
327*344a7f5eSAndroid Build Coastguard Worker        'extra-static-libs': {
328*344a7f5eSAndroid Build Coastguard Worker            'guava'
329*344a7f5eSAndroid Build Coastguard Worker        }
330*344a7f5eSAndroid Build Coastguard Worker    },
331*344a7f5eSAndroid Build Coastguard Worker    'androidx.room:room-guava': {},
332*344a7f5eSAndroid Build Coastguard Worker    'androidx.room:room-migration': {
333*344a7f5eSAndroid Build Coastguard Worker        'host_and_device': True
334*344a7f5eSAndroid Build Coastguard Worker    },
335*344a7f5eSAndroid Build Coastguard Worker    'androidx.room:room-ktx': {},
336*344a7f5eSAndroid Build Coastguard Worker    'androidx.room:room-paging': {},
337*344a7f5eSAndroid Build Coastguard Worker    'androidx.room:room-paging-guava': {},
338*344a7f5eSAndroid Build Coastguard Worker    'androidx.room:room-runtime': {},
339*344a7f5eSAndroid Build Coastguard Worker    'androidx.room:room-testing': {},
340*344a7f5eSAndroid Build Coastguard Worker    'androidx.room:room-compiler-processing': {
341*344a7f5eSAndroid Build Coastguard Worker        'host': True
342*344a7f5eSAndroid Build Coastguard Worker    },
343*344a7f5eSAndroid Build Coastguard Worker    'androidx.work:work-runtime': {},
344*344a7f5eSAndroid Build Coastguard Worker    'androidx.work:work-runtime-ktx': {},
345*344a7f5eSAndroid Build Coastguard Worker    'androidx.work:work-testing': {},
346*344a7f5eSAndroid Build Coastguard Worker
347*344a7f5eSAndroid Build Coastguard Worker    # Third-party dependencies
348*344a7f5eSAndroid Build Coastguard Worker    'com.google.android:flexbox': {
349*344a7f5eSAndroid Build Coastguard Worker        'name': 'flexbox',
350*344a7f5eSAndroid Build Coastguard Worker        'path': 'flexbox'
351*344a7f5eSAndroid Build Coastguard Worker    },
352*344a7f5eSAndroid Build Coastguard Worker
353*344a7f5eSAndroid Build Coastguard Worker    # Androidx Material Design Components
354*344a7f5eSAndroid Build Coastguard Worker    'com.google.android.material:material': {},
355*344a7f5eSAndroid Build Coastguard Worker}
356*344a7f5eSAndroid Build Coastguard Worker
357*344a7f5eSAndroid Build Coastguard Worker# Mapping of POM dependencies to Soong build targets
358*344a7f5eSAndroid Build Coastguard Workerdeps_rewrite = {
359*344a7f5eSAndroid Build Coastguard Worker    'auto-common': 'auto_common',
360*344a7f5eSAndroid Build Coastguard Worker    'auto-value-annotations': 'auto_value_annotations',
361*344a7f5eSAndroid Build Coastguard Worker    'com.google.auto.value:auto-value': 'libauto_value_plugin',
362*344a7f5eSAndroid Build Coastguard Worker    'com.google.protobuf:protobuf-java': 'libprotobuf-java-full',
363*344a7f5eSAndroid Build Coastguard Worker    'com.google.protobuf:protobuf-javalite': 'libprotobuf-java-lite',
364*344a7f5eSAndroid Build Coastguard Worker    'org.ow2.asm:asm': 'ow2-asm',
365*344a7f5eSAndroid Build Coastguard Worker    'org.ow2.asm:asm-commons': 'ow2-asm-commons',
366*344a7f5eSAndroid Build Coastguard Worker    'monitor': 'androidx.test.monitor',
367*344a7f5eSAndroid Build Coastguard Worker    'rules': 'androidx.test.rules',
368*344a7f5eSAndroid Build Coastguard Worker    'runner': 'androidx.test.runner',
369*344a7f5eSAndroid Build Coastguard Worker    'androidx.test:core': 'androidx.test.core',
370*344a7f5eSAndroid Build Coastguard Worker    'com.squareup:javapoet': 'javapoet',
371*344a7f5eSAndroid Build Coastguard Worker    'com.squareup.okio:okio-jvm': 'okio-lib',
372*344a7f5eSAndroid Build Coastguard Worker    'com.google.guava:listenablefuture': 'guava-listenablefuture-prebuilt-jar',
373*344a7f5eSAndroid Build Coastguard Worker    'sqlite-jdbc': 'xerial-sqlite-jdbc',
374*344a7f5eSAndroid Build Coastguard Worker    'com.intellij:annotations': 'jetbrains-annotations',
375*344a7f5eSAndroid Build Coastguard Worker    'javax.annotation:javax.annotation-api': 'javax-annotation-api-prebuilt-host-jar',
376*344a7f5eSAndroid Build Coastguard Worker    'org.robolectric:robolectric': 'Robolectric_all-target',
377*344a7f5eSAndroid Build Coastguard Worker    'org.jetbrains.kotlin:kotlin-stdlib-common': 'kotlin-stdlib',
378*344a7f5eSAndroid Build Coastguard Worker    'org.jetbrains.kotlinx:kotlinx-coroutines-core': 'kotlinx_coroutines',
379*344a7f5eSAndroid Build Coastguard Worker    'org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm': 'kotlinx_coroutines_test',
380*344a7f5eSAndroid Build Coastguard Worker    'org.jetbrains.kotlinx:kotlinx-coroutines-guava': 'kotlinx_coroutines_guava',
381*344a7f5eSAndroid Build Coastguard Worker    'org.jetbrains.kotlinx:kotlinx-coroutines-android': 'kotlinx_coroutines_android',
382*344a7f5eSAndroid Build Coastguard Worker    'org.jetbrains.kotlinx:kotlinx-coroutines-test':'kotlinx_coroutines_test',
383*344a7f5eSAndroid Build Coastguard Worker    'org.jetbrains.kotlinx:kotlinx-coroutines-rx2': 'kotlinx_coroutines_rx2',
384*344a7f5eSAndroid Build Coastguard Worker    'org.jetbrains.kotlinx:kotlinx-metadata-jvm': 'kotlinx_metadata_jvm',
385*344a7f5eSAndroid Build Coastguard Worker    'androidx.test.espresso:espresso-core':'androidx.test.espresso.core',
386*344a7f5eSAndroid Build Coastguard Worker    'androidx.test.espresso:espresso-idling-resource':'androidx.test.espresso.idling-resource',
387*344a7f5eSAndroid Build Coastguard Worker    'androidx.datastore:datastore-core-jvm': 'androidx.datastore_datastore-core',
388*344a7f5eSAndroid Build Coastguard Worker}
389*344a7f5eSAndroid Build Coastguard Worker
390*344a7f5eSAndroid Build Coastguard Worker# List of artifacts that will be updated from GMaven
391*344a7f5eSAndroid Build Coastguard Worker# Use pattern: `group:library:version:extension`
392*344a7f5eSAndroid Build Coastguard Worker# e.g.:
393*344a7f5eSAndroid Build Coastguard Worker#   androidx.appcompat:appcompat:1.2.0:aar
394*344a7f5eSAndroid Build Coastguard Worker# Use `latest` to always fetch the latest version.
395*344a7f5eSAndroid Build Coastguard Worker# e.g.:
396*344a7f5eSAndroid Build Coastguard Worker#   androidx.appcompat:appcompat:latest:aar
397*344a7f5eSAndroid Build Coastguard Worker# Also make sure you add `group:library`:{} to maven_to_make as well.
398*344a7f5eSAndroid Build Coastguard Workergmaven_artifacts = {}
399*344a7f5eSAndroid Build Coastguard Worker
400*344a7f5eSAndroid Build Coastguard Worker# Always remove these files.
401*344a7f5eSAndroid Build Coastguard Workerdenylist_files = [
402*344a7f5eSAndroid Build Coastguard Worker    'annotations.zip',
403*344a7f5eSAndroid Build Coastguard Worker    'public.txt',
404*344a7f5eSAndroid Build Coastguard Worker    'R.txt',
405*344a7f5eSAndroid Build Coastguard Worker    'AndroidManifest.xml',
406*344a7f5eSAndroid Build Coastguard Worker    os.path.join('libs', 'noto-emoji-compat-java.jar')
407*344a7f5eSAndroid Build Coastguard Worker]
408*344a7f5eSAndroid Build Coastguard Worker
409*344a7f5eSAndroid Build Coastguard Worker# Explicitly allow-listed initializers
410*344a7f5eSAndroid Build Coastguard Workerenabled_initializers = set([
411*344a7f5eSAndroid Build Coastguard Worker    'androidx.lifecycle.ProcessLifecycleInitializer',
412*344a7f5eSAndroid Build Coastguard Worker    'androidx.work.WorkManagerInitializer',
413*344a7f5eSAndroid Build Coastguard Worker    # TODO(282947321): update after http://aosp/2600447 lands
414*344a7f5eSAndroid Build Coastguard Worker    'androidx.compose.runtime.tracing.TracingInitializer',
415*344a7f5eSAndroid Build Coastguard Worker])
416*344a7f5eSAndroid Build Coastguard Worker
417*344a7f5eSAndroid Build Coastguard Workerandroid_manifest_namepaces = {
418*344a7f5eSAndroid Build Coastguard Worker    'android': 'http://schemas.android.com/apk/res/android',
419*344a7f5eSAndroid Build Coastguard Worker    'tools': 'http://schemas.android.com/tools'
420*344a7f5eSAndroid Build Coastguard Worker}
421*344a7f5eSAndroid Build Coastguard Worker
422*344a7f5eSAndroid Build Coastguard Workerstartup_initializer_pattern = re.compile(r'(\s+)android:value="androidx.startup".*')
423*344a7f5eSAndroid Build Coastguard Worker
424*344a7f5eSAndroid Build Coastguard Workerartifact_pattern = re.compile(r'^(.+?)-(\d+\.\d+\.\d+(?:-\w+\d+)?(?:-[\d.]+)*)\.(jar|aar)$')
425*344a7f5eSAndroid Build Coastguard Worker
426*344a7f5eSAndroid Build Coastguard Worker
427*344a7f5eSAndroid Build Coastguard Workerdef name_for_artifact(group_artifact):
428*344a7f5eSAndroid Build Coastguard Worker    """Returns the build system target name for a given library's Maven coordinate.
429*344a7f5eSAndroid Build Coastguard Worker
430*344a7f5eSAndroid Build Coastguard Worker    Args:
431*344a7f5eSAndroid Build Coastguard Worker        group_artifact: an unversioned Maven artifact coordinate, ex. androidx.core:core
432*344a7f5eSAndroid Build Coastguard Worker    Returns:
433*344a7f5eSAndroid Build Coastguard Worker        The build system target name for the artifact, ex. androidx.core_core.
434*344a7f5eSAndroid Build Coastguard Worker    """
435*344a7f5eSAndroid Build Coastguard Worker    for kmp_suffix in kmp_suffixes:
436*344a7f5eSAndroid Build Coastguard Worker        if group_artifact.endswith("-" + kmp_suffix):
437*344a7f5eSAndroid Build Coastguard Worker            loc = group_artifact.rfind("-" + kmp_suffix)
438*344a7f5eSAndroid Build Coastguard Worker            group_artifact = group_artifact[0:loc]
439*344a7f5eSAndroid Build Coastguard Worker            if group_artifact in maven_to_make:
440*344a7f5eSAndroid Build Coastguard Worker                raise ValueError(f'Do not specify KMP anchor artifact in '
441*344a7f5eSAndroid Build Coastguard Worker                                 f'maven_to_make: {group_artifact}')
442*344a7f5eSAndroid Build Coastguard Worker            deps_rewrite[group_artifact] = group_artifact.replace(':', '_')
443*344a7f5eSAndroid Build Coastguard Worker            break
444*344a7f5eSAndroid Build Coastguard Worker    return group_artifact.replace(':', '_')
445*344a7f5eSAndroid Build Coastguard Worker
446*344a7f5eSAndroid Build Coastguard Worker
447*344a7f5eSAndroid Build Coastguard Workerdef path_for_artifact(group_artifact):
448*344a7f5eSAndroid Build Coastguard Worker    """Returns the file system path for a given library's Maven coordinate.
449*344a7f5eSAndroid Build Coastguard Worker
450*344a7f5eSAndroid Build Coastguard Worker    Args:
451*344a7f5eSAndroid Build Coastguard Worker        group_artifact: an unversioned Maven artifact coordinate, ex. androidx.core:core
452*344a7f5eSAndroid Build Coastguard Worker    Returns:
453*344a7f5eSAndroid Build Coastguard Worker        The file system path for the artifact, ex. androidx/core/core.
454*344a7f5eSAndroid Build Coastguard Worker    """
455*344a7f5eSAndroid Build Coastguard Worker    return group_artifact.replace('.', '/').replace(':', '/')
456*344a7f5eSAndroid Build Coastguard Worker
457*344a7f5eSAndroid Build Coastguard Worker
458*344a7f5eSAndroid Build Coastguard Workerdef populate_maven_to_make(mapping):
459*344a7f5eSAndroid Build Coastguard Worker    """Modifies the input mapping by expanding Maven coordinate keys into build target names and
460*344a7f5eSAndroid Build Coastguard Worker    paths.
461*344a7f5eSAndroid Build Coastguard Worker
462*344a7f5eSAndroid Build Coastguard Worker    Args:
463*344a7f5eSAndroid Build Coastguard Worker        mapping: a map where the keys are Maven coordinates
464*344a7f5eSAndroid Build Coastguard Worker    """
465*344a7f5eSAndroid Build Coastguard Worker    for key in mapping:
466*344a7f5eSAndroid Build Coastguard Worker        if 'name' not in mapping[key]:
467*344a7f5eSAndroid Build Coastguard Worker            mapping[key]['name'] = name_for_artifact(key)
468*344a7f5eSAndroid Build Coastguard Worker        if 'path' not in maven_to_make[key]:
469*344a7f5eSAndroid Build Coastguard Worker            mapping[key]['path'] = path_for_artifact(key)
470*344a7f5eSAndroid Build Coastguard Worker
471*344a7f5eSAndroid Build Coastguard Worker
472*344a7f5eSAndroid Build Coastguard Workerdef detect_artifacts(maven_repo_dirs):
473*344a7f5eSAndroid Build Coastguard Worker    """Parses Maven libraries from the specified directories.
474*344a7f5eSAndroid Build Coastguard Worker
475*344a7f5eSAndroid Build Coastguard Worker    Args:
476*344a7f5eSAndroid Build Coastguard Worker        maven_repo_dirs: a list of maven repository roots
477*344a7f5eSAndroid Build Coastguard Worker    Returns:
478*344a7f5eSAndroid Build Coastguard Worker        A map of Maven coordinate keys to MavenLibraryInfo objects parsed from POM files.
479*344a7f5eSAndroid Build Coastguard Worker    """
480*344a7f5eSAndroid Build Coastguard Worker    maven_lib_info = {}
481*344a7f5eSAndroid Build Coastguard Worker
482*344a7f5eSAndroid Build Coastguard Worker    # Find the latest revision for each artifact, remove others
483*344a7f5eSAndroid Build Coastguard Worker    for repo_dir in maven_repo_dirs:
484*344a7f5eSAndroid Build Coastguard Worker        for root, dirs, files in os.walk(repo_dir):
485*344a7f5eSAndroid Build Coastguard Worker            for file in files:
486*344a7f5eSAndroid Build Coastguard Worker                if file[-4:] == '.pom':
487*344a7f5eSAndroid Build Coastguard Worker                    # Read the POM (hack hack hack).
488*344a7f5eSAndroid Build Coastguard Worker                    group_id = ''
489*344a7f5eSAndroid Build Coastguard Worker                    artifact_id = ''
490*344a7f5eSAndroid Build Coastguard Worker                    version = ''
491*344a7f5eSAndroid Build Coastguard Worker                    file = os.path.join(root, file)
492*344a7f5eSAndroid Build Coastguard Worker                    with open(file) as pom_file:
493*344a7f5eSAndroid Build Coastguard Worker                        for line in pom_file:
494*344a7f5eSAndroid Build Coastguard Worker                            if line[:11] == '  <groupId>':
495*344a7f5eSAndroid Build Coastguard Worker                                group_id = line[11:-11]
496*344a7f5eSAndroid Build Coastguard Worker                            elif line[:14] == '  <artifactId>':
497*344a7f5eSAndroid Build Coastguard Worker                                artifact_id = line[14:-14]
498*344a7f5eSAndroid Build Coastguard Worker                            elif line[:11] == '  <version>':
499*344a7f5eSAndroid Build Coastguard Worker                                version = line[11:-11]
500*344a7f5eSAndroid Build Coastguard Worker                    if group_id == '' or artifact_id == '' or version == '':
501*344a7f5eSAndroid Build Coastguard Worker                        print_e('Failed to find Maven artifact data in ' + file)
502*344a7f5eSAndroid Build Coastguard Worker                        continue
503*344a7f5eSAndroid Build Coastguard Worker
504*344a7f5eSAndroid Build Coastguard Worker                    # Locate the artifact.
505*344a7f5eSAndroid Build Coastguard Worker                    artifact_file = file[:-4]
506*344a7f5eSAndroid Build Coastguard Worker                    if os.path.exists(artifact_file + '.jar'):
507*344a7f5eSAndroid Build Coastguard Worker                        artifact_file = artifact_file + '.jar'
508*344a7f5eSAndroid Build Coastguard Worker                    elif os.path.exists(artifact_file + '.aar'):
509*344a7f5eSAndroid Build Coastguard Worker                        artifact_file = artifact_file + '.aar'
510*344a7f5eSAndroid Build Coastguard Worker                    else:
511*344a7f5eSAndroid Build Coastguard Worker                        # This error only occurs for a handful of gradle.plugin artifacts that only
512*344a7f5eSAndroid Build Coastguard Worker                        # ship POM files, so we probably don't need to log unless we're debugging.
513*344a7f5eSAndroid Build Coastguard Worker                        # print_e('Failed to find artifact for ' + artifact_file)
514*344a7f5eSAndroid Build Coastguard Worker                        continue
515*344a7f5eSAndroid Build Coastguard Worker
516*344a7f5eSAndroid Build Coastguard Worker                    # Make relative to root.
517*344a7f5eSAndroid Build Coastguard Worker                    artifact_file = artifact_file[len(root) + 1:]
518*344a7f5eSAndroid Build Coastguard Worker
519*344a7f5eSAndroid Build Coastguard Worker                    # Find the mapping.
520*344a7f5eSAndroid Build Coastguard Worker                    group_artifact = group_id + ':' + artifact_id
521*344a7f5eSAndroid Build Coastguard Worker                    if group_artifact in maven_to_make:
522*344a7f5eSAndroid Build Coastguard Worker                        key = group_artifact
523*344a7f5eSAndroid Build Coastguard Worker                    elif artifact_id in maven_to_make:
524*344a7f5eSAndroid Build Coastguard Worker                        key = artifact_id
525*344a7f5eSAndroid Build Coastguard Worker                    else:
526*344a7f5eSAndroid Build Coastguard Worker                        # No mapping entry, skip this library.
527*344a7f5eSAndroid Build Coastguard Worker                        continue
528*344a7f5eSAndroid Build Coastguard Worker
529*344a7f5eSAndroid Build Coastguard Worker                    # Store the latest version.
530*344a7f5eSAndroid Build Coastguard Worker                    version = LooseVersion(version)
531*344a7f5eSAndroid Build Coastguard Worker                    if key not in maven_lib_info \
532*344a7f5eSAndroid Build Coastguard Worker                            or version > maven_lib_info[key].version:
533*344a7f5eSAndroid Build Coastguard Worker                        maven_lib_info[key] = MavenLibraryInfo(key, group_id, artifact_id, version,
534*344a7f5eSAndroid Build Coastguard Worker                                                               root, repo_dir, artifact_file)
535*344a7f5eSAndroid Build Coastguard Worker
536*344a7f5eSAndroid Build Coastguard Worker    return maven_lib_info
537*344a7f5eSAndroid Build Coastguard Worker
538*344a7f5eSAndroid Build Coastguard Worker
539*344a7f5eSAndroid Build Coastguard Workerdef find_invalid_spec(artifact_list):
540*344a7f5eSAndroid Build Coastguard Worker    """Verifies whether all the artifacts in the list correspond to an entry in maven_to_make.
541*344a7f5eSAndroid Build Coastguard Worker
542*344a7f5eSAndroid Build Coastguard Worker    Args:
543*344a7f5eSAndroid Build Coastguard Worker        artifact_list: list of group IDs or artifact coordinates
544*344a7f5eSAndroid Build Coastguard Worker    Returns:
545*344a7f5eSAndroid Build Coastguard Worker        The first invalid artifact specification in the list, or None if all specs are valid.
546*344a7f5eSAndroid Build Coastguard Worker    """
547*344a7f5eSAndroid Build Coastguard Worker    if artifact_list is None:
548*344a7f5eSAndroid Build Coastguard Worker        return None
549*344a7f5eSAndroid Build Coastguard Worker    for prefix in artifact_list:
550*344a7f5eSAndroid Build Coastguard Worker        has_prefix = False
551*344a7f5eSAndroid Build Coastguard Worker        for artifact_id in maven_to_make:
552*344a7f5eSAndroid Build Coastguard Worker            if artifact_id.startswith(prefix):
553*344a7f5eSAndroid Build Coastguard Worker                has_prefix = True
554*344a7f5eSAndroid Build Coastguard Worker                break
555*344a7f5eSAndroid Build Coastguard Worker        if not has_prefix:
556*344a7f5eSAndroid Build Coastguard Worker            return prefix
557*344a7f5eSAndroid Build Coastguard Worker    return None
558*344a7f5eSAndroid Build Coastguard Worker
559*344a7f5eSAndroid Build Coastguard Worker
560*344a7f5eSAndroid Build Coastguard Workerdef transform_maven_repos(maven_repo_dirs, transformed_dir, extract_res=True,
561*344a7f5eSAndroid Build Coastguard Worker                          write_pom2bp_cmd=True, include_static_deps=True, include=None,
562*344a7f5eSAndroid Build Coastguard Worker                          exclude=None, prepend=None):
563*344a7f5eSAndroid Build Coastguard Worker    """Transforms a standard Maven repository to be compatible with the Android build system.
564*344a7f5eSAndroid Build Coastguard Worker
565*344a7f5eSAndroid Build Coastguard Worker    When using the include argument by itself, all other libraries will be excluded. When using the
566*344a7f5eSAndroid Build Coastguard Worker    exclude argument by itself, all other libraries will be included. When using both arguments, the
567*344a7f5eSAndroid Build Coastguard Worker    inclusion list will be applied followed by the exclusion list.
568*344a7f5eSAndroid Build Coastguard Worker
569*344a7f5eSAndroid Build Coastguard Worker    Args:
570*344a7f5eSAndroid Build Coastguard Worker        maven_repo_dirs: path to local Maven repository
571*344a7f5eSAndroid Build Coastguard Worker        transformed_dir: relative path for output, ex. androidx
572*344a7f5eSAndroid Build Coastguard Worker        extract_res: whether to extract Android resources like AndroidManifest.xml from AARs
573*344a7f5eSAndroid Build Coastguard Worker        write_pom2bp_cmd: whether pom2bp should write its own invocation arguments to output
574*344a7f5eSAndroid Build Coastguard Worker        include_static_deps: whether to pass --static-deps to pom2bp
575*344a7f5eSAndroid Build Coastguard Worker        include: list of Maven groupIds or unversioned artifact coordinates to include for
576*344a7f5eSAndroid Build Coastguard Worker                 updates, ex. androidx.core or androidx.core:core
577*344a7f5eSAndroid Build Coastguard Worker        exclude: list of Maven groupIds or unversioned artifact coordinates to exclude from
578*344a7f5eSAndroid Build Coastguard Worker                 updates, ex. androidx.core or androidx.core:core
579*344a7f5eSAndroid Build Coastguard Worker        prepend: Path to a file containing text to be inserted at the beginning of the generated
580*344a7f5eSAndroid Build Coastguard Worker                 build file
581*344a7f5eSAndroid Build Coastguard Worker    Returns:
582*344a7f5eSAndroid Build Coastguard Worker        True if successful, false otherwise.
583*344a7f5eSAndroid Build Coastguard Worker    """
584*344a7f5eSAndroid Build Coastguard Worker    # If neither include nor exclude is set, fall back to legacy behavior of including everything.
585*344a7f5eSAndroid Build Coastguard Worker    include_all = exclude is None and include is None
586*344a7f5eSAndroid Build Coastguard Worker
587*344a7f5eSAndroid Build Coastguard Worker    if exclude is None:
588*344a7f5eSAndroid Build Coastguard Worker        exclude = []
589*344a7f5eSAndroid Build Coastguard Worker    if include is None:
590*344a7f5eSAndroid Build Coastguard Worker        include = []
591*344a7f5eSAndroid Build Coastguard Worker
592*344a7f5eSAndroid Build Coastguard Worker    cwd = os.getcwd()
593*344a7f5eSAndroid Build Coastguard Worker    local_repo = os.path.join(cwd, transformed_dir)
594*344a7f5eSAndroid Build Coastguard Worker    working_dir = temp_dir
595*344a7f5eSAndroid Build Coastguard Worker
596*344a7f5eSAndroid Build Coastguard Worker    # Handle inclusions by stashing the remote artifacts for the inclusions, replacing the entire
597*344a7f5eSAndroid Build Coastguard Worker    # remote repo with the local repo, then restoring the stashed artifacts.
598*344a7f5eSAndroid Build Coastguard Worker    for remote_repo in maven_repo_dirs:
599*344a7f5eSAndroid Build Coastguard Worker        remote_repo = os.path.join(cwd, remote_repo)
600*344a7f5eSAndroid Build Coastguard Worker        paths_to_copy = []
601*344a7f5eSAndroid Build Coastguard Worker
602*344a7f5eSAndroid Build Coastguard Worker        # If we're including everything, move the entire repo to temp.
603*344a7f5eSAndroid Build Coastguard Worker        if include_all:
604*344a7f5eSAndroid Build Coastguard Worker            cp(remote_repo, working_dir)
605*344a7f5eSAndroid Build Coastguard Worker        else:
606*344a7f5eSAndroid Build Coastguard Worker            # Move included artifacts from repo to temp.
607*344a7f5eSAndroid Build Coastguard Worker            for group_artifact in include:
608*344a7f5eSAndroid Build Coastguard Worker                artifact_path = os.path.join('m2repository', path_for_artifact(group_artifact))
609*344a7f5eSAndroid Build Coastguard Worker                remote_path = os.path.join(remote_repo, artifact_path)
610*344a7f5eSAndroid Build Coastguard Worker                working_path = os.path.join(working_dir, artifact_path)
611*344a7f5eSAndroid Build Coastguard Worker                if os.path.exists(remote_path):
612*344a7f5eSAndroid Build Coastguard Worker                    print(f'Included {group_artifact} in update')
613*344a7f5eSAndroid Build Coastguard Worker                    paths_to_copy.append([remote_path, working_path])
614*344a7f5eSAndroid Build Coastguard Worker            for [remote_path, working_path] in paths_to_copy:
615*344a7f5eSAndroid Build Coastguard Worker                mv(remote_path, working_path)
616*344a7f5eSAndroid Build Coastguard Worker
617*344a7f5eSAndroid Build Coastguard Worker        # Replace all remaining artifacts in remote repo with local repo.
618*344a7f5eSAndroid Build Coastguard Worker        cp(local_repo, remote_repo)
619*344a7f5eSAndroid Build Coastguard Worker
620*344a7f5eSAndroid Build Coastguard Worker        # If we're including everything, restore the entire repo.
621*344a7f5eSAndroid Build Coastguard Worker        if include_all:
622*344a7f5eSAndroid Build Coastguard Worker            cp(working_dir, remote_repo)
623*344a7f5eSAndroid Build Coastguard Worker        else:
624*344a7f5eSAndroid Build Coastguard Worker            # Restore included artifacts to remote repo.
625*344a7f5eSAndroid Build Coastguard Worker            for [remote_path, working_path] in paths_to_copy:
626*344a7f5eSAndroid Build Coastguard Worker                mv(working_path, remote_path)
627*344a7f5eSAndroid Build Coastguard Worker
628*344a7f5eSAndroid Build Coastguard Worker    # Handle exclusions by replacing the remote artifacts for the exclusions with local artifacts.
629*344a7f5eSAndroid Build Coastguard Worker    # This must happen before we parse the artifacts.
630*344a7f5eSAndroid Build Coastguard Worker    for remote_repo in maven_repo_dirs:
631*344a7f5eSAndroid Build Coastguard Worker        for group_artifact in exclude:
632*344a7f5eSAndroid Build Coastguard Worker            artifact_path = os.path.join('m2repository', path_for_artifact(group_artifact))
633*344a7f5eSAndroid Build Coastguard Worker            remote_path = os.path.join(remote_repo, artifact_path)
634*344a7f5eSAndroid Build Coastguard Worker            if os.path.exists(remote_path):
635*344a7f5eSAndroid Build Coastguard Worker                rm(remote_path)
636*344a7f5eSAndroid Build Coastguard Worker                local_path = os.path.join(local_repo, artifact_path)
637*344a7f5eSAndroid Build Coastguard Worker                if os.path.exists(local_path):
638*344a7f5eSAndroid Build Coastguard Worker                    print(f'Excluded {group_artifact} from update, used local artifact')
639*344a7f5eSAndroid Build Coastguard Worker                    mv(local_path, remote_path)
640*344a7f5eSAndroid Build Coastguard Worker                else:
641*344a7f5eSAndroid Build Coastguard Worker                    print(f'Excluded {group_artifact} from update, no local artifact present')
642*344a7f5eSAndroid Build Coastguard Worker
643*344a7f5eSAndroid Build Coastguard Worker    # Parse artifacts.
644*344a7f5eSAndroid Build Coastguard Worker    maven_lib_info = detect_artifacts(maven_repo_dirs)
645*344a7f5eSAndroid Build Coastguard Worker
646*344a7f5eSAndroid Build Coastguard Worker    if not maven_lib_info:
647*344a7f5eSAndroid Build Coastguard Worker        print_e('Failed to detect artifacts')
648*344a7f5eSAndroid Build Coastguard Worker        return False
649*344a7f5eSAndroid Build Coastguard Worker
650*344a7f5eSAndroid Build Coastguard Worker    # Move libraries into the working directory, performing any necessary transformations.
651*344a7f5eSAndroid Build Coastguard Worker    for info in maven_lib_info.values():
652*344a7f5eSAndroid Build Coastguard Worker        transform_maven_lib(working_dir, info, extract_res)
653*344a7f5eSAndroid Build Coastguard Worker
654*344a7f5eSAndroid Build Coastguard Worker    # Generate a single Android.bp that specifies to use all of the above artifacts.
655*344a7f5eSAndroid Build Coastguard Worker    makefile = os.path.join(working_dir, 'Android.bp')
656*344a7f5eSAndroid Build Coastguard Worker    with open(makefile, 'w') as f:
657*344a7f5eSAndroid Build Coastguard Worker        args = ['pom2bp']
658*344a7f5eSAndroid Build Coastguard Worker        args.extend(['-sdk-version', '31'])
659*344a7f5eSAndroid Build Coastguard Worker        args.extend(['-default-min-sdk-version', '24'])
660*344a7f5eSAndroid Build Coastguard Worker        if not write_pom2bp_cmd:
661*344a7f5eSAndroid Build Coastguard Worker            args.extend(['-write-cmd=false'])
662*344a7f5eSAndroid Build Coastguard Worker        if include_static_deps:
663*344a7f5eSAndroid Build Coastguard Worker            args.append('-static-deps')
664*344a7f5eSAndroid Build Coastguard Worker        if prepend:
665*344a7f5eSAndroid Build Coastguard Worker            args.append(f'-prepend={prepend}')
666*344a7f5eSAndroid Build Coastguard Worker        rewrite_names = sorted(maven_to_make.keys())
667*344a7f5eSAndroid Build Coastguard Worker        args.extend([f'-rewrite=^{name}$={maven_to_make[name]["name"]}' for name in rewrite_names])
668*344a7f5eSAndroid Build Coastguard Worker        args.extend([f'-rewrite=^{key}$={value}' for key, value in deps_rewrite.items()])
669*344a7f5eSAndroid Build Coastguard Worker        args.extend(["-extra-static-libs=" + maven_to_make[name]['name'] + "=" + ",".join(
670*344a7f5eSAndroid Build Coastguard Worker            sorted(maven_to_make[name]['extra-static-libs'])) for name in maven_to_make if
671*344a7f5eSAndroid Build Coastguard Worker                     'extra-static-libs' in maven_to_make[name]])
672*344a7f5eSAndroid Build Coastguard Worker        args.extend(["-optional-uses-libs=" + maven_to_make[name]['name'] + "=" + ",".join(
673*344a7f5eSAndroid Build Coastguard Worker            sorted(maven_to_make[name]['optional-uses-libs'])) for name in maven_to_make if
674*344a7f5eSAndroid Build Coastguard Worker                     'optional-uses-libs' in maven_to_make[name]])
675*344a7f5eSAndroid Build Coastguard Worker        args.extend([f'-host={name}' for name in maven_to_make
676*344a7f5eSAndroid Build Coastguard Worker                     if maven_to_make[name].get('host')])
677*344a7f5eSAndroid Build Coastguard Worker        args.extend([f'-host-and-device={name}' for name in maven_to_make
678*344a7f5eSAndroid Build Coastguard Worker                     if maven_to_make[name].get('host_and_device')])
679*344a7f5eSAndroid Build Coastguard Worker        args.extend(['.'])
680*344a7f5eSAndroid Build Coastguard Worker        subprocess.check_call(args, stdout=f, cwd=working_dir)
681*344a7f5eSAndroid Build Coastguard Worker
682*344a7f5eSAndroid Build Coastguard Worker    # Replace the old directory.
683*344a7f5eSAndroid Build Coastguard Worker    local_repo = os.path.join(cwd, transformed_dir)
684*344a7f5eSAndroid Build Coastguard Worker    mv(working_dir, local_repo)
685*344a7f5eSAndroid Build Coastguard Worker    return True
686*344a7f5eSAndroid Build Coastguard Worker
687*344a7f5eSAndroid Build Coastguard Worker
688*344a7f5eSAndroid Build Coastguard Workerdef transform_maven_lib(working_dir, artifact_info, extract_res):
689*344a7f5eSAndroid Build Coastguard Worker    """Transforms the specified artifact for use in the Android build system.
690*344a7f5eSAndroid Build Coastguard Worker
691*344a7f5eSAndroid Build Coastguard Worker    Moves relevant files for the artifact represented by artifact_info of type MavenLibraryInfo into
692*344a7f5eSAndroid Build Coastguard Worker    the appropriate path inside working_dir, unpacking files needed by the build system from AARs.
693*344a7f5eSAndroid Build Coastguard Worker
694*344a7f5eSAndroid Build Coastguard Worker    Args:
695*344a7f5eSAndroid Build Coastguard Worker        working_dir: The directory into which the artifact should be moved
696*344a7f5eSAndroid Build Coastguard Worker        artifact_info: A MavenLibraryInfo representing the library artifact
697*344a7f5eSAndroid Build Coastguard Worker        extract_res: True to extract resources from AARs, false otherwise.
698*344a7f5eSAndroid Build Coastguard Worker    """
699*344a7f5eSAndroid Build Coastguard Worker    # Move library into working dir
700*344a7f5eSAndroid Build Coastguard Worker    new_dir = os.path.normpath(
701*344a7f5eSAndroid Build Coastguard Worker        os.path.join(working_dir, os.path.relpath(artifact_info.dir, artifact_info.repo_dir)))
702*344a7f5eSAndroid Build Coastguard Worker    mv(artifact_info.dir, new_dir)
703*344a7f5eSAndroid Build Coastguard Worker
704*344a7f5eSAndroid Build Coastguard Worker    maven_lib_type = os.path.splitext(artifact_info.file)[1][1:]
705*344a7f5eSAndroid Build Coastguard Worker
706*344a7f5eSAndroid Build Coastguard Worker    group_artifact = artifact_info.key
707*344a7f5eSAndroid Build Coastguard Worker    make_lib_name = maven_to_make[group_artifact]['name']
708*344a7f5eSAndroid Build Coastguard Worker    make_dir_name = maven_to_make[group_artifact]['path']
709*344a7f5eSAndroid Build Coastguard Worker
710*344a7f5eSAndroid Build Coastguard Worker    artifact_file = os.path.join(new_dir, artifact_info.file)
711*344a7f5eSAndroid Build Coastguard Worker
712*344a7f5eSAndroid Build Coastguard Worker    if maven_lib_type == 'aar':
713*344a7f5eSAndroid Build Coastguard Worker        if extract_res:
714*344a7f5eSAndroid Build Coastguard Worker            target_dir = os.path.join(working_dir, make_dir_name)
715*344a7f5eSAndroid Build Coastguard Worker            if not os.path.exists(target_dir):
716*344a7f5eSAndroid Build Coastguard Worker                os.makedirs(target_dir)
717*344a7f5eSAndroid Build Coastguard Worker
718*344a7f5eSAndroid Build Coastguard Worker            process_aar(artifact_file, target_dir)
719*344a7f5eSAndroid Build Coastguard Worker
720*344a7f5eSAndroid Build Coastguard Worker        with zipfile.ZipFile(artifact_file) as zip_file:
721*344a7f5eSAndroid Build Coastguard Worker            manifests_dir = os.path.join(working_dir, 'manifests')
722*344a7f5eSAndroid Build Coastguard Worker            lib_path = Path(os.path.join(manifests_dir, make_lib_name))
723*344a7f5eSAndroid Build Coastguard Worker            manifest_path = lib_path / 'AndroidManifest.xml'
724*344a7f5eSAndroid Build Coastguard Worker            zip_file.extract('AndroidManifest.xml', lib_path.as_posix())
725*344a7f5eSAndroid Build Coastguard Worker            contents = check_startup_initializers(manifest_path)
726*344a7f5eSAndroid Build Coastguard Worker            if contents:
727*344a7f5eSAndroid Build Coastguard Worker                manifest_path.write_text(contents)
728*344a7f5eSAndroid Build Coastguard Worker
729*344a7f5eSAndroid Build Coastguard Worker
730*344a7f5eSAndroid Build Coastguard Workerdef process_aar(artifact_file, target_dir):
731*344a7f5eSAndroid Build Coastguard Worker    """Extracts and cleans up the contents of an AAR file to the specified directory.
732*344a7f5eSAndroid Build Coastguard Worker
733*344a7f5eSAndroid Build Coastguard Worker    Removes classes.jar, empty directories, and denylisted files.
734*344a7f5eSAndroid Build Coastguard Worker
735*344a7f5eSAndroid Build Coastguard Worker    Args:
736*344a7f5eSAndroid Build Coastguard Worker        artifact_file: path to the AAR to extract
737*344a7f5eSAndroid Build Coastguard Worker        target_dir: directory into which the contents should be extracted
738*344a7f5eSAndroid Build Coastguard Worker    """
739*344a7f5eSAndroid Build Coastguard Worker    # Extract AAR file to target_dir.
740*344a7f5eSAndroid Build Coastguard Worker    with zipfile.ZipFile(artifact_file) as zip_file:
741*344a7f5eSAndroid Build Coastguard Worker        zip_file.extractall(target_dir)
742*344a7f5eSAndroid Build Coastguard Worker
743*344a7f5eSAndroid Build Coastguard Worker    # Remove classes.jar
744*344a7f5eSAndroid Build Coastguard Worker    classes_jar = os.path.join(target_dir, 'classes.jar')
745*344a7f5eSAndroid Build Coastguard Worker    if os.path.exists(classes_jar):
746*344a7f5eSAndroid Build Coastguard Worker        os.remove(classes_jar)
747*344a7f5eSAndroid Build Coastguard Worker
748*344a7f5eSAndroid Build Coastguard Worker    # Remove empty dirs.
749*344a7f5eSAndroid Build Coastguard Worker    for root, dirs, files in os.walk(target_dir, topdown=False):
750*344a7f5eSAndroid Build Coastguard Worker        for dir_name in dirs:
751*344a7f5eSAndroid Build Coastguard Worker            dir_path = os.path.join(root, dir_name)
752*344a7f5eSAndroid Build Coastguard Worker            if not os.listdir(dir_path):
753*344a7f5eSAndroid Build Coastguard Worker                os.rmdir(dir_path)
754*344a7f5eSAndroid Build Coastguard Worker
755*344a7f5eSAndroid Build Coastguard Worker    # Remove top-level cruft.
756*344a7f5eSAndroid Build Coastguard Worker    for file in denylist_files:
757*344a7f5eSAndroid Build Coastguard Worker        file_path = os.path.join(target_dir, file)
758*344a7f5eSAndroid Build Coastguard Worker        if os.path.exists(file_path):
759*344a7f5eSAndroid Build Coastguard Worker            os.remove(file_path)
760*344a7f5eSAndroid Build Coastguard Worker
761*344a7f5eSAndroid Build Coastguard Worker
762*344a7f5eSAndroid Build Coastguard Workerdef fetch_gmaven_artifact(artifact):
763*344a7f5eSAndroid Build Coastguard Worker    """Fetch a GMaven artifact.
764*344a7f5eSAndroid Build Coastguard Worker
765*344a7f5eSAndroid Build Coastguard Worker    Downloads a GMaven artifact
766*344a7f5eSAndroid Build Coastguard Worker    (https://developer.android.com/studio/build/dependencies#gmaven-access)
767*344a7f5eSAndroid Build Coastguard Worker
768*344a7f5eSAndroid Build Coastguard Worker    Args:
769*344a7f5eSAndroid Build Coastguard Worker        artifact: an instance of GMavenArtifact.
770*344a7f5eSAndroid Build Coastguard Worker    """
771*344a7f5eSAndroid Build Coastguard Worker    pom_path = maven_path_for_artifact(
772*344a7f5eSAndroid Build Coastguard Worker        'gmaven', artifact.group, artifact.library, artifact.version, 'pom')
773*344a7f5eSAndroid Build Coastguard Worker    artifact_path = maven_path_for_artifact(
774*344a7f5eSAndroid Build Coastguard Worker        'gmaven', artifact.group, artifact.library, artifact.version, artifact.ext)
775*344a7f5eSAndroid Build Coastguard Worker
776*344a7f5eSAndroid Build Coastguard Worker    download_file_to_disk(artifact.get_pom_file_url(), pom_path)
777*344a7f5eSAndroid Build Coastguard Worker    download_file_to_disk(artifact.get_artifact_url(), artifact_path)
778*344a7f5eSAndroid Build Coastguard Worker
779*344a7f5eSAndroid Build Coastguard Worker    return os.path.dirname(artifact_path)
780*344a7f5eSAndroid Build Coastguard Worker
781*344a7f5eSAndroid Build Coastguard Worker
782*344a7f5eSAndroid Build Coastguard Workerdef download_file_to_disk(url, filepath):
783*344a7f5eSAndroid Build Coastguard Worker    """Download the file at URL to the location dictated by the path.
784*344a7f5eSAndroid Build Coastguard Worker
785*344a7f5eSAndroid Build Coastguard Worker    Args:
786*344a7f5eSAndroid Build Coastguard Worker        url: Remote URL to download file from.
787*344a7f5eSAndroid Build Coastguard Worker        filepath: Filesystem path to write the file to.
788*344a7f5eSAndroid Build Coastguard Worker    """
789*344a7f5eSAndroid Build Coastguard Worker    print(f'Downloading URL: {url}')
790*344a7f5eSAndroid Build Coastguard Worker    file_data = request.urlopen(url)
791*344a7f5eSAndroid Build Coastguard Worker
792*344a7f5eSAndroid Build Coastguard Worker    try:
793*344a7f5eSAndroid Build Coastguard Worker        os.makedirs(os.path.dirname(filepath))
794*344a7f5eSAndroid Build Coastguard Worker    except os.error:
795*344a7f5eSAndroid Build Coastguard Worker        # This is a common situation - os.makedirs fails if dir already exists.
796*344a7f5eSAndroid Build Coastguard Worker        pass
797*344a7f5eSAndroid Build Coastguard Worker    try:
798*344a7f5eSAndroid Build Coastguard Worker        with open(filepath, 'wb') as f:
799*344a7f5eSAndroid Build Coastguard Worker            f.write(six.ensure_binary(file_data.read()))
800*344a7f5eSAndroid Build Coastguard Worker    except Exception as e:
801*344a7f5eSAndroid Build Coastguard Worker        print_e(e.__class__, 'occurred while reading', filepath)
802*344a7f5eSAndroid Build Coastguard Worker        os.remove(os.path.dirname(filepath))
803*344a7f5eSAndroid Build Coastguard Worker        raise
804*344a7f5eSAndroid Build Coastguard Worker
805*344a7f5eSAndroid Build Coastguard Worker
806*344a7f5eSAndroid Build Coastguard Workerdef check_startup_initializers(manifest_path: Path) -> Optional[str]:
807*344a7f5eSAndroid Build Coastguard Worker    try:
808*344a7f5eSAndroid Build Coastguard Worker        for prefix in android_manifest_namepaces:
809*344a7f5eSAndroid Build Coastguard Worker            ET.register_namespace(prefix, android_manifest_namepaces[prefix])
810*344a7f5eSAndroid Build Coastguard Worker
811*344a7f5eSAndroid Build Coastguard Worker        # Use ElementTree to check if we need updates.
812*344a7f5eSAndroid Build Coastguard Worker        # That way we avoid false positives.
813*344a7f5eSAndroid Build Coastguard Worker        contents = manifest_path.read_text()
814*344a7f5eSAndroid Build Coastguard Worker        root = ET.fromstring(contents)
815*344a7f5eSAndroid Build Coastguard Worker        needs_changes = _check_node(root)
816*344a7f5eSAndroid Build Coastguard Worker        if needs_changes:
817*344a7f5eSAndroid Build Coastguard Worker            # Ideally we would use ElementTree here.
818*344a7f5eSAndroid Build Coastguard Worker            # Instead, we are using regular expressions here so we can
819*344a7f5eSAndroid Build Coastguard Worker            # preserve comments and whitespaces.
820*344a7f5eSAndroid Build Coastguard Worker            lines = contents.splitlines()
821*344a7f5eSAndroid Build Coastguard Worker            output = StringIO()
822*344a7f5eSAndroid Build Coastguard Worker            for line in lines:
823*344a7f5eSAndroid Build Coastguard Worker                matcher = startup_initializer_pattern.match(line)
824*344a7f5eSAndroid Build Coastguard Worker                if matcher:
825*344a7f5eSAndroid Build Coastguard Worker                    prefix = matcher.group(1)
826*344a7f5eSAndroid Build Coastguard Worker                    # Adding an explicit tools:node="remove" so this is still traceable
827*344a7f5eSAndroid Build Coastguard Worker                    # when looking at the source.
828*344a7f5eSAndroid Build Coastguard Worker                    output.write(f'{prefix}android:value="androidx.startup"\n')
829*344a7f5eSAndroid Build Coastguard Worker                    output.write(f'{prefix}tools:node="remove" />')
830*344a7f5eSAndroid Build Coastguard Worker                else:
831*344a7f5eSAndroid Build Coastguard Worker                    output.write(line)
832*344a7f5eSAndroid Build Coastguard Worker                output.write('\n')
833*344a7f5eSAndroid Build Coastguard Worker
834*344a7f5eSAndroid Build Coastguard Worker            output.write('\n')
835*344a7f5eSAndroid Build Coastguard Worker            return output.getvalue()
836*344a7f5eSAndroid Build Coastguard Worker    except BaseException as exception:
837*344a7f5eSAndroid Build Coastguard Worker        print(
838*344a7f5eSAndroid Build Coastguard Worker            f'Unable to parse manifest file with path {manifest_path}.\n\n Details ({exception})'
839*344a7f5eSAndroid Build Coastguard Worker        )
840*344a7f5eSAndroid Build Coastguard Worker
841*344a7f5eSAndroid Build Coastguard Workerdef _attribute_name(namespace: str, attribute: str) -> str:
842*344a7f5eSAndroid Build Coastguard Worker    if not namespace in android_manifest_namepaces:
843*344a7f5eSAndroid Build Coastguard Worker        raise ValueError(f'Unexpected namespace {namespace}')
844*344a7f5eSAndroid Build Coastguard Worker
845*344a7f5eSAndroid Build Coastguard Worker    return f'{{{android_manifest_namepaces[namespace]}}}{attribute}'
846*344a7f5eSAndroid Build Coastguard Worker
847*344a7f5eSAndroid Build Coastguard Worker
848*344a7f5eSAndroid Build Coastguard Workerdef _check_node(node: ET.Element) -> bool:
849*344a7f5eSAndroid Build Coastguard Worker    for child in node:
850*344a7f5eSAndroid Build Coastguard Worker        # Find the initialization provider
851*344a7f5eSAndroid Build Coastguard Worker        is_provider = child.tag == 'provider'
852*344a7f5eSAndroid Build Coastguard Worker        provider_name = child.attrib.get(_attribute_name('android', 'name'))
853*344a7f5eSAndroid Build Coastguard Worker        is_initialization_provider = provider_name == 'androidx.startup.InitializationProvider'
854*344a7f5eSAndroid Build Coastguard Worker
855*344a7f5eSAndroid Build Coastguard Worker        if is_provider and is_initialization_provider:
856*344a7f5eSAndroid Build Coastguard Worker            metadata_nodes = child.findall('meta-data', namespaces=android_manifest_namepaces)
857*344a7f5eSAndroid Build Coastguard Worker            return _needs_disable_initialization(metadata_nodes)
858*344a7f5eSAndroid Build Coastguard Worker
859*344a7f5eSAndroid Build Coastguard Worker        if len(child) > 0:
860*344a7f5eSAndroid Build Coastguard Worker            return _check_node(child)
861*344a7f5eSAndroid Build Coastguard Worker
862*344a7f5eSAndroid Build Coastguard Worker    return False
863*344a7f5eSAndroid Build Coastguard Worker
864*344a7f5eSAndroid Build Coastguard Worker
865*344a7f5eSAndroid Build Coastguard Workerdef _needs_disable_initialization(metadata_nodes: Iterable[ET.Element]) -> bool:
866*344a7f5eSAndroid Build Coastguard Worker    needs_update = False
867*344a7f5eSAndroid Build Coastguard Worker    for node in metadata_nodes:
868*344a7f5eSAndroid Build Coastguard Worker        name = node.attrib.get(_attribute_name('android', 'name'))
869*344a7f5eSAndroid Build Coastguard Worker        value = node.attrib.get(_attribute_name('android', 'value'))
870*344a7f5eSAndroid Build Coastguard Worker        if value == 'androidx.startup':
871*344a7f5eSAndroid Build Coastguard Worker            if name not in enabled_initializers:
872*344a7f5eSAndroid Build Coastguard Worker                needs_update = True
873*344a7f5eSAndroid Build Coastguard Worker
874*344a7f5eSAndroid Build Coastguard Worker    return needs_update
875*344a7f5eSAndroid Build Coastguard Worker
876*344a7f5eSAndroid Build Coastguard Worker
877*344a7f5eSAndroid Build Coastguard Workerdef update_gmaven(gmaven_artifacts_list):
878*344a7f5eSAndroid Build Coastguard Worker    artifacts = [GMavenArtifact(artifact) for artifact in gmaven_artifacts_list]
879*344a7f5eSAndroid Build Coastguard Worker    for artifact in artifacts:
880*344a7f5eSAndroid Build Coastguard Worker        if artifact.version == 'latest':
881*344a7f5eSAndroid Build Coastguard Worker            artifact.version = artifact.get_latest_version()
882*344a7f5eSAndroid Build Coastguard Worker
883*344a7f5eSAndroid Build Coastguard Worker    if not transform_maven_repos(['gmaven'], gmaven_dir, extract_res=False):
884*344a7f5eSAndroid Build Coastguard Worker        return []
885*344a7f5eSAndroid Build Coastguard Worker    return [artifact.key for artifact in artifacts]
886*344a7f5eSAndroid Build Coastguard Worker
887*344a7f5eSAndroid Build Coastguard Worker
888*344a7f5eSAndroid Build Coastguard Workerdef update_androidx(target, build_id, local_file, include, exclude, beyond_corp):
889*344a7f5eSAndroid Build Coastguard Worker    """Fetches and extracts Jetpack library prebuilts.
890*344a7f5eSAndroid Build Coastguard Worker
891*344a7f5eSAndroid Build Coastguard Worker    Args:
892*344a7f5eSAndroid Build Coastguard Worker        target: Android build server target name, must be specified if local_file is empty
893*344a7f5eSAndroid Build Coastguard Worker        build_id: Optional Android build server ID, must be specified if local_file is empty
894*344a7f5eSAndroid Build Coastguard Worker        local_file: Optional local top-of-tree ZIP, must be specified if build_id is empty
895*344a7f5eSAndroid Build Coastguard Worker        include: List of Maven groupIds or unversioned artifact coordinates to include for
896*344a7f5eSAndroid Build Coastguard Worker                 updates, ex. android.core or androidx.core:core
897*344a7f5eSAndroid Build Coastguard Worker        exclude: List of Maven groupIds or unversioned artifact coordinates to exclude from
898*344a7f5eSAndroid Build Coastguard Worker                 updates, ex. android.core or androidx.core:core
899*344a7f5eSAndroid Build Coastguard Worker        beyond_corp: Whether to use BeyondCorp-compatible artifact fetcher
900*344a7f5eSAndroid Build Coastguard Worker    Returns:
901*344a7f5eSAndroid Build Coastguard Worker        True if successful, false otherwise.
902*344a7f5eSAndroid Build Coastguard Worker    """
903*344a7f5eSAndroid Build Coastguard Worker    if build_id:
904*344a7f5eSAndroid Build Coastguard Worker        repo_file = 'top-of-tree-m2repository-all-%s.zip' % build_id.fs_id
905*344a7f5eSAndroid Build Coastguard Worker        repo_dir = fetch_and_extract(target, build_id.url_id, repo_file, beyond_corp, None)
906*344a7f5eSAndroid Build Coastguard Worker    else:
907*344a7f5eSAndroid Build Coastguard Worker        repo_dir = fetch_and_extract(target, None, None, beyond_corp, local_file)
908*344a7f5eSAndroid Build Coastguard Worker    if not repo_dir:
909*344a7f5eSAndroid Build Coastguard Worker        print_e('Failed to extract AndroidX repository')
910*344a7f5eSAndroid Build Coastguard Worker        return False
911*344a7f5eSAndroid Build Coastguard Worker
912*344a7f5eSAndroid Build Coastguard Worker    prepend_path = os.path.relpath('update_prebuilts/prepend_androidx_license', start=temp_dir)
913*344a7f5eSAndroid Build Coastguard Worker
914*344a7f5eSAndroid Build Coastguard Worker    # Transform the repo archive into a Makefile-compatible format.
915*344a7f5eSAndroid Build Coastguard Worker    if not transform_maven_repos([repo_dir], androidx_dir, write_pom2bp_cmd=False,
916*344a7f5eSAndroid Build Coastguard Worker                                 extract_res=False, include=include, exclude=exclude,
917*344a7f5eSAndroid Build Coastguard Worker                                 prepend=prepend_path):
918*344a7f5eSAndroid Build Coastguard Worker        return False
919*344a7f5eSAndroid Build Coastguard Worker
920*344a7f5eSAndroid Build Coastguard Worker    # Import JavaPlugins.bp in Android.bp.
921*344a7f5eSAndroid Build Coastguard Worker    makefile = os.path.join(androidx_dir, 'Android.bp')
922*344a7f5eSAndroid Build Coastguard Worker    with open(makefile, 'a+') as f:
923*344a7f5eSAndroid Build Coastguard Worker        f.write('\nbuild = ["JavaPlugins.bp"]\n')
924*344a7f5eSAndroid Build Coastguard Worker
925*344a7f5eSAndroid Build Coastguard Worker    # Keep OWNERs file, JavaPlugins.bp file, and TEST_MAPPING files untouched.
926*344a7f5eSAndroid Build Coastguard Worker    files_to_restore = [androidx_owners, java_plugins_bp_path, test_mapping_file,
927*344a7f5eSAndroid Build Coastguard Worker                        drop_config_toml, compose_test_mapping_file]
928*344a7f5eSAndroid Build Coastguard Worker    for file_to_restore in files_to_restore:
929*344a7f5eSAndroid Build Coastguard Worker        # Ignore any output or error - these files are not gauranteed to exist, but
930*344a7f5eSAndroid Build Coastguard Worker        # if they do, we want to restore them.
931*344a7f5eSAndroid Build Coastguard Worker        subprocess.call(['git', 'restore', file_to_restore],
932*344a7f5eSAndroid Build Coastguard Worker                        stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
933*344a7f5eSAndroid Build Coastguard Worker
934*344a7f5eSAndroid Build Coastguard Worker    return True
935*344a7f5eSAndroid Build Coastguard Worker
936*344a7f5eSAndroid Build Coastguard Worker
937*344a7f5eSAndroid Build Coastguard Workerdef update_jetifier(target, build_id, beyond_corp):
938*344a7f5eSAndroid Build Coastguard Worker    """
939*344a7f5eSAndroid Build Coastguard Worker    Fetches and extracts Jetifier tool prebuilts.
940*344a7f5eSAndroid Build Coastguard Worker
941*344a7f5eSAndroid Build Coastguard Worker    Args:
942*344a7f5eSAndroid Build Coastguard Worker        target: Android build server target name
943*344a7f5eSAndroid Build Coastguard Worker        build_id: Android build server ID
944*344a7f5eSAndroid Build Coastguard Worker        beyond_corp: Whether to use BeyondCorp-compatible artifact fetcher
945*344a7f5eSAndroid Build Coastguard Worker    Return:
946*344a7f5eSAndroid Build Coastguard Worker        Whether the prebuilt was successfully updated.
947*344a7f5eSAndroid Build Coastguard Worker    """
948*344a7f5eSAndroid Build Coastguard Worker    repo_file = 'jetifier-standalone.zip'
949*344a7f5eSAndroid Build Coastguard Worker    repo_dir = fetch_and_extract(target, build_id.url_id, repo_file, beyond_corp)
950*344a7f5eSAndroid Build Coastguard Worker    if not repo_dir:
951*344a7f5eSAndroid Build Coastguard Worker        print_e('Failed to extract Jetifier')
952*344a7f5eSAndroid Build Coastguard Worker        return False
953*344a7f5eSAndroid Build Coastguard Worker
954*344a7f5eSAndroid Build Coastguard Worker    rm(jetifier_dir)
955*344a7f5eSAndroid Build Coastguard Worker    mv(os.path.join(repo_dir, 'jetifier-standalone'), jetifier_dir)
956*344a7f5eSAndroid Build Coastguard Worker    os.chmod(os.path.join(jetifier_dir, 'bin', 'jetifier-standalone'), 0o755)
957*344a7f5eSAndroid Build Coastguard Worker    return True
958*344a7f5eSAndroid Build Coastguard Worker
959*344a7f5eSAndroid Build Coastguard Worker
960*344a7f5eSAndroid Build Coastguard Workerdef update_constraint(local_file):
961*344a7f5eSAndroid Build Coastguard Worker    """
962*344a7f5eSAndroid Build Coastguard Worker    Extracts ConstraintLayout library prebuilts.
963*344a7f5eSAndroid Build Coastguard Worker
964*344a7f5eSAndroid Build Coastguard Worker    Args:
965*344a7f5eSAndroid Build Coastguard Worker        local_file: local Maven repository ZIP containing library artifacts
966*344a7f5eSAndroid Build Coastguard Worker    Return:
967*344a7f5eSAndroid Build Coastguard Worker        Whether the prebuilts were successfully updated.
968*344a7f5eSAndroid Build Coastguard Worker    """
969*344a7f5eSAndroid Build Coastguard Worker    repo_dir = extract_artifact(local_file)
970*344a7f5eSAndroid Build Coastguard Worker    if not repo_dir:
971*344a7f5eSAndroid Build Coastguard Worker        print_e('Failed to extract Constraint Layout')
972*344a7f5eSAndroid Build Coastguard Worker        return False
973*344a7f5eSAndroid Build Coastguard Worker    return transform_maven_repos([repo_dir], os.path.join(extras_dir, 'constraint-layout-x'),
974*344a7f5eSAndroid Build Coastguard Worker                                 extract_res=False)
975*344a7f5eSAndroid Build Coastguard Worker
976*344a7f5eSAndroid Build Coastguard Worker
977*344a7f5eSAndroid Build Coastguard Workerdef update_material(local_file):
978*344a7f5eSAndroid Build Coastguard Worker    """
979*344a7f5eSAndroid Build Coastguard Worker    Extracts Material Design Components library prebuilts.
980*344a7f5eSAndroid Build Coastguard Worker
981*344a7f5eSAndroid Build Coastguard Worker    Args:
982*344a7f5eSAndroid Build Coastguard Worker        local_file: local Maven repository ZIP containing library artifacts
983*344a7f5eSAndroid Build Coastguard Worker    Return:
984*344a7f5eSAndroid Build Coastguard Worker        Whether the prebuilts were successfully updated.
985*344a7f5eSAndroid Build Coastguard Worker    """
986*344a7f5eSAndroid Build Coastguard Worker    design_dir = extract_artifact(local_file)
987*344a7f5eSAndroid Build Coastguard Worker    if not design_dir:
988*344a7f5eSAndroid Build Coastguard Worker        print_e('Failed to extract Material Design Components')
989*344a7f5eSAndroid Build Coastguard Worker        return False
990*344a7f5eSAndroid Build Coastguard Worker    return transform_maven_repos([design_dir], os.path.join(extras_dir, 'material-design-x'),
991*344a7f5eSAndroid Build Coastguard Worker                                 extract_res=False)
992*344a7f5eSAndroid Build Coastguard Worker
993*344a7f5eSAndroid Build Coastguard Worker
994*344a7f5eSAndroid Build Coastguard Workerdef fetch_artifact(target, build_id, artifact_path, beyond_corp, local_mode):
995*344a7f5eSAndroid Build Coastguard Worker    if not local_mode:
996*344a7f5eSAndroid Build Coastguard Worker        return buildserver_fetch_artifact(target, build_id, artifact_path, beyond_corp)
997*344a7f5eSAndroid Build Coastguard Worker
998*344a7f5eSAndroid Build Coastguard Worker    copy_from = os.path.join(repo_root_dir.resolve(), 'out/dist', artifact_path)
999*344a7f5eSAndroid Build Coastguard Worker    copy_to = os.path.join('.', os.path.dirname(artifact_path))
1000*344a7f5eSAndroid Build Coastguard Worker    print(f'Copying {copy_from} to {copy_to}...')
1001*344a7f5eSAndroid Build Coastguard Worker    result_path = None
1002*344a7f5eSAndroid Build Coastguard Worker    try:
1003*344a7f5eSAndroid Build Coastguard Worker        if not os.path.exists(copy_to):
1004*344a7f5eSAndroid Build Coastguard Worker            os.makedirs(copy_to)
1005*344a7f5eSAndroid Build Coastguard Worker        copied = 0
1006*344a7f5eSAndroid Build Coastguard Worker        for file in glob.glob(copy_from):
1007*344a7f5eSAndroid Build Coastguard Worker            result_path = shutil.copy(file, copy_to)
1008*344a7f5eSAndroid Build Coastguard Worker            copied += 1
1009*344a7f5eSAndroid Build Coastguard Worker        # Multiple files, return destination folder.
1010*344a7f5eSAndroid Build Coastguard Worker        if copied > 1:
1011*344a7f5eSAndroid Build Coastguard Worker            result_path = artifact_path
1012*344a7f5eSAndroid Build Coastguard Worker    except Exception as e:
1013*344a7f5eSAndroid Build Coastguard Worker        print(f'Error: {e} occured while copying')
1014*344a7f5eSAndroid Build Coastguard Worker        raise
1015*344a7f5eSAndroid Build Coastguard Worker    return result_path
1016*344a7f5eSAndroid Build Coastguard Worker
1017*344a7f5eSAndroid Build Coastguard Worker
1018*344a7f5eSAndroid Build Coastguard Workerdef fetch_artifacts(target, build_id, artifact_dict, beyond_corp, local_mode):
1019*344a7f5eSAndroid Build Coastguard Worker    if not local_mode:
1020*344a7f5eSAndroid Build Coastguard Worker        return buildserver_fetch_artifacts(target, build_id, artifact_dict, beyond_corp)
1021*344a7f5eSAndroid Build Coastguard Worker
1022*344a7f5eSAndroid Build Coastguard Worker    for artifact, target_path in artifact_dict.items():
1023*344a7f5eSAndroid Build Coastguard Worker        artifact_path = fetch_artifact(target, build_id.url_id, artifact, beyond_corp, local_mode)
1024*344a7f5eSAndroid Build Coastguard Worker        if not artifact_path:
1025*344a7f5eSAndroid Build Coastguard Worker            return False
1026*344a7f5eSAndroid Build Coastguard Worker        mv(artifact_path, target_path)
1027*344a7f5eSAndroid Build Coastguard Worker    return True
1028*344a7f5eSAndroid Build Coastguard Worker
1029*344a7f5eSAndroid Build Coastguard Worker
1030*344a7f5eSAndroid Build Coastguard Workerdef update_framework(target, build_id, sdk_dir, beyond_corp, local_mode):
1031*344a7f5eSAndroid Build Coastguard Worker    api_scope_list = ['public', 'system', 'test', 'module-lib', 'system-server']
1032*344a7f5eSAndroid Build Coastguard Worker    if sdk_dir == 'current':
1033*344a7f5eSAndroid Build Coastguard Worker        api_scope_list.append('core')
1034*344a7f5eSAndroid Build Coastguard Worker
1035*344a7f5eSAndroid Build Coastguard Worker    for api_scope in api_scope_list:
1036*344a7f5eSAndroid Build Coastguard Worker        target_dir = os.path.join(sdk_dir, api_scope)
1037*344a7f5eSAndroid Build Coastguard Worker        if api_scope == 'core':
1038*344a7f5eSAndroid Build Coastguard Worker            artifact_to_path = {'core.current.stubs.jar': os.path.join(target_dir, 'android.jar')}
1039*344a7f5eSAndroid Build Coastguard Worker        else:
1040*344a7f5eSAndroid Build Coastguard Worker            artifact_to_path = {
1041*344a7f5eSAndroid Build Coastguard Worker                'apistubs/android/' + api_scope + '/*.jar': os.path.join(target_dir, '*'),
1042*344a7f5eSAndroid Build Coastguard Worker            }
1043*344a7f5eSAndroid Build Coastguard Worker            if api_scope == 'public' or api_scope == 'module-lib':
1044*344a7f5eSAndroid Build Coastguard Worker                # Distinct core-for-system-modules.jar files are only provided
1045*344a7f5eSAndroid Build Coastguard Worker                # for the public and module-lib API surfaces.
1046*344a7f5eSAndroid Build Coastguard Worker                artifact_to_path[
1047*344a7f5eSAndroid Build Coastguard Worker                    'system-modules/' + api_scope + '/core-for-system-modules.jar'] = os.path.join(
1048*344a7f5eSAndroid Build Coastguard Worker                    target_dir, '*')
1049*344a7f5eSAndroid Build Coastguard Worker
1050*344a7f5eSAndroid Build Coastguard Worker        if not fetch_artifacts(target, build_id, artifact_to_path, beyond_corp, local_mode):
1051*344a7f5eSAndroid Build Coastguard Worker            return False
1052*344a7f5eSAndroid Build Coastguard Worker
1053*344a7f5eSAndroid Build Coastguard Worker        if api_scope == 'public':
1054*344a7f5eSAndroid Build Coastguard Worker            # Fetch a few artifacts from the public sdk.
1055*344a7f5eSAndroid Build Coastguard Worker            if local_mode:
1056*344a7f5eSAndroid Build Coastguard Worker                artifact = 'android-sdk*.zip'
1057*344a7f5eSAndroid Build Coastguard Worker            else:
1058*344a7f5eSAndroid Build Coastguard Worker                artifact = f'sdk-repo-linux-platforms-{build_id.fs_id}.zip'
1059*344a7f5eSAndroid Build Coastguard Worker            artifact_path = fetch_artifact(target, build_id.url_id, artifact, beyond_corp, local_mode)
1060*344a7f5eSAndroid Build Coastguard Worker            if not artifact_path:
1061*344a7f5eSAndroid Build Coastguard Worker                return False
1062*344a7f5eSAndroid Build Coastguard Worker
1063*344a7f5eSAndroid Build Coastguard Worker            with zipfile.ZipFile(artifact_path) as zipFile:
1064*344a7f5eSAndroid Build Coastguard Worker                extra_files = [
1065*344a7f5eSAndroid Build Coastguard Worker                    'android.jar',
1066*344a7f5eSAndroid Build Coastguard Worker                    'framework.aidl',
1067*344a7f5eSAndroid Build Coastguard Worker                    'uiautomator.jar']
1068*344a7f5eSAndroid Build Coastguard Worker                for filename in extra_files:
1069*344a7f5eSAndroid Build Coastguard Worker                    matches = list(filter(lambda path: filename in path, zipFile.namelist()))
1070*344a7f5eSAndroid Build Coastguard Worker                    if len(matches) != 1:
1071*344a7f5eSAndroid Build Coastguard Worker                        print_e('Expected 1 file named \'%s\' in zip %s, found %d' %
1072*344a7f5eSAndroid Build Coastguard Worker                                (filename, zipFile.filename, len(matches)))
1073*344a7f5eSAndroid Build Coastguard Worker                        return False
1074*344a7f5eSAndroid Build Coastguard Worker                    zip_path = matches[0]
1075*344a7f5eSAndroid Build Coastguard Worker                    src_path = zipFile.extract(zip_path)
1076*344a7f5eSAndroid Build Coastguard Worker                    dst_path = os.path.join(target_dir, filename)
1077*344a7f5eSAndroid Build Coastguard Worker                    mv(src_path, dst_path)
1078*344a7f5eSAndroid Build Coastguard Worker
1079*344a7f5eSAndroid Build Coastguard Worker    # Fetch the lint api databases
1080*344a7f5eSAndroid Build Coastguard Worker    lint_database_artifacts = {}
1081*344a7f5eSAndroid Build Coastguard Worker    for api_scope in ['public', 'system', 'module-lib', 'system-server']:
1082*344a7f5eSAndroid Build Coastguard Worker        data_folder = 'data' if api_scope == 'public' else api_scope + '-data'
1083*344a7f5eSAndroid Build Coastguard Worker        lint_database_artifacts[os.path.join(data_folder, 'api-versions.xml')] = os.path.join(sdk_dir, api_scope, 'data', 'api-versions.xml')
1084*344a7f5eSAndroid Build Coastguard Worker        lint_database_artifacts[os.path.join(data_folder, 'annotations.zip')] = os.path.join(sdk_dir, api_scope, 'data', 'annotations.zip')
1085*344a7f5eSAndroid Build Coastguard Worker    fetch_artifacts(target, build_id, lint_database_artifacts, beyond_corp, local_mode)
1086*344a7f5eSAndroid Build Coastguard Worker
1087*344a7f5eSAndroid Build Coastguard Worker    return True
1088*344a7f5eSAndroid Build Coastguard Worker
1089*344a7f5eSAndroid Build Coastguard Worker
1090*344a7f5eSAndroid Build Coastguard Workerdef update_makefile(build_id):
1091*344a7f5eSAndroid Build Coastguard Worker    template = '"%s",\n\
1092*344a7f5eSAndroid Build Coastguard Worker        "current"'
1093*344a7f5eSAndroid Build Coastguard Worker    makefile = os.path.join(git_dir, 'Android.bp')
1094*344a7f5eSAndroid Build Coastguard Worker
1095*344a7f5eSAndroid Build Coastguard Worker    with open(makefile, 'r+') as f:
1096*344a7f5eSAndroid Build Coastguard Worker        contents = f.read().replace('"current"', template % build_id)
1097*344a7f5eSAndroid Build Coastguard Worker        f.seek(0)
1098*344a7f5eSAndroid Build Coastguard Worker        f.write(contents)
1099*344a7f5eSAndroid Build Coastguard Worker
1100*344a7f5eSAndroid Build Coastguard Worker    return True
1101*344a7f5eSAndroid Build Coastguard Worker
1102*344a7f5eSAndroid Build Coastguard Worker
1103*344a7f5eSAndroid Build Coastguard Workerdef finalize_sdk(target, build_id, sdk_version, beyond_corp, local_mode):
1104*344a7f5eSAndroid Build Coastguard Worker    target_finalize_dir = sdk_version
1105*344a7f5eSAndroid Build Coastguard Worker
1106*344a7f5eSAndroid Build Coastguard Worker    for api_scope in ['public', 'system', 'test', 'module-lib', 'system-server']:
1107*344a7f5eSAndroid Build Coastguard Worker        artifact_to_path = {f'apistubs/android/{api_scope}/api/*.txt': os.path.join(
1108*344a7f5eSAndroid Build Coastguard Worker            target_finalize_dir, api_scope, 'api', '*')}
1109*344a7f5eSAndroid Build Coastguard Worker
1110*344a7f5eSAndroid Build Coastguard Worker        if not fetch_artifacts(target, build_id, artifact_to_path, beyond_corp, local_mode):
1111*344a7f5eSAndroid Build Coastguard Worker            return False
1112*344a7f5eSAndroid Build Coastguard Worker
1113*344a7f5eSAndroid Build Coastguard Worker    return update_framework(target, build_id, target_finalize_dir, beyond_corp, local_mode) and update_makefile(
1114*344a7f5eSAndroid Build Coastguard Worker        target_finalize_dir)
1115*344a7f5eSAndroid Build Coastguard Worker
1116*344a7f5eSAndroid Build Coastguard Worker
1117*344a7f5eSAndroid Build Coastguard Workerdef update_framework_current(target, build_id, beyond_corp, local_mode):
1118*344a7f5eSAndroid Build Coastguard Worker    return update_framework(target, build_id, current_path, beyond_corp, local_mode)
1119*344a7f5eSAndroid Build Coastguard Worker
1120*344a7f5eSAndroid Build Coastguard Worker
1121*344a7f5eSAndroid Build Coastguard Workerdef update_buildtools(target, arch, build_id, beyond_corp):
1122*344a7f5eSAndroid Build Coastguard Worker    artifact_path = fetch_and_extract(target, build_id.url_id,
1123*344a7f5eSAndroid Build Coastguard Worker                                      f'sdk-repo-{arch}-build-tools-{build_id.fs_id}.zip',
1124*344a7f5eSAndroid Build Coastguard Worker                                      beyond_corp)
1125*344a7f5eSAndroid Build Coastguard Worker    if not artifact_path:
1126*344a7f5eSAndroid Build Coastguard Worker        return False
1127*344a7f5eSAndroid Build Coastguard Worker
1128*344a7f5eSAndroid Build Coastguard Worker    top_level_dir = os.listdir(artifact_path)[0]
1129*344a7f5eSAndroid Build Coastguard Worker    src_path = os.path.join(artifact_path, top_level_dir)
1130*344a7f5eSAndroid Build Coastguard Worker    dst_path = os.path.join(buildtools_dir, arch)
1131*344a7f5eSAndroid Build Coastguard Worker
1132*344a7f5eSAndroid Build Coastguard Worker    # There are a few libraries that have been manually added to the
1133*344a7f5eSAndroid Build Coastguard Worker    # build tools, copy them from the destination back to the source
1134*344a7f5eSAndroid Build Coastguard Worker    # before the destination is overwritten.
1135*344a7f5eSAndroid Build Coastguard Worker    files_to_save = (
1136*344a7f5eSAndroid Build Coastguard Worker        'lib64/libconscrypt_openjdk_jni.dylib',
1137*344a7f5eSAndroid Build Coastguard Worker        'lib64/libconscrypt_openjdk_jni.so',
1138*344a7f5eSAndroid Build Coastguard Worker        'bin/lib64/libwinpthread-1.dll',
1139*344a7f5eSAndroid Build Coastguard Worker    )
1140*344a7f5eSAndroid Build Coastguard Worker    for file in files_to_save:
1141*344a7f5eSAndroid Build Coastguard Worker        src_file = os.path.join(dst_path, file)
1142*344a7f5eSAndroid Build Coastguard Worker        dst_file = os.path.join(src_path, file)
1143*344a7f5eSAndroid Build Coastguard Worker        if os.path.exists(dst_path):
1144*344a7f5eSAndroid Build Coastguard Worker            mv(src_file, dst_file)
1145*344a7f5eSAndroid Build Coastguard Worker
1146*344a7f5eSAndroid Build Coastguard Worker    mv(src_path, dst_path)
1147*344a7f5eSAndroid Build Coastguard Worker
1148*344a7f5eSAndroid Build Coastguard Worker    # Move all top-level files to /bin and make them executable
1149*344a7f5eSAndroid Build Coastguard Worker    bin_path = os.path.join(dst_path, 'bin')
1150*344a7f5eSAndroid Build Coastguard Worker    top_level_files = filter(lambda e: os.path.isfile(os.path.join(dst_path, e)), os.listdir(dst_path))
1151*344a7f5eSAndroid Build Coastguard Worker    for file in top_level_files:
1152*344a7f5eSAndroid Build Coastguard Worker        src_file = os.path.join(dst_path, file)
1153*344a7f5eSAndroid Build Coastguard Worker        dst_file = os.path.join(bin_path, file)
1154*344a7f5eSAndroid Build Coastguard Worker        mv(src_file, dst_file)
1155*344a7f5eSAndroid Build Coastguard Worker        os.chmod(dst_file, 0o755)
1156*344a7f5eSAndroid Build Coastguard Worker
1157*344a7f5eSAndroid Build Coastguard Worker    # Make the files under lld-bin executable
1158*344a7f5eSAndroid Build Coastguard Worker    lld_bin_files = os.listdir(os.path.join(dst_path, 'lld-bin'))
1159*344a7f5eSAndroid Build Coastguard Worker    for file in lld_bin_files:
1160*344a7f5eSAndroid Build Coastguard Worker        os.chmod(os.path.join(dst_path, 'lld-bin', file), 0o755)
1161*344a7f5eSAndroid Build Coastguard Worker
1162*344a7f5eSAndroid Build Coastguard Worker    # Remove renderscript
1163*344a7f5eSAndroid Build Coastguard Worker    rm(os.path.join(dst_path, 'renderscript'))
1164*344a7f5eSAndroid Build Coastguard Worker
1165*344a7f5eSAndroid Build Coastguard Worker    return True
1166*344a7f5eSAndroid Build Coastguard Worker
1167*344a7f5eSAndroid Build Coastguard Worker
1168*344a7f5eSAndroid Build Coastguard Workerdef has_uncommitted_changes():
1169*344a7f5eSAndroid Build Coastguard Worker    try:
1170*344a7f5eSAndroid Build Coastguard Worker        # Make sure we don't overwrite any pending changes.
1171*344a7f5eSAndroid Build Coastguard Worker        diff_command = f'cd {git_dir} && git diff --quiet'
1172*344a7f5eSAndroid Build Coastguard Worker        subprocess.check_call(diff_command, shell=True)
1173*344a7f5eSAndroid Build Coastguard Worker        subprocess.check_call(f'{diff_command} --cached', shell=True)
1174*344a7f5eSAndroid Build Coastguard Worker        return False
1175*344a7f5eSAndroid Build Coastguard Worker    except subprocess.CalledProcessError:
1176*344a7f5eSAndroid Build Coastguard Worker        return True
1177*344a7f5eSAndroid Build Coastguard Worker
1178*344a7f5eSAndroid Build Coastguard Workerdef check_string_major_minor_format(s):
1179*344a7f5eSAndroid Build Coastguard Worker    # Verify that the string follows the major.minor format:
1180*344a7f5eSAndroid Build Coastguard Worker    # Examples of allowed strings: 1.0, 2.34
1181*344a7f5eSAndroid Build Coastguard Worker    # Examples of disallowed strings: 0.1, 1.01
1182*344a7f5eSAndroid Build Coastguard Worker    if not re.match(r'[1-9][0-9]*\.(0|[1-9][0-9]*)', s):
1183*344a7f5eSAndroid Build Coastguard Worker        raise ValueError('string not a major.minor version (e.g. 1.0, 2.34, 56.7890)')
1184*344a7f5eSAndroid Build Coastguard Worker    return s
1185*344a7f5eSAndroid Build Coastguard Worker
1186*344a7f5eSAndroid Build Coastguard Worker
1187*344a7f5eSAndroid Build Coastguard Workerdef main():
1188*344a7f5eSAndroid Build Coastguard Worker    parser = argparse.ArgumentParser(
1189*344a7f5eSAndroid Build Coastguard Worker        description='Update current prebuilts')
1190*344a7f5eSAndroid Build Coastguard Worker    parser.add_argument(
1191*344a7f5eSAndroid Build Coastguard Worker        'source', nargs='?',
1192*344a7f5eSAndroid Build Coastguard Worker        help='Build server build ID or local Maven ZIP file')
1193*344a7f5eSAndroid Build Coastguard Worker    parser.add_argument(
1194*344a7f5eSAndroid Build Coastguard Worker        '-m', '--material', action='store_true',
1195*344a7f5eSAndroid Build Coastguard Worker        help='If specified, updates only Material Design Components')
1196*344a7f5eSAndroid Build Coastguard Worker    parser.add_argument(
1197*344a7f5eSAndroid Build Coastguard Worker        '-c', '--constraint', action='store_true',
1198*344a7f5eSAndroid Build Coastguard Worker        help='If specified, updates only Constraint Layout')
1199*344a7f5eSAndroid Build Coastguard Worker    parser.add_argument(
1200*344a7f5eSAndroid Build Coastguard Worker        '-j', '--jetifier', action='store_true',
1201*344a7f5eSAndroid Build Coastguard Worker        help='If specified, updates only Jetifier')
1202*344a7f5eSAndroid Build Coastguard Worker    parser.add_argument(
1203*344a7f5eSAndroid Build Coastguard Worker        '-p', '--platform', action='store_true',
1204*344a7f5eSAndroid Build Coastguard Worker        help='If specified, updates only the Android Platform')
1205*344a7f5eSAndroid Build Coastguard Worker    parser.add_argument(
1206*344a7f5eSAndroid Build Coastguard Worker        '-f', '--finalize_sdk', type=check_string_major_minor_format,
1207*344a7f5eSAndroid Build Coastguard Worker        help='Finalize the build as the specified SDK version. Must be used together with -e')
1208*344a7f5eSAndroid Build Coastguard Worker    parser.add_argument(
1209*344a7f5eSAndroid Build Coastguard Worker        '-e', '--finalize_extension', type=int,
1210*344a7f5eSAndroid Build Coastguard Worker        help='Finalize the build as the specified extension SDK version. Must be used together with -f')
1211*344a7f5eSAndroid Build Coastguard Worker    parser.add_argument('--bug', type=int, help='The bug number to add to the commit message.')
1212*344a7f5eSAndroid Build Coastguard Worker    parser.add_argument(
1213*344a7f5eSAndroid Build Coastguard Worker        '--sdk_target',
1214*344a7f5eSAndroid Build Coastguard Worker        default=framework_sdk_target,
1215*344a7f5eSAndroid Build Coastguard Worker        help='If specified, the name of the build target from which to retrieve the SDK when -p or -f '
1216*344a7f5eSAndroid Build Coastguard Worker             'is specified.')
1217*344a7f5eSAndroid Build Coastguard Worker    parser.add_argument(
1218*344a7f5eSAndroid Build Coastguard Worker        '-b', '--buildtools', action='store_true',
1219*344a7f5eSAndroid Build Coastguard Worker        help='If specified, updates only the Build Tools')
1220*344a7f5eSAndroid Build Coastguard Worker    parser.add_argument(
1221*344a7f5eSAndroid Build Coastguard Worker        '-x', '--androidx', action='store_true',
1222*344a7f5eSAndroid Build Coastguard Worker        help='If specified, updates only the Jetpack (androidx) libraries excluding those covered by '
1223*344a7f5eSAndroid Build Coastguard Worker             'other arguments')
1224*344a7f5eSAndroid Build Coastguard Worker    parser.add_argument(
1225*344a7f5eSAndroid Build Coastguard Worker        '--include', action='append', default=[],
1226*344a7f5eSAndroid Build Coastguard Worker        help='If specified with -x, includes the specified Jetpack library Maven group or artifact for '
1227*344a7f5eSAndroid Build Coastguard Worker             'updates. Applied before exclude.')
1228*344a7f5eSAndroid Build Coastguard Worker    parser.add_argument(
1229*344a7f5eSAndroid Build Coastguard Worker        '--exclude', action='append', default=[],
1230*344a7f5eSAndroid Build Coastguard Worker        help='If specified with -x, excludes the specified Jetpack library Maven group or artifact '
1231*344a7f5eSAndroid Build Coastguard Worker             'from updates')
1232*344a7f5eSAndroid Build Coastguard Worker    parser.add_argument(
1233*344a7f5eSAndroid Build Coastguard Worker        '-g', '--gmaven', action='store_true',
1234*344a7f5eSAndroid Build Coastguard Worker        help='If specified, updates only the artifact from GMaven libraries excluding those covered by '
1235*344a7f5eSAndroid Build Coastguard Worker             'other arguments')
1236*344a7f5eSAndroid Build Coastguard Worker    parser.add_argument(
1237*344a7f5eSAndroid Build Coastguard Worker        '--commit-first', action='store_true',
1238*344a7f5eSAndroid Build Coastguard Worker        help='If specified, then if uncommited changes exist, commit before continuing')
1239*344a7f5eSAndroid Build Coastguard Worker    parser.add_argument(
1240*344a7f5eSAndroid Build Coastguard Worker        '--beyond-corp', action='store_true',
1241*344a7f5eSAndroid Build Coastguard Worker        help='If specified, then fetch artifacts with tooling that works on BeyondCorp devices')
1242*344a7f5eSAndroid Build Coastguard Worker    parser.add_argument(
1243*344a7f5eSAndroid Build Coastguard Worker        '--local_mode', action="store_true",
1244*344a7f5eSAndroid Build Coastguard Worker        help='Local mode: use locally built artifacts and don\'t upload the result to Gerrit.')
1245*344a7f5eSAndroid Build Coastguard Worker    rm(temp_dir)
1246*344a7f5eSAndroid Build Coastguard Worker
1247*344a7f5eSAndroid Build Coastguard Worker    args = parser.parse_args()
1248*344a7f5eSAndroid Build Coastguard Worker
1249*344a7f5eSAndroid Build Coastguard Worker    # Validate combinations of arguments.
1250*344a7f5eSAndroid Build Coastguard Worker    if not args.source and (args.platform or args.buildtools or args.jetifier
1251*344a7f5eSAndroid Build Coastguard Worker                            or args.androidx or args.material or args.finalize_sdk
1252*344a7f5eSAndroid Build Coastguard Worker                            or args.constraint):
1253*344a7f5eSAndroid Build Coastguard Worker        parser.error('You must specify a build ID or local Maven ZIP file')
1254*344a7f5eSAndroid Build Coastguard Worker        sys.exit(1)
1255*344a7f5eSAndroid Build Coastguard Worker    if not (args.gmaven or args.platform or args.buildtools or args.jetifier
1256*344a7f5eSAndroid Build Coastguard Worker            or args.androidx or args.material or args.finalize_sdk
1257*344a7f5eSAndroid Build Coastguard Worker            or args.finalize_extension or args.constraint):
1258*344a7f5eSAndroid Build Coastguard Worker        parser.error('You must specify at least one target to update')
1259*344a7f5eSAndroid Build Coastguard Worker        sys.exit(1)
1260*344a7f5eSAndroid Build Coastguard Worker    if args.local_mode and not args.finalize_sdk:
1261*344a7f5eSAndroid Build Coastguard Worker        parser.error('Local mode can only be used when finalizing an SDK.')
1262*344a7f5eSAndroid Build Coastguard Worker        sys.exit(1)
1263*344a7f5eSAndroid Build Coastguard Worker    if (args.finalize_sdk is None) != (args.finalize_extension is None):
1264*344a7f5eSAndroid Build Coastguard Worker        parser.error('Either both or neither of -e and -f must be specified.')
1265*344a7f5eSAndroid Build Coastguard Worker        sys.exit(1)
1266*344a7f5eSAndroid Build Coastguard Worker    if args.finalize_sdk and not args.bug:
1267*344a7f5eSAndroid Build Coastguard Worker        parser.error('Specifying a bug ID with --bug is required when finalizing an SDK.')
1268*344a7f5eSAndroid Build Coastguard Worker        sys.exit(1)
1269*344a7f5eSAndroid Build Coastguard Worker
1270*344a7f5eSAndroid Build Coastguard Worker    # Validate the build environment for POM-dependent targets.
1271*344a7f5eSAndroid Build Coastguard Worker    if (args.constraint or args.material or args.androidx or args.gmaven) \
1272*344a7f5eSAndroid Build Coastguard Worker            and which('pom2bp') is None:
1273*344a7f5eSAndroid Build Coastguard Worker        parser.error('Cannot find pom2bp in path; please run lunch to set up build environment. '
1274*344a7f5eSAndroid Build Coastguard Worker                     'You may also need to run \'m pom2bp\' if it hasn\'t been built already.')
1275*344a7f5eSAndroid Build Coastguard Worker        sys.exit(1)
1276*344a7f5eSAndroid Build Coastguard Worker
1277*344a7f5eSAndroid Build Coastguard Worker    # Validate include/exclude arguments.
1278*344a7f5eSAndroid Build Coastguard Worker    if args.exclude:
1279*344a7f5eSAndroid Build Coastguard Worker        invalid_spec = find_invalid_spec(args.exclude)
1280*344a7f5eSAndroid Build Coastguard Worker        if invalid_spec:
1281*344a7f5eSAndroid Build Coastguard Worker            parser.error('Unknown artifact specification in exclude: ' + invalid_spec)
1282*344a7f5eSAndroid Build Coastguard Worker            sys.exit(1)
1283*344a7f5eSAndroid Build Coastguard Worker    if args.include:
1284*344a7f5eSAndroid Build Coastguard Worker        invalid_spec = find_invalid_spec(args.include)
1285*344a7f5eSAndroid Build Coastguard Worker        if invalid_spec:
1286*344a7f5eSAndroid Build Coastguard Worker            parser.error('Unknown artifact specification in include: ' + invalid_spec)
1287*344a7f5eSAndroid Build Coastguard Worker            sys.exit(1)
1288*344a7f5eSAndroid Build Coastguard Worker
1289*344a7f5eSAndroid Build Coastguard Worker    # Validate the git status.
1290*344a7f5eSAndroid Build Coastguard Worker    if not args.local_mode and has_uncommitted_changes():
1291*344a7f5eSAndroid Build Coastguard Worker        if args.commit_first:
1292*344a7f5eSAndroid Build Coastguard Worker            subprocess.check_call(f'cd {git_dir} && git add -u', shell=True)
1293*344a7f5eSAndroid Build Coastguard Worker            subprocess.check_call(f'cd {git_dir} && git commit -m \'save working state\'',
1294*344a7f5eSAndroid Build Coastguard Worker                                  shell=True)
1295*344a7f5eSAndroid Build Coastguard Worker    if not args.local_mode and has_uncommitted_changes():
1296*344a7f5eSAndroid Build Coastguard Worker        self_file = os.path.basename(__file__)
1297*344a7f5eSAndroid Build Coastguard Worker        print_e(f'FAIL: There are uncommitted changes here. Please commit or stash before '
1298*344a7f5eSAndroid Build Coastguard Worker                f'continuing, because {self_file} will run "git reset --hard" if execution fails')
1299*344a7f5eSAndroid Build Coastguard Worker        sys.exit(1)
1300*344a7f5eSAndroid Build Coastguard Worker
1301*344a7f5eSAndroid Build Coastguard Worker    if args.bug:
1302*344a7f5eSAndroid Build Coastguard Worker        commit_msg_suffix = f'\n\nBug: {args.bug}'
1303*344a7f5eSAndroid Build Coastguard Worker    else:
1304*344a7f5eSAndroid Build Coastguard Worker        commit_msg_suffix = ''
1305*344a7f5eSAndroid Build Coastguard Worker
1306*344a7f5eSAndroid Build Coastguard Worker    # Are we fetching a build ID or using a local file?
1307*344a7f5eSAndroid Build Coastguard Worker    build_id = None
1308*344a7f5eSAndroid Build Coastguard Worker    file = None
1309*344a7f5eSAndroid Build Coastguard Worker    if args.source:
1310*344a7f5eSAndroid Build Coastguard Worker        build_id = parse_build_id(args.source)
1311*344a7f5eSAndroid Build Coastguard Worker        if build_id is None:
1312*344a7f5eSAndroid Build Coastguard Worker            file = args.source
1313*344a7f5eSAndroid Build Coastguard Worker
1314*344a7f5eSAndroid Build Coastguard Worker    try:
1315*344a7f5eSAndroid Build Coastguard Worker        components = []
1316*344a7f5eSAndroid Build Coastguard Worker        if args.constraint:
1317*344a7f5eSAndroid Build Coastguard Worker            if update_constraint(file):
1318*344a7f5eSAndroid Build Coastguard Worker                components.append('Constraint Layout')
1319*344a7f5eSAndroid Build Coastguard Worker            else:
1320*344a7f5eSAndroid Build Coastguard Worker                print_e('Failed to update Constraint Layout, aborting...')
1321*344a7f5eSAndroid Build Coastguard Worker                sys.exit(1)
1322*344a7f5eSAndroid Build Coastguard Worker        if args.material:
1323*344a7f5eSAndroid Build Coastguard Worker            if update_material(file):
1324*344a7f5eSAndroid Build Coastguard Worker                components.append('Material Design Components')
1325*344a7f5eSAndroid Build Coastguard Worker            else:
1326*344a7f5eSAndroid Build Coastguard Worker                print_e('Failed to update Material Design Components, aborting...')
1327*344a7f5eSAndroid Build Coastguard Worker                sys.exit(1)
1328*344a7f5eSAndroid Build Coastguard Worker        if args.gmaven:
1329*344a7f5eSAndroid Build Coastguard Worker            updated_artifacts = update_gmaven(gmaven_artifacts)
1330*344a7f5eSAndroid Build Coastguard Worker            if updated_artifacts:
1331*344a7f5eSAndroid Build Coastguard Worker                components.append('\n'.join(updated_artifacts))
1332*344a7f5eSAndroid Build Coastguard Worker            else:
1333*344a7f5eSAndroid Build Coastguard Worker                print_e('Failed to update GMaven, aborting...')
1334*344a7f5eSAndroid Build Coastguard Worker                sys.exit(1)
1335*344a7f5eSAndroid Build Coastguard Worker        if args.androidx:
1336*344a7f5eSAndroid Build Coastguard Worker            if update_androidx('androidx', build_id, file, args.include, args.exclude,
1337*344a7f5eSAndroid Build Coastguard Worker                               args.beyond_corp):
1338*344a7f5eSAndroid Build Coastguard Worker                components.append('AndroidX')
1339*344a7f5eSAndroid Build Coastguard Worker            else:
1340*344a7f5eSAndroid Build Coastguard Worker                print_e('Failed to update AndroidX, aborting...')
1341*344a7f5eSAndroid Build Coastguard Worker                sys.exit(1)
1342*344a7f5eSAndroid Build Coastguard Worker        if args.jetifier:
1343*344a7f5eSAndroid Build Coastguard Worker            if update_jetifier('androidx', build_id, args.beyond_corp):
1344*344a7f5eSAndroid Build Coastguard Worker                components.append('Jetifier')
1345*344a7f5eSAndroid Build Coastguard Worker            else:
1346*344a7f5eSAndroid Build Coastguard Worker                print_e('Failed to update Jetifier, aborting...')
1347*344a7f5eSAndroid Build Coastguard Worker                sys.exit(1)
1348*344a7f5eSAndroid Build Coastguard Worker        if args.platform or args.finalize_sdk:
1349*344a7f5eSAndroid Build Coastguard Worker            if update_framework_current(args.sdk_target, build_id, args.beyond_corp, args.local_mode):
1350*344a7f5eSAndroid Build Coastguard Worker                components.append('platform SDK')
1351*344a7f5eSAndroid Build Coastguard Worker            else:
1352*344a7f5eSAndroid Build Coastguard Worker                print_e('Failed to update platform SDK, aborting...')
1353*344a7f5eSAndroid Build Coastguard Worker                sys.exit(1)
1354*344a7f5eSAndroid Build Coastguard Worker        if args.finalize_sdk:
1355*344a7f5eSAndroid Build Coastguard Worker            n = args.finalize_sdk
1356*344a7f5eSAndroid Build Coastguard Worker            if not finalize_sdk(args.sdk_target, build_id, n, args.beyond_corp, args.local_mode):
1357*344a7f5eSAndroid Build Coastguard Worker                print_e('Failed to finalize SDK %d, aborting...' % n)
1358*344a7f5eSAndroid Build Coastguard Worker                sys.exit(1)
1359*344a7f5eSAndroid Build Coastguard Worker
1360*344a7f5eSAndroid Build Coastguard Worker            if not args.local_mode:
1361*344a7f5eSAndroid Build Coastguard Worker                # HACK: extension sdk finalization will create a new branch, hiding this commit.
1362*344a7f5eSAndroid Build Coastguard Worker                # Let's create it in advance for now.
1363*344a7f5eSAndroid Build Coastguard Worker                # TODO(b/228451704) do a proper fix?
1364*344a7f5eSAndroid Build Coastguard Worker                branch_name = 'finalize-%d' % args.finalize_extension
1365*344a7f5eSAndroid Build Coastguard Worker                subprocess.check_output(['repo', 'start', branch_name])
1366*344a7f5eSAndroid Build Coastguard Worker                # We commit the finalized dir separately from the current sdk update.
1367*344a7f5eSAndroid Build Coastguard Worker                msg = f'Import final sdk version {n} from build {build_id.url_id}{commit_msg_suffix}'
1368*344a7f5eSAndroid Build Coastguard Worker                subprocess.check_call(['git', 'add', '%d' % n])
1369*344a7f5eSAndroid Build Coastguard Worker                subprocess.check_call(['git', 'add', 'Android.bp'])
1370*344a7f5eSAndroid Build Coastguard Worker                subprocess.check_call(['git', 'commit', '-m', msg])
1371*344a7f5eSAndroid Build Coastguard Worker
1372*344a7f5eSAndroid Build Coastguard Worker            # Finalize extension sdk level
1373*344a7f5eSAndroid Build Coastguard Worker            readme = (f'Finalized together with '
1374*344a7f5eSAndroid Build Coastguard Worker                      f'Android {args.finalize_sdk} (all modules)')
1375*344a7f5eSAndroid Build Coastguard Worker            cmd = extension_sdk_finalization_cmd.format(
1376*344a7f5eSAndroid Build Coastguard Worker                readme=readme,
1377*344a7f5eSAndroid Build Coastguard Worker                bug=args.bug,
1378*344a7f5eSAndroid Build Coastguard Worker                extension_version=args.finalize_extension,
1379*344a7f5eSAndroid Build Coastguard Worker                build_id=build_id.url_id,
1380*344a7f5eSAndroid Build Coastguard Worker                local_mode='--local_mode' if args.local_mode else '')
1381*344a7f5eSAndroid Build Coastguard Worker            subprocess.check_call(shlex.split(cmd), cwd=repo_root_dir.resolve())
1382*344a7f5eSAndroid Build Coastguard Worker        if args.buildtools:
1383*344a7f5eSAndroid Build Coastguard Worker            if update_buildtools('sdk-sdk_mac', 'darwin', build_id, args.beyond_corp) \
1384*344a7f5eSAndroid Build Coastguard Worker                    and update_buildtools('sdk', 'linux', build_id, args.beyond_corp) \
1385*344a7f5eSAndroid Build Coastguard Worker                    and update_buildtools('sdk', 'windows', build_id, args.beyond_corp):
1386*344a7f5eSAndroid Build Coastguard Worker                components.append('build tools')
1387*344a7f5eSAndroid Build Coastguard Worker            else:
1388*344a7f5eSAndroid Build Coastguard Worker                print_e('Failed to update build tools, aborting...')
1389*344a7f5eSAndroid Build Coastguard Worker                sys.exit(1)
1390*344a7f5eSAndroid Build Coastguard Worker
1391*344a7f5eSAndroid Build Coastguard Worker        if args.local_mode:
1392*344a7f5eSAndroid Build Coastguard Worker            print('Updated prebuilts using locally built artifacts. Don\'t submit or use for anything besides local testing.')
1393*344a7f5eSAndroid Build Coastguard Worker            sys.exit(0)
1394*344a7f5eSAndroid Build Coastguard Worker
1395*344a7f5eSAndroid Build Coastguard Worker        # Build the git commit.
1396*344a7f5eSAndroid Build Coastguard Worker        subprocess.check_call(['git', 'add', current_path, buildtools_dir])
1397*344a7f5eSAndroid Build Coastguard Worker
1398*344a7f5eSAndroid Build Coastguard Worker        # Build the commit message.
1399*344a7f5eSAndroid Build Coastguard Worker        components_msg = ', '.join(components)
1400*344a7f5eSAndroid Build Coastguard Worker        argv_msg = ' '.join(sys.argv)
1401*344a7f5eSAndroid Build Coastguard Worker        if not args.source and args.gmaven:
1402*344a7f5eSAndroid Build Coastguard Worker            src_msg = 'GMaven'
1403*344a7f5eSAndroid Build Coastguard Worker        elif not args.source.isnumeric():
1404*344a7f5eSAndroid Build Coastguard Worker            src_msg = 'local Maven ZIP'
1405*344a7f5eSAndroid Build Coastguard Worker        else:
1406*344a7f5eSAndroid Build Coastguard Worker            src_msg = f'build {build_id.url_id}'
1407*344a7f5eSAndroid Build Coastguard Worker        msg = f'Import {components_msg} from {src_msg}\n\n{argv_msg}{commit_msg_suffix}'
1408*344a7f5eSAndroid Build Coastguard Worker
1409*344a7f5eSAndroid Build Coastguard Worker        # Create the git commit.
1410*344a7f5eSAndroid Build Coastguard Worker        subprocess.check_call(['git', 'commit', '-q', '-m', msg])
1411*344a7f5eSAndroid Build Coastguard Worker
1412*344a7f5eSAndroid Build Coastguard Worker        if args.finalize_sdk:
1413*344a7f5eSAndroid Build Coastguard Worker            print('NOTE: Created three commits:')
1414*344a7f5eSAndroid Build Coastguard Worker            subprocess.check_call(['git', 'log', '-3', '--oneline'])
1415*344a7f5eSAndroid Build Coastguard Worker        else:
1416*344a7f5eSAndroid Build Coastguard Worker            print('Created commit:')
1417*344a7f5eSAndroid Build Coastguard Worker            subprocess.check_call(['git', 'log', '-1', '--oneline'])
1418*344a7f5eSAndroid Build Coastguard Worker        print('Remember to test this change before uploading it to Gerrit!')
1419*344a7f5eSAndroid Build Coastguard Worker
1420*344a7f5eSAndroid Build Coastguard Worker    except Exception as e:
1421*344a7f5eSAndroid Build Coastguard Worker        print(f'ERROR: {e} occured while updating prebuilts')
1422*344a7f5eSAndroid Build Coastguard Worker        raise
1423*344a7f5eSAndroid Build Coastguard Worker    finally:
1424*344a7f5eSAndroid Build Coastguard Worker        if args.local_mode:
1425*344a7f5eSAndroid Build Coastguard Worker            print('No cleaning up in local mode, manual cleanup required.')
1426*344a7f5eSAndroid Build Coastguard Worker        else:
1427*344a7f5eSAndroid Build Coastguard Worker            # Revert all stray files, including the downloaded zip.
1428*344a7f5eSAndroid Build Coastguard Worker            try:
1429*344a7f5eSAndroid Build Coastguard Worker                with open(os.devnull, 'w') as bitbucket:
1430*344a7f5eSAndroid Build Coastguard Worker                    subprocess.check_call(['git', 'add', '-Af', '.'], stdout=bitbucket)
1431*344a7f5eSAndroid Build Coastguard Worker                    subprocess.check_call(
1432*344a7f5eSAndroid Build Coastguard Worker                        ['git', 'commit', '-m', 'COMMIT TO REVERT - RESET ME!!!', '--allow-empty'],
1433*344a7f5eSAndroid Build Coastguard Worker                        stdout=bitbucket)
1434*344a7f5eSAndroid Build Coastguard Worker                    subprocess.check_call(['git', 'reset', '--hard', 'HEAD~1'], stdout=bitbucket)
1435*344a7f5eSAndroid Build Coastguard Worker            except subprocess.CalledProcessError:
1436*344a7f5eSAndroid Build Coastguard Worker                print_e('ERROR: Failed cleaning up, manual cleanup required!!!')
1437*344a7f5eSAndroid Build Coastguard Worker
1438*344a7f5eSAndroid Build Coastguard Worker
1439*344a7f5eSAndroid Build Coastguard Worker# Add automatic entries to maven_to_make.
1440*344a7f5eSAndroid Build Coastguard Workerpopulate_maven_to_make(maven_to_make)
1441*344a7f5eSAndroid Build Coastguard Worker
1442*344a7f5eSAndroid Build Coastguard Workerif __name__ == '__main__':
1443*344a7f5eSAndroid Build Coastguard Worker    main()
1444