ICU version upgrade

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.

Prerequisites

  1. Install the prerequisite tools
  2. Generate a github read-access token and setup a local ~/.m2/setting.xml
  3. Check out aosp/master

Steps

  1. Create a new branch in AOSP
    • The branch is a staging branch to rebase Android-specific patches onto the new upstream versions.
    • See detailed instruction at http://g3doc/company/teams/android-build-team/playbook/create_branch#creating-new-git-branches.
    • Choose a branch name
      • Create aosp/icu{version} branch, e.g. aosp/icu67 in the external/icu project forked from aosp/master
      • For the external/cldr project, we don't need a new branch. We use the `aosp/upstream-release-cldr as the mirror of the upstream release branch. We don’t modify this branch with Android patches, but merge this branch into aosp/master where the Android patches are located.
  2. Configure the versions and temp directory
    1. Customize the following environment variables. The following example targets the ICU 71.1 and CLDR 41.0 version.
    export ICU_VERSION=71
    export ICU_MINOR_VERSION=1
    export CLDR_VERSION=41
    export ICU_UPGRADE_BUG=1234567890 # buganizer bug
    # Initially empty directory to store upstream source
    export UPSTREAM_CLDR_GIT=/media/user/disk/icu-git/cldr
    export UPSTREAM_ICU_GIT=/media/user/disk/icu-git/icu
    
    1. Build the clean source of AOSP
    source build/envsetup.sh
    lunch sdk_phone_x86_64-userdebug
    m
    
  3. Copy the CLDR sources into the upstream-release-cldr branch
    1. Copy sources
    export CLDR_UPSTREAM_BRANCH=release-${CLDR_VERSION}
    
    cd ${ANDROID_BUILD_TOP}/external/cldr
    git branch ${CLDR_UPSTREAM_BRANCH} --track aosp/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
    
    1. Merge the upstream sources with patches in aosp/master
    export CLDR_BRANCH=cldr${CLDR_VERSION}-master
    git branch ${CLDR_BRANCH} --track aosp/master
    git checkout ${CLDR_BRANCH}
    git merge ${CLDR_UPSTREAM_BRANCH}
    
    1. Resolve any merge conflicts with the Android-specific patches. Continue creating the merge commit
    git merge --continue
    
    1. Amend the commit message
    Merge branch aosp/upstream-release-cldr into aosp/master
    
    Bug: <ICU_UPGRADE_BUG>
    Test: external/icu/tools/updatecldrdata.py
    
  4. Copy ICU upstream sources into external/icu
cd ${ANDROID_BUILD_TOP}/external/icu
export ICU_BRANCH=icu${ICU_VERSION}
export UPSTREAM_RELEASE_TAG=release-${ICU_VERSION}-${ICU_MINOR_VERSION}
git fetch aosp ${ICU_BRANCH}
git branch ${ICU_BRANCH} --track aosp/${ICU_BRANCH}
git checkout ${ICU_BRANCH}

# Clone the repo locally
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\)" -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 aosp/${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\)" -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
  1. Apply Android-specific patches into external/icu
    1. Cherry-pick the patches from the last staging branch. For example using the following query
      1. https://r.android.com/q/%2522Android+patch%2522+branch:icu71+status:merged
    2. Cherry-pick the patches since the ICU upgrade
      1. Find the patches with this query. https://r.android.com/q/%2522Android+patch%2522+project:platform/external/icu+status:merged+-owner:automerger+-owner:android-build-coastguard-worker%2540google.com+branch:master
  2. Regenerate and commit the artifacts
    1. 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
    
    1. Update icu binary data files
    tools/updateicudata.py
    git add -A
    git commit -F- <<EOF
    Regenerated binary data files with Android CLDR patches
    
    Binary data files updated using:
    tools/updateicudata.py
    
    Test: n/a
    EOF
    
    1. Pin the public API surface temporarily
      1. We will later expose the new APIs after submitting the version upgrade CLs.
    ./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
    
    1. Regenerate android_icu4j/
      1. Commands
      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
      
      1. If any java patches are not applied perfectly, remove the .orig and .rej files with the following command
      find android_icu4j/ -name *.orig -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
      
    2. 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
    
    1. Regenerate libicu/ sources
      1. Commands
      ./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
      
      1. Review the changes in libicu/ndk_headers/unicode. Check that no ABI change is in the C struct or API signature.
      git diff ./libicu/ndk_headers/
      
      1. May need to run this to update .patch files
      # 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
      
    2. [Not required for every ICU release] Increment Distro major version
    3. Generate time zone files
    cd $ANDROID_BUILD_TOP/system/timezone
    ./update-tzdata.py
    git add -A
    git commit -F- <<EOF
    Regenerate data files for ICU 63.1 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.
    
    Test: n/a
    EOF
    
    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
    
    Test: n/a
    EOF
    
    1. Update the version numbers in the METADATA
      1. Update the external/icu/README.version
      2. Update version and upgrade date in external/cldr/METADATA
      3. git commit the file change
    2. Regenerate frameworks/base/libs/androidfw/LocaleDataTables.cpp
    croot frameworks/base
    ./tools/localedata/extract_icu_data.py $ANDROID_BUILD_TOP > libs/androidfw/LocaleDataTables.cpp
    git commit -F- <<EOF
    Regenerate LocaleDataTables.cpp due to ICU ${ICU_VERSION} upgrade
    
    The command:
    ./tools/localedata/extract_icu_data.py \$ANDROID_BUILD_TOP > libs/androidfw/LocaleDataTables.cpp
    EOF
    
  3. Build and run test
    1. Build by m droid cts
    2. Run the device tests by atest CtsIcu4cTestCases CtsIcuTestCases CtsLibcoreTestCases CtsLibcoreOjTestCases CtsBionicTestCases CtsTextTestCases minikin_tests -- --abi x86_64 # the primary ABI
    3. Run the host-side test by
      1. ICU4J host-side test ant check
      2. ICU4C host-side test make CINTLTST_OPTS=-w INTLTEST_OPTS=-w check (Currently, it has some failing tests. No of failures?)
  4. Upload the CLs to gerrit for code reviews from aosp/icu* in external/icu and aosp/upstream-release-cldr in external/cldr
repo upload --cbr -o uploadvalidator~skip --no-verify --re=reviewer .
  1. Merge aosp/icu* branch to aosp/master
cd $ANDROID_BUILD_TOP/external/icu
repo start icu${ICU_VERSION}-master .
git merge icu${ICU_VERSION}
# Amend the commit messsage
git commit --amend -F- <<EOF
Merge branch aosp/icu${ICU_VERSION} into aosp/master

Bug: ${ICU_UPGRADE_BUG}
Test: atest CtsIcu4cTestCases CtsIcuTestCases CtsLibcoreTestCases CtsLibcoreOjTestCases CtsBionicTestCases CtsTextTestCases minikin_tests
EOF
  1. Upload and submit changes from external/icu, external/cldr, libcore, frameworks/base, system/timezone
    1. repo upload --cbr -o uploadvalidator~skip --no-verify --re=reviewer .
    2. Code review the diff in android_icu4j/src/main/tests/android/icu/extratest/expected_transliteration_id_list.txt
      1. If a transliteration id is removed from the list, it may introduce app compatibility issues if the app depends on them. However, app has been warned to check the availability before invoking them. https://developer.android.com/reference/android/icu/text/Transliterator#getAvailableIDs()
  2. Update frameworks/libs/native_bridge_supoprt stubs for libicuuc and libicui18n
    1. See this internal doc
    2. An example CL https://r.android.com/1556263 should be regenerated.
  3. After submitting all the CLs to aosp/master, expose the new stable ICU4J APIs to Android SDK
rm tools/srcgen/allowlisted-public-api.txt
./tools/generate_android_icu4j.sh
# Modify Icu4jTransform.java to allowlist more classes if needed. Check the error message for the details
m 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
  1. Send email android-libcore@ and icu-team@ to announce this.
    1. Some Android teams may have dependency on the new ICU version for other features.
    2. Email template
Hi, Libcore and ICU team,

ICU <version> just landed Android AOSP.
https://android.googlesource.com/platform/external/icu/+/master/README.version
as well as Android S (or Android 12).
https://googleplex-android.googlesource.com/platform/external/icu/+/sc-dev/README.version

Note:
- Contains bug fixes / build changes with a small set of API methods added.
- Unicode stays at version 14, and no new version has been published yet.

Historic version of this doc

http://g3doc/third_party/icu/g3doc/update/android