1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.car.hal; 18 19 import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.EPOCH_TIME; 20 21 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DUMP_INFO; 22 23 import static java.util.Objects.requireNonNull; 24 25 import android.annotation.Nullable; 26 import android.content.BroadcastReceiver; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.IntentFilter; 30 import android.hardware.automotive.vehicle.V2_0.VehicleArea; 31 import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig; 32 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue; 33 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyStatus; 34 import android.util.IndentingPrintWriter; 35 36 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport; 37 38 import java.io.PrintWriter; 39 import java.time.Instant; 40 import java.util.Collection; 41 import java.util.List; 42 43 /** Writes the Android System time to EPOCH_TIME in the VHAL, if supported. */ 44 public final class TimeHalService extends HalServiceBase { 45 46 private static final int[] SUPPORTED_PROPERTIES = new int[]{EPOCH_TIME}; 47 48 private final Context mContext; 49 50 private final VehicleHal mHal; 51 52 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 53 @Override 54 public void onReceive(Context context, Intent intent) { 55 if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) { 56 updateProperty(System.currentTimeMillis()); 57 } 58 } 59 }; 60 61 private boolean mReceiverRegistered; 62 63 @Nullable 64 private Instant mLastAndroidTimeReported; 65 66 private boolean mAndroidTimeSupported; 67 TimeHalService(Context context, VehicleHal hal)68 TimeHalService(Context context, VehicleHal hal) { 69 mContext = requireNonNull(context); 70 mHal = requireNonNull(hal); 71 } 72 73 @Override init()74 public void init() { 75 if (!mAndroidTimeSupported) { 76 return; 77 } 78 79 updateProperty(System.currentTimeMillis()); 80 81 IntentFilter filter = new IntentFilter(Intent.ACTION_TIME_CHANGED); 82 mContext.registerReceiver(mReceiver, filter); 83 mReceiverRegistered = true; 84 } 85 86 @Override release()87 public void release() { 88 if (mReceiverRegistered) { 89 mContext.unregisterReceiver(mReceiver); 90 mReceiverRegistered = false; 91 } 92 93 mAndroidTimeSupported = false; 94 mLastAndroidTimeReported = null; 95 } 96 97 @Override getAllSupportedProperties()98 public int[] getAllSupportedProperties() { 99 return SUPPORTED_PROPERTIES; 100 } 101 102 @Override takeProperties(Collection<VehiclePropConfig> properties)103 public void takeProperties(Collection<VehiclePropConfig> properties) { 104 for (VehiclePropConfig property : properties) { 105 switch (property.prop) { 106 case EPOCH_TIME: 107 mAndroidTimeSupported = true; 108 return; 109 } 110 } 111 } 112 113 @Override onHalEvents(List<VehiclePropValue> values)114 public void onHalEvents(List<VehiclePropValue> values) { 115 } 116 isAndroidTimeSupported()117 public boolean isAndroidTimeSupported() { 118 return mAndroidTimeSupported; 119 } 120 updateProperty(long timeMillis)121 private void updateProperty(long timeMillis) { 122 VehiclePropValue propValue = new VehiclePropValue(); 123 propValue.prop = EPOCH_TIME; 124 propValue.areaId = VehicleArea.GLOBAL; 125 propValue.status = VehiclePropertyStatus.AVAILABLE; 126 propValue.timestamp = timeMillis; 127 propValue.value.int64Values.add(timeMillis); 128 129 mHal.set(propValue); 130 mLastAndroidTimeReported = Instant.ofEpochMilli(timeMillis); 131 } 132 133 @Override 134 @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO) dump(PrintWriter printWriter)135 public void dump(PrintWriter printWriter) { 136 IndentingPrintWriter writer = new IndentingPrintWriter(printWriter); 137 writer.println("*ExternalTime HAL*"); 138 writer.increaseIndent(); 139 writer.printf( 140 "mLastAndroidTimeReported: %d millis", 141 mLastAndroidTimeReported.toEpochMilli()); 142 writer.decreaseIndent(); 143 writer.flush(); 144 } 145 } 146