온디바이스 맞춤설정(ODP)은 애플리케이션으로부터 최종 사용자의 정보를 보호하기 위해 설계되었습니다. 애플리케이션은 ODP를 사용하여 최종 사용자를 위해 제품과 서비스를 맞춤설정하지만, 애플리케이션과 최종 사용자 간에 ODP 외부에서 직접적인 상호작용이 있는 경우가 아니라면 사용자를 위해 이루어진 정확한 맞춤설정을 볼 수는 없습니다. 머신러닝 모델 또는 통계 분석이 포함된 애플리케이션의 경우 ODP는 적절한 개인 정보 차등 보호 메커니즘을 사용하여 적절하게 익명처리될 수 있도록 일련의 서비스와 알고리즘을 제공합니다. 자세한 내용은 기기 내 맞춤설정에 관한 설명을 참고하세요.
ODP는 네트워크, 로컬 디스크 또는 기기에서 실행되는 기타 서비스에 직접 액세스할 수 없지만 다음과 같은 로컬 영구 데이터 소스에 액세스할 수 있는 IsolatedProcess
에서 개발자 코드를 실행합니다.
RemoteData
- 개발자가 운영하는 원격 백엔드(해당하는 경우)에서 다운로드한 변경 불가능한 키-값 데이터입니다.LocalData
- 해당하는 경우 개발자가 로컬에서 유지하는 변경 가능한 키-값 데이터입니다.UserData
- 플랫폼에서 제공하는 사용자 데이터입니다.
다음 출력이 지원됩니다.
- 지속적인 출력: 이러한 출력은 향후 로컬 처리, 표시된 출력 생성, 제휴 학습을 통한 모델 학습 또는 제휴 분석을 통한 교차 기기 통계 분석에 사용할 수 있습니다.
- 표시된 출력:
- 개발자는
SurfaceView
내의WebView
에서 ODP로 렌더링된 HTML을 반환할 수 있습니다. 여기에서 렌더링된 콘텐츠는 호출 앱에 표시되지 않습니다. - 개발자는 HTML 출력 내에 ODP에서 제공하는 이벤트 URL을 삽입하여 렌더링된 HTML과의 사용자 상호작용 로깅 및 처리를 트리거할 수 있습니다. ODP는 이러한 URL에 대한 요청을 가로채고 코드를 호출하여
EVENTS
테이블에 기록되는 데이터를 생성합니다.
- 개발자는
클라이언트 앱과 SDK는 ODP를 호출하여 ODP API를 통해 SurfaceView
에 HTML 콘텐츠를 표시할 수 있습니다. SurfaceView
에서 렌더링된 콘텐츠는 호출 앱에 표시되지 않습니다. 클라이언트 앱 또는 SDK는 ODP로 개발하는 앱과 다른 항목일 수 있습니다.
ODP 서비스는 ODP를 호출하여 UI 내에 맞춤설정된 콘텐츠를 표시하려는 클라이언트 앱을 관리합니다. 개발자가 제공한 엔드포인트에서 콘텐츠를 다운로드하고 다운로드된 데이터의 후처리를 위한 로직을 호출합니다. 또한 IsolatedProcess
와 다른 서비스 및 앱 간의 모든 통신을 중재합니다.
클라이언트 앱은 OnDevicePersonalizationManager
클래스의 메서드를 사용하여 IsolatedProcess
에서 실행되는 개발자의 코드와 상호작용합니다. IsolatedProcess
에서 실행되는 개발자 코드는 IsolatedService
클래스를 확장하고 IsolatedWorker
인터페이스를 구현합니다. IsolatedService
는 각 요청에 대해 IsolatedWorker
의 인스턴스를 만들어야 합니다.
다음 다이어그램은 OnDevicePersonalizationManager
및 IsolatedWorker
의 메서드 간 관계를 보여줍니다.
클라이언트 앱은 이름이 IsolatedService
인 execute
메서드를 사용하여 ODP를 호출합니다. ODP 서비스는 호출을 IsolatedWorker
의 onExecute
메서드로 전달합니다. IsolatedWorker
는 유지할 레코드와 표시할 콘텐츠를 반환합니다. ODP 서비스는 영구 출력을 REQUESTS
또는 EVENTS
테이블에 쓰고 표시된 출력에 대한 불투명 참조를 클라이언트 앱에 반환합니다. 클라이언트 앱은 향후 requestSurfacePackage
호출에서 이 불투명 참조를 사용하여 UI 내에 디스플레이 콘텐츠를 표시할 수 있습니다.
영구 출력
ODP 서비스는 개발자가 onExecute
를 구현한 후 반환되면 REQUESTS
테이블에 레코드를 유지합니다. REQUESTS
테이블의 각 레코드에는 ODP 서비스에서 생성된 일반적인 요청별 데이터와 반환된 Rows
목록이 포함되어 있습니다. 각 Row
에는 (key, value)
쌍 목록이 포함됩니다. 각 값은 스칼라, 문자열 또는 blob입니다. 숫자 값은 집계 후에 보고될 수 있으며, 문자열 또는 blob 데이터는 로컬 또는 중앙 개인 정보 차등 보호를 적용한 후에 보고될 수 있습니다. 개발자는 후속 사용자 상호작용 이벤트를 EVENTS
테이블에 쓸 수도 있습니다. EVENTS
테이블의 각 레코드는 REQUESTS
테이블의 행과 연결됩니다. ODP 서비스는 호출 앱의 타임스탬프와 패키지 이름, ODP 개발자의 APK를 각 레코드와 함께 투명하게 로깅합니다.
시작하기 전에
ODP로 개발을 시작하기 전에 패키지 매니페스트를 설정하고 개발자 모드를 사용 설정해야 합니다.
패키지 매니페스트 설정
ODP를 사용하려면 다음이 필요합니다.
- ODP 구성 정보가 포함된 패키지의 XML 리소스를 가리키는
AndroidManifest.xml
의<property>
태그 - 다음 예와 같이
IsolatedService
를 확장하는 클래스를 식별하는AndroidManifest.xml
의<service>
태그입니다.<service>
태그의 서비스는exported
속성과isolatedProcess
속성을true
로 설정해야 합니다. - 2단계의 서비스 클래스를 식별하는, 1단계에서 지정한 XML 리소스의
<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
테이블을 채우기 위해 콘텐츠를 다운로드할 URL 엔드포인트를 지정해야 합니다. 제휴 컴퓨팅 기능을 사용하는 경우 제휴 컴퓨팅 클라이언트가 연결될 제휴 컴퓨팅 서버 URL 엔드포인트도 지정해야 합니다.
<!-- 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 스튜디오 문서의 개발자 옵션 사용 설정 섹션에 있는 안내에 따라 개발자 모드를 사용 설정합니다.
스위치 및 플래그 설정
ODP에는 특정 기능을 제어하는 데 사용되는 일련의 스위치와 플래그가 있습니다.
- _global_killswitch: 모든 ODP 기능의 전역 스위치입니다. ODP를 사용하려면 false로 설정합니다.
- _federated_compute_kill_switch: _ODP의 모든 학습 (제휴 학습) 기능을 제어하는 스위치입니다. 학습을 사용하려면 false로 설정하세요.
- _caller_app_allowlist: ODP를 호출할 수 있는 사용자를 제어합니다. 앱(pkg 이름, [선택사항] 인증서)을 여기에 추가하거나 *로 설정하여 모두 허용할 수 있습니다.
- _quarantine_service_allowlist: 격리된 서비스 프로세스에서 실행할 수 있는 서비스를 제어합니다.
다음 명령어를 실행하여 제한 없이 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에 의해 트리거되는 이벤트를 처리해야 합니다. 이러한 모든 메서드에는 기본적인 노옵(no-op) 구현이 있으므로 개발자는 관심 없는 메서드 구현을 건너뛸 수 있습니다.
OnDevicePersonalizationManager
클래스는 앱과 SDK가 격리된 프로세스에서 실행되는 개발자가 구현한 IsolatedService
와 상호작용할 수 있는 API를 제공합니다. 다음은 의도된 사용 사례입니다.
SurfaceView에 표시할 HTML 콘텐츠 생성
호출 앱은 OnDevicePersonalizationManager#execute
를 사용하여 표시할 콘텐츠를 생성하기 위해 후속 requestSurfacePackage
호출에서 반환된 SurfacePackageToken
객체를 사용하여 SurfaceView
에서 결과를 렌더링하도록 요청할 수 있습니다.
성공하면 ODP 서비스에서 렌더링된 뷰의 SurfacePackage
를 사용하여 broadcast receiver가 호출됩니다. 클라이언트 애플리케이션은 뷰 계층 구조 내 SurfaceView
에 SurfacePackage
를 삽입해야 합니다.
앱이 이전 OnDevicePersonalizationManager#execute
호출에서 반환된 SurfacePackageToken
를 사용하여 requestSurfacePackage
를 호출하면 ODP 서비스는 IsolatedWorker#onRender
를 호출하여 펜싱된 프레임 내에 렌더링할 HTML 스니펫을 가져옵니다. 이 단계에서는 개발자가 LocalData
또는 UserData
에 액세스할 수 없습니다. 이렇게 하면 개발자가 생성된 HTML의 애셋 가져오기 URL 내에 민감할 수 있는 UserData
를 삽입하는 것을 방지할 수 있습니다. 개발자는 IsolatedService#getEventUrlProvider
를 사용하여 생성된 HTML에 포함할 추적 URL을 생성할 수 있습니다. HTML이 렌더링되면 ODP 서비스는 이러한 URL에 대한 요청을 가로채고 IsolatedWorker#onEvent
를 호출합니다. onRender()
를 구현할 때 getRemoteData()
를 호출할 수 있습니다.
HTML 콘텐츠 내 이벤트 추적
EventUrlProvider
클래스는 개발자가 HTML 출력에 포함할 수 있는 이벤트 추적 URL을 생성하는 API를 제공합니다. HTML이 렌더링되면 ODP는 이벤트 URL의 페이로드로 IsolatedWorker#onEvent
를 호출합니다.
ODP 서비스는 렌더링된 HTML 내에서 ODP에서 생성된 이벤트 URL에 대한 요청을 가로채고 IsolatedWorker#onEvent
를 호출하며 반환된 EventLogRecord
를 EVENTS
테이블에 기록합니다.
지속적인 결과 쓰기
OnDevicePersonalizationManager#execute
를 사용하면 서비스에서 영구 스토리지 (REQUESTS
및 EVENTS
테이블)에 데이터를 쓸 수 있습니다. 다음은 이러한 테이블에 쓸 수 있는 항목입니다.
REQUESTS
테이블에 추가할RequestLogRecord
EVENTS
테이블에 추가할EventLogRecord
객체 목록으로, 각 객체에는 이전에 작성된RequestLogRecord
에 대한 포인터가 포함됩니다.
기기 내 저장소의 지속적인 결과는 모델 학습에 제휴 학습에 의해 사용될 수 있습니다.
기기 내 학습 작업 관리
제휴 컴퓨팅 학습 작업이 시작되고 ODP를 채택한 개발자가 제공한 학습 예시를 가져오려는 경우 ODP 서비스는 IsolatedWorker#onTrainingExample
를 호출합니다. onTrainingExample()
를 구현할 때 getRemoteData()
, getLocalData()
, getUserData()
, getLogReader()
를 호출할 수 있습니다.
제휴 컴퓨팅 작업을 예약하거나 취소하려면 모든 ODP IsolatedService
에 API를 제공하는 FederatedComputeScheduler
클래스를 사용하면 됩니다. 각 제휴 컴퓨팅 작업은 모집단 이름으로 식별할 수 있습니다.
새 제휴 컴퓨팅 작업을 예약하기 전에 다음을 실행합니다.
- 이 채우기 이름을 가진 태스크가 이미 원격 제휴 컴퓨팅 서버에 생성되어 있어야 합니다.
- 제휴 컴퓨팅 서버 URL 엔드포인트는 이미 패키지 매니페스트 설정에서
federated-compute-settings
태그로 지정되어 있어야 합니다.
영구 출력과의 상호작용
다음 섹션에서는 ODP의 영구 출력과 상호작용하는 방법을 설명합니다.
로컬 테이블 읽기
LogReader
클래스는 REQUESTS
및 EVENTS
테이블을 읽는 API를 제공합니다. 이러한 테이블에는 onExecute()
또는 onEvent()
호출 중에 IsolatedService
에 의해 작성된 데이터가 포함되어 있습니다. 이 표의 데이터는 제휴 학습을 통한 모델 학습 또는 제휴 분석을 통한 교차 기기 통계 분석에 사용할 수 있습니다.
다운로드한 콘텐츠와의 상호작용
다음 섹션에서는 ODP에서 다운로드한 콘텐츠와 상호작용하는 방법을 설명합니다.
서버에서 콘텐츠 다운로드
ODP 서비스는 IsolatedService
의 패키지 매니페스트에 선언된 URL에서 콘텐츠를 주기적으로 다운로드하고 다운로드가 완료된 후 onDownloadCompleted
를 호출합니다. 다운로드 파일은 키-값 쌍이 포함된 JSON 파일입니다.
ODP를 채택하는 개발자는 다운로드한 콘텐츠의 하위 집합을 RemoteData
테이블에 추가하고 삭제할 하위 집합을 선택할 수 있습니다. 개발자는 다운로드한 콘텐츠를 수정할 수 없습니다. 이렇게 하면 RemoteData
테이블에 사용자 데이터가 포함되지 않습니다. 또한 개발자는 원하는 대로 LocalData
테이블을 채울 수 있습니다. 예를 들어 미리 계산된 결과를 캐시할 수 있습니다.
다운로드 요청 형식
ODP는 개발자 패키지 매니페스트에 선언된 URL 엔드포인트를 주기적으로 폴링하여 RemoteData
테이블을 채우는 콘텐츠를 가져옵니다.
나중에 설명하는 것처럼 엔드포인트는 JSON 응답을 반환해야 합니다. JSON 응답에는 채워질 키-값 쌍의 목록과 함께 전송되는 데이터의 버전을 식별하는 syncToken
가 포함되어야 합니다. syncToken
값은 UTC 시간 경계로 고정된 초 단위의 타임스탬프여야 합니다. 다운로드 요청의 일부로 ODP는 이전에 완료된 다운로드의 syncToken
및 기기 국가를 다운로드 URL의 syncToken 및 country 매개변수로 제공합니다. 서버는 이전 syncToken
를 사용하여 증분 다운로드를 구현할 수 있습니다.
다운로드 파일 형식
다운로드된 파일은 다음 구조의 JSON 파일입니다. JSON 파일에는 다운로드 중인 데이터의 버전을 식별하는 syncToken이 포함되어야 합니다. syncToken은 1시간 경계로 제한된 UTC 타임스탬프여야 하며 이전 다운로드의 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와 상호작용하는 방법을 설명합니다.
제휴 컴퓨팅 서버 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 저장소에서 확인할 수 있습니다.