Gerenciar atualizações do sistema

Este guia para desenvolvedores explica como o controlador de política de dispositivo (DPC, na sigla em inglês) pode gerenciar as atualizações do sistema Android em nome do usuário do dispositivo.

Introdução

Os dispositivos Android podem receber e instalar atualizações over the air (OTA) no software do sistema e do aplicativo. O Android notifica o usuário do dispositivo de que uma atualização do sistema está disponível e que o usuário do dispositivo pode instalar a atualização imediatamente ou mais tarde.

Usando seu DPC, um administrador de TI pode gerenciar as atualizações do sistema para o usuário do dispositivo. Os DPCs podem ter um dispositivo totalmente gerenciado (chamado de proprietário do dispositivo) ou um perfil de trabalho (chamado de proprietário do perfil). A Tabela 1 mostra como os proprietários de dispositivos podem gerenciar as atualizações do sistema, enquanto os do perfil só podem informar informações sobre atualizações do sistema.

Tabela 1: as tarefas disponíveis para DPCs dependem do modo proprietário

Tarefa Proprietário de dispositivo Perfil de proprietário
Verificar se há atualizações do sistema pendentes
Receber callbacks quando novas atualizações do sistema forem disponibilizadas
Definir uma política de atualização local para controlar quando o Android instala atualizações do sistema
Congelar a versão do SO em períodos críticos

Conferir se há atualizações pendentes

Uma atualização pendente é uma atualização do sistema para um dispositivo que ainda não foi instalado. O DPC pode ajudar os administradores de TI a verificar quais dispositivos têm atualizações do sistema pendentes e, talvez, solicitar que os usuários dos dispositivos instalem atualizações críticas imediatamente.

Os proprietários de dispositivos e de perfis com o Android 8.0 (nível 26 da API) ou versões mais recentes podem verificar se um dispositivo tem uma atualização do sistema pendente. Chame DevicePolicyManager.getPendingSystemUpdate(), que retorna null se o dispositivo estiver atualizado. Se uma atualização do sistema estiver pendente, o método retornará informações sobre a atualização.

Saiba mais sobre uma atualização pendente

Depois de chamar getPendingSystemUpdate(), você pode inspecionar o valor SystemUpdateInfo retornado para saber mais sobre a atualização pendente. O exemplo abaixo mostra como você pode descobrir quando uma atualização pendente foi disponibilizada pela primeira vez para o dispositivo:

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));
}

Callbacks do sistema

Quando uma atualização é disponibilizada, o sistema Android notifica os proprietários do dispositivo sobre a nova atualização. No Android 8.0 ou versões mais recentes, o sistema também notifica os proprietários de perfil.

Na subclasse DeviceAdminReceiver, substitua o callback onSystemUpdatePending(). Você não precisa registrar ou anunciar seu DPC para receber o callback. O sistema pode chamar esse método mais de uma vez para uma única atualização. Portanto, verifique o status da atualização antes de responder. Chame getPendingSystemUpdate() para saber mais sobre a atualização do sistema no callback. O exemplo a seguir mostra como fazer isso:

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.
    // ...
  }
}

Quando um sistema tem mais de um DPC, por exemplo, perfis de trabalho em dispositivos totalmente gerenciados, o proprietário do dispositivo e o proprietário do perfil recebem o callback.

Atualizar políticas

Um proprietário de dispositivo pode controlar quando as atualizações são instaladas definindo uma política de atualização do sistema local. Há três tipos de política de atualização do sistema:

Automático
Instala atualizações do sistema assim que elas são disponíveis (sem interação do usuário). A definição desse tipo de política instala imediatamente todas as atualizações pendentes que podem ser adiadas ou aguardando uma janela de manutenção.
Com janela
Instala atualizações do sistema durante uma janela de manutenção diária (sem interação do usuário). Defina o início e o término da janela de manutenção diária, em minutos, do dia, ao criar uma nova política em janela.
Adiado
Adia a instalação de atualizações do sistema por 30 dias. Após o período de 30 dias, o sistema vai solicitar que o usuário do dispositivo instale a atualização.

Períodos de adiamento

O sistema limita cada atualização a um adiamento de 30 dias. O período começa quando o sistema adia a atualização pela primeira vez, e a definição de novas políticas de adiamento não é estendida.

Além do adiamento, o Android pode não conseguir instalar uma atualização por outros motivos, como falta de conectividade, espaço em disco insuficiente ou pouca bateria.

O sistema redefine o timer de 30 dias se uma atualização diferente ficar disponível durante o período, permitindo que os administradores de TI testem as atualizações combinadas do sistema. Após 30 dias sem uma nova atualização, o sistema solicita que o usuário instale todas as atualizações pendentes. Mais tarde, quando uma nova atualização do sistema é disponibilizada, o período de 30 dias começa novamente.

Como definir uma política

Você pode definir políticas de atualização no Android 8.0 (nível 26 da API) ou versões mais recentes. Para especificar quando o dispositivo vai instalar atualizações do sistema, crie uma instância de SystemUpdatePolicy usando um dos três tipos descritos acima. Para definir uma política, o proprietário do dispositivo chama o método DevicePolicyManager setSystemUpdatePolicy(). O exemplo de código a seguir mostra como fazer isso. Para conferir um exemplo de política em janela, consulte a documentação de 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);

As instâncias de política não podem ser alteradas depois de criadas. Para mudar quando um dispositivo instala as atualizações, crie e defina uma nova política. Para remover uma política de um dispositivo, chame setSystemUpdatePolicy(), transmitindo null como o argumento policy. Depois que o DPC remove uma política, o usuário do dispositivo recebe notificações de quaisquer atualizações do sistema disponíveis.

Os apps podem chamar getSystemUpdatePolicy() para receber a política atual do dispositivo. Se esse método retornar null, isso significa que uma política não está definida no momento.

Períodos de congelamento

Para congelar a versão do SO em períodos críticos, como feriados ou outros horários de pico, os proprietários de dispositivos podem suspender as atualizações do sistema por até 90 dias. Quando um dispositivo está em um período de congelamento, ele se comporta da seguinte maneira:

  • O dispositivo não recebe notificações sobre atualizações pendentes do sistema.
  • As atualizações do sistema para o SO não foram instaladas.
  • Os usuários de dispositivos não podem verificar manualmente se há atualizações do sistema nas Configurações.

O sistema aplica um período de buffer obrigatório de 60 dias após qualquer período de congelamento definido para evitar que o dispositivo fique congelado indefinidamente. Lembre-se de que congelar as atualizações do sistema pode impedir que os dispositivos recebam atualizações críticas.

Figura 1. Dois períodos de congelamento definidos para um dispositivo
Agenda mostrando dois períodos de congelamento em um ano com buffers de 60 dias.

Você definiu períodos de congelamento em uma política de atualização. Não é possível definir períodos de congelamento sem definir uma política. Quando o dispositivo estiver fora dos períodos de congelamento definidos, o comportamento normal da política (automático, com janela ou adiado) será aplicado.

Como definir um período de congelamento

Você pode definir períodos de congelamento no Android 9 (nível 28 da API) ou versões mais recentes. Um proprietário de dispositivo define um período de congelamento em uma política de atualização do sistema antes de definir a política para o dispositivo. As etapas são:

  1. Crie uma nova política de atualização do sistema ou acesse a atual.
  2. Defina os períodos de congelamento na política chamando setFreezePeriods().
  3. Defina a política e os períodos de congelamento do dispositivo chamando setSystemUpdatePolicy().

Como o período de congelamento se repete anualmente, as datas de início e término do período são representadas por valores de mês e dia. A data de início precisa começar pelo menos 60 dias após o término de qualquer período de congelamento anterior. O exemplo a seguir mostra como definir dois períodos de congelamento para uma política de atualização do sistema:

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 ...
}

As datas de início e término são inclusivas. Se o dia de início for maior que o dia de término (como winterSale no exemplo anterior), o período de congelamento se estenderá até o ano seguinte.

Ao definir períodos de congelamento em uma política de atualização do sistema, o Android testa estes requisitos:

  • O período de congelamento é maior que 90 dias.
  • O intervalo entre os períodos de congelamento é de pelo menos 60 dias.
  • Os períodos de congelamento não se sobrepõem.
  • Não há períodos de congelamento duplicados.

Ao definir a política de atualização do sistema para um dispositivo, o Android repete esses testes e inclui todos os períodos de congelamento atuais ou passados para o dispositivo.

O Android gera uma SystemUpdatePolicy.ValidationFailedException quando um desses testes falha.

Para conferir uma lista de períodos de congelamento definidos anteriormente em um objeto de política de atualização do sistema, todos os apps instalados podem chamar SystemUpdatePolicy.getFreezePeriods(). O exemplo abaixo chama esse método para registrar os períodos de congelamento de um dispositivo:

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());
  }
}

Anos bissextos

O Android usa o calendário ISO 8601, também chamado de calendário gregoriano, para calcular períodos de congelamento e ignora anos bissextos. Isso significa que 29 de fevereiro não é reconhecido como uma data válida e é tratado como se fosse 28 de fevereiro. Portanto, 29 de fevereiro não é contabilizado no cálculo da duração de um período de congelamento.

Desenvolvimento e teste

Ao desenvolver e testar o recurso de atualização do sistema do DPC, pode ser necessário criar muitos períodos de congelamento. Como o Android verifica um intervalo de 60 dias entre os períodos de congelamento anteriores, talvez não seja possível definir um novo período sem limpar o registro dos períodos anteriores. Para limpar o registro do período de congelamento do dispositivo, execute o seguinte comando no shell do Android Debug Bridge (adb):

adb shell dpm clear-freeze-period-record

Você pode confirmar se um dispositivo está em período de congelamento verificando se a interface do usuário para atualizações do sistema está desativada.

Outros recursos

Para saber mais sobre atualizações do sistema, leia a documentação Atualizações OTA do Android Open Source Project.