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