Panduan developer Personalisasi di Perangkat

Personalisasi di Perangkat (ODP) dirancang untuk melindungi informasi pengguna akhir dari aplikasi. Aplikasi menggunakan ODP untuk menyesuaikan produk dan layanannya bagi pengguna akhir, tetapi aplikasi tidak akan dapat melihat penyesuaian yang tepat yang dibuat untuk pengguna (kecuali jika ada interaksi langsung di luar ODP antara aplikasi dan pengguna akhir). Untuk aplikasi dengan model machine learning atau analisis statistik, ODP menyediakan serangkaian layanan dan algoritma untuk memastikan bahwa layanan dan algoritma tersebut dianonimkan dengan benar menggunakan mekanisme Privasi Diferensial yang sesuai. Untuk mengetahui detail selengkapnya, lihat penjelasan tentang Personalisasi di Perangkat.

ODP menjalankan kode developer di IsolatedProcess yang tidak memiliki akses langsung ke jaringan, disk lokal, atau layanan lain yang berjalan di perangkat, tetapi memiliki akses ke sumber data yang dipertahankan secara lokal berikut:

  • RemoteData - Data nilai kunci yang tidak dapat diubah yang didownload dari backend jarak jauh yang dioperasikan developer, jika berlaku.
  • LocalData - Data nilai kunci yang dapat diubah secara lokal dipertahankan oleh developer, jika berlaku.
  • UserData - Data pengguna yang disediakan oleh platform.

Output berikut didukung:

  • Output persisten: Output ini dapat digunakan dalam pemrosesan lokal pada masa mendatang, menghasilkan output yang ditampilkan, pelatihan model yang difasilitasi Federated Learning, atau analisis statistik lintas perangkat yang difasilitasi Federated Analytics.
    • Developer dapat menulis permintaan serta hasil pemrosesannya ke tabel REQUESTS lokal.
    • Developer dapat menulis data tambahan yang terkait dengan permintaan sebelumnya ke tabel EVENTS.
  • Output yang ditampilkan:
    • Developer dapat menampilkan HTML yang dirender oleh ODP dalam WebView di dalam SurfaceView. Konten yang dirender di sana tidak akan terlihat oleh aplikasi pemanggil.
    • Developer dapat menyematkan URL Peristiwa yang disediakan ODP dalam output HTML untuk memicu logging dan pemrosesan interaksi pengguna dengan HTML yang dirender. ODP mencegat permintaan ke URL tersebut dan memanggil kode untuk menghasilkan data yang ditulis ke tabel EVENTS.

Aplikasi klien dan SDK dapat memanggil ODP untuk menampilkan konten HTML di SurfaceView menggunakan ODP API. Konten yang dirender di SurfaceView tidak terlihat oleh aplikasi panggilan. Aplikasi klien atau SDK dapat berupa entitas yang berbeda dengan yang dikembangkan dengan ODP.

Layanan ODP mengelola aplikasi klien yang ingin memanggil ODP untuk menampilkan konten yang dipersonalisasi dalam UI-nya. Fungsi ini mendownload konten dari endpoint yang disediakan developer dan memanggil logika untuk pascapemrosesan data yang didownload. Layanan ini juga memediasi semua komunikasi antara IsolatedProcess dan layanan serta aplikasi lainnya.

Aplikasi klien menggunakan metode di class OnDevicePersonalizationManager untuk berinteraksi dengan kode developer yang berjalan di IsolatedProcess. Kode developer yang berjalan di IsolatedProcess memperluas class IsolatedService dan mengimplementasikan antarmuka IsolatedWorker. IsolatedService harus membuat instance IsolatedWorker untuk setiap permintaan.

Diagram berikut menunjukkan hubungan antara metode di OnDevicePersonalizationManager dan IsolatedWorker.

Diagram hubungan antara OnDevicePersonalizationManager dan IsolatedWorker.

Aplikasi klien memanggil ODP menggunakan metode execute dengan IsolatedService yang telah diberi nama. Layanan ODP meneruskan panggilan ke metode onExecute dari IsolatedWorker. IsolatedWorker menampilkan kumpulan data yang akan disimpan dan konten yang akan ditampilkan. Layanan ODP menulis output persisten ke tabel REQUESTS atau EVENTS, dan menampilkan referensi buram ke output yang ditampilkan ke aplikasi klien. Aplikasi klien dapat menggunakan referensi buram ini pada panggilan requestSurfacePackage mendatang untuk menampilkan konten tampilan apa pun dalam UI-nya.

Output persisten

Layanan ODP menyimpan data di tabel REQUESTS setelah implementasi onExecute oleh developer ditampilkan. Setiap kumpulan data dalam tabel REQUESTS berisi beberapa data per permintaan umum yang dihasilkan oleh layanan ODP, dan daftar Rows yang ditampilkan. Setiap Row berisi daftar (key, value) pasangan. Setiap nilai adalah skalar, String, atau blob. Nilai numerik dapat dilaporkan setelah agregasi, dan data string atau blob dapat dilaporkan setelah menerapkan Privasi Diferensial lokal atau pusat. Developer juga dapat menulis peristiwa interaksi pengguna berikutnya ke tabel EVENTS—setiap kumpulan data dalam tabel EVENTS dikaitkan dengan baris dalam tabel REQUESTS. Layanan ODP secara transparan mencatat stempel waktu dan nama paket aplikasi panggilan serta APK developer ODP dengan setiap data.

Sebelum memulai

Sebelum mulai mengembangkan dengan ODP, Anda perlu menyiapkan manifes paket dan mengaktifkan mode developer.

Setelan manifes paket

Untuk menggunakan ODP, hal-hal berikut diperlukan:

  1. Tag <property> dalam AndroidManifest.xml yang mengarah ke resource XML dalam paket yang berisi informasi konfigurasi ODP.
  2. Tag <service> di AndroidManifest.xml yang mengidentifikasi class yang memperluas IsolatedService, seperti ditunjukkan dalam contoh berikut. Layanan dalam tag <service> harus memiliki atribut exported dan isolatedProcess yang ditetapkan ke true.
  3. Tag <service> dalam resource XML yang ditentukan di Langkah 1 yang mengidentifikasi class layanan dari Langkah 2. Tag <service> juga harus menyertakan setelan khusus ODP tambahan di dalam tag itu sendiri, seperti yang ditunjukkan dalam contoh kedua.

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>

Manifes Khusus ODP dalam Resource XML

File resource XML yang ditentukan dalam tag <property> juga harus mendeklarasikan class layanan dalam tag <service>, dan menentukan endpoint URL tempat ODP akan mendownload konten untuk mengisi tabel RemoteData, seperti yang ditunjukkan dalam contoh berikut. Jika menggunakan fitur komputasi gabungan, Anda juga harus menentukan endpoint URL server komputasi gabungan yang akan dihubungkan oleh Klien komputasi gabungan.

<!-- 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>

Aktifkan Mode Developer

Aktifkan mode developer dengan mengikuti petunjuk di bagian Mengaktifkan Opsi Developer dalam dokumentasi Android Studio.

Setelan Tombol dan Flag

ODP memiliki serangkaian tombol dan flag yang digunakan untuk mengontrol fungsi tertentu:

  • _global_killswitch: tombol global untuk semua fitur ODP; tetapkan ke false untuk menggunakan ODP
  • _federated_compute_kill_switch: _tombol yang mengontrol semua fungsi pelatihan (federated learning) ODP; ditetapkan ke salah untuk menggunakan pelatihan
  • _caller_app_allowlist: mengontrol siapa yang diizinkan untuk memanggil ODP, aplikasi (nama paket, sertifikat [opsional]) dapat ditambahkan di sini atau ditetapkan sebagai * untuk mengizinkan semua
  • _isolated_service_allowlist: mengontrol layanan yang dapat berjalan dalam proses Layanan Terisolasi.

Anda dapat menjalankan perintah berikut untuk mengonfigurasi semua tombol dan flag agar menggunakan ODP tanpa batasan:

# 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 sisi perangkat

Lihat dokumentasi referensi Android API untuk ODP.

Interaksi dengan IsolatedService

Class IsolatedService adalah class dasar abstrak yang harus diperluas oleh semua developer yang ingin mengembangkan aplikasi terhadap ODP, dan dideklarasikan dalam manifes paket sebagai berjalan dalam proses terisolasi. Layanan ODP memulai layanan ini dalam proses terpisah dan membuat permintaan ke layanan tersebut. IsolatedService menerima permintaan dari layanan ODP dan membuat IsolatedWorker untuk menangani permintaan tersebut.

Developer perlu menerapkan metode dari antarmuka IsolatedWorker untuk menangani permintaan aplikasi klien, penyelesaian download, dan peristiwa yang dipicu oleh HTML yang dirender. Semua metode ini memiliki implementasi tanpa operasi default, sehingga developer dapat melewati implementasi metode yang tidak mereka minati.

Class OnDevicePersonalizationManager menyediakan API bagi aplikasi dan SDK untuk berinteraksi dengan IsolatedService yang diterapkan developer dan berjalan dalam proses terisolasi. Berikut ini beberapa kasus penggunaan yang dimaksudkan:

Membuat konten HTML untuk ditampilkan di SurfaceView

Untuk membuat konten yang akan ditampilkan, dengan OnDevicePersonalizationManager#execute, aplikasi panggilan dapat menggunakan objek SurfacePackageToken yang ditampilkan dalam panggilan requestSurfacePackage berikutnya untuk meminta hasil dirender dalam SurfaceView.

Jika berhasil, penerima akan dipanggil dengan SurfacePackage untuk View yang dirender oleh layanan ODP. Aplikasi klien harus memasukkan SurfacePackage ke dalam SurfaceView dalam hierarki View-nya.

Saat aplikasi melakukan panggilan requestSurfacePackage dengan SurfacePackageToken yang ditampilkan oleh panggilan OnDevicePersonalizationManager#execute sebelumnya, layanan ODP akan memanggil IsolatedWorker#onRender untuk mengambil cuplikan HTML yang akan dirender dalam frame berpagar. Developer tidak memiliki akses ke LocalData atau UserData selama fase ini. Hal ini mencegah developer menyematkan UserData yang berpotensi sensitif dalam URL pengambilan aset di HTML yang dihasilkan. Developer dapat menggunakan IsolatedService#getEventUrlProvider untuk membuat URL pelacakan yang akan disertakan dalam HTML yang dihasilkan. Saat HTML dirender, layanan ODP akan mencegat permintaan ke URL ini dan memanggil IsolatedWorker#onEvent. Seseorang dapat memanggil getRemoteData() saat mengimplementasikan onRender().

Melacak peristiwa dalam konten HTML

Class EventUrlProvider menyediakan API untuk membuat URL pelacakan peristiwa yang dapat disertakan developer dalam output HTML mereka. Saat HTML dirender, ODP akan memanggil IsolatedWorker#onEvent dengan payload URL peristiwa.

Layanan ODP mencegat permintaan ke URL peristiwa yang dihasilkan ODP dalam HTML yang dirender, memanggil IsolatedWorker#onEvent, dan mencatat EventLogRecord yang ditampilkan ke dalam tabel EVENTS.

Menulis hasil yang persisten

Dengan OnDevicePersonalizationManager#execute, layanan ini memiliki opsi untuk menulis data ke penyimpanan persisten (tabel REQUESTS dan EVENTS). Berikut adalah entri yang dapat ditulis ke dalam tabel ini:

  • RequestLogRecord untuk ditambahkan ke tabel REQUESTS.
  • daftar objek EventLogRecord yang akan ditambahkan ke tabel EVENTS, masing-masing berisi pointer ke RequestLogRecord yang ditulis sebelumnya.

Hasil persisten di penyimpanan perangkat dapat digunakan oleh Federated Learning untuk pelatihan model.

Mengelola tugas pelatihan di perangkat

Layanan ODP memanggil IsolatedWorker#onTrainingExample saat tugas pelatihan komputasi gabungan dimulai dan ingin mendapatkan contoh pelatihan yang disediakan oleh developer yang mengadopsi ODP. Anda dapat memanggil getRemoteData(), getLocalData(), getUserData(), dan getLogReader() saat mengimplementasikan onTrainingExample().

Untuk menjadwalkan atau membatalkan tugas komputasi gabungan, Anda dapat menggunakan class FederatedComputeScheduler yang menyediakan API untuk semua IsolatedService ODP. Setiap tugas komputasi gabungan dapat diidentifikasi berdasarkan nama populasinya.

Sebelum Anda menjadwalkan tugas komputasi gabungan baru:

  • Tugas dengan nama populasi ini seharusnya sudah dibuat di server komputasi gabungan jarak jauh.
  • Endpoint URL server komputasi gabungan harus sudah ditentukan di setelan manifes paket dengan tag federated-compute-settings.

Interaksi dengan output persisten

Bagian berikut menjelaskan cara berinteraksi dengan output persisten di ODP.

Membaca tabel lokal

Class LogReader menyediakan API untuk membaca tabel REQUESTS dan EVENTS. Tabel ini berisi data yang ditulis oleh IsolatedService selama panggilan onExecute() atau onEvent(). Data dalam tabel ini dapat digunakan untuk pelatihan model yang difasilitasi Federated Learning, atau analisis statistik lintas perangkat yang difasilitasi Federated Analytics.

Interaksi dengan konten yang didownload

Bagian berikut menjelaskan cara berinteraksi dengan konten yang didownload di ODP.

Mendownload konten dari server

Layanan ODP secara berkala mendownload konten dari URL yang dideklarasikan dalam manifes paket IsolatedService, dan memanggil onDownloadCompleted setelah download selesai. Hasil download adalah file JSON yang berisi key-value pair.

Developer yang mengadopsi ODP dapat memilih subset konten yang didownload yang harus ditambahkan ke tabel RemoteData dan mana yang harus dihapus. Developer tidak dapat mengubah konten yang didownload - ini memastikan bahwa tabel RemoteData tidak berisi data pengguna. Selain itu, developer bebas mengisi tabel LocalData sesuai pilihan; misalnya, mereka dapat menyimpan beberapa hasil prakomputasi dalam cache.

Download format permintaan

ODP secara berkala memeriksa endpoint URL yang dideklarasikan di manifes paket developer untuk mengambil konten guna mengisi tabel RemoteData.

Endpoint diharapkan menampilkan respons JSON seperti yang dijelaskan nanti. Respons JSON harus berisi syncToken yang mengidentifikasi versi data yang dikirim, beserta daftar pasangan nilai kunci yang akan diisi. Nilai syncToken harus berupa stempel waktu dalam detik, yang dikunci ke batas jam UTC. Sebagai bagian dari permintaan download, ODP menyediakan syncToken dari download yang telah diselesaikan sebelumnya serta negara perangkat sebagai syncToken dan parameter negara di URL download. Server dapat menggunakan syncToken sebelumnya untuk menerapkan download inkremental.

Format file download

File yang didownload adalah file JSON dengan struktur berikut. File JSON diharapkan berisi syncToken untuk mengidentifikasi versi data yang sedang didownload. syncToken harus berupa stempel waktu UTC yang dilampirkan ke batas jam, dan harus melebihi syncToken dari download sebelumnya. Jika syncToken tidak memenuhi kedua persyaratan, konten yang didownload akan dihapus tanpa pemrosesan.

Isian adalah daftar tuple (kunci, data, encoding). key diharapkan berupa string UTF-8. Kolom encoding adalah parameter opsional yang menentukan cara kolom data dienkode - kolom ini dapat disetel ke "utf8" atau "base64", dan dianggap "utf8" secara default. Kolom key dikonversi menjadi objek String dan kolom data dikonversi menjadi array byte sebelum memanggil 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 sisi server

Bagian ini menjelaskan cara berinteraksi dengan API server komputasi gabungan.

Federated Compute Server API

Untuk menjadwalkan tugas komputasi gabungan di sisi klien, Anda memerlukan tugas dengan nama populasi yang dibuat di server komputasi gabungan jarak jauh. Di bagian ini, kita akan membahas cara membuat tugas tersebut di server komputasi gabungan.

Diagram topologi klien-server komputasi gabungan.

Saat membuat tugas baru untuk Task Builder, developer ODP harus menyediakan dua kumpulan file:

  1. Model tff.learning.models.FunctionalModel tersimpan melalui panggilan API tff.learning.models.save_functional_model. Anda dapat menemukan satu contoh di repositori GitHub kami.
  2. File fcp_server_config.json yang mencakup kebijakan, penyiapan federated learning, dan penyiapan privasi diferensial. Berikut adalah contoh 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
  }
}

Anda dapat menemukan contoh lainnya di repositori GitHub kami.

Setelah menyiapkan kedua input ini, panggil Task Builder untuk membuat artefak dan membuat tugas baru. Petunjuk lebih mendetail tersedia di repositori GitHub kami.