時區規則

機器人10棄用基於APK-時區數據更新機構(Android中8.1和Android 9提供),並用其替換基於APEX-模塊更新機制。 AOSP 繼續包含 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)

在 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文件。
  • 在ICU4J / ICU4C庫代碼external/icu/使用ICU .dat文件。

這些庫跟踪覆蓋文件可能存在於/data/misc/zoneinfo/current目錄。覆蓋的文件被認為含有改進的時區規則數據,從而使得能夠在不改變被更新設備/system

需要時區規則數據的Android系統組件首先檢查以下位置:

  • libcore/bionic/代碼中使用/data的拷貝tzdatatzlookup.xml文件。
  • ICU4J / ICU4C代碼使用中的文件/data並回退到/system對於不存在數據文件(格式,本地化字符串等)。

發行版文件

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

發行版文件格式取決於 Android 版本,因為內容會隨著 ICU 版本、Android 平台要求和其他版本的變化而變化。 Android 為每個 IANA 更新(除了更新平台系統文件)提供支持的 Android 版本的發行版文件。為了使他們的設備保持最新,OEM 可以使用這些發行版文件或使用 Android 源代碼樹(其中包含生成發行版文件所需的腳本和其他文件)創建自己的發行版文件。

時區更新組件

時區規則更新涉及將發行版文件傳輸到設備以及安全安裝其中包含的文件。傳輸和安裝需要以下內容:

  • 平台服務功能( timezone.RulesManagerService ),默認情況下是禁用的。 OEM 必須通過配置啟用該功能。 RulesManagerService系統中的服務器進程和階段時區更新操作運行通過寫/data/misc/zoneinfo/stagedRulesManagerService也可以替換或刪除已經上演操作。
  • TimeZoneUpdater ,一個nonupdateable系統的應用程序(又名更新應用程序)。 OEM 必須將此應用包含在使用該功能的設備的系統映像中。
  • OEM TimeZoneData ,一個可更新的系統的應用程序(也稱為數據應用)攜帶發行文件到設備,使它們可用於更新的應用程序。 OEM 必須將此應用包含在使用該功能的設備的系統映像中。
  • tzdatacheck ,為的時區更新的正確和安全操作所需的啟動時間二進制。

Android 源代碼樹包含上述組件的通用源代碼,OEM 可以選擇使用而無需修改。測試代碼提供給原始設備製造商能夠自動檢查,他們已經正確啟用該功能。

發行版安裝

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

  1. 數據應用程序通過應用程序商店下載或側向載荷更新。系統服務器進程(通過timezone.RulesManagerServer/timezone.PackageTracker班)手錶更改所配置的,OEM專用,數據應用程序包的名稱。

    數據應用更新
    圖1.數據應用程序更新
  2. 該服務器處理的觸發器通過廣播進行更新檢查,有針對性的意圖與令牌的更新應用了獨特的,一次性使用。系統服務器會跟踪它生成的最新令牌,以便它可以確定它觸發的最新檢查何時完成;任何其他標記都將被忽略。

    觸發更新
    圖2.觸發更新檢查
  3. 在更新過程中檢查,更新應用程序將執行以下任務:
    • 通過調用 RulesManagerService 查詢當前設備狀態。

      調用規則管理器服務
      圖3.數據更新應用,調用RulesManagerService
    • 通過查詢明確定義的 ContentProvider URL 和列規範來查詢 Data 應用程序以獲取有關發行版的信息。

      獲取發行信息
      圖4.數據的應用程序更新,獲取有關發行信息
  4. 在更新應用程序需要基於它的信息的適當行動。可用的操作包括:
    • 請求安裝。 Distro 數據從 Data 應用程序中讀取並傳遞給系統服務器中的 RulesManagerService。 RulesManagerService 再次確認發行版格式版本和內容適合設備並分階段安裝。
    • 要求卸載(這是罕見的)。例如,如果更新的APK在/data正在被禁用或卸載,該裝置返回到存在於該版本/system
    • 沒做什麼。當發現 Data 應用發行版無效時發生。
    在所有情況下,更新程序應用程序都會使用檢查令牌調用 RulesManagerService,以便系統服務器知道檢查已完成並成功。

    檢查完成
    圖5.檢查完成
  5. 重新啟動和 tzdatacheck。當設備下次啟動時,tzdatacheck 二進製文件會執行任何分階段操作。 tzdatacheck 二進製文件可以執行以下任務:
    • 執行由處理創建,更換新的分期手術,和/或刪除/data/misc/zoneinfo/current其它系統組件已經打開,並開始使用文件之前的文件。
    • 檢查中的文件/data是在當前平台的版本,如果設備剛剛收到系統更新和發行格式版本已經改變可能並非如此正確。
    • 確保IANA規則版本相同或較新的版本/system 。這可以防止在系統更新離開設備與舊的時區規則數據比存在於/system的圖像。

可靠性

端到端安裝過程是異步的,並且分為三個 OS 進程。在安裝過程中的任何時候,設備可能會斷電、磁盤空間不足或遇到其他問題,導致安裝檢查不完整。在最好的不成功情況下,Updater 應用程序會通知系統服務器它不成功;在最不成功的情況下,RulesManagerService 根本不會收到任何調用。

為了解決這個問題,系統服務器代碼會跟踪觸發的更新檢查是否已完成以及最後檢查的數據應用程序的版本代碼是什麼。當設備空閒和充電時,系統服務器代碼可以檢查當前狀態。如果它發現不完整的更新檢查或意外的數據應用程序版本,它會自發地觸發更新檢查。

安全

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

  • 表明系統映像配置錯誤的問題會阻止設備啟動;實例包括壞更新程序或數據的應用程序的配置或更新程序或數據的應用程序不是在/system/priv-app
  • 表明安裝了錯誤數據應用程序的問題不會阻止設備啟動,但會阻止觸發更新檢查;示例包括缺乏所需的系統權限或數據應用程序未在預期的 URI 上公開 ContentProvider。

對於文件的權限/data/misc/zoneinfo目錄正在使用SELinux的規則執行。正如任何APK,數據的應用程序必須使用簽署同樣的密鑰簽名/system/priv-app版本。預計數據應用程序將具有專用的、特定於 OEM 的包名稱和密鑰。

集成時區更新

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

  • 創建自己的數據應用程序。
  • 在系統映像構建中包含更新程序和數據應用程序。
  • 配置系統服務器啟用RulesManagerService。

準備

在開始之前,OEM 應審查以下政策、質量保證和安全注意事項:

  • 為其數據應用程序創建專用的應用程序特定簽名密鑰。
  • 為時區更新創建發布和版本控制策略,以了解將更新哪些設備以及它們如何確保更新僅安裝在需要它們的設備上。例如,OEM 可能希望為其所有設備使用一個數據應用程序,或者可能選擇為不同設備使用不同的數據應用程序。該決定會影響包名稱的選擇、可能使用的版本代碼和 QA 策略。
  • 了解他們是要使用來自 AOSP 的庫存 Android 時區數據還是創建自己的時區數據。

創建數據應用

AOSP包括建立在數據的應用程序所需的所有源代碼和生成規則packages/apps/TimeZoneData ,有說明書和示例模板AndroidManifest.xml ,位於其他文件packages/apps/TimeZoneData/oem_template 。示例模板包括用於真實數據應用 APK 的構建目標和用於創建數據應用測試版本的額外目標。

OEM 可以使用自己的圖標、名稱、翻譯和其他詳細信息自定義數據應用程序。然而,隨著數據的應用程序無法啟動,圖標只出現在設置>應用屏幕。

數據的應用程序的目的是用一個小吃構建產生適合於被加入到系統中的圖像(初始版本),並通過一個應用程序商店(用於隨後的更新)簽名並分發的APK來構建。有關使用小吃的詳細信息,請參閱大廈使用小吃的數據應用

原始設備製造商必須在設備中的系統映像安裝數據應用預建/system/priv-app 。到包括在系統中的圖像的預建的APK(由小吃構建過程中產生),OEM可以在複製的示例文件packages/apps/TimeZoneData/oem_template/data_app_prebuilt 。示例模板還包括用於在測試套件中包含數據應用程序的測試版本的構建目標。

在系統映像中包含更新程序和數據應用程序

原始設備製造商必須將更新和數據應用的APK在/system/priv-app的系統映像的目錄。為此,系統映像構建必須明確包含更新程序應用程序和數據應用程序預構建目標。

更新程序應用程序應使用平台密鑰進行簽名,並與任何其他系統應用程序一樣包含在內。目標是定義packages/apps/TimeZoneUpdater作為TimeZoneUpdater 。數據應用程序包含特定於 OEM,並取決於為預構建選擇的目標名稱。

配置系統服務器

啟用時區更新,原始設備製造商可以通過重寫在定義的配置屬性來配置系統服務器frameworks/base/core/res/res/values/config.xml

財產描述需要覆蓋嗎?
config_enableUpdateableTimeZoneRules
必須設置為true ,以使RulesManagerService。是的
config_timeZoneRulesUpdateTrackingEnabled
必須設置為true讓系統監聽更改數據的應用程序。是的
config_timeZoneRulesDataPackage
OEM 特定數據應用程序的包名稱。是的
config_timeZoneRulesUpdaterPackage
為默認更新程序應用程序配置。僅在提供不同的 Updater 應用實現時更改。
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版本的發行文件,原始設備製造商必須創建數據的應用程序為每個支持的Android版本,一個OEM想要更新的新版本。例如,如果 OEM 想要為 Android 8.1、9 和 10 設備提供更新,他們必須完成該過程 3 次。

步驟 1:更新系統/時區和外部/icu 數據文件

在這一步中,原始設備製造商採取普通的Android提交的system/timezoneexternal/icu從AOSP釋放-dev分支機構和適用這些提交自己的Android源代碼的副本。

該系統/時區AOSP補丁包含更新的文件中system/timezone/input_datasystem/timezone/output_data 。原始設備製造商誰需要進行額外的局部修復可以修改輸入文件,然後使用文件system/timezone/input_dataexternal/icu生成的文件output_data

最重要的文件是system/timezone/output_data/distro/distro.zip ,數據應用APK建時會自動包含在內。

第 2 步:更新 Data 應用程序的版本代碼

在此步驟中,OEM 更新數據應用程序的版本代碼。構建自動拿起distro.zip ,但因此它認為是新的,使用由以前的更新替換安裝在設備上預加載的數據應用或數據的應用程序數據的應用程序的新版本必須有一個新版本的代碼。

當構建使用從複製文件中的數據的應用程序package/apps/TimeZoneData/oem_template/data_app ,你可以找到的版本代碼/版本名稱應用到的APK Android.mk

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 負責質量保證並在發布前在其設備上測試更新的 Data 應用程序。

數據應用版本代碼策略

該數據的應用程序必須有一個合適的版本管理策略,以確保設備接收正確的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 。示例如下表所示。

#版本代碼最小SDK版本{主要格式版本}、{次要格式版本}、{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,revision=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 系統映像版本。與安裝在一O形MR1版本的裝置/data其然後接收系統更新至P使用/system優先於O形MR1版本中版本/data因為P版本總是高於任何應用程序用於O- MR1。

使用 Tapas 構建數據應用程序

OEM 負責管理時區數據應用程序的大部分方面並正確配置系統映像。數據的應用程序的目的是用一個小吃構建產生適合於被加入到系統中的圖像(初始版本),並通過一個應用程序商店(用於隨後的更新)簽名並分發的APK來構建。

小吃是簡裝使用減少的源代碼樹產生的應用程序的分發版本的Android構建系統的版本。熟悉正常 Android 構建系統的 OEM 應該識別來自正常 Android 平台構建的構建文件。

創建清單

簡化的源代碼樹通常使用自定義清單文件來實現,該文件僅引用構建系統和構建應用程序所需的 Git 項目。按照指令後創建數據的應用程序,原始設備製造商應該有使用下的模板文件創建至少兩個OEM特定的Git項目packages/apps/TimeZoneData/oem_template

  • 一個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="master"
        clone_depth="1" />
    <repo-hooks
        in-project="platform/tools/repohooks"
        enabled-list="pre-upload" />

運行小吃構建

源代碼樹建立後,調用小吃使用下面的命令進行編譯:

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

一個成功的構建在生成文件out/dist測試目錄。這些文件可以放在 prebuilts 目錄中以包含在系統映像中和/或通過兼容設備的應用程序商店分發。