1 /* 2 * Copyright 2019 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.internal.telephony.nitz; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.app.timedetector.TelephonyTimeSuggestion; 22 import android.app.timedetector.TimeDetector; 23 import android.app.timezonedetector.TelephonyTimeZoneSuggestion; 24 import android.app.timezonedetector.TimeZoneDetector; 25 import android.content.Context; 26 import android.os.SystemClock; 27 import android.os.TimestampedValue; 28 import android.util.LocalLog; 29 30 import com.android.internal.telephony.Phone; 31 import com.android.internal.telephony.metrics.TelephonyMetrics; 32 import com.android.internal.util.IndentingPrintWriter; 33 34 import java.io.PrintWriter; 35 import java.util.Objects; 36 37 /** 38 * The real implementation of {@link TimeServiceHelper}. 39 */ 40 public final class TimeServiceHelperImpl implements TimeServiceHelper { 41 42 private final int mSlotIndex; 43 private final TimeDetector mTimeDetector; 44 private final TimeZoneDetector mTimeZoneDetector; 45 46 private final LocalLog mTimeZoneLog = new LocalLog(30, false /* mUseLocalTimestamps */); 47 private final LocalLog mTimeLog = new LocalLog(30, false /* mUseLocalTimestamps */); 48 49 /** 50 * Records the last time zone suggestion made. Used to avoid sending duplicate suggestions to 51 * the time zone service. The value can be {@code null} to indicate no previous suggestion has 52 * been made. 53 */ 54 @NonNull 55 private TelephonyTimeZoneSuggestion mLastSuggestedTimeZone; 56 TimeServiceHelperImpl(@onNull Phone phone)57 public TimeServiceHelperImpl(@NonNull Phone phone) { 58 mSlotIndex = phone.getPhoneId(); 59 Context context = Objects.requireNonNull(phone.getContext()); 60 mTimeDetector = Objects.requireNonNull(context.getSystemService(TimeDetector.class)); 61 mTimeZoneDetector = 62 Objects.requireNonNull(context.getSystemService(TimeZoneDetector.class)); 63 } 64 65 @Override suggestDeviceTime(@onNull TelephonyTimeSuggestion timeSuggestion)66 public void suggestDeviceTime(@NonNull TelephonyTimeSuggestion timeSuggestion) { 67 mTimeLog.log("Sending time suggestion: " + timeSuggestion); 68 69 Objects.requireNonNull(timeSuggestion); 70 71 if (timeSuggestion.getUtcTime() != null) { 72 TimestampedValue<Long> utcTime = timeSuggestion.getUtcTime(); 73 TelephonyMetrics.getInstance().writeNITZEvent(mSlotIndex, utcTime.getValue()); 74 } 75 mTimeDetector.suggestTelephonyTime(timeSuggestion); 76 } 77 78 @Override maybeSuggestDeviceTimeZone(@onNull TelephonyTimeZoneSuggestion newSuggestion)79 public void maybeSuggestDeviceTimeZone(@NonNull TelephonyTimeZoneSuggestion newSuggestion) { 80 Objects.requireNonNull(newSuggestion); 81 82 TelephonyTimeZoneSuggestion oldSuggestion = mLastSuggestedTimeZone; 83 if (shouldSendNewTimeZoneSuggestion(oldSuggestion, newSuggestion)) { 84 mTimeZoneLog.log("Suggesting time zone update: " + newSuggestion); 85 mTimeZoneDetector.suggestTelephonyTimeZone(newSuggestion); 86 mLastSuggestedTimeZone = newSuggestion; 87 } 88 } 89 shouldSendNewTimeZoneSuggestion( @ullable TelephonyTimeZoneSuggestion oldSuggestion, @NonNull TelephonyTimeZoneSuggestion newSuggestion)90 private static boolean shouldSendNewTimeZoneSuggestion( 91 @Nullable TelephonyTimeZoneSuggestion oldSuggestion, 92 @NonNull TelephonyTimeZoneSuggestion newSuggestion) { 93 if (oldSuggestion == null) { 94 // No previous suggestion. 95 return true; 96 } 97 // This code relies on PhoneTimeZoneSuggestion.equals() to only check meaningful fields. 98 return !Objects.equals(newSuggestion, oldSuggestion); 99 } 100 101 @Override dumpLogs(IndentingPrintWriter ipw)102 public void dumpLogs(IndentingPrintWriter ipw) { 103 ipw.println("TimeServiceHelperImpl:"); 104 ipw.increaseIndent(); 105 ipw.println("SystemClock.elapsedRealtime()=" + SystemClock.elapsedRealtime()); 106 ipw.println("System.currentTimeMillis()=" + System.currentTimeMillis()); 107 108 ipw.println("Time Logs:"); 109 ipw.increaseIndent(); 110 mTimeLog.dump(ipw); 111 ipw.decreaseIndent(); 112 113 ipw.println("Time zone Logs:"); 114 ipw.increaseIndent(); 115 mTimeZoneLog.dump(ipw); 116 ipw.decreaseIndent(); 117 ipw.decreaseIndent(); 118 } 119 120 @Override dumpState(PrintWriter pw)121 public void dumpState(PrintWriter pw) { 122 pw.println(" TimeServiceHelperImpl.mLastSuggestedTimeZone=" + mLastSuggestedTimeZone); 123 } 124 } 125