裝置端個人化功能 (ODP) 的設計宗旨,是要防止應用程式存取使用者資訊。應用程式會使用 ODP 為使用者自訂產品和服務,但無法查看為使用者進行的確切自訂項目 (除非應用程式與使用者之間在 ODP 以外有直接互動)。對於含有機器學習模型或統計分析的應用程式,ODP 提供一組服務和演算法,確保這些內容妥善完成去識別化,並使用適當的差異化隱私機制。詳情請參閱「裝置端個人化」相關說明。
ODP 會在 IsolatedProcess
中執行開發人員程式碼,該程式碼無法直接存取裝置上執行的網路、本機磁碟或其他服務,但可存取下列本機快取資料來源:
RemoteData
- 從開發人員營運的遠端後端下載的不可變鍵/值資料 (如適用)。LocalData
:開發人員在本機保留的可變動鍵/值資料 (如適用)。UserData
:平台提供的使用者資料。
支援下列輸出內容:
- 持久性輸出:這些輸出內容可用於日後的本機處理作業、產生顯示輸出內容、聯合學習輔助的模型訓練,或聯合數據分析輔助的跨裝置統計分析。
- 顯示的輸出內容:
- 開發人員可以在
SurfaceView
內的WebView
中,傳回由 ODP 算繪的 HTML。叫用應用程式不會看到在該處算繪的內容。 - 開發人員可以在 HTML 輸出內容中嵌入 ODP 提供的「事件網址」,藉此記錄和處理使用者與算繪的 HTML 之間的互動。ODP 會攔截對這些網址的要求,並叫用程式碼產生資料,然後將資料寫入
EVENTS
資料表。
- 開發人員可以在
用戶端應用程式和 SDK 可以叫用 ODP,使用 ODP API 在 SurfaceView
中顯示 HTML 內容。呼叫的應用程式無法查看 SurfaceView
中顯示的內容。用戶端應用程式或 SDK 可以是與使用 ODP 開發的實體不同。
ODP 服務會管理用戶端應用程式,讓應用程式能夠叫用 ODP,在 UI 中顯示個人化內容。它會從開發人員提供的端點下載內容,並叫用邏輯,以便對下載的資料進行後處理。也會調解 IsolatedProcess
與其他服務和應用程式之間的所有通訊。
用戶端應用程式使用 OnDevicePersonalizationManager
類別的方法,與在 IsolatedProcess
中執行的開發人員程式碼互動。在 IsolatedProcess
中執行的程式碼會擴充 IsolatedService
類別,並實作 IsolatedWorker
介面。IsolatedService
必須為每個要求建立 IsolatedWorker
的例項。
下圖顯示 OnDevicePersonalizationManager
和 IsolatedWorker
中的方法之間的關係。
OnDevicePersonalizationManager
和 IsolatedWorker
關係的圖表。用戶端應用程式會使用 execute
方法,搭配已命名的 IsolatedService
呼叫 ODP。ODP 服務將呼叫轉送至 IsolatedWorker
的 onExecute
方法。IsolatedWorker
會傳回要保存的記錄和要顯示的內容。ODP 服務會將持續性輸出內容寫入 REQUESTS
或 EVENTS
資料表,並將顯示輸出內容的半透明參照值傳回給用戶端應用程式。用戶端應用程式可以在日後的 requestSurfacePackage
呼叫中使用此半透明參照值,在其 UI 中顯示任何顯示內容。
持續性輸出
開發人員實作 onExecute
後,ODP 服務會在 REQUESTS
表格中持續保留記錄。REQUESTS
資料表中的每筆記錄都包含 ODP 服務產生的常見個別要求資料,以及傳回的 Rows
清單。每個 Row
都包含 (key, value)
組合的清單。每個值都是純量、字串或 blob。系統會在匯總完成後回報數值,並在套用本機或中央差異化隱私後回報字串或 blob 資料。開發人員也可以將後續使用者互動事件寫入 EVENTS
資料表,EVENTS
資料表中的每筆記錄都會與 REQUESTS
資料表中的一列建立關聯。ODP 服務會透過每筆記錄,公開記錄呼叫應用程式的時間戳記、套件名稱和 ODP 開發人員的 APK。
事前準備
開始使用 ODP 進行開發前,請先設定套件資訊清單並啟用開發人員模式。
套件資訊清單設定
如要使用 ODP,您必須具備下列條件:
AndroidManifest.xml
中的<property>
標記,指向套件中的 XML 資源,其中包含 ODP 設定資訊。AndroidManifest.xml
中的<service>
標記,用於識別擴充IsolatedService
的類別,如以下範例所示。<service>
標記中的服務必須將exported
和isolatedProcess
屬性設為true
。- 於步驟 1 指定的 XML 資源中的
<service>
標記,用於識別步驟 2 的服務類別。<service>
標記也必須在標記本身中加入其他 ODP 專屬設定,如第二個範例所示。
AndroidManifest.xml
<!-- Contents of AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.odpsample" >
<application android:label="OdpSample">
<!-- XML resource that contains other ODP settings. -->
<property android:name="android.ondevicepersonalization.ON_DEVICE_PERSONALIZATION_CONFIG"
android:resource="@xml/OdpSettings"></property>
<!-- The service that ODP binds to. -->
<service android:name="com.example.odpsample.SampleService"
android:exported="true" android:isolatedProcess="true" />
</application>
</manifest>
XML 資源中的 ODP 專屬資訊清單
<property>
標記中指定的 XML 資源檔案,也必須在 <service>
標記中宣告服務類別,並指定 ODP 會從中下載內容來填入 RemoteData
資料表的網址端點,如以下範例所示。如果您使用聯合運算功能,則必須一併指定聯合運算伺服器網址端點,供聯合運算用戶端連線。
<!-- Contents of res/xml/OdpSettings.xml -->
<on-device-personalization>
<!-- Name of the service subclass -->
<service name="com.example.odpsample.SampleService">
<!-- If this tag is present, ODP will periodically poll this URL and
download content to populate REMOTE_DATA. Developers that do not need to
download content from their servers can skip this tag. -->
<download-settings url="https://example.com/get" />
<!-- If you want to use federated compute feature to train a model, you
need to specify this tag. -->
<federated-compute-settings url="https://fcpserver.example.com/" />
</service>
</on-device-personalization>
啟用開發人員模式
按照 Android Studio 說明文件的「啟用開發人員選項」部分,啟用開發人員模式。
切換和旗標設定
ODP 提供一組切換鈕和旗標,可用於控制特定功能:
- _global_killswitch:所有 ODP 功能的通用切換鈕;設為 false 即可使用 ODP
- _federated_compute_kill_switch: _這個切換鈕可控制 ODP 的所有訓練 (聯合學習) 功能;將其設為 false 即可使用訓練
- _caller_app_allowlist:控管允許呼叫 ODP 的人員、應用程式 (pkg 名稱、[選填] 憑證) 可在這裡新增,或設為「*」全部允許
- _isolated_service_allowlist:控制哪些服務可以在 Isolated Service 程序中執行。
您可以執行下列指令,將所有切換鈕和旗標設為在不受限制的情況下使用 ODP:
# Set flags and killswitches
adb shell device_config set_sync_disabled_for_tests persistent
adb shell device_config put on_device_personalization global_kill_switch false
adb shell device_config put on_device_personalization federated_compute_kill_switch false
adb shell device_config put on_device_personalization caller_app_allow_list \"*\"
adb shell device_config put on_device_personalization isolated_service_allow_list \"*\"
裝置端 API
請參閱 ODP 的 Android API 參考說明文件。
與IsolatedService
的互動
IsolatedService
類別是抽象基本類別,所有打算針對 ODP 開發的開發人員都必須擴充此類別,並在套件資訊清單中宣告以隔離程序執行。ODP 服務會在獨立的程序中啟動這項服務,並對該服務發出要求。IsolatedService
會接收 ODP 服務的要求,並建立 IsolatedWorker
來處理要求。
開發人員必須實作來自 IsolatedWorker
介面的方法,才能處理用戶端應用程式要求、下載完成事件,以及由轉譯的 HTML 觸發的事件。所有這些方法都有預設的無操作實作項目,因此開發人員可以略過實作不感興趣的方法。
OnDevicePersonalizationManager
類別提供 API,可讓應用程式和 SDK 與開發人員在獨立程序中執行的 IsolatedService
互動。以下是一些預定用途:
產生要在 SurfaceView 中顯示的 HTML 內容
為了透過 OnDevicePersonalizationManager#execute
產生要顯示的內容,呼叫應用程式可在後續的 requestSurfacePackage
呼叫中使用傳回的 SurfacePackageToken
物件,要求在 SurfaceView
中顯示結果。
成功時,系統會針對 ODP 服務算繪的檢視畫面,使用 SurfacePackage
呼叫接收器。用戶端應用程式需要將 SurfacePackage
插入其檢視區塊階層中的 SurfaceView
。
當應用程式以先前 OnDevicePersonalizationManager#execute
呼叫傳回的 SurfacePackageToken
進行 requestSurfacePackage
呼叫時,ODP 服務會呼叫 IsolatedWorker#onRender
,擷取要在受限框架內轉譯的 HTML 片段。開發人員在這個階段無法存取 LocalData
或 UserData
。這可防止開發人員在產生的 HTML 中,將可能含有機密資訊的 UserData
嵌入素材資源擷取網址中。開發人員可以使用 IsolatedService#getEventUrlProvider
產生追蹤網址,並納入產生的 HTML 中。當 HTML 轉譯時,ODP 服務會攔截傳送至這些網址的要求,並呼叫 IsolatedWorker#onEvent
。實作 onRender()
時,可叫用 getRemoteData()
。
追蹤 HTML 內容中的事件
EventUrlProvider
類別提供的 API 可產生事件追蹤網址,開發人員可能會將此網址納入他們的 HTML 輸出內容中。顯示 HTML 時,ODP 會使用事件網址的酬載叫用 IsolatedWorker#onEvent
。
ODP 服務會從算繪的 HTML 中攔截向 ODP 產生的事件網址發出的要求、呼叫 IsolatedWorker#onEvent
,並將傳回的 EventLogRecord
記錄至 EVENTS
資料表。
寫入永久結果
透過 OnDevicePersonalizationManager#execute
,服務可以選擇將資料寫入永久性儲存空間 (REQUESTS
和 EVENTS
資料表)。以下是可寫入這些資料表的項目:
- 要新增至
REQUESTS
資料表的RequestLogRecord
。 - 要新增至
EVENTS
資料表的EventLogRecord
物件清單,每個物件都包含指向先前寫入的RequestLogRecord
的指標。
聯合學習技術可運用裝置端儲存空間的永久性進行模型訓練。
管理裝置端訓練工作
聯合運算訓練工作開始時,ODP 服務會呼叫 IsolatedWorker#onTrainingExample
,並希望取得採用 ODPv2 的開發人員提供的訓練範例。實作 onTrainingExample()
時,您可以叫用 getRemoteData()
、getLocalData()
、getUserData()
和 getLogReader()
。
如要安排或取消聯合運算工作,您可以使用為所有 ODP IsolatedService
提供 API 的 FederatedComputeScheduler
類別。每個聯合運算工作都可以透過其填充名稱進行識別。
排定新的聯合運算工作前,請先完成下列步驟:
- 遠端聯合運算伺服器上應已有名稱相同的工作。
- 套件資訊清單設定中應已使用
federated-compute-settings
標記指定聯合運算伺服器網址端點。
與永久輸出互動
以下章節說明如何與 ODP 中的永久輸出內容互動。
讀取本機資料表
LogReader
類別提供可讀取 REQUESTS
和 EVENTS
資料表的 API。這些資料表包含 IsolatedService
在 onExecute()
或 onEvent()
呼叫期間寫入的資料。這些資料表中的資料可用於聯合學習輔助的模型訓練,或是聯合數據分析輔助的跨裝置統計分析。
與下載內容的互動情形
以下章節說明如何在 ODP 中與下載內容互動。
從伺服器下載內容
ODP 服務會定期從 IsolatedService
套件資訊清單中宣告的網址下載內容,並在下載完成後呼叫 onDownloadCompleted
。下載檔是包含鍵/值組合的 JSON 檔案。
採用 ODP 後,開發人員可以選擇要將哪些下載內容子集新增至 RemoteData
資料表,並應將其捨棄。開發人員無法修改已下載的內容,這麼做可確保 RemoteData
資料表不含任何使用者資料。此外,開發人員可以在自己的選擇中自由填入 LocalData
資料表。例如,他們可以快取一些預先計算的結果。
下載要求格式
ODP 會定期輪詢開發人員套件資訊清單中宣告的網址端點,以擷取要填入 RemoteData
資料表的內容。
端點應會傳回 JSON 回應,詳情請參閱後文。JSON 回應必須包含 syncToken
,可識別傳送的資料版本,以及要填入的鍵/值組合清單。syncToken
值必須是以秒為單位的時間戳記,且限制為世界標準時間時差。在下載要求中,ODP 會提供先前完成下載的 syncToken
,以及裝置國家/地區做為下載網址中的 syncToken 和國家/地區參數。伺服器可以使用先前的 syncToken
實作遞增下載作業。
下載檔案格式
下載的檔案是 JSON 檔案,具有下列結構。JSON 檔案應包含 syncToken,用於識別要下載的資料版本。syncToken 必須是世界標準時間的時間戳記,且必須超過上次下載的 syncToken。如果 syncToken 不符合上述兩項規定,系統就會捨棄下載的內容,而不會進行處理。
內容欄位是 (鍵、資料、編碼) 元組的清單。key
應為 UTF-8 字串。encoding
欄位是選用參數,用於指定 data
欄位的編碼方式。該欄位可設為「utf8」或「base64」,且預設會假設為「utf8」。key
欄位會轉換為 String
物件,而 data
欄位會在呼叫 onDownloadCompleted().
之前轉換為位元組陣列
{
// syncToken must be a UTC timestamp clamped to an hour boundary, and must be
// greater than the syncToken of the previously completed download.
"syncToken": <timeStampInSecRoundedToUtcHour>,
"contents": [
// List of { key, data } pairs.
{ "key": "key1",
"data": "data1"
},
{ "key": "key2",
"data": "data2",
"encoding": "base64"
},
// ...
]
}
伺服器端 API
本節說明如何與聯合運算伺服器 API 互動。
Federated Compute Server API
如要在用戶端排定聯合運算工作,您需要在遠端聯合運算伺服器上建立具有填充名稱的任務。在本節中,我們將說明如何在聯合運算伺服器上建立這類工作。
為工作單元建立新工作時,ODP 開發人員應提供兩組檔案:
- 透過呼叫 tff.learning.models.save_functional_model API 呼叫儲存的 tff.learning.models.FunctionalModel 模型。您可以在 GitHub 存放區中找到一個範例。
- 包含政策、聯合學習設定和差異化隱私設定的 fcp_server_config.json。以下是 fcp_server_config.json 的範例:
{
# Task execution mode.
mode: TRAINING_AND_EVAL
# Identifies the set of client devices that participate.
population_name: "mnist_cnn_task"
policies {
# Policy for sampling on-device examples. It is checked every
# time a device is attempting to start a new training.
min_separation_policy {
# The minimum separation required between two successful
# consective task executions. If a client successfully contributes
# to a task at index `x`, the earliest they can contribute again
# is at index `(x + minimum_separation)`. This is required by
# DP.
minimum_separation: 1
}
data_availability_policy {
# The minimum number of examples on a device to be considered
# eligible for training.
min_example_count: 1
}
# Policy for releasing training results to developers adopting ODP.
model_release_policy {
# The maximum number of training rounds.
num_max_training_rounds: 512
}
}
# Federated learning setups. They are applied inside Task Builder.
federated_learning {
# Use federated averaging to build federated learning process.
# Options you can choose:
# * FED_AVG: Federated Averaging algorithm
# (https://arxiv.org/abs/2003.00295)
# * FED_SGD: Federated SGD algorithm
# (https://arxiv.org/abs/1602.05629)
type: FED_AVG
learning_process {
# Optimizer used at client side training. Options you can choose:
# * ADAM
# * SGD
client_optimizer: SGD
# Learning rate used at client side training.
client_learning_rate: 0.02
# Optimizer used at server side training. Options you can choose:
# * ADAM
# * SGD
server_optimizer: SGD
# Learning rate used at server side training.
server_learning_rate: 1.0
runtime_config {
# Number of participating devices for each round of training.
report_goal: 2
}
metrics {
name: "sparse_categorical_accuracy"
}
}
evaluation {
# A checkpoint selector controls how checkpoints are chosen for
# evaluation. One evaluation task typically runs per training
# task, and on each round of execution, the eval task
# randomly picks one checkpoint from the past 24 hours that has
# been selected for evaluation by these rules.
# Every_k_round and every_k_hour are definitions of quantization
# buckets which each checkpoint is placed in for selection.
checkpoint_selector: "every_1_round"
# The percentage of a populate that should delicate to this
# evaluation task.
evaluation_traffic: 0.2
# Number of participating devices for each round of evaluation.
report_goal: 2
}
}
# Differential Privacy setups. They are enforced inside the Task
# Builder.
differential_privacy {
# * fixed_gaussian: DP-SGD with fixed clipping norm described in
# "Learning Differentially Private Recurrent
# Language Models"
# (https://arxiv.org/abs/1710.06963).
type: FIXED_GAUSSIAN
# The value of the clipping norm.
clip_norm: 0.1
# Noise multiplier for the Gaussian noise.
noise_multiplier: 0.1
}
}
您可以在 GitHub 存放區中找到更多範例。
準備好這兩項輸入內容後,請叫用工作單元建立器來建構構件,並產生新的工作。您可以在 GitHub 存放區中找到更詳細的操作說明。