On-Device Personalization (ODP) is designed to protect end users' information from applications. Applications use ODP to customize their products and services for end users, but they won't be able to see the exact customizations made for the user (unless there are direct interactions outside of ODP between the application and the end user). For applications with machine learning models or statistical analyses, ODP provides a set of services and algorithms to ensure that they are properly anonymized using the appropriate Differential Privacy mechanisms. For further details, see the explainer on On-Device Personalization.
ODP runs developer code in an IsolatedProcess which has no direct access to the network, local disks or other services running on the device but has access to the following locally persisted data sources:
RemoteData- Immutable key-value data downloaded from remote, developer operated backends, if applicable.LocalData- Mutable key-value data locally persisted by the developer, if applicable.UserData- User data provided by the platform.
The following outputs are supported:
- Persistent output: These outputs can be used in future local processing, producing displayed outputs, Federated Learning facilitated model training, or Federated Analytics facilitated cross-device statistical analysis.
- Displayed output:
- Developers can return HTML that is rendered by ODP in a
WebViewinside aSurfaceView. The content rendered there won't be visible to the invoking app. - Developers can embed ODP-provided Event URLs within the HTML output to trigger the logging and processing of user interactions with the rendered HTML. ODP intercepts requests to those URLs and invokes code to generate data that gets written to the
EVENTStable.
- Developers can return HTML that is rendered by ODP in a
Client apps and SDKs can invoke ODP to display HTML content in a SurfaceView using ODP APIs. Content rendered in a SurfaceView is not visible to the calling app. The client app or SDK can be a different entity than the one developing with ODP.
The ODP service manages the client app that wishes to invoke ODP to show personalized content within its UI. It downloads content from developer provided endpoints and invokes logic for postprocessing of the downloaded data. It also mediates all communications between the IsolatedProcess and other services and apps.
Client apps use methods in the OnDevicePersonalizationManager class to interact with the developer's code running in an IsolatedProcess. Developer's code running in an IsolatedProcess extends the IsolatedService class and implements the IsolatedWorker interface. The IsolatedService needs to create an instance of IsolatedWorker for each request.
The following diagram shows the relationship between the methods in OnDevicePersonalizationManager and IsolatedWorker.
OnDevicePersonalizationManager and IsolatedWorker.A client app calls ODP using the execute method with a named IsolatedService. The ODP service forwards the call to the onExecute method of the IsolatedWorker. The IsolatedWorker returns records to be persisted and content to be displayed. The ODP service writes the persistent output to the REQUESTS or EVENTS table, and returns an opaque reference to the displayed output to the client app. The client app can use this opaque reference in a future requestSurfacePackage call to display any of the display content within its UI.
Persistent output
The ODP service persists a record in the REQUESTS table after the developer's implementation of onExecute returns. Each record in the REQUESTS table contains some common per-request data generated by the ODP service, and a list of Rows returned. Each Row contains a list of (key, value) pairs. Each value is a scalar, String or blob. The numeric values can be reported after aggregation, and the string or blob data can be reported after applying local or central Differential Privacy. Developers can also write subsequent user interaction events to the EVENTS table—each record in the EVENTS table is associated with a row in the REQUESTS table. The ODP service transparently logs a timestamp and the package name of the calling app and the ODP developer's APK with each record.
Before you begin
Before you begin developing with ODP, you need to set up your package manifest and enable developer mode.
Package manifest settings
To use ODP the following is required:
- A
<property>tag inAndroidManifest.xmlthat points to an XML resource in the package that contains ODP configuration information. - A
<service>tag inAndroidManifest.xmlthat identifies the class that extendsIsolatedService, as shown in the following example. The service in the<service>tag must have the attributesexportedandisolatedProcessset totrue. - A
<service>tag in the XML resource specified in Step 1 that identifies the service class from Step 2. The<service>tag must also include additional ODP-specific settings inside the tag itself, as shown in the second example.
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>
ODP-Specific Manifest in XML Resource
The XML resource file specified in the <property> tag must also declare the service class in a <service> tag, and specify the URL endpoint from which ODP will download content to populate the RemoteData table, as shown in the following example. If you are using the federated compute features, you also need to specify the federated compute server URL endpoint to which the federated compute Client will connect.
<!-- 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>
Enable Developer Mode
Enable developer mode by following the instructions in the Enable Developer Options section of the Android Studio documentation.
Switch and Flag settings
ODP has a set of switches and flags that are used to control certain functionalities:
- _global_killswitch: the global switch for all ODP features; set to false to use ODP
- _federated_compute_kill_switch: _the switch controlling all training (federated learning) functionalities of ODP; set to false to use training
- _caller_app_allowlist: controls who is allowed to call ODP, apps (pkg name, [optional] certificate) can be added here or set it as * to allow all
- _isolated_service_allowlist: controls which services can run in the Isolated Service process.
You can run the following commands to configure all switches and flags to use ODP without restrictions:
# 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 \"*\"
Device-side APIs
Check out the Android API reference documentation for ODP.
Interactions with IsolatedService
The IsolatedService class is an abstract base class that all developers intending to develop against ODP must extend, and declare in their package manifest as running in an isolated process. The ODP service starts this service in an isolated process and makes requests to it. The IsolatedService receives requests from the ODP service and creates an IsolatedWorker to handle the request.
Developers need to implement the methods from the IsolatedWorker interface to handle client app requests, download completions, and events triggered by the rendered HTML. All these methods have default no-op implementations, so developers can skip implementing the methods that they are not interested in.
The OnDevicePersonalizationManager class provides an API for apps and SDKs to interact with a developer-implemented IsolatedService running in an isolated process. The following are some intended use cases:
Generate HTML content to display in a SurfaceView
To generate content to display, with OnDevicePersonalizationManager#execute, the calling app can use the returned SurfacePackageToken object in a subsequent requestSurfacePackage call to request the result to be rendered in a SurfaceView .
On success, the receiver is called with a SurfacePackage for a View rendered by the ODP service. Client applications need to insert the SurfacePackage into a SurfaceView within their View hierarchy.
When an app makes a requestSurfacePackage call with a SurfacePackageToken returned by a prior OnDevicePersonalizationManager#execute call the ODP service calls IsolatedWorker#onRender to fetch the HTML snippet to be rendered within a fenced frame. A developer does not have access to LocalData or UserData during this phase. This prevents the developer from embedding potentially sensitive UserData within asset fetch URLs in the generated HTML. Developers can use IsolatedService#getEventUrlProvider to generate tracking URLs to include in the generated HTML. When the HTML is rendered, the ODP service will intercept requests to these URLs and call IsolatedWorker#onEvent. One can invoke getRemoteData() when implementing onRender().
Track events within HTML content
The EventUrlProvider class provides APIs to generate event tracking URLs that developers may include in their HTML output. When the HTML is rendered, ODP will invoke IsolatedWorker#onEvent with the payload of the event URL.
The ODP service intercepts requests to ODP generated event URLs within the rendered HTML, calls IsolatedWorker#onEvent and logs the returned EventLogRecord into the EVENTS table.
Write persistent results
With OnDevicePersonalizationManager#execute, the service has the option to write data to persistent storage (REQUESTS and EVENTS tables). Here are the entries one can write into these tables:
- a
RequestLogRecordto be added to theREQUESTStable. - a list of
EventLogRecordobjects to be added to theEVENTStable, each containing a pointer to a previously writtenRequestLogRecord.
Persistent results in on-device storage can be consumed by Federated Learning for model training.
Manage on-device training tasks
The ODP service calls IsolatedWorker#onTrainingExample when a federated compute training job starts and wants to get training examples provided by developers adopting ODP. You can invoke getRemoteData(), getLocalData(),