From f9a39201aafdb9b660d8c57fb8ffa051a9dc31c7 Mon Sep 17 00:00:00 2001 From: bachinger Date: Tue, 12 Jul 2022 20:43:24 +0000 Subject: [PATCH] Add migration script Note: This was already reviewed in . This doesn't mean we cannot apply further changes though. PiperOrigin-RevId: 460542835 --- github/media3-migration.sh | 386 +++++++++++++++++++++++++++++++++++++ 1 file changed, 386 insertions(+) create mode 100644 github/media3-migration.sh diff --git a/github/media3-migration.sh b/github/media3-migration.sh new file mode 100644 index 0000000000..f80ac4dfa3 --- /dev/null +++ b/github/media3-migration.sh @@ -0,0 +1,386 @@ +#!/bin/bash +# Copyright (C) 2022 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +## +shopt -s extglob + +PACKAGE_MAPPINGS='com.google.android.exoplayer2 androidx.media3.exoplayer +com.google.android.exoplayer2.analytics androidx.media3.exoplayer.analytics +com.google.android.exoplayer2.audio androidx.media3.exoplayer.audio +com.google.android.exoplayer2.castdemo androidx.media3.demo.cast +com.google.android.exoplayer2.database androidx.media3.database +com.google.android.exoplayer2.decoder androidx.media3.decoder +com.google.android.exoplayer2.demo androidx.media3.demo.main +com.google.android.exoplayer2.drm androidx.media3.exoplayer.drm +com.google.android.exoplayer2.ext.av1 androidx.media3.decoder.av1 +com.google.android.exoplayer2.ext.cast androidx.media3.cast +com.google.android.exoplayer2.ext.cronet androidx.media3.datasource.cronet +com.google.android.exoplayer2.ext.ffmpeg androidx.media3.decoder.ffmpeg +com.google.android.exoplayer2.ext.flac androidx.media3.decoder.flac +com.google.android.exoplayer2.ext.ima androidx.media3.exoplayer.ima +com.google.android.exoplayer2.ext.leanback androidx.media3.ui.leanback +com.google.android.exoplayer2.ext.okhttp androidx.media3.datasource.okhttp +com.google.android.exoplayer2.ext.opus androidx.media3.decoder.opus +com.google.android.exoplayer2.ext.rtmp androidx.media3.datasource.rtmp +com.google.android.exoplayer2.ext.vp9 androidx.media3.decoder.vp9 +com.google.android.exoplayer2.ext.workmanager androidx.media3.exoplayer.workmanager +com.google.android.exoplayer2.extractor androidx.media3.extractor +com.google.android.exoplayer2.gldemo androidx.media3.demo.gl +com.google.android.exoplayer2.mediacodec androidx.media3.exoplayer.mediacodec +com.google.android.exoplayer2.metadata androidx.media3.extractor.metadata +com.google.android.exoplayer2.offline androidx.media3.exoplayer.offline +com.google.android.exoplayer2.playbacktests androidx.media3.test.exoplayer.playback +com.google.android.exoplayer2.robolectric androidx.media3.test.utils.robolectric +com.google.android.exoplayer2.scheduler androidx.media3.exoplayer.scheduler +com.google.android.exoplayer2.source androidx.media3.exoplayer.source +com.google.android.exoplayer2.source.dash androidx.media3.exoplayer.dash +com.google.android.exoplayer2.source.hls androidx.media3.exoplayer.hls +com.google.android.exoplayer2.source.rtsp androidx.media3.exoplayer.rtsp +com.google.android.exoplayer2.source.smoothstreaming androidx.media3.exoplayer.smoothstreaming +com.google.android.exoplayer2.surfacedemo androidx.media3.demo.surface +com.google.android.exoplayer2.testdata androidx.media3.test.data +com.google.android.exoplayer2.testutil androidx.media3.test.utils +com.google.android.exoplayer2.text androidx.media3.extractor.text +com.google.android.exoplayer2.trackselection androidx.media3.exoplayer.trackselection +com.google.android.exoplayer2.transformer androidx.media3.transformer +com.google.android.exoplayer2.transformerdemo androidx.media3.demo.transformer +com.google.android.exoplayer2.ui androidx.media3.ui +com.google.android.exoplayer2.upstream androidx.media3.datasource +com.google.android.exoplayer2.upstream.cache androidx.media3.datasource.cache +com.google.android.exoplayer2.upstream.crypto androidx.media3.exoplayer.upstream.crypto +com.google.android.exoplayer2.util androidx.media3.common.util +com.google.android.exoplayer2.util androidx.media3.exoplayer.util +com.google.android.exoplayer2.video androidx.media3.exoplayer.video' + + +CLASS_RENAMINGS='com.google.android.exoplayer2.ui.StyledPlayerView androidx.media3.ui.PlayerView +StyledPlayerView PlayerView +com.google.android.exoplayer2.ui.StyledPlayerControlView androidx.media3.ui.PlayerControlView +StyledPlayerControlView PlayerControlView +com.google.android.exoplayer2.ExoPlayerLibraryInfo androidx.media3.common.MediaLibraryInfo +ExoPlayerLibraryInfo MediaLibraryInfo +com.google.android.exoplayer2.SimpleExoPlayer androidx.media3.exoplayer.ExoPlayer +SimpleExoPlayer ExoPlayer' + +CLASS_MAPPINGS='com.google.android.exoplayer2.text.span androidx.media3.common.text HorizontalTextInVerticalContextSpan LanguageFeatureSpan RubySpan SpanUtil TextAnnotation TextEmphasisSpan +com.google.android.exoplayer2.text androidx.media3.common.text CueGroup Cue +com.google.android.exoplayer2.text androidx.media3.exoplayer.text ExoplayerCuesDecoder SubtitleDecoderFactory TextOutput TextRenderer +com.google.android.exoplayer2.upstream.crypto androidx.media3.datasource AesCipherDataSource AesCipherDataSink AesFlushingCipher +com.google.android.exoplayer2.util androidx.media3.common.util AtomicFile Assertions BundleableUtil BundleUtil Clock ClosedSource CodecSpecificDataUtil ColorParser ConditionVariable Consumer CopyOnWriteMultiset EGLSurfaceTexture GlProgram GlUtil HandlerWrapper LibraryLoader ListenerSet Log LongArray MediaFormatUtil NetworkTypeObserver NonNullApi NotificationUtil ParsableBitArray ParsableByteArray RepeatModeUtil RunnableFutureTask SystemClock SystemHandlerWrapper TimedValueQueue TimestampAdjuster TraceUtil UnknownNull UnstableApi UriUtil Util XmlPullParserUtil +com.google.android.exoplayer2.util androidx.media3.common ErrorMessageProvider FlagSet FileTypes MimeTypes PriorityTaskManager +com.google.android.exoplayer2.metadata androidx.media3.common Metadata +com.google.android.exoplayer2.metadata androidx.media3.exoplayer.metadata MetadataDecoderFactory MetadataOutput MetadataRenderer +com.google.android.exoplayer2.audio androidx.media3.common AudioAttributes AuxEffectInfo +com.google.android.exoplayer2.ui androidx.media3.common AdOverlayInfo AdViewProvider +com.google.android.exoplayer2.source.ads androidx.media3.common AdPlaybackState +com.google.android.exoplayer2.source androidx.media3.common MediaPeriodId TrackGroup +com.google.android.exoplayer2.offline androidx.media3.common StreamKey +com.google.android.exoplayer2.ui androidx.media3.exoplayer.offline DownloadNotificationHelper +com.google.android.exoplayer2.trackselection androidx.media3.common TrackSelectionParameters TrackSelectionOverride +com.google.android.exoplayer2.video androidx.media3.common ColorInfo VideoSize +com.google.android.exoplayer2.upstream androidx.media3.common DataReader +com.google.android.exoplayer2.upstream androidx.media3.exoplayer.upstream Allocation Allocator BandwidthMeter CachedRegionTracker DefaultAllocator DefaultBandwidthMeter DefaultLoadErrorHandlingPolicy Loader LoaderErrorThrower ParsingLoadable SlidingPercentile TimeToFirstByteEstimator +com.google.android.exoplayer2.audio androidx.media3.extractor AacUtil Ac3Util Ac4Util DtsUtil MpegAudioUtil OpusUtil WavUtil +com.google.android.exoplayer2.util androidx.media3.extractor NalUnitUtil ParsableNalUnitBitArray +com.google.android.exoplayer2.video androidx.media3.extractor AvcConfig DolbyVisionConfig HevcConfig +com.google.android.exoplayer2.decoder androidx.media3.exoplayer DecoderCounters DecoderReuseEvaluation +com.google.android.exoplayer2.util androidx.media3.exoplayer MediaClock StandaloneMediaClock +com.google.android.exoplayer2 androidx.media3.exoplayer FormatHolder PlayerMessage +com.google.android.exoplayer2 androidx.media3.common BasePlayer BundleListRetriever Bundleable ControlDispatcher C DefaultControlDispatcher DeviceInfo ErrorMessageProvider ExoPlayerLibraryInfo Format ForwardingPlayer HeartRating IllegalSeekPositionException MediaItem MediaMetadata ParserException PercentageRating PlaybackException PlaybackParameters Player PositionInfo Rating StarRating ThumbRating Timeline Tracks +com.google.android.exoplayer2.drm androidx.media3.common DrmInitData' + +DEPENDENCY_MAPPINGS='exoplayer media3-exoplayer +exoplayer-common media3-common +exoplayer-core media3-exoplayer +exoplayer-dash media3-exoplayer-dash +exoplayer-database media3-database +exoplayer-datasource media-datasource +exoplayer-decoder media3-decoder +exoplayer-extractor media3-extractor +exoplayer-hls media3-exoplayer-hls +exoplayer-robolectricutils media3-test-utils-robolectric +exoplayer-rtsp media3-exoplayer-rtsp +exoplayer-smoothstreaming media3-exoplayer-smoothstreaming +exoplayer-testutils media3-test-utils +exoplayer-transformer media3-transformer +exoplayer-ui media3-ui +extension-cast media3-cast +extension-cronet media3-datasource-cronet +extension-ima media3-exoplayer-ima +extension-leanback media3-ui-leanback +extension-okhttp media3-datasource-okhttp +extension-rtmp media3-datasource-rtmp +extension-workmanager media3-exoplayer-workmanager' + +# Rewrites classes, packages and dependencies from the legacy ExoPlayer package structure +# to androidx.media3 structure. + +MEDIA3_VERSION="1.0.0-beta02" +LEGACY_PEER_VERSION="2.18.1" + +function usage() { + echo "usage: $0 [-p|-c|-d|-v]|[-m|-l [-x ] [-f] PROJECT_ROOT]" + echo " PROJECT_ROOT: path to your project root (location of 'gradlew')" + echo " -p: list package mappings and then exit" + echo " -c: list class mappings (precedence over package mappings) and then exit" + echo " -d: list dependency mappings and then exit" + echo " -m: migrate packages, classes and dependencies to AndroidX Media3" + echo " -l: list files that will be considered for rewrite and then exit" + echo " -x: exclude the path from the list of file to be changed: 'app/src/test'" + echo " -f: force the action even when validation fails" + echo " -v: print the exoplayer2/media3 version strings of this script and exit" + echo " --noclean : Do not call './gradlew clean' in project directory." + echo " -h, --help: show this help text" +} + +function print_pairs { + while read -r line; + do + IFS=' ' read -ra PAIR <<< "$line" + printf "%-55s %-30s\n" "${PAIR[0]}" "${PAIR[1]}" + done <<< "$(echo "$@")" +} + +function print_class_mappings { + while read -r mapping; + do + old=$(echo "$mapping" | cut -d ' ' -f1) + new=$(echo "$mapping" | cut -d ' ' -f2) + classes=$(echo "$mapping" | cut -d ' ' -f3-) + for clazz in $classes; + do + printf "%-80s %-30s\n" "$old.$clazz" "$new.$clazz" + done + done <<< "$(echo "$CLASS_MAPPINGS" | sort)" +} + +ERROR_COUNTER=0 +VALIDATION_ERRORS='' + +function add_validation_error { + let ERROR_COUNTER++ + VALIDATION_ERRORS+="\033[31m[$ERROR_COUNTER] ->\033[0m ${1}" +} + +function validate_exoplayer_version() { + has_exoplayer_dependency='' + while read -r file; + do + local version + version=$(grep -m 1 "com\.google\.android\.exoplayer:" "$file" | cut -d ":" -f3 | tr -d \" | tr -d \') + if [[ ! -z $version ]] && [[ ! "$version" =~ $LEGACY_PEER_VERSION ]]; + then + add_validation_error "The version does not match '$LEGACY_PEER_VERSION'. \ +Update to '$LEGACY_PEER_VERSION' or use the migration script matching your \ +current version. Current version '$version' found in\n $file\n" + fi + done <<< "$(find . -type f -name "build.gradle")" +} + +function validate_string_not_contained { + local pattern=$1 # regex + local failure_message=$2 + while read -r file; + do + if grep -q -e "$pattern" "$file"; + then + add_validation_error "$failure_message:\n $file\n" + fi + done <<< "$files" +} + +function validate_string_patterns { + validate_string_not_contained \ + 'com\.google\.android\.exoplayer2\..*\*' \ + 'Replace wildcard import statements with fully qualified import statements'; + validate_string_not_contained \ + 'com\.google\.android\.exoplayer2\.ui\.PlayerView' \ + 'Migrate PlayerView to StyledPlayerView before migrating'; + validate_string_not_contained \ + 'LegacyPlayerView' \ + 'Migrate LegacyPlayerView to StyledPlayerView before migrating'; + validate_string_not_contained \ + 'com\.google\.android\.exoplayer2\.ext\.mediasession' \ + 'The MediaSessionConnector is integrated in androidx.media3.session.MediaSession' +} + +SED_CMD_INPLACE='sed -i ' +if [[ "$OSTYPE" == "darwin"* ]]; then + SED_CMD_INPLACE="sed -i '' " +fi + +MIGRATE_FILES='1' +LIST_FILES_ONLY='1' +PRINT_CLASS_MAPPINGS='1' +PRINT_PACKAGE_MAPPINGS='1' +PRINT_DEPENDENCY_MAPPINGS='1' +PRINT_VERSION='1' +NO_CLEAN='1' +FORCE='1' +IGNORE_VERSION='1' +EXCLUDED_PATHS='' + +while [[ $1 =~ ^-.* ]]; +do + case "$1" in + -m ) MIGRATE_FILES='';; + -l ) LIST_FILES_ONLY='';; + -c ) PRINT_CLASS_MAPPINGS='';; + -p ) PRINT_PACKAGE_MAPPINGS='';; + -d ) PRINT_DEPENDENCY_MAPPINGS='';; + -v ) PRINT_VERSION='';; + -f ) FORCE='';; + -x ) shift; EXCLUDED_PATHS="$(printf "%s\n%s" $EXCLUDED_PATHS $1)";; + --noclean ) NO_CLEAN='';; + * ) usage && exit 1;; + esac + shift +done + +if [[ -z $PRINT_DEPENDENCY_MAPPINGS ]]; +then + print_pairs "$DEPENDENCY_MAPPINGS" + exit 0 +elif [[ -z $PRINT_PACKAGE_MAPPINGS ]]; +then + print_pairs "$PACKAGE_MAPPINGS" + exit 0 +elif [[ -z $PRINT_CLASS_MAPPINGS ]]; +then + print_class_mappings + exit 0 +elif [[ -z $PRINT_VERSION ]]; +then + echo "$LEGACY_PEER_VERSION -> $MEDIA3_VERSION. This script is written to migrate from ExoPlayer $LEGACY_PEER_VERSION to AndroidX Media3 $MEDIA3_VERSION" + exit 0 +elif [[ -z $1 ]]; +then + usage + exit 1 +fi + +if [[ ! -f $1/gradlew ]]; +then + echo "directory seems not to exist or is not a gradle project (missing 'gradlew')" + usage + exit 1 +fi + +PROJECT_ROOT=$1 +cd "$PROJECT_ROOT" + +# Create the set of files to transform +exclusion="/build/|/.idea/|/res/drawable|/res/color|/res/mipmap|/res/values|" +if [[ ! -z $EXCLUDED_PATHS ]]; +then + while read -r path; + do + exclusion="$exclusion./$path|" + done <<< "$EXCLUDED_PATHS" +fi +files=$(find . -name '*\.java' -o -name '*\.kt' -o -name '*\.xml' | grep -Ev "'$exclusion'") + +# Validate project and exit in case of validation errors +validate_string_patterns +validate_exoplayer_version "$PROJECT_ROOT" +if [[ ! -z $FORCE && ! -z "$VALIDATION_ERRORS" ]]; +then + echo "=============================================" + echo "Validation errors (use -f to force execution)" + echo "---------------------------------------------" + echo -e "$VALIDATION_ERRORS" + exit 1 +fi + +if [[ -z $LIST_FILES_ONLY ]]; +then + echo "$files" | cut -c 3- + find . -type f -name 'build\.gradle' | cut -c 3- + exit 0 +fi + +# start migration after successful validation or when forced to disregard validation +# errors + +if [[ ! -z "$MIGRATE_FILES" ]]; +then + echo "nothing to do" + usage + exit 0 +fi + +PWD=$(pwd) +if [[ ! -z $NO_CLEAN ]]; +then + cd "$PROJECT_ROOT" + ./gradlew clean + cd "$PWD" +fi + +# create expressions for class renamings +renaming_expressions='' +while read -r renaming; +do + src=$(echo "$renaming" | cut -d ' ' -f1 | sed -e 's/\./\\\./g') + dest=$(echo "$renaming" | cut -d ' ' -f2) + renaming_expressions+="-e s/$src/$dest/g " +done <<< "$CLASS_RENAMINGS" + +# create expressions for class mappings +classes_expressions='' +while read -r mapping; +do + src=$(echo "$mapping" | cut -d ' ' -f1 | sed -e 's/\./\\\./g') + dest=$(echo "$mapping" | cut -d ' ' -f2) + classes=$(echo "$mapping" | cut -d ' ' -f3-) + for clazz in $classes; + do + classes_expressions+="-e s/$src\.$clazz/$dest.$clazz/g " + done +done <<< "$CLASS_MAPPINGS" + +# create expressions for package mappings +packages_expressions='' +while read -r mapping; +do + src=$(echo "$mapping" | cut -d ' ' -f1 | sed -e 's/\./\\\./g') + dest=$(echo "$mapping" | cut -d ' ' -f2) + packages_expressions+="-e s/$src/$dest/g " +done <<< "$PACKAGE_MAPPINGS" + +# do search and replace with expressions in each selected file +while read -r file; +do + echo "migrating $file" + expr="$renaming_expressions $classes_expressions $packages_expressions" + $SED_CMD_INPLACE $expr $file +done <<< "$files" + +# create expressions for dependencies in gradle files +EXOPLAYER_GROUP="com\.google\.android\.exoplayer" +MEDIA3_GROUP="androidx.media3" +dependency_expressions="" +while read -r mapping +do + OLD=$(echo "$mapping" | cut -d ' ' -f1 | sed -e 's/\./\\\./g') + NEW=$(echo "$mapping" | cut -d ' ' -f2) + dependency_expressions="$dependency_expressions -e s/$EXOPLAYER_GROUP:$OLD:.*\"/$MEDIA3_GROUP:$NEW:$MEDIA3_VERSION\"/g -e s/$EXOPLAYER_GROUP:$OLD:.*'/$MEDIA3_GROUP:$NEW:$MEDIA3_VERSION'/" +done <<< "$DEPENDENCY_MAPPINGS" + +## do search and replace for dependencies in gradle files +while read -r build_file; +do + echo "migrating build file $build_file" + $SED_CMD_INPLACE $dependency_expressions $build_file +done <<< "$(find . -type f -name 'build\.gradle')"