裝置端個人化開發人員指南

裝置端個人化功能 (ODP) 的設計宗旨,是要防止應用程式存取使用者資訊。應用程式會使用 ODP 為使用者自訂產品和服務,但無法查看為使用者進行的確切自訂項目 (除非應用程式與使用者之間在 ODP 以外有直接互動)。對於含有機器學習模型或統計分析的應用程式,ODP 提供一組服務和演算法,確保這些內容妥善完成去識別化,並使用適當的差異化隱私機制。詳情請參閱「裝置端個人化功能」說明。

ODP 會在 IsolatedProcess 中執行開發人員程式碼,該程式碼無法直接存取網路、本機磁碟或裝置上執行的其他服務,但可存取下列本機快取資料來源:

  • RemoteData:從遠端下載的不可變動鍵/值資料 (如果適用),由開發人員操作的後端。
  • LocalData:開發人員在本機保留的可變動鍵/值資料 (如適用)。
  • UserData:平台提供的使用者資料。

支援以下輸出內容:

  • 持久性輸出:這些輸出內容可用於日後的本機處理作業、產生顯示輸出內容、聯合學習輔助的模型訓練,或聯合數據分析輔助的跨裝置統計分析。
    • 開發人員可以將要求和處理結果寫入本機 REQUESTS 資料表。
    • 開發人員可以將與先前要求相關聯的其他資料寫入 EVENTS 資料表。
  • 顯示的輸出內容:
    • 開發人員可以傳回由 ODP 在 SurfaceView 內的 WebView 中轉譯的 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 例項。

下圖顯示 OnDevicePersonalizationManagerIsolatedWorker 中方法之間的關係。

OnDevicePersonalizationManagerIsolatedWorker 之間的關係圖表。

用戶端應用程式會使用名為 IsolatedServiceexecute 方法呼叫 ODP。ODP 服務會將呼叫轉送至 IsolatedWorkeronExecute 方法。IsolatedWorker 會傳回要保存的記錄和要顯示的內容。ODP 服務會將持續性輸出內容寫入 REQUESTSEVENTS 資料表,並將顯示輸出內容的非透明參照值傳回給用戶端應用程式。用戶端應用程式可以在日後的 requestSurfacePackage 呼叫中使用這個非透明參照值,在其 UI 中顯示任何顯示內容。

持續性輸出

開發人員實作 onExecute 後,ODP 服務會在 REQUESTS 表格中儲存記錄。REQUESTS 資料表中的每筆記錄都包含 ODP 服務產生的常見個別要求資料,以及傳回的 Rows 清單。每個 Row 都包含 (key, value) 組合的清單。每個值都是純量、字串或 blob。系統可在匯總後回報數值,並在套用區域或中央差異化隱私技術後回報字串或 Blob 資料。開發人員也可以將後續使用者互動事件寫入 EVENTS 資料表,EVENTS 資料表中的每筆記錄都會與 REQUESTS 資料表中的一列建立關聯。ODP 服務會在每個記錄中,以公開的方式記錄時間戳記、呼叫應用程式的套件名稱,以及 ODP 開發人員的 APK。

事前準備

開始使用 ODP 進行開發前,請先設定套件資訊清單並啟用開發人員模式。

套件資訊清單設定

如要使用 ODP,您必須具備下列條件:

  1. AndroidManifest.xml 中的 <property> 標記,指向套件中的 XML 資源,其中包含 ODP 設定資訊。
  2. AndroidManifest.xml 中的 <service> 標記,用於識別擴充 IsolatedService 的類別,如以下範例所示。<service> 標記中的服務必須將 exportedisolatedProcess 屬性設為 true
  3. 在步驟 1 中指定的 XML 資源中,用於識別步驟 2 中服務類別的 <service> 標記。<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 說明文件中「Enable Developer Options」部分的操作說明,啟用開發人員模式。

切換和旗標設定

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 中顯示結果。

成功時,接收器會透過 SurfacePackage 呼叫 ODP 服務所轉譯的 View。用戶端應用程式需要將 SurfacePackage 插入其檢視區塊階層中的 SurfaceView

當應用程式以先前 OnDevicePersonalizationManager#execute 呼叫傳回的 SurfacePackageToken 進行 requestSurfacePackage 呼叫時,ODP 服務會呼叫 IsolatedWorker#onRender,擷取要在受限框架內轉譯的 HTML 片段。開發人員在此階段無法存取 LocalDataUserData。這可防止開發人員在產生的 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,服務可以選擇將資料寫入永久性儲存空間 (REQUESTSEVENTS 資料表)。以下是可寫入這些資料表的項目:

  • 要新增至 REQUESTS 資料表的 RequestLogRecord
  • 要新增至 EVENTS 資料表的 EventLogRecord 物件清單,每個物件都包含指向先前寫入的 RequestLogRecord 的指標。

聯合學習可使用裝置端儲存空間中的永久結果來訓練模型。

管理裝置端訓練工作

聯合運算訓練工作開始時,ODP 服務會呼叫 IsolatedWorker#onTrainingExample,並希望取得採用 ODPv2 的開發人員提供的訓練範例。實作 onTrainingExample() 時,您可以叫用 getRemoteData()getLocalData()getUserData()getLogReader()

如要排定或取消聯合運算工作,您可以使用 FederatedComputeScheduler 類別,該類別會為所有 ODP IsolatedService 提供 API。每個聯合運算工作都可以透過其填充名稱進行識別。

排定新的聯合運算工作前:

  • 在遠端聯合運算伺服器上,應已建立具有此填充名稱的工作。
  • 您應該已在套件資訊清單設定中使用 federated-compute-settings 標記指定聯合運算伺服器網址端點。

與持續性輸出的互動

以下章節將說明如何在 ODP 中與持續性輸出內容互動。

讀取本機資料表

LogReader 類別提供可讀取 REQUESTSEVENTS 資料表的 API。這些資料表包含 IsolatedServiceonExecute()onEvent() 呼叫期間寫入的資料。這些資料表中的資料可用於聯合學習輔助的模型訓練,或是聯合數據分析輔助的跨裝置統計分析。

與下載內容互動

以下章節將說明如何在 ODP 中與下載的內容互動。

從伺服器下載內容

ODP 服務會定期從 IsolatedService 的套件資訊清單中宣告的網址下載內容,並在下載完成後呼叫 onDownloadCompleted。下載內容是包含鍵/值組合的 JSON 檔案。

採用 ODP 的開發人員可以選擇要將下載內容的哪些子集新增至 RemoteData 資料表,以及要捨棄哪些子集。開發人員無法修改下載的內容,確保 RemoteData 表格不含任何使用者資料。此外,開發人員可以自由填入 LocalData 資料表,例如,他們可以快取一些預先計算的結果。

下載要求格式

ODP 會定期輪詢開發人員套件資訊清單中宣告的網址端點,擷取內容並填入 RemoteData 資料表。

端點應傳回 JSON 回應,如後文所述。JSON 回應必須包含 syncToken,用於識別要傳送的資料版本,以及要填入的鍵/值組合清單。syncToken 值必須是以秒為單位的時間戳記,且會以世界標準時間 (UTC) 的每小時邊界為準。在下載要求中,ODP 會提供先前完成下載的 syncToken,以及裝置國家/地區做為下載網址中的 syncToken 和國家/地區參數。伺服器可以使用先前的 syncToken 實作遞增下載作業。

下載檔案格式

下載的檔案是 JSON 檔案,具有下列結構。JSON 檔案應包含 syncToken,以便識別要下載的資料版本。syncToken 必須是世界標準時間的時間戳記,且必須超過上次下載的 syncToken。如果 syncToken 不符合上述兩項規定,系統就會捨棄下載的內容,而不會進行處理。

內容欄位是 (鍵、資料、編碼) 元組的清單。key 應為 UTF-8 字串。encoding 欄位是選用參數,可指定 data 欄位的編碼方式。您可以將該欄位設為「utf8」或「base64」,且預設為「utf8」。呼叫 onDownloadCompleted(). 之前,key 欄位會轉換為 String 物件,而 data 欄位會轉換為位元組陣列

{
  // 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 開發人員應提供兩組檔案:

  1. 透過呼叫 tff.learning.models.save_functional_model API 呼叫,儲存的 tff.learning.models.FunctionalModel 模型。您可以在 GitHub 存放區中找到一個範例
  2. 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 存放區。