Prioridade da fonte de tempo

O framework do Android usa várias fontes de tempo para sincronização. O foco desta página são as origens de tempo automáticas Network Time Protocol (NTP) e Network Identity and Time Zone (NITZ). Por padrão, no Android 12 ou versões mais recentes, o framework prioriza o NTP como a fonte de tempo em vez do NITZ, porque ele é mais preciso e confiável do que o NITZ. Em situações em que o NTP não está disponível, a estrutura usa NITZ. Isso é uma inversão da prioridade padrão em relação às versões anteriores da plataforma. Por padrão, no Android 11 e versões anteriores, o framework prioriza o NITZ em vez de NTP.

Para mais detalhes sobre essa mudança, consulte os seguintes patches do AOSP: 1563678, 1513323 (links em inglês).

Configurar a prioridade da fonte de horário

Para configurar qual origem de tempo tem prioridade por padrão para uma versão específica do Android, configure a chave config_autoTimeSourcesPriority em frameworks/base/core/res/res/values/config.xml durante o build. As sugestões de horário da fonte com o valor mais alto na lista têm precedência sobre as fontes com valores mais baixos na lista.

As origens de horário do Android que podem ser configuradas são encontradas em TimeDetectorStrategy.java. As origens a seguir estão configuradas para uso por padrão:

  • Telefonia (NITZ)
  • Rede (NTP)

Testes

Para verificar se o dispositivo usa o NITZ quando ele não está disponível (quando os dados móveis e o Wi-Fi estão desativados), faça o seguinte:

  1. Verifique se há um chip funcionando no DUT
  2. Desative os dados móveis e o Wi-Fi
  3. Coloque o dispositivo no modo avião para verificar se o rádio celular está desligado
  4. Desativar a detecção automática de tempo
  5. Definir o relógio manualmente para um valor de hora incorreto no futuro
  6. Reinicialize o dispositivo.
  7. Ativar a detecção automática de tempo
  8. Tire o dispositivo do modo avião

Estas etapas acionam uma mudança no relógio do sistema assim que um sinal NITZ é recebido. Para conferir como o horário do dispositivo está definido, execute o comando abaixo:

adb shell dumpsys time_detector

Para verificar se o relógio do sistema usa o NITZ, confirme o seguinte na resposta ao comando:

  • A mEnvironment.isAutoTimeDetectionEnabled() está true.
  • mEnvironment.autoOriginPriorities() contém uma lista de fontes de horário em que as fontes mais altas na lista têm precedência sobre as fontes mais baixas na lista.
  • A seção Time change log mostra que o relógio do sistema está definido usando uma sugestão de telefonia.
  • A seção Telephony suggestion history contém sugestões de horários.
  • A seção Network suggestion history está vazia.

As sugestões de horário nas seções Telephony suggestion history e Network suggestion history são consideradas a fonte da verdade para o tempo. Se o dispositivo estiver conectado à Internet e tiver um chip, as sugestões serão geradas usando NTP (rede) e NITZ (telefonia). Neste caso de teste, somente a seção Telephony suggestion history contém sugestões porque o NTP está desativado.

A seção Time change log registra as mudanças feitas no relógio do sistema do dispositivo e a sugestão usada. O relógio do sistema é definido com base na ordem das fontes de horário na lista de prioridades na chave config_autoTimeSourcesPriority. No entanto, as sugestões de uma fonte de prioridade mais alta poderão ser ignoradas se a sugestão for muito antiga ou inválida. Além disso, se a sugestão válida de maior prioridade corresponder ao horário do relógio do sistema atual do dispositivo em alguns segundos, o horário não vai ser mudado. Nesse caso de teste, desde que as sugestões não estejam desatualizadas, o relógio do sistema será definido usando uma das sugestões do Telephony suggestion history.

Confira abaixo um exemplo de saída em que o dispositivo volta a usar o NITZ quando o NTP está indisponível.

TimeDetectorStrategy:
  mLastAutoSystemClockTimeSet=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}
  mEnvironment.isAutoTimeDetectionEnabled()=true
  mEnvironment.elapsedRealtimeMillis()=73059
  mEnvironment.systemClockMillis()=1614186767818
  mEnvironment.systemClockUpdateThresholdMillis()=2000
  mEnvironment.autoTimeLowerBound()=2021-02-24T15:44:15Z(1614181455000)
  mEnvironment.autoOriginPriorities()=[network,telephony]
  Time change log:
    66261 / 2021-02-24T17:12:41.020Z - Set system clock using time=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000} cause=Found good telephony suggestion., bestTelephonySuggestion=TelephonyTimeSuggestion{mSlotIndex='0', mUtcTime=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}, mDebugInfo=[Sending new time suggestion nitzSignal=TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}}, reason=handleNitzReceived(TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}})]}, detectionReason=New telephony time suggested. timeSuggestion=TelephonyTimeSuggestion{mSlotIndex='0', mUtcTime=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}, mDebugInfo=[Sending new time suggestion nitzSignal=TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}}, reason=handleNitzReceived(TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}})]} elapsedRealtimeMillis=66259 newSystemClockMillis=1614186761019
  Telephony suggestion history:
    key idx: 0=0
    val idx: 0=TelephonyTimeSuggestion{mSlotIndex='0', mUtcTime=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}, mDebugInfo=[Sending new time suggestion nitzSignal=TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}}, reason=handleNitzReceived(TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}})]}
      Historic values=[
        0@PT1M6.258S: TelephonyTimeSuggestion{mSlotIndex='0', mUtcTime=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}, mDebugInfo=[Sending new time suggestion nitzSignal=TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}}, reason=handleNitzReceived(TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}})]}
      ]
  Network suggestion history:
    {Empty}
  Gnss suggestion history:
    {Empty}
  External suggestion history:
    {Empty}

Para referência como uma comparação com a saída no cenário de teste, veja a seguir um exemplo de saída típica em que o dispositivo recebe sugestões de horário de fontes de horário NTP e NITZ.

TimeDetectorStrategy:
  mLastAutoSystemClockTimeSet=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}
  mEnvironment.isAutoTimeDetectionEnabled()=true
  mEnvironment.elapsedRealtimeMillis()=302926
  mEnvironment.systemClockMillis()=1614186997685
  mEnvironment.systemClockUpdateThresholdMillis()=2000
  mEnvironment.autoTimeLowerBound()=2021-02-24T15:44:15Z(1614181455000)
  mEnvironment.autoOriginPriorities()=[network,telephony]
  Time change log:
    66261 / 2021-02-24T17:12:41.020Z - Set system clock using time=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000} cause=Found good telephony suggestion., bestTelephonySuggestion=TelephonyTimeSuggestion{mSlotIndex='0', mUtcTime=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}, mDebugInfo=[Sending new time suggestion nitzSignal=TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}}, reason=handleNitzReceived(TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}})]}, detectionReason=New telephony time suggested. timeSuggestion=TelephonyTimeSuggestion{mSlotIndex='0', mUtcTime=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}, mDebugInfo=[Sending new time suggestion nitzSignal=TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}}, reason=handleNitzReceived(TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}})]} elapsedRealtimeMillis=66259 newSystemClockMillis=1614186761019
  Telephony suggestion history:
    key idx: 0=0
    val idx: 0=TelephonyTimeSuggestion{mSlotIndex='0', mUtcTime=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}, mDebugInfo=[Sending new time suggestion nitzSignal=TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}}, reason=handleNitzReceived(TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}})]}
      Historic values=[
        0@PT1M6.258S: TelephonyTimeSuggestion{mSlotIndex='0', mUtcTime=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}, mDebugInfo=[Sending new time suggestion nitzSignal=TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}}, reason=handleNitzReceived(TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}})]}
      ]
  Network suggestion history:
    0@PT4M4.04S: NetworkTimeSuggestion{mUtcTime=TimestampedValue{mReferenceTimeMillis=244038, mValue=1614186939242}, mDebugInfo=[Origin: NetworkTimeUpdateService. event=3]}
  Gnss suggestion history:
    {Empty}
  External suggestion history:
    {Empty}