時區規則

Android 10 棄用了基於 APK 的時區資料更新機制(在 Android 8.1 和 Android 9 中提供),並替換為基於 APEX 的模組更新機制。 AOSP 8.1 至 13 仍包含 OEM 啟用基於 APK 的更新所需的平台程式碼,因此升級至 Android 10 的裝置仍可透過 APK 接收合作夥伴提供的時區資料更新。但是,APK 更新機制不應在同時接收模組更新的生產設備上使用,因為基於 APK 的更新會取代基於 APEX 的更新(即,接收 APK 更新的設備將忽略基於 APEX 的更新) )。

時區更新(Android 10+)

Android 10 及更高版本中支援的時區資料模組更新了 Android 裝置上的夏令時 (DST) 和時區,標準化了可能因宗教、政治和地緣政治原因而頻繁更改的資料。

更新使用以下程序:

  1. IANA發佈時區資料庫更新 發布更新以回應一個或多個政府更改其國家/地區的時區規則。
  2. Google 或 Android 合作夥伴準備包含更新時區的時區資料模組更新(APEX 檔案)。
  3. 最終使用者裝置下載更新、重新啟動,然後套用更改,之後裝置的時區資料包含更新中的新時區資料。

有關模組的詳細信息,請參閱模組化系統組件

時區更新 (Android 8.1–9)

注意:基於APK的時區資料更新機制功能已從Android 14開始完全刪除,並且在原始碼中找不到。合作夥伴應完全遷移到時區主線模組。

在 Android 8.1 和 Android 9 中,OEM 可以使用基於 APK 的機制將更新的時區規則資料推送到設備,而無需進行系統更新。這種機制使用戶能夠及時接收更新(從而延長 Android 裝置的使用壽命),並使 Android 合作夥伴能夠獨立於系統映像更新來測試時區更新。

Android 核心庫團隊提供了更新普通 Android 裝置上的時區規則所需的資料檔案。 OEM 可以選擇在為其裝置建立時區更新時使用這些資料文件,也可以根據需要建立自己的資料檔案。在所有情況下,OEM 保留對其支援設備的品質保證/測試、計時和時區規則更新啟動的控制權。

Android時區源碼及數據

所有庫存 Android 裝置(甚至不使用此功能的裝置)都需要時區規則數據,並且必須在/system分區中附帶一組預設時區規則資料。然後,Android 原始碼樹中以下庫中的程式碼將使用該資料:

  • libcore/中的託管程式碼(例如java.util.TimeZone )使用tzdatatzlookup.xml檔案。
  • bionic/中的本機函式庫程式碼(例如,對於mktime 、本機時間系統呼叫)使用tzdata檔案。
  • external/icu/中的 ICU4J/ICU4C 庫程式碼使用 icu .dat檔。

這些庫追蹤/data/misc/zoneinfo/current目錄中可能存在的覆蓋檔案。覆蓋檔案預計將包含改進的時區規則數據,從而使設備能夠在不更改/system的情況下進行更新。

需要時區規則資料的Android系統元件先檢查以下位置:

  • libcore/bionic/程式碼使用tzdatatzlookup.xml檔案的/data副本。
  • ICU4J/ICU4C 程式碼使用/data中的文件,並回退到/system文件以取得不存在的資料(格式、本地化字串等)。

發行版文件

Distro .zip檔包含填入/data/misc/zoneinfo/current目錄所需的資料檔。發行版文件還包含允許設備檢測版本控制問題的元資料。

發行版檔案格式取決於 Android 版本,因為內容會隨著 ICU 版本、Android 平台要求和其他版本變更而變化。 Android 為每個 IANA 更新(除了更新平台系統檔案之外)提供支援的 Android 版本的發行版檔案。為了讓他們的裝置保持最新,OEM 可以使用這些發行版檔案或使用 Android 原始碼樹(其中包含生成發行版檔案所需的腳本和其他檔案)來建立自己的發行版檔案。

時區更新元件

時區規則更新涉及將發行版檔案傳輸到裝置以及其中包含的檔案的安全安裝。傳輸和安裝需要滿足以下條件:

  • 平台服務功能 ( timezone.RulesManagerService ),預設為停用。 OEM 必須透過設定啟用該功能。 RulesManagerService在系統伺服器程序中執行,並透過寫入/data/misc/zoneinfo/staged staged 來暫存時區更新操作。 RulesManagerService也可以取代或刪除已經暫存的操作。
  • TimeZoneUpdater ,不可更新的系統應用程式(又稱Updater 應用程式)。 OEM 必須將此應用程式包含在使用該功能的裝置的系統映像中。
  • OEM TimeZoneData ,一個可更新的系統應用程式(也稱為資料應用程式),它將發行版檔案傳送到裝置並使它們可供更新程式應用程式使用。 OEM 必須將此應用程式包含在使用該功能的裝置的系統映像中。
  • tzdatacheck ,時區更新的正確和安全操作所需的啟動時二進位。

Android 原始碼樹包含上述元件的通用原始碼,OEM 可以選擇使用而無需修改。提供測試程式碼以使 OEM 能夠自動檢查他們是否已正確啟用該功能。

發行版安裝

發行版安裝過程包括以下步驟:

  1. 數據應用程式透過應用程式商店下載或旁加載進行更新。系統伺服器進程(透過timezone.RulesManagerServer/timezone.PackageTracker類別)監視已配置的、特定於 OEM 的資料應用程式包名稱的變更。

    數據應用程式更新
    圖 1.數據應用程式更新
  2. 系統伺服器進程透過使用唯一的一次性令牌向更新程式應用程式廣播目標意圖來觸發更新檢查。系統伺服器追蹤它產生的最新令牌,以便確定它觸發的最近檢查何時完成;任何其他標記將被忽略。

    觸發更新
    圖 2.觸發器更新檢查
  3. 在更新檢查期間,更新程式應用程式執行以下任務:
    • 透過呼叫RulesManagerService查詢目前設備狀態。

      呼叫規則管理服務
      圖 3.資料應用程式更新,呼叫 RulesManagerService
    • 透過查詢明確定義的 ContentProvider URL 和列規範來查詢資料應用程序,以獲取有關發行版的資訊。

      取得發行版訊息
      圖 4.數據應用程式更新,獲取有關發行版的信息
  4. 更新程序應用程式根據其擁有的資訊採取適當的操作。可用的操作包括:
    • 請求安裝。發行版資料從資料應用程式讀取並傳遞到系統伺服器中的 RulesManagerService。 RulesManagerService 重新確認發行版格式版本和內容適合設備並分階段安裝。
    • 請求卸載(這種情況很少見)。例如,如果/data中更新的 APK 被停用或卸載,並且裝置將返回/system中存在的版本。
    • 沒做什麼。當發現資料應用發行版無效時發生。
    在所有情況下,Updater 應用程式都會使用檢查權杖呼叫 RulesManagerService,以便系統伺服器知道檢查已完成且成功。

    檢查完成
    圖 5.檢查完成
  5. 重新啟動並進行 tzdatacheck。當設備下次啟動時,tzdatacheck 二進位檔案將執行任何分階段操作。 tzdatacheck 二進位檔案可以執行下列任務:
    • 在其他系統元件開啟並開始使用/data/misc/zoneinfo/current檔案之前,透過處理這些檔案的建立、替換和/或刪除來執行分階段操作。
    • 檢查/data中的檔案對於目前平台版本是否正確,如果裝置剛剛收到系統更新且發行版格式版本已更改,則情況可能並非如此。
    • 確保 IANA 規則版本與/system中的版本相同或更高。這可以防止系統更新使設備留下比/system映像中存在的時區規則資料更舊的時區規則資料。

可靠性

端到端安裝過程是異步的,並分為三個作業系統進程。在安裝過程中的任何時候,設備都可能斷電、磁碟空間不足或遇到其他問題,導致安裝檢查不完整。在最好的不成功情況下,更新程式應用程式會通知系統伺服器它不成功;在最壞的不成功情況下,RulesManagerService 根本不會收到任何呼叫。

為了處理這個問題,系統伺服器程式碼會追蹤觸發的更新檢查是否已完成以及資料應用程式的最後檢查的版本代碼是什麼。當設備空閒和充電時,系統伺服器代碼可以檢查當前狀態。如果它發現更新檢查不完整或意外的Data App版本,它會自發性觸發更新檢查。

安全

啟用後,系統伺服器中的 RulesManagerService 程式碼會執行多項檢查以確保系統可以安全使用。

  • 表明系統映像配置錯誤導致設備無法啟動的問題;範例包括錯誤的更新程式或資料應用程式設定或更新程式或資料應用程式不在/system/priv-app中。
  • 表示安裝了錯誤資料應用程式的問題不會阻止裝置啟動,但會阻止觸發更新檢查;範例包括缺乏所需的系統權限或資料應用程式未在預期的 URI 上公開 ContentProvider。

/data/misc/zoneinfo目錄的檔案權限是使用 SELinux 規則強制執行的。與任何 APK 一樣,資料應用程式必須使用用於簽署/system/priv-app版本的相同金鑰進行簽署。數據應用程式預計將有一個專用的、特定於 OEM 的套件名稱和密鑰。

整合時區更新

若要啟用時區更新功能,OEM 通常:

  • 創建自己的數據應用程式。
  • 在系統映像建置中包含更新程式和資料應用程式。
  • 配置系統伺服器以啟用RulesManagerService。

準備中

在開始之前,原始設備製造商應檢查以下政策、品質保證和安全注意事項:

  • 為其資料應用程式建立專用的特定於應用程式的簽章金鑰。
  • 為時區更新建立發布和版本控制策略,以了解哪些裝置將要更新,以及如何確保更新僅安裝在需要更新的裝置上。例如,OEM 可能希望為其所有設備配備一個數據應用程序,或者可能選擇為不同的設備配備不同的數據應用程式。此決定會影響套件名稱的選擇,可能會影響所使用的版本代碼以及 QA 策略。
  • 了解他們是否想要使用 AOSP 提供的 Android 時區資料或建立自己的時區資料。

創建數據應用程式

AOSP 包含在packages/apps/TimeZoneData中建立資料應用程式所需的所有原始程式碼和建置規則,以及AndroidManifest.xml和位於packages/apps/TimeZoneData/oem_template中的其他檔案的說明和範例範本。範例範本包括真實資料應用程式 APK 的建置目標和用於建立資料應用程式測試版本的額外目標。

OEM 可以使用自己的圖示、名稱、翻譯和其他詳細資訊自訂資料應用程式。但是,由於無法啟動數據應用程序,該圖標僅出現在“設定”>“應用程式”畫面中。

資料應用程式旨在使用Tapas構建來構建,該構建會產生適合添加到系統映像(用於初始版本)並透過應用程式商店簽署和分發(用於後續更新)的 APK。有關使用 Tapas 的詳細信息,請參閱使用 Tapas 建立資料應用程式

OEM 必須在/system/priv-app中的裝置系統映像中安裝預先建置的資料應用程式。要在系統映像中包含預先建置的 APK(由 Tapas 建置過程產生),OEM 可以複製packages/apps/TimeZoneData/oem_template/data_app_prebuilt中的範例檔案。範例範本還包括用於在測試套件中包含資料應用程式的測試版本的建置目標。

在系統映像中包含更新程式和資料應用程式

OEM 必須將更新程式和資料應用程式 APK 放置在系統映像的/system/priv-app目錄中。為此,系統映像建置必須明確包含更新程式應用程式和資料應用程式預先建置目標。

更新程式應用程式應使用平台金鑰進行簽名,並與任何其他系統應用程式一樣包含在內。目標在packages/apps/TimeZoneUpdater中定義為TimeZoneUpdater 。資料應用程式包含特定於 OEM,並且取決於為預先建置選擇的目標名稱。

設定係統伺服器

若要啟用時區更新,OEM 可以透過覆寫frameworks/base/core/res/res/values/config.xml中定義的設定屬性來設定係統伺服器。

財產描述需要覆蓋嗎?
config_enableUpdateableTimeZoneRules
必須設為true才能啟用 RulesManagerService。是的
config_timeZoneRulesUpdateTrackingEnabled
必須設為true才能讓系統偵聽資料應用程式的變更。是的
config_timeZoneRulesDataPackage
OEM 特定資料應用程式的套件名稱。是的
config_timeZoneRulesUpdaterPackage
配置為預設更新程式應用程式。僅在提供不同的更新程式應用程式實作時才進行更改。
config_timeZoneRulesCheckTimeMillisAllowed
RulesManagerService 觸發更新檢查與安裝、解除安裝或不執行任何操作之間允許的時間。在這一點之後,可以產生自發性的可靠性觸發。
config_timeZoneRulesCheckRetryCount
RulesManagerService 停止產生更多檢查之前允許的連續不成功更新檢查的次數。

配置覆蓋應位於系統映像(而不是供應商或其他映像)中,因為配置錯誤的設備可能會拒絕啟動。如果配置覆蓋位於供應商映像中,則更新至沒有資料應用程式(或具有不同資料應用程式/更新程式應用程式套件名稱)的系統映像將被視為配置錯誤。

xTS測試

xTS 是指任何特定於 OEM 的測試套件,類似於使用 Tradefed 的標準 Android 測試套件(例如 CTS 和 VTS)。擁有此類測試套件的 OEM 可以添加以下位置提供的 Android 時區更新測試:

  • packages/apps/TimeZoneData/testing/xts包含基本自動化功能測試所需的程式碼。
  • packages/apps/TimeZoneData/oem_template/xts包含一個範例目錄結構,用於在類似 Tradefed 的 xTS 套件中包含測試。與其他模板目錄一樣,原始設備製造商 (OEM) 需要根據自己的需求進行複製和自訂。
  • packages/apps/TimeZoneData/oem_template/data_app_prebuilt包含建置時配置,用於包含測試所需的預先建置測試 APK。

建立時區更新

當 IANA 發布一組新的時區規則時,Android 核心庫團隊會產生修補程式以更新 AOSP 中的版本。使用庫存 Android 系統和發行版檔案的 OEM 可以取得這些提交,使用它們建立資料應用程式的新版本,然後發布新版本以更新生產中的裝置。

由於資料應用程式包含與 Android 版本密切相關的發行版文件,因此 OEM 必須為 OEM 想要更新的每個受支援的 Android 版本建立新版本的資料應用程式。例如,如果 OEM 想要為 Android 8.1、9 和 10 裝置提供更新,則必須完成該流程 3 次。

第 1 步:更新系統/時區和外部/icu 資料檔

在此步驟中,OEM 從 AOSP 中的release -dev 分支獲取system/timezoneexternal/icu的 Android 提交,並將這些提交套用到其 Android 原始碼副本。

system/timezone AOSP 修補程式包含system/timezone/input_datasystem/timezone/output_data中的更新檔案。需要進行其他本地修復的 OEM 可以修改輸入文件,然後使用system/timezone/input_dataexternal/icu中的文件在output_data中產生文件。

最重要的檔案是system/timezone/output_data/distro/distro.zip ,建構資料套用 APK 時會自動包含該檔案。

步驟2:更新資料應用程式的版本代碼

在此步驟中,OEM 會更新資料應用程式的版本代碼。建置會自動選擇distro.zip ,但新版本的資料應用程式必須具有新的版本代碼,以便將其識別為新版本,並用於替換預先載入的資料應用程式或透過先前的更新安裝在裝置上的數據應用程式.

當使用從package/apps/TimeZoneData/oem_template/data_app複製的檔案建立資料應用程式時,您可以在Android.mk中找到應用於 APK 的版本代碼/版本名稱:

TIME_ZONE_DATA_APP_VERSION_CODE :=
TIME_ZONE_DATA_APP_VERSION_NAME :=

類似的條目可以在testing/Android.mk中找到(但是測試版本程式碼必須高於系統鏡像版本)。詳細參考範例版本程式碼策略方案;如果使用範例方案或類似方案,則不需要更新測試版本程式碼,因為它們保證高於真實版本程式碼。

第 3 步:重建、簽名、測試和發布

在此步驟中,OEM 使用 Tapas 重建 APK,對產生的 APK 進行簽名,然後測試並發布 APK:

  • 對於未發布的裝置(或為已發布的裝置準備系統更新時),請在資料應用程式預先建置目錄中提交新的 APK,以確保系統映像和 xTS 測試具有最新的 APK。 OEM 應測試新檔案是否正常運作(即,它通過 CTS 和任何 OEM 特定的自動和手動測試)。
  • 對於不再接收系統更新的已發佈設備,簽署的 APK 可能只能透過應用程式商店發布。

OEM 負責品質保證並在發布之前在其設備上測試更新的數據應用程式。

資料app版本代碼策略

資料應用程式必須具有適當的版本控制策略,以確保裝置接收正確的 APK。例如,如果收到的系統更新包含比從應用程式商店下載的 APK 舊的 APK,則應保留應用程式商店版本。

APK版本代碼應包含以下資訊:

  • 發行版格式版本(主要+次要)
  • 遞增(不透明)的版本號

目前,平台 API 等級與發行版格式版本密切相關,因為每個 API 等級通常與新版本的 ICU 相關聯(這使得發行版檔案不相容)。將來,Android 可能會改變這一點,以便發行版檔案可以跨多個 Android 平台版本工作(並且在資料應用程式版本程式碼方案中不使用 API 層級)。

版本程式碼策略範例

此範例版本控制編號方案確保較高的發行版格式版本取代較低的發行版格式版本。 AndroidManifest.xml使用android:minSdkVersion來確保舊設備不會收到高於其處理能力的發行版格式版本。

版本檢查
圖 6.版本程式碼策略範例
例子價值目的
預訂的允許未來的替代方案/測試 APK。它最初(隱式)為 0。由於基礎類型是有符號 32 位元 int 類型,因此該方案最多支援兩個未來編號方案修訂版。
01主要格式版本追蹤 3 個十進制數字的主要格式版本。發行版格式支援 3 位十進制數字,但此處僅使用 2 位數字。考慮到每個 API 等級的預期主要增量,它不太可能達到 100。主要版本 1 相當於 API 等級 27。
1小格式版本追蹤 3 位十進制數字次要格式版本。發行版格式支援 3 位十進制數字,但此處僅使用 1 位數字。不太可能達到10。
X預訂的對於生產版本為 0(對於測試 APK 可能有所不同)。
ZZZZZ不透明版本號按需分配的十進制數。包括間隙,以便在需要時進行插頁式更新。

如果使用二進位而不是十進制,則該方案可以更好地打包,但該方案具有人類可讀的優點。如果用盡完整的數字範圍,資料應用程式套件名稱可能會變更。

版本名稱是人類可讀的詳細資訊表示形式,例如: major=001,minor=001,iana=2017a, revision=1,respin=2 。示例如下表所示。

#版本程式碼最小SdkVersion {主要格式版本}、{次要格式版本}、{IANA 規則版本}、{修訂版}
1 11000010 O-MR1主要=001,次要=001,iana=2017a,修訂=1
2 21000010主=002,次要=001,iana=2017a,修訂=1
3 11000020 O-MR1主要=001,次要=001,iana=2017a,修訂=2
4 11000030 O-MR1主要=001,次要=001,iana=2017b,修訂=1
5 21000020主=002,次要=001,iana=2017b,修訂=1
6 11000040 O-MR1主要=001,次要=001,iana=2018a,修訂=1
7 21000030主=002,次要=001,iana=2018a,修訂=1
8 1123456789 - -
9 11000021 O-MR1主=001,次要=001,iana=2017a,修訂=2,respin=2
  • 範例 1 和 2 顯示了同一 2017a IANA 版本的兩個 APK 版本,但主要格式版本不同。 2 在數值上高於 1,這是確保較新設備接收更高格式版本所必需的。 minSdkVersion 確保 P 版本不會提供給 O 裝置。
  • 範例 3 是範例 1 的修訂/修復,數值高於 1。
  • 範例 4 和 5 顯示了 O-MR1 和 P 的 2017b 版本。由於數字較高,它們取代了各自前身的先前 IANA 版本/Android 修訂版。
  • 範例 6 和 7 顯示了 O-MR1 和 P 的 2018a 版本。
  • 例8演示了使用Y完全替代Y=0方案。
  • 範例 9 示範如何使用 3 和 4 之間留下的間隙來重新旋轉 apk。

由於每個裝置在系統映像中都附帶了預設的、適當版本的 APK,因此不存在在 P 裝置上安裝 O-MR1 版本的風險,因為它的版本號低於 P 系統映像版本。在/data中安裝了 O-MR1 版本的設備,然後接收到 P 的系統更新時,會優先使用/system版本而不是/data中的O-MR1 版本,因為P 版本始終高於任何適用於O-的應用程式先生1。

使用 Tapas 建立數據應用程式

OEM 負責管理時區資料應用程式的大部分方面並正確配置系統映像。數據應用程式旨在使用Tapas構建進行構建,該構建生成適合添加到系統映像(用於初始版本)並透過應用程式商店簽署和分發(用於後續更新)的 APK。

Tapas是 Android 建置系統的精簡版本,它使用精簡的原始碼樹來產生應用程式的可分發版本。熟悉普通 Android 建置系統的 OEM 應該能夠識別來自普通 Android 平台建置的建置檔案。

建立清單

精簡的原始程式碼樹通常透過自訂清單檔案來實現,該檔案僅引用建置系統和建置應用程式所需的 Git 專案。在按照建立資料應用程式中的說明進行操作後,OEM 應該使用packages/apps/TimeZoneData/oem_template下的範本檔案建立至少兩個 OEM 特定的 Git 專案:

  • 一個 Git 專案包含應用程式文件,例如建立應用程式 APK 檔案所需的清單和建置檔案(例如, vendor/ oem /apps/TimeZoneData )。該專案還包含可供 xTS 測試使用的測試 APK 的建置規則。
  • 一個 Git 專案包含由應用程式建置產生的簽章 APK,以包含在系統映像建置和 xTS 測試中。

應用程式建置利用了與平台建置共享的其他幾個 Git 項目,或包含獨立於 OEM 的程式碼庫。

以下清單片段包含支援時區資料應用程式的 O-MR1 建置所需的最小 Git 項目集。 OEM 必須將其特定於 OEM 的 Git 項目(通常包括包含簽署憑證的項目)新增至此清單,並且可以相應地配置不同的分支。

   <!-- Tapas Build -->
    <project
        path="build"
        name="platform/build">
        <copyfile src="core/root.mk" dest="Makefile" />
    </project>
    <project
        path="prebuilts/build-tools"
        name="platform/prebuilts/build-tools"
        clone-depth="1" />
    <project
        path="prebuilts/go/linux-x86"
        name="platform/prebuilts/go/linux-x86"
        clone-depth="1" />
    <project
        path="build/blueprint"
        name="platform/build/blueprint" />
    <project
        path="build/kati"
        name="platform/build/kati" />
    <project
        path="build/soong"
        name="platform/build/soong">
        <linkfile src="root.bp" dest="Android.bp" />
        <linkfile src="bootstrap.bash" dest="bootstrap.bash" />
    </project>

    <!-- SDK for system / public API stubs -->
    <project
        path="prebuilts/sdk"
        name="platform/prebuilts/sdk"
        clone-depth="1" />
    <!-- App source -->
    <project
        path="system/timezone"
        name="platform/system/timezone" />
    <project
        path="packages/apps/TimeZoneData"
        name="platform/packages/apps/TimeZoneData" />
    <!-- Enable repohooks -->
    <project
        path="tools/repohooks"
        name="platform/tools/repohooks"
        revision="main"
        clone_depth="1" />
    <repo-hooks
        in-project="platform/tools/repohooks"
        enabled-list="pre-upload" />

運行 Tapas 構建

建立原始碼樹後,使用以下命令呼叫Tapas建構:

source build/envsetup.sh
tapas
make -j30 showcommands dist TARGET_BUILD_APPS='TimeZoneData TimeZoneData_test1 TimeZoneData_test2'  TARGET_BUILD_VARIANT=userdebug

成功的建置會在out/dist目錄中產生用於測試的檔案。這些檔案可以放入預先建置目錄中以包含在系統映像中和/或透過相容裝置的應用程式商店進行分發。