Руководство разработчика персонализации на устройстве,Руководство разработчика персонализации на устройстве,Руководство разработчика персонализации на устройстве

Персонализация на устройстве (ODP) предназначена для защиты информации конечных пользователей от приложений. Приложения используют ODP для настройки своих продуктов и услуг для конечных пользователей, но они не смогут увидеть точные настройки, сделанные для пользователя (если только между приложением и конечным пользователем не происходит прямого взаимодействия за пределами ODP). Для приложений с моделями машинного обучения или статистическим анализом ODP предоставляет набор сервисов и алгоритмов, гарантирующих их надлежащую анонимность с использованием соответствующих механизмов дифференциальной конфиденциальности. Дополнительные сведения см. в пояснении к разделу «Персонализация на устройстве» .

ODP запускает код разработчика в IsolatedProcess , который не имеет прямого доступа к сети, локальным дискам или другим службам, работающим на устройстве, но имеет доступ к следующим локально сохраняемым источникам данных:

  • RemoteData — неизменяемые данные «ключ-значение», загружаемые с удаленных серверов, управляемых разработчиком, если применимо.
  • LocalData — изменяемые данные «ключ-значение», локально сохраненные разработчиком, если применимо.
  • UserData — данные пользователя, предоставленные платформой.

Поддерживаются следующие выходные данные:

  • Постоянный вывод: эти выходные данные можно использовать в будущей локальной обработке, создавая отображаемые выходные данные, обучение модели с помощью Federated Learning или статистический анализ между устройствами с помощью Federated Analytics.
    • Разработчики могут записывать запросы, а также результаты их обработки в локальную таблицу REQUESTS .
    • Разработчики могут записывать дополнительные данные, связанные с предыдущим запросом, в таблицу EVENTS .
  • Отображаемый вывод:
    • Разработчики могут возвращать HTML, отображаемый ODP, в WebView внутри SurfaceView . Отображаемый там контент не будет виден вызывающему приложению.
    • Разработчики могут встраивать URL-адреса событий, предоставленные ODP, в выходные данные HTML, чтобы инициировать регистрацию и обработку взаимодействий пользователей с визуализированным HTML. ODP перехватывает запросы к этим URL-адресам и вызывает код для генерации данных, которые записываются в таблицу EVENTS .

Клиентские приложения и пакеты SDK могут вызывать ODP для отображения содержимого HTML в SurfaceView с помощью API-интерфейсов ODP. Содержимое, отображаемое в SurfaceView , не видимо для вызывающего приложения. Клиентское приложение или пакет SDK могут быть объектом, отличным от того, который разрабатывается с помощью ODP.

Служба ODP управляет клиентским приложением, которое хочет вызвать ODP для отображения персонализированного контента в своем пользовательском интерфейсе. Он загружает контент с конечных точек, предоставленных разработчиком, и вызывает логику для постобработки загруженных данных. Он также является посредником во всех взаимодействиях между IsolatedProcess и другими службами и приложениями.

Клиентские приложения используют методы класса OnDevicePersonalizationManager для взаимодействия с кодом разработчика, выполняющимся в IsolatedProcess . Код разработчика, выполняющийся в IsolatedProcess расширяет класс IsolatedService и реализует интерфейс IsolatedWorker . IsolatedService необходимо создать экземпляр IsolatedWorker для каждого запроса.

На следующей диаграмме показана связь между методами OnDevicePersonalizationManager и IsolatedWorker .

Схема связи между OnDevicePersonalizationManager и IsolatedWorker .

Клиентское приложение вызывает ODP, используя метод execute с именем IsolatedService . Служба ODP перенаправляет вызов методу onExecute класса IsolatedWorker . IsolatedWorker возвращает записи, которые необходимо сохранить, и содержимое, которое необходимо отобразить. Служба ODP записывает постоянные выходные данные в таблицу REQUESTS или EVENTS и возвращает непрозрачную ссылку на отображаемые выходные данные клиентскому приложению. Клиентское приложение может использовать эту непрозрачную ссылку в будущем вызове requestSurfacePackage для отображения любого отображаемого содержимого в своем пользовательском интерфейсе.

Постоянный вывод

Служба ODP сохраняет запись в таблице REQUESTS после возврата реализации onExecute реализованной разработчиком. Каждая запись в таблице REQUESTS содержит некоторые общие данные для каждого запроса, созданные службой ODP, и список возвращаемых Rows . Каждая Row содержит список пар (key, value) . Каждое значение представляет собой скаляр, строку или большой двоичный объект. Числовые значения могут сообщаться после агрегирования, а строковые или BLOB-данные могут сообщаться после применения локальной или центральной дифференциальной конфиденциальности. Разработчики также могут записывать последующие события взаимодействия с пользователем в таблицу EVENTS — каждая запись в таблице EVENTS связана со строкой в ​​таблице REQUESTS . Служба ODP прозрачно регистрирует метку времени и имя пакета вызывающего приложения и APK-файла разработчика ODP с каждой записью.

Прежде чем начать

Прежде чем приступить к разработке с помощью ODP, вам необходимо настроить манифест пакета и включить режим разработчика.

Настройки манифеста пакета

Для использования ODP необходимо следующее:

  1. Тег <property> в AndroidManifest.xml , указывающий на XML-ресурс в пакете, содержащий информацию о конфигурации ODP.
  2. Тег <service> в AndroidManifest.xml , идентифицирующий класс, расширяющий IsolatedService , как показано в следующем примере. У службы в теге <service> должны быть exported атрибуты, а isolatedProcess установлено значение true .
  3. Тег <service> в XML-ресурсе, указанном на шаге 1, который идентифицирует класс обслуживания из шага 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>

ODP-специфичный манифест в XML-ресурсе

Файл ресурсов XML, указанный в теге <property> , также должен объявить класс обслуживания в теге <service> и указать конечную точку URL-адреса, из которой ODP будет загружать содержимое для заполнения таблицы RemoteData , как показано в следующем примере. Если вы используете функции федеративных вычислений, вам также необходимо указать конечную точку 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 Studio.

Настройки переключателя и флага

ODP имеет набор переключателей и флагов, которые используются для управления определенными функциями:

  • _global_kill переключатель : глобальный переключатель для всех функций ODP; установите значение false, чтобы использовать ODP
  • _federated_compute_kill_switch: _ коммутатор, управляющий всеми функциями обучения (федеративного обучения) ODP; установите значение false, чтобы использовать обучение
  • Список _caller_app_allow : контролирует, кому разрешено вызывать ODP. Сюда можно добавить приложения (имя пакета, [необязательный] сертификат) или установить его как *, чтобы разрешить все
  • Список _isolated_service_allow : контролирует, какие службы могут запускаться в процессе изолированной службы.

Вы можете запустить следующие команды, чтобы настроить все переключатели и флаги для использования 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 на стороне устройства

Ознакомьтесь со справочной документацией по API Android для ODP.

Взаимодействие с IsolatedService

Класс IsolatedService — это абстрактный базовый класс, который все разработчики, намеревающиеся разрабатывать с использованием ODP, должны расширить и объявить в манифесте своего пакета как работающий в изолированном процессе. Служба ODP запускает эту службу в изолированном процессе и отправляет к ней запросы. IsolatedService получает запросы от службы ODP и создает IsolatedWorker для обработки запроса.

Разработчикам необходимо реализовать методы из интерфейса IsolatedWorker для обработки запросов клиентских приложений, завершения загрузки и событий, инициируемых визуализированным HTML. Все эти методы имеют реализации по умолчанию, не требующие операций, поэтому разработчики могут пропустить реализацию методов, которые им не интересны.

Класс OnDevicePersonalizationManager предоставляет приложениям и пакетам SDK API для взаимодействия с реализованным разработчиком IsolatedService , работающим в изолированном процессе. Ниже приведены некоторые предполагаемые варианты использования:

Создайте HTML-контент для отображения в SurfaceView.

Чтобы сгенерировать контент для отображения с помощью OnDevicePersonalizationManager#execute , вызывающее приложение может использовать возвращенный объект SurfacePackageToken в последующем вызове requestSurfacePackage , чтобы запросить отображение результата в SurfaceView .

В случае успеха получатель вызывается с помощью SurfacePackage для представления, отображаемого службой ODP. Клиентским приложениям необходимо вставить SurfacePackage в SurfaceView в своей иерархии представлений.

Когда приложение выполняет вызов requestSurfacePackage с SurfacePackageToken , возвращенным предыдущим вызовом OnDevicePersonalizationManager#execute служба ODP вызывает IsolatedWorker#onRender для получения фрагмента HTML для визуализации в изолированном фрейме. На этом этапе разработчик не имеет доступа к LocalData или UserData . Это не позволяет разработчику встраивать потенциально конфиденциальные UserData в URL-адреса выборки ресурсов в сгенерированном HTML. Разработчики могут использовать IsolatedService#getEventUrlProvider для создания URL-адресов отслеживания для включения в сгенерированный HTML. Когда HTML отображается, служба ODP перехватывает запросы к этим URL-адресам и вызывает IsolatedWorker#onEvent . Можно вызвать getRemoteData() при реализации onRender() .

Отслеживание событий в HTML-контенте

Класс EventUrlProvider предоставляет API для создания URL-адресов отслеживания событий, которые разработчики могут включать в свои выходные данные HTML. Когда HTML визуализируется, ODP вызовет IsolatedWorker#onEvent с полезной нагрузкой URL-адреса события.

Служба ODP перехватывает запросы к URL-адресам событий, сгенерированных ODP, в отображаемом HTML, вызывает IsolatedWorker#onEvent и записывает возвращенную EventLogRecord в таблицу EVENTS .

Напишите стойкие результаты

С помощью OnDevicePersonalizationManager#execute служба имеет возможность записывать данные в постоянное хранилище (таблицы REQUESTS и EVENTS ). Вот записи, которые можно записать в эти таблицы:

  • RequestLogRecord который необходимо добавить в таблицу REQUESTS .
  • список объектов EventLogRecord , добавляемых в таблицу EVENTS , каждый из которых содержит указатель на ранее записанный RequestLogRecord .

Постоянные результаты в хранилище на устройстве могут быть использованы Федеративным обучением для обучения модели.

Управление задачами обучения на устройстве

Служба ODP вызывает IsolatedWorker#onTrainingExample , когда запускается задание по обучению федеративным вычислениям, и ей требуется получить примеры обучения, предоставленные разработчиками, использующими ODP. Вы можете вызвать getRemoteData() , getLocalData() , getUserData() и getLogReader() при реализации onTrainingExample() .

Чтобы запланировать или отменить задания объединенных вычислений, вы можете использовать класс FederatedComputeScheduler , который предоставляет API для всех ODP IsolatedService . Каждое объединенное вычислительное задание можно идентифицировать по имени его совокупности.

Прежде чем запланировать новое задание федеративных вычислений:

  • Задача с таким именем совокупности уже должна быть создана на удаленном интегрированном вычислительном сервере.
  • Конечная точка URL-адреса федеративного вычислительного сервера уже должна быть указана в настройках манифеста пакета с помощью тега federated-compute-settings .

Взаимодействие с постоянным выводом

В следующем разделе описывается, как взаимодействовать с постоянным выводом в ODP.

Чтение локальных таблиц

Класс LogReader предоставляет API для чтения таблиц REQUESTS и EVENTS . Эти таблицы содержат данные, которые были записаны функцией IsolatedService во время вызовов onExecute() или onEvent() . Данные в этих таблицах можно использовать для обучения моделей с помощью Federated Learning или статистического анализа между устройствами с помощью Federated Analytics.

Взаимодействие с загруженным контентом

В следующем разделе описывается, как взаимодействовать с загруженным контентом в ODP.

Загрузка контента с серверов

Служба ODP периодически загружает содержимое с URL-адреса, объявленного в манифесте пакета IsolatedService , и вызывает onDownloadCompleted после завершения загрузки. Загрузка представляет собой JSON-файл, содержащий пары ключ-значение.

Разработчики, использующие ODP, могут выбирать, какое подмножество загруженного контента следует добавить в таблицу RemoteData , а какое следует удалить. Разработчики не могут изменять загруженное содержимое — это гарантирует, что таблица RemoteData не будет содержать никаких пользовательских данных. Кроме того, разработчики могут заполнять таблицу LocalData по своему усмотрению; например, они могут кэшировать некоторые предварительно вычисленные результаты.

Скачать формат запроса

ODP периодически опрашивает конечную точку URL-адреса, объявленную в манифесте пакета разработчика, чтобы получить содержимое для заполнения таблицы RemoteData .

Ожидается, что конечная точка вернет ответ JSON, как описано ниже. Ответ JSON должен содержать syncToken , идентифицирующий версию отправляемых данных, а также список пар ключ-значение, которые необходимо заполнить. Значение syncToken должно быть меткой времени в секундах, привязанной к границе часа в формате UTC. В рамках запроса на загрузку ODP предоставляет syncToken ранее завершенной загрузки и страну устройства в качестве параметров syncToken и страны в URL-адресе загрузки. Сервер может использовать предыдущий syncToken для реализации дополнительных загрузок.

Скачать формат файла

Загруженный файл представляет собой файл JSON со следующей структурой. Ожидается, что файл JSON будет содержать syncToken для идентификации версии загружаемых данных. syncToken должен представлять собой временную метку 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-интерфейсы федеративного вычислительного сервера

Чтобы запланировать задание объединенных вычислений на стороне клиента, вам понадобится задача с именем совокупности, созданная на удаленном сервере объединенных вычислений. В этом разделе мы расскажем, как создать такую ​​задачу на объединенном вычислительном сервере.

Схема топологии клиент-сервер объединенных вычислений.

При создании новой задачи для Task Builder разработчики ODP должны предоставить два набора файлов:

  1. Сохраненная модель tff.learning.models.FunctionalModel посредством вызова API tff.learning.models.save_functional_model . Вы можете найти один пример в нашем репозитории 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.