xref: /aosp_15_r20/prebuilts/misc/common/androidx-media3/update-from-gmaven.py (revision 847dbab7980efcc7f5706bb9c6d844b91a680afd)
1#!/usr/bin/python3
2
3# Helper script for updating androidx.media3 prebuilts from maven
4#
5# Usage:
6#   a. Initialize android environment: $ . ./build/envsetup.sh; lunch <target>
7#   b. Build pom2bp and bpfmt (needed by this script): $ m pom2bp bpfmt
8#       * If this fails with 'fatal error: thread exhaustion'
9#         (and then an *enormous* thread dump), retry the command.
10#   c. Start a new repo branch in project `prebuilts/misc`.
11#   d. Update this script:
12#        * Set `media3Version` to the target version
13#        * Extend `downloadArtifact` calls to include new modules if needed.
14#        * Extend external dependency rewrite for any new external dependencies
15#          of the imported Media3 modules.
16#   e. Run the script from the Android source root:
17#      $ ./prebuilts/misc/common/androidx-media3/update-from-gmaven.py
18#
19# The script will then:
20#   1. Remove the previous artifacts
21#   2. Download the aars and poms into a file structure mirroring their maven
22#      path
23#   3. Extract the AndroidManifest from the aars into the manifests folder
24#   4. Run pom2bp to generate the Android.bp
25#   5. Amend Android.bp with the existing visibility targets, java version, and
26#      removal of unavailable dependencies.
27#
28# Manual verification steps:
29#   1. Build the 'leaf' imported modules (i.e. the set that ends up depending
30#      on *everything* transitively), e.g.
31#      $ m androidx.media3.media3-exoplayer-dash androidx.media3.media3-exoplayer androidx.media3.media3-session androidx.media3.media3-test-utils androidx.media3.media3-transformer androidx.media3.media3-ui
32
33import os
34import re
35import subprocess
36import sys
37
38media3Version="1.5.0-rc01"
39
40mavenToBpPatternMap = {
41    "androidx.media3:" : "androidx.media3.",
42    }
43
44androidBpPath = "Android.bp"
45javaVersionPattern = r'java_version:\s*"[\d\.]*",'
46mockWebServerUnavailableComment = """// Missing a dependency on okhttp3.mockwebserver because this package is not currently
47// available in /external/. This means the parts of this library that require this
48// dependency are not usable."""
49
50def cmd(args):
51   print(args)
52   out = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
53   if (out.returncode != 0):
54      print(out.stderr.decode("utf-8"))
55      sys.exit(out.returncode)
56   out_string = out.stdout.decode("utf-8")
57   print(out_string)
58   return out_string
59
60def chdir(path):
61   print("cd %s" % path)
62   os.chdir(path)
63
64def getAndroidRoot():
65   if os.path.isdir(".repo/projects"):
66      return os.getcwd()
67   elif 'TOP' in os.environ:
68      return os.environ['TOP']
69   else:
70      print("Error: Run from android source root or set TOP envvar")
71      sys.exit(-1)
72
73def downloadArtifact(groupId, artifactId, version):
74   """Downloads an aar, sources.jar and pom from google maven"""
75   groupPath = groupId.replace('.', '/')
76   artifactDirPath = os.path.join(groupPath, artifactId, version)
77   artifactPath = os.path.join(artifactDirPath, "%s-%s" % (artifactId, version))
78   cmd("mkdir -p " + artifactDirPath)
79   # download aar
80   cmd("wget -O %s.aar https://dl.google.com/dl/android/maven2/%s.aar" % (artifactPath, artifactPath))
81
82   # extract AndroidManifest.xml from aar, into path expected by pom2bp
83   manifestDir = getManifestPath("%s:%s" % (groupId,artifactId))
84   cmd("mkdir -p " + manifestDir)
85   cmd("unzip -o %s.aar AndroidManifest.xml -d %s" % (artifactPath, manifestDir))
86
87   # download pom
88   cmd("wget -O %s.pom https://dl.google.com/dl/android/maven2/%s.pom" % (artifactPath, artifactPath))
89
90   # download sources.jar
91   cmd("wget -O %s-sources.jar https://dl.google.com/dl/android/maven2/%s-sources.jar" % (artifactPath, artifactPath))
92
93def downloadApk(groupId, artifactId, version):
94   """Downloads an apk from google maven"""
95   groupPath = groupId.replace('.', '/')
96   artifactDirPath = os.path.join(groupPath, artifactId, version)
97   artifactPath = os.path.join(artifactDirPath, "%s-%s" % (artifactId, version))
98   cmd("mkdir -p " + artifactDirPath)
99   # download apk
100   cmd("wget -O %s.apk https://dl.google.com/dl/android/maven2/%s.apk" % (artifactPath, artifactPath))
101   # download pom
102   cmd("wget -O %s.pom https://dl.google.com/dl/android/maven2/%s.pom" % (artifactPath, artifactPath))
103
104def getManifestPath(mavenArtifactName):
105  """Get the path to the aar's manifest as generated by pom2bp."""
106  manifestPath = mavenArtifactName
107  for searchPattern in mavenToBpPatternMap:
108    manifestPath = manifestPath.replace(searchPattern, mavenToBpPatternMap[searchPattern])
109  return "manifests/%s" % manifestPath
110
111def getJavaVersionFromAndroidBp():
112  """Returns the java_version line of the Android.bp file"""
113  with open(androidBpPath, 'r') as f:
114      content = f.read()
115  match = re.search(javaVersionPattern, content)
116  return match.group(0)  # Return the entire line
117
118def getLibraryVisibilityFromAndroidBp():
119  """Returns the entire library_visibility section of the Android.bp file"""
120  with open(androidBpPath, 'r') as f:
121      content = f.read()
122  match = re.search(r'library_visibility\s*=\s*\[([^]]*)\]', content, re.DOTALL)
123  return match.group(0)  # Return the entire matched section
124
125def fixAndroidBp(library_visibility, java_version):
126  """Fixes the Android.bp file by overwriting the visibility and java_version, and removes
127      unavailable mockwebserver dependency"""
128  with open(androidBpPath, 'r') as f:
129      build_content = f.read()
130  build_content = re.sub(javaVersionPattern, java_version, build_content)
131  build_content = build_content.replace(
132    r'"mockwebserver",', mockWebServerUnavailableComment)
133  # Find the end of the package section (the first closing curly bracket)
134  package_end_index = build_content.find('}')
135  # Insert the library_visibility section after the package section
136  modified_build_content = (
137      build_content[:package_end_index + 1]
138      + '\n\n' + library_visibility
139      + build_content[package_end_index + 1:]
140  )
141  with open(androidBpPath, 'w') as f:
142      f.write(modified_build_content)
143
144def addTagsToAndroidBpTargets(targetType, newTag):
145  """Adds the specified tag to all targets of the specified type in Android.bp"""
146  with open(androidBpPath, "r") as f:
147      lines = f.readlines()
148  modified_lines = []
149  in_target = False
150  for line in lines:
151      if line.strip().startswith(targetType + " {"):
152          in_target = True
153          modified_lines.append(line)
154      elif in_target and line.strip().startswith("}"):
155          modified_lines.append("    " + newTag + ",\n")
156          in_target = False
157          modified_lines.append(line)
158      else:
159          modified_lines.append(line)
160  with open(androidBpPath, "w") as f:
161      f.writelines(modified_lines)
162
163prebuiltDir = os.path.join(getAndroidRoot(), "prebuilts/misc/common/androidx-media3")
164chdir(prebuiltDir)
165
166libraryVisibility = getLibraryVisibilityFromAndroidBp()
167javaVersion = getJavaVersionFromAndroidBp()
168
169cmd("rm -rf androidx/media3")
170cmd("rm -rf manifests")
171
172downloadArtifact("androidx.media3", "media3-common", media3Version)
173downloadArtifact("androidx.media3", "media3-container", media3Version)
174downloadArtifact("androidx.media3", "media3-database", media3Version)
175downloadArtifact("androidx.media3", "media3-datasource", media3Version)
176downloadArtifact("androidx.media3", "media3-decoder", media3Version)
177downloadArtifact("androidx.media3", "media3-effect", media3Version)
178downloadArtifact("androidx.media3", "media3-exoplayer", media3Version)
179downloadArtifact("androidx.media3", "media3-exoplayer-dash", media3Version)
180downloadArtifact("androidx.media3", "media3-extractor", media3Version)
181downloadArtifact("androidx.media3", "media3-muxer", media3Version)
182downloadArtifact("androidx.media3", "media3-session", media3Version)
183downloadArtifact("androidx.media3", "media3-test-utils", media3Version)
184downloadArtifact("androidx.media3", "media3-transformer", media3Version)
185downloadArtifact("androidx.media3", "media3-ui", media3Version)
186
187atxRewriteStr = ""
188for name in mavenToBpPatternMap:
189  atxRewriteStr += "-rewrite %s=%s " % (name, mavenToBpPatternMap[name])
190
191cmd("pom2bp " + atxRewriteStr +
192    # map external maven dependencies to Android module names
193    "-rewrite androidx.annotation:annotation=androidx.annotation_annotation " +
194    "-rewrite androidx.annotation:annotation-experimental=androidx.annotation_annotation-experimental " +
195    "-rewrite androidx.collection:collection=androidx.collection_collection " +
196    "-rewrite androidx.core:core=androidx.core_core " +
197    "-rewrite androidx.exifinterface:exifinterface=androidx.exifinterface_exifinterface " +
198    "-rewrite androidx.media:media=androidx.media_media " +
199    "-rewrite androidx.recyclerview:recyclerview=androidx.recyclerview_recyclerview " +
200    "-rewrite androidx.test:core=androidx.test.core " +
201    "-rewrite androidx.test.ext:junit=androidx.test.ext.junit " +
202    "-rewrite androidx.test.ext:truth=androidx.test.ext.truth " +
203    "-rewrite com.google.guava:guava=guava " +
204    "-rewrite com.google.truth:truth=truth " +
205    "-rewrite com.google.truth.extensions:truth-java8-extension=truth-java8-extension " +
206    "-rewrite org.mockito:mockito-core=mockito-core " +
207    "-sdk-version current " +
208    "-static-deps " +
209    "-prepend prepend-license.txt " +
210    ". > Android.bp")
211
212fixAndroidBp(libraryVisibility, javaVersion)
213addTagsToAndroidBpTargets("android_library_import", 'visibility: ["//visibility:private"]')
214addTagsToAndroidBpTargets("android_library", 'visibility: library_visibility')
215cmd("bpfmt -w " + androidBpPath)
216