Upgrade the ICU on Android to the new upstream version. The new upstream versions can be found at https://github.com/unicode-org/icu/releases.
The below contains the steps and commands in order to upgrade the ICU version in the AOSP.
Change-Id later.external/icu project in the AOSP,icu-staging branch. Then we merge into goog/main later.external/cldr projectsource build/envsetup.sh lunch cf_x86_64_phone-trunk_staging-userdebug mThe build should succeed. Otherwise, your local repo may be broken. Please consider to re-sync.
icu4j/ and icu4c or external/cldr.external/icu/tools/updatecldrdata.py external/icu/tools/updateicudata.py system/timezone/update-tzdata.py external/icu/tools/srcgen/generate_android_icu4j.sh external/icu/tools/icu4c_srcgen/generate_libandroidicu.py external/icu/tools/icu4c_srcgen/generate_ndk.py
Configure the versions and temp directory
export ICU_VERSION=76 export ICU_MINOR_VERSION=1 export CLDR_VERSION=46 export ICU_UPGRADE_BUG=1234567890 # buganizer bug
export UPSTREAM_CLDR_GIT=</path/to/directory/on/your/disk/cldr> export UPSTREAM_ICU_GIT=</path/to/directory/on/your/disk/icu>
mkdir -p ${UPSTREAM_CLDR_GIT} mkdir -p ${UPSTREAM_ICU_GIT}
Copy the CLDR sources into the upstream-release-cldr branch
2a. Copy sources
export CLDR_UPSTREAM_BRANCH=release-${CLDR_VERSION} cd ${ANDROID_BUILD_TOP}/external/cldr git fetch goog upstream-release-cldr git branch ${CLDR_UPSTREAM_BRANCH} --track goog/upstream-release-cldr git checkout ${CLDR_UPSTREAM_BRANCH} git clone https://github.com/unicode-org/cldr.git ${UPSTREAM_CLDR_GIT} git --git-dir=${UPSTREAM_CLDR_GIT}/.git --work-tree=${UPSTREAM_CLDR_GIT} fetch git --git-dir=${UPSTREAM_CLDR_GIT}/.git --work-tree=${UPSTREAM_CLDR_GIT} checkout ${CLDR_UPSTREAM_BRANCH} rm -rf * cp -r ${UPSTREAM_CLDR_GIT}/* . git clean -dfX # Remove ignored files git add -A git commit -F- <<EOF Copy upstream ${CLDR_UPSTREAM_BRANCH} Bug: ${ICU_UPGRADE_BUG} Test: n/a EOF # Upload this CL to upstream-release-cldr branch repo upload --cbr -o nokeycheck -o uploadvalidator~skip --no-verify .
2b. Merge the upstream sources with patches in goog/main
export CLDR_BRANCH=cldr${CLDR_VERSION}-main git branch ${CLDR_BRANCH} --track goog/main git checkout ${CLDR_BRANCH} git merge ${CLDR_UPSTREAM_BRANCH} -m " Merge CLDR ${CLDR_VERSION} in upstream-release-cldr into goog/main Bug: ${ICU_UPGRADE_BUG} Test: external/icu/tools/updatecldrdata.py "
2c. Resolve any merge conflicts with the Android-specific patches. Continue creating the merge commit
git merge --continue
2d. Upload the CL to main branch
repo upload --cbr -o nokeycheck -o uploadvalidator~skip --no-verify .
Copy ICU upstream sources into external/icu
cd ${ANDROID_BUILD_TOP}/external/icu export ICU_BRANCH=icu-staging export UPSTREAM_RELEASE_TAG=release-${ICU_VERSION}.${ICU_MINOR_VERSION} git fetch goog main ${ICU_BRANCH} git branch ${ICU_BRANCH} --track goog/${ICU_BRANCH} git checkout ${ICU_BRANCH} # Merge main into the staging branch. git merge --no-ff goog/main -m " Merge branch goog/main into ${ICU_BRANCH} Bug: ${ICU_UPGRADE_BUG} Test: n/a " # Clone the upstream CLDR repo locally to ${UPSTREAM_ICU_GIT} test -d ${UPSTREAM_ICU_GIT}/.git || git clone https://github.com/unicode-org/icu.git ${UPSTREAM_ICU_GIT} git --git-dir=${UPSTREAM_ICU_GIT}/.git --work-tree=${UPSTREAM_ICU_GIT} fetch git --git-dir=${UPSTREAM_ICU_GIT}/.git --work-tree=${UPSTREAM_ICU_GIT} checkout ${UPSTREAM_RELEASE_TAG} find icu4j/ -type f,d ! -regex ".*/\(Android.mk\|Android.bp\|adjust_icudt_path.mk\|liblayout-jarjar-rules.txt\|.gitignore\|AndroidTest.xml\)" -delete && \ find icu4c/ -type f,d ! -regex ".*/\(Android.mk\|Android.bp\|.gitignore\|AndroidTest.xml\|robo-jarjar-rules.txt\)" -delete && \ cp -r ${UPSTREAM_ICU_GIT}/icu4j . && \ cp -r ${UPSTREAM_ICU_GIT}/icu4c . && \ git checkout HEAD -- icu4c/.gitignore icu4j/.gitignore && # Android has extra .gitignores. Use our version. \ rm -r tools/cldr && \ cp -r ${UPSTREAM_ICU_GIT}/tools/cldr tools/cldr && \ git add -A && \ git commit -F- <<EOF Copy ICU ${UPSTREAM_RELEASE_TAG} into goog/${ICU_BRANCH} Copy the files with the following commands: find icu4j/ -type f,d ! -regex ".*/\(Android.mk\|Android.bp\|adjust_icudt_path.mk\|liblayout-jarjar-rules.txt\|.gitignore\|AndroidTest.xml\)" -delete find icu4c/ -type f,d ! -regex ".*/\(Android.mk\|Android.bp\|.gitignore\|AndroidTest.xml\|robo-jarjar-rules.txt\)" -delete cp -r \${UPSTREAM_ICU_GIT}/icu4j . cp -r \${UPSTREAM_ICU_GIT}/icu4c . git checkout HEAD -- icu4c/.gitignore icu4j/.gitignore rm -r tools/cldr cp -r \${UPSTREAM_ICU_GIT}/tools/cldr tools/cldr EOF
Apply Android-specific patches into external/icu
4a. Cherry-pick the patches from the last staging branch. For example using the following query for ICU 71 patches
git cherry-pick <first_patch_in_the_chain>~1..<last_patch_in_the_chain>
4b. Cherry-pick theq patches since the ICU upgrade
4c. Reset Change-Id in the cherry-picked CLs
THE_COPY_COMMIT=$(git log --pretty=format:'%h' -n 1 --grep "Copy ICU ${UPSTREAM_RELEASE_TAG} into goog/${ICU_BRANCH}") git filter-branch -f --msg-filter 'sed "s/Change-Id: .*//g"' ${THE_COPY_COMMIT}..HEAD git rebase -i ${THE_COPY_COMMIT} # It should open vim # Replace pick with reword in vim `%s/pick /reword /g` # Close all commit message edits with :wq in vim # It triggers the git-hook to generate a Change-Id. # TODO: Find a better way to generate Change-Id
Regenerate and commit the artifacts
5a. Update icu source data files
croot external/icu tools/updatecldrdata.py && \ git add -A && \ git commit -F- <<EOF Regenerated source data files with Android CLDR patches Source data files updated using: tools/updatecldrdata.py Test: n/a EOF
5b. Update icu binary data files
tools/updateicudata.py && \ git add -A && \ git commit -F- <<EOF Regenerated binary data files with Android ICU patches Binary data files updated using: tools/updateicudata.py Test: n/a EOF
5c. Pin the public API surface temporarily
./tools/srcgen/generate_allowlisted_public_api.sh && \ git add -A && \ git commit -F- <<EOF Pin the current API list Test: ./tools/srcgen/generate_allowlisted_public_api.sh EOF
5d. Regenerate android_icu4j/
tools/srcgen/generate_android_icu4j.sh && \ git add -A && \ git commit -F- <<EOF Regenerate android_icu4j/ from icu4j/ android_icu4j files updated using: tools/srcgen/generate_android_icu4j.sh Test: n/a EOF
find android_icu4j/ \( -name "*.orig" -o -name "*.rej" \) -delete # Please manually update and resolve conflict of the java doc in android_icu4j/ git commit -amend # Regenerate the patch files ./tools/srcgen/javadoc_patches/create_patches.sh git add -A && git commit -F- <<EOF Regenerate java doc patches Test: n/a EOF
5e. Re-genereate libandroidicu/ sources
./tools/icu4c_srcgen/generate_libandroidicu.py git add -A && git commit -F- <<EOF Regenerate libandroidicu The command: ./tools/icu4c_srcgen/generate_libandroidicu.py Test: n/a EOF
5f. Regenerate libicu/ sources
./tools/icu4c_srcgen/generate_ndk.py git add -A && git commit -a -F- <<EOF Regenerate libicu.so and ICU4C CTS headers The command: ./tools/icu4c_srcgen/generate_ndk.py Test: n/a EOF
git diff HEAD~1 ./libicu/ndk_headers/
# Manually update doxygen doc in the .h headers in libicu/ndk_headers ./tools/icu4c_srcgen/doc_patches/create_patches.sh git add -A && git commit -F- <<EOF Regenerate patches in libicu headers EOF
5g. [Not required for every ICU release] Increment Distro major version
5h. Generate time zone files
cd $ANDROID_BUILD_TOP/system/timezone repo start ${ICU_BRANCH} . ./update-tzdata.py && \ git add -A && \ git commit -F- <<EOF Regenerate data files for ICU ${ICU_VERSION} upgrade Binary data files updated using: system/timezone/update-tzdata.py This updates the ICU version number inside of icu_tzdata.dat but doesn't change the timezone data itself. Bug: ${ICU_UPGRADE_BUG} Test: n/a EOF # If only the build time in icu4c/source/data/misc/zoneinfo64.txt, this step isn't needed. cd $ANDROID_BUILD_TOP/external/icu git add -A git commit -F- <<EOF Regenerate tz-related data files Data files updated using: system/timezone/update-tzdata.py Bug: ${ICU_UPGRADE_BUG} Test: n/a EOF
5i. Regenerate frameworks/base/libs/androidfw/LocaleDataLookup.cpp
croot frameworks/base repo start icu${ICU_VERSION} . ./tools/localedata/extract_icu_data.py $ANDROID_BUILD_TOP > libs/androidfw/LocaleDataLookup.cpp git commit -a -F- <<EOF Regenerate LocaleDataLookup.cpp due to ICU ${ICU_VERSION} upgrade The command: ./tools/localedata/extract_icu_data.py \$ANDROID_BUILD_TOP > libs/androidfw/LocaleDataLookup.cpp Bug: ${ICU_UPGRADE_BUG} Test: atest libandroidfw_tests FrameworksCoreTests:android.text.format EOF
Build and run test
6a. Build by m droid cts
6b. Run the device tests by atest CtsIcu4cTestCases CtsIcuTestCases CtsLibcoreTestCases CtsLibcoreOjTestCases CtsBionicTestCases CtsTextTestCases minikin_tests -- --abi x86_64 # the primary ABI
CtsIcu4cTestCases causes a native crash, e.g. exit code 137, check adb logcat for native crash dump.m CtsIcu4cTestCases && \ adb push out/soong/.intermediates/external/icu/icu4c/source/test/intltest/intltest64/android_x86_64_silvermont/intltest64 /data/local/tmp/intltest && \ # replace android_x86_64_silvermont if you are not using cuttlefish. adb push out/host/linux-x86/testcases/CtsIcu4cTestCases/icu4c_test_data.zip /data/local/tmp/icu4c_test_data.zip && \ adb shell unzip -o -d /data/local/tmp/ /data/local/tmp/icu4c_test_data.zip && \ adb shell chmod a+x /data/local/tmp/intltest && \ adb shell /data/local/tmp/intltest -w -x /data/local/tmp/intltest_res.xml
6c. [No longer needed] Run the host-side test by
ant checkmake CINTLTST_OPTS=-w INTLTEST_OPTS=-w check (Currently, it has some failing tests. No of failures?)6d. If libcore/ tests are changed, verify the change
m mts && mts-tradefed run mts-art on Android S.art/tools/run-libcore-tests.sh --mode=host, because LUCI uses older ICU versions.Upload the CLs to gerrit for code reviews from goog/icu-staging in external/icu and goog/upstream-release-cldr in external/cldr
repo upload --cbr -o nokeycheck -o uploadvalidator~skip --no-verify .
Merge goog/icu* branch to goog/main
cd $ANDROID_BUILD_TOP/external/icu repo start icu${ICU_VERSION}-main . git merge --no-ff icu-staging -m " Merge branch goog/icu-staging into goog/main Bug: ${ICU_UPGRADE_BUG} Test: atest CtsIcu4cTestCases CtsIcuTestCases CtsLibcoreTestCases CtsLibcoreOjTestCases CtsBionicTestCases CtsTextTestCases minikin_tests "
Update the version numbers in the METADATA 9a. Update the external/icu/METADATA in git_main 9b. Update version and upgrade date in external/cldr/METADATA 9c. git commit the file change
Upload and submit changes from external/icu, external/cldr, libcore, frameworks/base, system/timezone
10a. repo upload --cbr -o uploadvalidator~skip --no-verify .
10b. Code review the diff in android_icu4j/src/main/tests/android/icu/extratest/expected_transliteration_id_list.txt
After submitting all the CLs to goog/main, expose the new stable ICU4J APIs to Android SDK
rm tools/srcgen/allowlisted-public-api.txt ./tools/srcgen/generate_android_icu4j.sh # Modify Icu4jTransform.java to allowlist more classes if needed. Check the error message for the details m update-api droid git commit -a -F- <<EOF Expose the new stable APIs from ICU4J ${ICU_VERSION} According to the upstream API coverage report external/icu/icu4j/coverage-exclusion.txt, the methods should have API coverage running in the existing CtsIcuTestCases. Bug: ${ICU_UPGRADE_BUG} Test: atest CtsIcuTestCases EOF
Send email android-libcore@ and icu-team@ to announce this.
Hi, Libcore and ICU team, ICU <version> just landed Android AOSP. https://googleplex-android.googlesource.com/platform/external/icu/+/main/METADATA Note: - Contains bug fixes / build changes with a small set of API methods added. - Unicode stays at version 16, and no new version has been published yet.