확장 가능한 시간 관리

Android Automotive 운영체제(AAOS)는 자동차의 지능적인 시간 소스가 될 것으로 예상됩니다. 자동차의 시간 게이트웨이가 되는 것에는 고유한 어려움이 따릅니다. 일부 차량에서는 AAOS가 다른 온보딩 시스템을 위한 차량의 시간 소스 역할을 하고 여러 입력(예: TCU)에서 시계를 지능적으로 설정하는 기능을 제공해야 합니다.

기본 Android 시간 관리 아키텍처를 보장하기 위해 이 섹션에서는 플랫폼 수준에서 해결되는 일반적인 시간 문제를 설명합니다.

*확장 가능한 시간 관리(ETM)*는 파트너가 AAOS와 Android 외부의 다른 차량 시스템 간에 시간을 동기화할 수 있는 메커니즘과 API를 제공합니다. 이 기능은 이러한 다른 차량 시스템(ECU, BCM 장치, 대시 시계 등)이 CAN, 이더넷, 다른 수단을 통해 VHAL에 연결되어 있다고 가정합니다. 따라서 AAOS가 시간을 VHAL과 동기화하도록 설정하면 핵심 목표를 달성할 수 있습니다.

이 기능은 다음 작업을 실행하지 않습니다.

  • Android에 여러 유형의 시간 추가(예: SystemTimevDisplayTime을 구분)
  • VHAL이 다른 차량 시스템, ECU, BCM, 대시 시계에서 시간 값을 가져오고 설정하는 방법 해결. 이는 각 VHAL의 구현 세부정보로 간주됩니다. 이 콘텐츠는 시간 동기화 기능을 사용 설정하는 데 필요한 AAOS와 VHAL 간의 상호작용만 지정합니다.
  • TimeDetectorServiceTimeDetectorStrategy의 디자인 선택 및 구현 세부정보에 관한 자세한 내용은 자동 시간 감지를 참고하세요.
  • 원한다면 자동차에 여러 시간 소스를 추가하여 맞춤 VHAL 구현에 통합할 수 있습니다. 그러면 VHAL이 EXTERNAL_CAR_TIME 속성을 통해, 통합된 단일 시간 값을 전달합니다.
  • Google에서는 Android의 금융 거래에 관한 NIST 정밀도 타이밍과 같은 시간 정확성 표준에 관한 지원을 명시적으로 추가하지 않습니다. OEM은 시스템에 정확한 시간 소스를 제공해야 합니다.

Android의 시간 개선사항

Android 12에서는 제공된 위치 관리자 서비스를 통해 위성에서 시간을 가져오는 기능을 제공합니다. 공급업체는 시간 소스 우선순위 구성 오버레이를 통해 사용 설정된 시간 추천의 우선순위를 구성하는 오버레이를 제공할 수 있습니다. 핵심 Android 시간 소스는 다음과 같습니다.

  1. 텔레포니 스택, 네트워크 ID 및 시간대(NITZ)
  2. 수동 시간 선택
  3. 단순 네트워크 시간 프로토콜(SNTP)
  4. Android 12의 새로운 기능인 글로벌 항법 위성 시스템(GNSS)
  5. Android Automotive OS의 새로운 기능인 ExternalTime

용어

다음 용어는 이 페이지 전체에서 사용됩니다.

용어 정의
차체 제어 모듈(BCM) 차량의 전자 액세서리 모니터링 및 제어를 담당하는 전자 제어 장치의 일반적인 용어입니다.
계측 제어기 통신망(CAN) 직렬 통신 프로토콜입니다.
전자 제어 장치(ECU) ECU는 사용자 HAL 속성을 통해 Android 기반 인포테인먼트 시스템과 상호작용할 수 있습니다.
글로벌 항법 위성 시스템(GNSS) 우주에서 신호를 제공하는 위성으로 GNSS 수신기에 위치 및 타이밍 데이터를 전송합니다.
미국 국립 표준 기술 연구소(NIST) 정밀한 타임스탬프를 사용 설정합니다.
네트워크 ID 및 시간대(NITZ) 무선 네트워크를 통해 휴대기기에 현지 시간 및 날짜, 시간대, DST 오프셋과 네트워크 제공업체 ID 정보를 프로비저닝하는 메커니즘입니다.
실시간 통신(RTC) 모든 사용자가 정보를 즉시 또는 미미한 지연 시간으로 교환할 수 있는 통신 모드입니다.
단순 네트워크 시간 프로토콜(SNTP) 네트워크 시간 프로토콜(NTP)의 간소화된 버전입니다.
텔레매틱 컨트롤 유닛(TCU) 차량에 내장된 시스템으로 차량 추적을 제어합니다.

시간 동기화를 위한 새로운 VHAL 속성

확장 가능한 시간 관리는 Android와 다양한 ECU 또는 자동차에 설치된 장치 간의 시간 동기화를 위해 VHAL에 새로운 속성을 2가지 추가합니다.

  • EXTERNAL_CAR_TIME. ECU나 BCM, 기타 차량 시스템(AAOS 외부)에서 AAOS로 시간을 동기화합니다.
  • EPOCH_TIME. AAOS에서 ECU나 BCM, 기타 차량 시스템으로 시간을 동기화합니다.

VHAL은 단일 시간 소스를 확인하여 다른 장치에 전달합니다. AAOS는 시간 정보 소스일 수도 있고 아닐 수도 있습니다.

  • Android가 시간 정보 소스로 선택되면 VHAL은 Android에서 다른 차량 시스템(예: ECU, BCM)으로 시간 변경사항을 전달하는 쓰기 전용 속성 EPOCH_TIME을 지원합니다.
  • Android가 시간 정보 소스로 선택되지 않으면 VHAL은 Android에서 다른 차량 시스템(예: ECU, BCM)으로 시간 변경사항을 전달하는 읽기 전용 속성 EXTERNAL_CAR_TIME을 지원합니다.
EXTERNAL_CAR_TIME EPOCH_TIME
(마스터 브랜치의 ANDROID_TIME)
VHAL > Android Android > VHAL

에포크 시간(Android)

지원되는 경우 AAOS는 이 속성에 작성하여 Android 시스템 시간을 VHAL에 전달합니다. AAOS는 CarServices가 초기화될 때 한 번, 그리고 INTENT_ACTION_TIME_CHANGED에서 알 수 있듯이 AAOS 시간 소스가 변경될 때마다 이 속성에 작성합니다. 이는 다른 차량 시스템(예: 대시 시계)과 ECU를 Android 시간과 동기화하는 데 유용할 수 있습니다. VHAL 구현은 다른 연결된 시스템과 ECU에 전달될 수 있는 시간 값 및 업데이트를 Android에서 수신합니다. 이 속성이 지원되는 경우 일반적으로 Android가 시간 정보 소스입니다.

새로운 VHAL 속성 두 개가 제공됩니다. 하나는 Android에서 ECU로의 통신용 EPOCH_TIME이고 다른 하나는 ECU에서 Android로의 통신용 EXTERNAL_CAR_TIME입니다. 일반적으로 OEM은 이러한 속성 중 하나만 구현해야 합니다.

AAOS 관련 공급업체, 하드웨어, 인터페이스, 맞춤 공급업체 시간 소스는 다음과 같습니다.

하루 중 특정 시간(ToD) OEM 백엔드
단순 네트워크 시간 프로토콜(SNTP) OEM 백엔드
온보딩 ECU(예: BCM). 다음이 포함될 수 있음

OEM은 이를 단일 시간으로 통합하고 EXTERNAL_CAR_TIME을 사용하여 Android에 전달해야 합니다. 그러면 Android에서 이 값을 사용하여 시스템 시간을 구성된 우선순위에 따라 고려합니다.

EPOCH_TIME

  /**
     * Current date and time, encoded as Unix time (in milliseconds).
     * This value denotes the number of milliseconds seconds that have
     * elapsed since 1/1/1970 UTC.
     *
     * AAOS will write to this value to give VHAL the Android system's time,
     * if the VHAL supports this property. This can be useful to synchronize
     * other vehicle systems (dash clock etc) with Android's time.
     *
     * AAOS writes to this property once during boot, and
     * will thereafter write only when some time-source changes are propagated.
     * AAOS will fill in VehiclePropValue.timestamp correctly.
     * Note that AAOS will not send updates for natural elapse of time.
     *     int64Values[0] = provided Unix time (in milliseconds)
     *
     * Note that the property may take >0 ms to get propagated through the stack
     * and, having a timestamped property helps reduce any time drift. So,
     * for all writes to the property, the timestamp can be used to negate this
     * drift:
     *     drift = currentTimeMillis - PropValue.timestamp
     *     effectiveTime = PropValue.value.int64Values[0] + diff
     *
     * Aside, this property could have been better named ANDROID_EPOCH_TIME, but it
     * continues to be called EPOCH_TIME for legacy reasons. We will try to fix
     * this naming discrepancy when we migrate to AIDL.
     *
     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
     * @access VehiclePropertyAccess:WRITE_ONLY
     * @unit VehicleUnit:MILLI_SECS
     */
    EPOCH_TIME = (
        0xxxxx
        | VehiclePropertyGroup:SYSTEM
        | VehiclePropertyType:INT64
        | VehicleArea:GLOBAL),

외부 자동차 시간

컴파일 시 OEM에서 외부 시간을 구성한 경우, Android에서 자체 시스템 시간을 설정하는 데 외부 시간을 사용할 수 있습니다. AAOS는 이 속성을 구독하고 읽어서 ExternalTimeSuggestion을 생성하고 이를 TimeManager 서비스에 전달합니다. 이는 Android의 시간을 다른 차량 시스템(예: 대시 시계) 및 ECU와 동기화하는 데 유용합니다. VHAL 구현은 부팅할 때와 시계 동기화가 변경될 때마다 이 속성에 쓸 것으로 예상됩니다. VHAL 구현은 시간의 자연스러운 진행을 위해 이 속성에 쓸 것으로 예상되지 않습니다. 일반적으로 이 속성이 지원되면 Android는 시간 정보 소스가 아닙니다.

  /**
     * Current date and time for the Car, encoded as Unix time (in milliseconds).
     * This value denotes the number of milliseconds seconds that have
     * elapsed since 1/1/1970 UTC.
     *
     * This property signals a change in CarTime to Android. VHAL must report the
     * most accurate current CarTime when this property is read, and publish a
     * change to this property when the CarTime value has changed.
     * Android will read and subscribe to this property to fetch time from VHAL,
     * if the property is supported. This can be useful to synchronize Android's
     * time with other vehicle systems (dash clock etc).
     *     int64Values[0] = provided Unix time (in milliseconds)
     *
     * Whenever a new Value for the property is received, AAOS will create
     * and send an "ExternalTimeSuggestion" to the "TimeDetectorService".
     * If other sources do not have a higher priority, Android will use this
     * to set the system time. For information on how to adjust time source
     * priorities and how time suggestions are handled (including how Android
     * handles gitter, drift, and minimum resolution) see Time Detector Service
     * documentation.
     *
     * Note that the property may take >0 ms to get propagated through the stack
     * and, having a timestamped property helps reduce any time drift. So,
     * for all writes to the property, the timestamp can be used to negate this
     * drift:
     *     drift = currentTimeMillis - PropValue.timestamp
     *     effectiveTime = PropValue.value.int64Values[0] + diff
     *
     * WARNING: It is recommended to use Android's own systems for GNSS, NTP,
     * Telephony etc. instead of wiring those through the VHAL using this property.
     *
     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
     * @access VehiclePropertyAccess:READ_ONLY
     * @unit VehicleUnit:MILLI_SECS
     */
    EXTERNAL_CAR_TIME = (
        0xxxxx
        | VehiclePropertyGroup:SYSTEM
        | VehiclePropertyType:INT64
        | VehicleArea:GLOBAL),

ExternalTime 및 ExternalTimeSuggestion

TimeManager 서비스에 ExternalTime을 추천하는 새 경로를 추가합니다. TimeDetectorService(및 이에 상응하는 TimeManager)는 여러 다양한 시간 소스를 사용합니다. 현재 Android에서 시스템 시계를 설정하는 데 사용할 수 있는 3가지 시간 소스는 텔레포니 스택의 네트워크 ID 및 시간대(NITZ), 네트워크 시간 프로토콜(NTP), 사용자가 제공한 수동 시간입니다.

ExternalTime은 AAOS 플랫폼을 타겟팅하기 위해 만들어진 새로운 시간 소스입니다. Android 시간을 자동차 내 ECU 또는 BCM 장치와 동기화하는 데 유용합니다(하지만 여전히 Android 외부에 있음). ExternalTime은 구성 가능한 우선순위를 사용하여 시스템 시간 소스로 올바르게 연결됩니다. TimeDetectorStrategy 구성에서 적절하게 구성되면 외부 시간이 다른 시간 소스보다 우선합니다.

다음 시퀀스 다이어그램은 새 디자인을 보여줍니다.

그림 1: 시퀀스 다이어그램

여러 속성 지원

OEM은 EPOCH_TIMEEXTERNAL_CAR_TIME 속성을 모두 지원하도록 선택할 수 있습니다.

예를 들어 자동차에 특정 시간 소스(예: DCF77)에 연결된 ECU가 있지만 값은 Android 내의 다른 소스(예: GNSS나 NTP, 텔레포니)를 사용한 확인을 위해 Android에 전달해야 하는 경우입니다. 이 경우 OEM은 EXTERNAL_CAR_TIME을 통해 ECU의 시간 값을 Android에 전달하고 EPOCH_TIME을 사용하여 확인된 시스템 시간을 수신할 수 있습니다. 그런 다음 이를 사용하여 다른 주변기기의 시간을 설정합니다.

Android 시스템과 VHAL 구현 간의 정보 흐름에서 피드백 루프를 방지하는 것이 중요합니다. 따라서 두 속성을 모두 지원하는 OEM의 유일한 제약조건은 EXTERNAL_CAR_TIME을 통해 제공되는 값이 어떠한 방식으로도 EPOCH_TIME에서 수신한 값에 종속되어서는 안 된다는 점입니다.

Intent.ACTION_TIME_CHANGED의 BroadcastReceiver 등록

TimeHalService(자동차 서비스의 새 클래스)는 VHAL 속성 EPOCH_TIME에 쓸 수 있도록 Intent.ACTION_TIME_CHANGEDBroadcastReceiver를 등록하여 VHAL에 Android 시스템 시간의 변경사항을 알립니다.

외부 시간을 추천하는 새로운 TimeManager API

시간 추천 기능은 android.app.time.TimeManager#suggestExternalTime()이라는 새로운 Android @SystemAPI를 통해 노출됩니다. 이 메서드는 TimeDetectorService#suggestExternalTime에 추천을 전달하는데, 이는 결과적으로 TimeDetectorStrategy#suggestExternalTime에 전달됩니다. TimeDetectorStrategy는 마지막 ExternalTimeSuggestion 인스턴스를 추적하고 원래 external이 시간 detectorstrategy 구성에서 우선순위가 지정된 경우 이 추천을 사용합니다.

새 SUGGEST_EXTERNAL_TIME 권한

SUGGEST_EXTERNAL_TIME이라는 새로운 권한이 추가되었습니다. TimeManager.sugestExternalTime() API는 이 권한으로 관리되어 서드 파티 개발자가 SUGGEST_EXTERNAL_TIME 권한으로 호출할 수 있도록 합니다. 새 권한은 privileged 보호 수준으로 표시됩니다. 이로 인해 시스템 이미지에 사전 설치된 서드 파티 앱에 이 권한이 잠재적으로 부여될 수 있지만 이는 허용됩니다.

  • 서드 파티 앱에 이 권한을 부여하려면 OEM 조정이 필요하므로 '권한이 있는'을 추가하더라도 큰 위험이 발생하지는 않습니다.
  • 이 API는 추천된 타임스탬프가 즉시 새 시스템 타임스탬프로 사용된다는 것을 보장하지 않습니다. ExternalTimeSuggestion을 사용하려면 외부 시간 소스가 다른 시간 소스(예: GNSS)보다 우선순위가 높도록 시스템을 구성해야 합니다. 이 구성은 OEM에서 실행합니다.
  • 앱은 TimeManager.setTime()을 직접 사용하여 시스템 시간을 설정할 수 있고 그러려면 SET_TIME 권한이 필요합니다. 이 새로운 권한과 API 모델도 권한이 있으며 기존 API와 일치합니다.

시간 확장성 구현

이 새로운 기능의 고품질 구현을 보장하려면 새로운 VHAL 속성을 사용하고 값을 올바르게 전파하도록 AAOS를 구성하는 방법을 OEM이 알아야 합니다. 이 섹션은 각 OEM이 시간 확장성을 배포하고 구성하려는 대상 및 방법을 결정할 수 있도록 OEM에 제공됩니다.

AAOS 시간 소스 구성

AAOS는 OEM이 자동차의 다양한 장치(Android, ECR, BCM 등) 간에 시간을 동기화하는 방법을 결정할 수 있도록 VHAL 속성 2가지(EPOCH_TIMEEXTERNAL_CAR_TIME)와 구성 가능한 TimeDetectorStrategy를 지원합니다. 먼저 OEM은 단일 시간 정보 소스가 무엇인지 결정해야 합니다. Android의 관점에서 이는 Android 또는 외부 소스(예: ECU나 BCM, 대시 시계)입니다.

이러한 경우 OEM은 다른 자동차 시스템(예: ECU, BCM)을 AAOS 시간과 동기화하는 것이 좋습니다. 이렇게 하려면 VHAL은 쓰기 전용 속성 EPOCH_TIME을 지원하고 AAOS가 이 속성에 시스템 시간을 쓸 때마다 수신된 업데이트를 처리하거나 전달해야 합니다.

흐름은 아래에 설명되어 있습니다.

  1. VHAL은 EPOCH_TIME VHAL 속성을 통해 Android의 시스템 시간을 수신합니다.
  2. TimeHalService는 부팅할 때와 Android의 시간 소스가 동기화될 때마다 시스템 시간을 읽어 이 속성에 씁니다.
  3. VHAL은 수신된 시간 값을 다양한 ECU 및 BCM 장치에 전파할 수 있습니다.

Android가 시간 소스 역할을 하지 않는 경우

이러한 경우 OEM은 시간 정보 소스인 자동차 시스템(예: ECU 또는 BCM)과 AAOS 시간을 동기화하는 것이 좋습니다. 이렇게 하려면 VHAL은 읽기 전용 속성 EXTERNAL_CAR_TIME을 지원하고 시간 소스가 시계를 변경하거나 재보정할 때마다 이 속성 업데이트를 게시해야 합니다.

또한 EM은 TimeDetectorStrategy 구성에서 xexternal 시간이 적절한 우선순위를 갖는지 확인해야 합니다.

<!-- Specifies priority of automatic time sources. Suggestions from higher entries in the list take precedence over lower ones.
See com.android.server.timedetector.TimeDetectorStrategy for available sources. -->
     <string-array name="config_autoTimeSourcesPriority">
        <item>external</item>
        <item>gnss</item>
        <item>network</item>
        <item>telephony</item>
    </string-array>

흐름은 다음과 같이 요약됩니다.

  1. VHAL은 EXTERNAL_CAR_TIME 속성을 업데이트합니다.
  2. CarServices의 TimeHalService는 구독을 통해 속성을 읽습니다.
  3. TimeHalServiceExternalTimeSuggestion을 만들어 TimeManager.로 전송합니다.
  4. TimeManager는 이 추천을 TimeDetectorService.로 전달합니다.
  5. TimeDetectorServiceTimeDetectorStrategy를 사용하여 새로운 시스템 시간을 선택합니다.

부록 A, 속성 변경사항

EPOCH_TIME

TimeHalService는 속성이 VHAL에서 지원하는 것으로 보고되는 경우 EPOCH_TIME을 지원하는 다음 기능을 제공합니다.

  1. 부팅 시 EPOCH_TIME 속성에 시스템 시간을 씁니다.
  2. Intent.ACTION_TIME_CHANGED용 BroadcastReceiver를 등록하고 브로드캐스트가 수신될 때마다 시스템 시간을 EPOCH_TIME 속성에 씁니다.
public class TimeHalService extends HalServiceBase {
    …

    @Override
    public void init() {
        updateProperty(System.currentTimeMillis());

        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_TIME_CHANGED);

        mReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) {
                    updateProperty(System.currentTimeMillis());
                }
            }
        };

        mContext.registerReceiver(
                mReceiver, filter, /* broadcastPermissions = */ null,
                new Handler(Looper.myLooper()));
    }

    private void updateProperty(long timeMillis) {
        VehiclePropValue propValue = new VehiclePropValue();
        propValue.prop = VehicleProperty.EPOCH_TIME;
        propValue.areaId = VehicleArea.GLOBAL;
        propValue.status = VehiclePropertyStatus.AVAILABLE;
        propValue.timestamp = timeMillis;
        propValue.value.int64Values.add(timeMillis);

        Slogf.d(TAG, "Sending Android Time: " + propValue);
        mHal.set(propValue);
    }
}

EXTERNAL_TIME

TimeHalService는 속성이 VHAL에서 지원하는 것으로 보고되는 경우 EXTERNAL_CAR_TIME을 지원하는 다음 기능을 제공합니다.

  1. 가능한 경우 EXTERNAL_CAR_TIME 속성을 구독합니다.
  2. EXTERNAL_CAR_TIME 값이 수신되면 ExternalTimeSuggestion을 만들어 TimeManager 서비스로 전송합니다.
public class TimeHalService extends HalServiceBase {
    private static final float SAMPLE_FREQ_HZ = 1.0 / 60 / 60;

    …

    @Override
    public void init() {
        VehiclePropValue propValue = mHal.get(VehicleProperty.EXTERNAL_CAR_TIME);
        suggestExternalTime(propValue);

        mHal.subscribeProperty(this, EPOCH_TIME, SAMPLE_FREQ_HZ);
    }

    @Override
    public void onHalEvents(List<VehiclePropValue> values) {
        for (VehiclePropValue value : values) {
            suggestExternalTime(value);
        }
    }

    private void suggestExternalTime(VehiclePropValue value) {
        if (value.prop != VehicleProperty.EXTERNAL_CAR_TIME
             || value.status != VehiclePropertyStatus.AVAILABLE) {
            return;
        }

        long epochTime = value.value.int64Values.get(0);
        // timestamp is stored in nanoseconds but the suggest API uses
        // milliseconds.
        long elapsedRealtime = value.timestamp / 1_000_000;

        mLastExternalTimeSuggestion =
            new ExternalTimeSuggestion(elapsedRealtime, epochTime);

        Slogf.d(TAG, "Sending Time Suggestion: " + mLastExternalTimeSuggestion);
        mTimeManager.suggestExternalTime(mLastExternalTimeSuggestion);
    }
}