Управление обновлениями системы

В этом руководстве для разработчиков рассказывается, как контроллер политик устройств (DPC) может управлять обновлениями системы Android от имени пользователя устройства.

Введение

Устройства Android могут получать и устанавливать беспроводные обновления для системы и прикладного ПО. Android уведомляет пользователя о доступности обновления системы, и пользователь может установить его сразу или позже.

С помощью контроллера политики устройств администратор может управлять обновлениями системы на устройстве пользователя. Контроллер политики может управлять полностью управляемым устройством (владелец устройства) или только рабочим профилем (владелец профиля). В таблице 1 показано, как владельцы устройств могут управлять обновлениями системы, в то время как владельцы профилей могут только сообщать информацию об обновлениях системы.

Таблица 1. Задачи, доступные контроллерам политики устройств в зависимости от режима владения

Задача Владелец устройства Владелец профиля
Проверьте наличие обновлений системы
Как получать обратные вызовы, когда становятся доступны новые обновления системы
Как настроить правила локального обновления, чтобы контролировать установку обновлений системы Android
Как зафиксировать версию ОС на критически важные периоды

Проверьте наличие ожидающих обновлений

Ожидающее обновление – это обновление системы для устройства, которое ещё не было установлено. Контроллер политики устройств помогает администраторам проверять, на каких устройствах есть ожидающие обновления системы, и при необходимости просить пользователей установить критические обновления.

Владельцы устройств и профилей с Android 8.0 (уровень API 26) или более поздней версии могут проверить, есть ли для устройства ожидающее обновление системы. Вызовите DevicePolicyManager.getPendingSystemUpdate(). Если на устройстве установлена актуальная версия, возвращается null. Если обновление системы ожидает установки, метод возвращает информацию о нем.

Как узнать больше об ожидающем обновлении

После вызова getPendingSystemUpdate() вы можете проверить возвращенное значение SystemUpdateInfo, чтобы узнать больше об ожидающем обновлении. В примере ниже показано, как узнать, когда обновление стало доступно для устройства.

Kotlin

val firstAvailable =
        dpm.getPendingSystemUpdate(adminName)?.receivedTime
firstAvailable?.let {
    Log.i(TAG, "Update first available: ${Date(firstAvailable)}")
}

Java

SystemUpdateInfo updateInfo = dpm.getPendingSystemUpdate(adminName);
if (updateInfo != null) {
  Long firstAvailable = updateInfo.getReceivedTime();
  Log.i(TAG, "Update first available: " + new Date(firstAvailable));
}

Системные обратные вызовы

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

В подклассе DeviceAdminReceiver переопределите обратный вызов onSystemUpdatePending(). Для получения обратного вызова не нужно регистрировать или рекламировать DPC. Система может вызвать этот метод несколько раз для одного обновления, поэтому перед ответом проверьте статус обновления. Позвоните по номеру getPendingSystemUpdate(), чтобы узнать больше об обновлении системы. Ниже приведен пример.

Kotlin

/**
 * Called when a new update is available.
 */
override fun onSystemUpdatePending(context: Context?, intent: Intent?,
                                   receivedTime: Long) {

    // System update information is supported in API level 26 or higher.
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
        return
    }

    val updateInfo = getManager(context)
            .getPendingSystemUpdate(getWho(context))
            ?: return
    if (updateInfo.securityPatchState ==
            SystemUpdateInfo.SECURITY_PATCH_STATE_TRUE) {
        // Perhaps install because this is a security patch.
        // ...
    }
}

Java

/**
 * Called when a new update is available.
 */
public void onSystemUpdatePending (Context context, Intent intent,
                                   long receivedTime) {

  // System update information is supported in API level 26 or higher.
  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
    return;
  }
  SystemUpdateInfo updateInfo = getManager(context)
      .getPendingSystemUpdate(getWho(context));
  if (updateInfo == null) {
    return;
  }
  if (updateInfo.getSecurityPatchState() ==
      SystemUpdateInfo.SECURITY_PATCH_STATE_TRUE) {
    // Perhaps install because this is a security patch.
    // ...
  }
}

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

Обновить правила

Владелец устройства может управлять установкой обновлений, задав правила обновления локальной системы. Правила обновления системы могут быть трех типов:

Автоматически
Обновления системы устанавливаются сразу после того, как становятся доступны (без участия пользователя). Если задано это правило, все ожидающие обновления, которые могли быть отложены или запланированы на время перерыва на техническое обслуживание, устанавливаются немедленно.
Оконный режим
Обновления системы устанавливаются во время ежедневного перерыва на техническое обслуживание (без участия пользователя). При создании нового правила с интервалом укажите время начала и окончания ежедневного перерыва на техническое обслуживание в минутах.
Перенесен
Установка обновлений системы откладывается на 30 дней. По окончании этого срока система предлагает пользователю установить обновление.

Периоды отсрочки

Каждое обновление можно отложить только один раз на 30 дней. Период начинается, когда система впервые откладывает обновление, и настройка новых правил отсрочки не продлевает его.

Помимо откладывания, Android может не установить обновление по другим причинам, например из-за отсутствия подключения, нехватки места на диске или низкого заряда батареи.

Если в течение 30-дневного периода появится новое обновление, система начнет отсчет заново. Это позволяет администраторам протестировать комбинированные обновления системы. Когда пройдет 30 дней без нового обновления, система предложит пользователю установить все доступные обновления. Позже, когда станет доступно новое обновление системы, 30-дневный период начнется заново.

Как настроить правило

Правила обновления можно настроить в Android 8.0 (уровень API 26) или более поздней версии. Чтобы указать, когда устройство должно устанавливать обновления системы, создайте экземпляр SystemUpdatePolicy, используя один из трех типов, описанных выше. Чтобы задать правило, владелец устройства вызывает метод DevicePolicyManager setSystemUpdatePolicy(). Ниже приведен пример кода. Пример политики с окном можно найти в документации по SystemUpdatePolicy.

Kotlin

// Create the system update policy to postpone installation for 30 days.
val policy = SystemUpdatePolicy.createPostponeInstallPolicy()

// Get a DevicePolicyManager instance to set the policy on the device.
val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE)
        as DevicePolicyManager
val adminName = getComponentName(context)

// Set the policy.
dpm.setSystemUpdatePolicy(adminName, policy)

Java

// Create the system update policy to postpone installation for 30 days.
SystemUpdatePolicy policy = SystemUpdatePolicy.createPostponeInstallPolicy();

// Get a DevicePolicyManager instance to set the policy on the device.
DevicePolicyManager dpm = (DevicePolicyManager) context
    .getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName adminName = getComponentName(context);

// Set the policy.
dpm.setSystemUpdatePolicy(adminName, policy);

Экземпляры правил нельзя изменить после создания. Чтобы изменить время установки обновлений на устройстве, создайте и настройте новое правило. Чтобы удалить правило с устройства, вызовите setSystemUpdatePolicy(), передав null в качестве аргумента policy. После того как контроллер политики удалит правило, пользователь устройства увидит уведомления обо всех доступных обновлениях системы.

Приложения могут вызывать getSystemUpdatePolicy(), чтобы получить текущие правила для устройства. Если метод возвращает null, значит правило не задано.

Периоды заморозки

Чтобы зафиксировать версию ОС на критические периоды, например праздники или другие периоды высокой загрузки, владельцы устройств могут приостановить обновления системы на срок до 90 дней. В период заморозки устройство ведет себя следующим образом:

  • Устройство не получает уведомления об ожидающих обновлениях системы.
  • Обновления ОС не устанавливаются.
  • Пользователи устройств не могут вручную проверять наличие обновлений системы в настройках.

Чтобы устройство не было заблокировано на неопределенный срок, система принудительно устанавливает обязательный 60-дневный буферный период после любого заданного периода заморозки. Помните, что заморозка обновлений системы может помешать устройствам получать критические обновления.

Рисунок 1. Для устройства задано два периода заморозки.
Календарь с двумя периодами заморозки в год и 60-дневными буферами.

Периоды заморозки задаются в правилах обновления. Вы не можете задать периоды заморозки, не настроив правила. Когда периоды без обновлений не действуют, применяется одно из стандартных правил: AUTOMATIC, WINDOWED или POSTPONE.

Как установить период заморозки

Периоды заморозки можно задать в Android 9 (уровень API 28) или более поздней версии. Владелец устройства устанавливает период заморозки в правилах обновления системы, прежде чем задать правила для устройства. Вот что нужно сделать:

  1. Создайте новое правило обновления системы или получите текущее.
  2. Задайте периоды заморозки в правиле, вызвав метод setFreezePeriods().
  3. Задайте правила и периоды заморозки для устройства, вызвав setSystemUpdatePolicy().

Поскольку период заморозки повторяется ежегодно, даты его начала и окончания представлены значениями месяца и дня. Новый период замораживания может начаться не ранее чем через 60 дней после окончания предыдущего. В примере ниже показано, как задать два периода заморозки для существующего правила обновления системы.

Kotlin

// Get the existing policy from the DevicePolicyController instance.
val policy = dpm.systemUpdatePolicy ?: return

try {
    // Set the two annual freeze periods on the policy for our retail
    // point-of-sale devices.
    val summerSale = FreezePeriod(
            MonthDay.of(6, 1),
            MonthDay.of(7, 31)) // Jun 1 - Jul 31 inclusive
    val winterSale = FreezePeriod(
            MonthDay.of(11, 20),
            MonthDay.of(1, 12)) // Nov 20 - Jan 12 inclusive
    policy.freezePeriods = Arrays.asList(summerSale, winterSale)

    // Set the policy again to activate the freeze periods.
    dpm.setSystemUpdatePolicy(adminName, policy)

} catch (e: SystemUpdatePolicy.ValidationFailedException) {
    // There must be previous periods recorded on the device because
    // summerSale and winterSale don’t overlap and are separated by more
    // than 60 days. Report the overlap ...
}

Java

// Get the existing policy from the DevicePolicyController instance.
SystemUpdatePolicy policy = dpm.getSystemUpdatePolicy();

try {
  // Set the two annual freeze periods on the policy for our
  // retail point-of-sale devices.
  FreezePeriod summerSale = new FreezePeriod(
      MonthDay.of(6, 1),
      MonthDay.of(7, 31)); // Jun 1 - Jul 31 inclusive
  FreezePeriod winterSale = new FreezePeriod(
      MonthDay.of(11, 20),
      MonthDay.of(1, 12)); // Nov 20 - Jan 12 inclusive
  policy.setFreezePeriods(Arrays.asList(summerSale, winterSale));

  // Don’t forget to set the policy again to activate the freeze periods.
  dpm.setSystemUpdatePolicy(adminName, policy);

} catch (SystemUpdatePolicy.ValidationFailedException e) {
  // There must be previous periods recorded on the device because summerSale
  // and winterSale don’t overlap and are separated by more than 60 days.
  // Report the overlap ...
}

Даты начала и окончания включаются в период. Если день начала больше дня окончания (например, winterSale в предыдущем примере), период заморозки продлевается на следующий год.

При настройке периодов заморозки в правилах обновления системы Android проверяет следующие требования:

  • Период без обновлений не должен превышать 90 дней.
  • Интервал между периодами заморозки составляет не менее 60 дней.
  • Периоды заморозки не пересекаются.
  • Нет повторяющихся периодов заморозки.

При настройке правил обновления системы для устройства Android повторяет эти проверки и учитывает все текущие или прошлые периоды заморозки для устройства.

Если любая из этих проверок не пройдена, Android выдает ошибку SystemUpdatePolicy.ValidationFailedException.

Чтобы получить список периодов заморозки, заданных ранее в объекте правил обновления системы, все установленные приложения могут вызвать метод SystemUpdatePolicy.getFreezePeriods(). В примере ниже этот метод вызывается для регистрации периодов заморозки устройства.

Kotlin

// Log any freeze periods that might be set on a system update policy.
dpm.systemUpdatePolicy?.freezePeriods?.forEach {
    Log.i(TAG, "Freeze period: $it")
}

Java

// Log any freeze periods that might be set on a system update policy.
SystemUpdatePolicy currentPolicy = dpm.getSystemUpdatePolicy();
if (currentPolicy != null) { // A policy might not be set.
  for (FreezePeriod freezePeriod : currentPolicy.getFreezePeriods()) {
    Log.i(TAG, "Freeze period: " + freezePeriod.toString());
  }
}

Високосные годы

Для расчета периодов заморозки Android использует календарь ISO 8601 (также известный как григорианский календарь) и игнорирует високосные годы. Это означает, что 29 февраля не распознается как действительная дата и обрабатывается как 28 февраля. Поэтому 29 февраля не учитывается при расчете продолжительности периода заморозки.

Разработка и тестирование

При разработке и тестировании функции обновления системы в контроллере политики устройств может потребоваться создать несколько периодов заморозки. Поскольку Android проверяет, прошло ли 60 дней с момента окончания предыдущего периода заморозки, вы не сможете установить новый период, не очистив запись о предыдущих. Чтобы удалить запись о периоде заморозки, выполните следующую команду в оболочке Android Debug Bridge (adb):

adb shell dpm clear-freeze-period-record

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

Обновление системы через Google Play (Mainline)

Обновления системы через Google Play (обновления Mainline) скачиваются автоматически. Чтобы их установить, необходима перезагрузка устройства. Она не происходит автоматически, а инициируется пользователем, администратором или выполнением правила. В последнем случае при перезагрузке устанавливается соответствующее обновление системы от Google/OEM и все ранее скачанные обновления системы через Google Play.

Чтобы установить их вручную, выберите Настройки > Об устройстве > Версия Android > Обновление системы через Google Play.

Как откатить обновление

В некоторых случаях для восстановления состояния устройства после проблемной установки обновления системы через Google Play можно использовать инструмент отката обновлений системы через Google Play (GPSUR). Этот инструмент предназначен для опытных пользователей. Его также можно использовать по указанию службы поддержки. В противном случае возможна потеря данных. Вот как использовать инструмент GPSUR:

  1. Если на вашем компьютере запущен Android Debug Bridge (adb), остановите его, чтобы он не мешал процессу отката. Чтобы остановить adb, выполните команду adb kill-server.
  2. Откройте инструмент GPSUR.
  3. Нажмите Allow ADB access (Разрешить доступ к ADB), чтобы инструмент мог взаимодействовать с тестовым устройством через ADB.
  4. Нажмите Добавить устройство.
  5. Выберите устройство из списка и нажмите Подключить. В этом списке может не быть полного названия устройства.
  6. На экране устройства выберите Всегда разрешать отладку с этого компьютера и нажмите ОК, чтобы разрешить подключение для отладки по USB.
  7. Выберите подключенное устройство в браузере.
  8. Если на устройстве есть доступные откаты, текст кнопки на странице должен измениться с Откаты недоступны на Откатить недавние обновления. Нажмите Откатить недавние обновления.
  9. Прочитайте предупреждения в окне Подтверждение отката и нажмите Подтвердить.
  10. Дождитесь завершения отката. После этого появится окно Откат выполнен и устройство перезагрузится. Теперь можно отключить устройство.

Дополнительные ресурсы

Дополнительную информацию об обновлениях системы можно найти в документации по беспроводным обновлениям на сайте Android Open Source Project.