1 /*
2  * Copyright 2018 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;
18 
19 import android.annotation.NonNull;
20 import android.content.ContentResolver;
21 import android.content.Context;
22 import android.os.SystemClock;
23 import android.os.SystemProperties;
24 import android.os.TimestampedValue;
25 import android.provider.Settings;
26 
27 import com.android.internal.util.IndentingPrintWriter;
28 
29 import java.io.FileDescriptor;
30 import java.io.PrintWriter;
31 
32 /**
33  * An interface for the Android component that handles NITZ and related signals for time and time
34  * zone detection.
35  *
36  * {@hide}
37  */
38 public interface NitzStateMachine {
39 
40     /**
41      * Called when the country suitable for time zone detection is detected.
42      *
43      * @param countryIsoCode the countryIsoCode to use for time zone detection, may be "" for test
44      *     cells only, otherwise {@link #handleCountryUnavailable()} should be called
45      */
handleCountryDetected(@onNull String countryIsoCode)46     void handleCountryDetected(@NonNull String countryIsoCode);
47 
48     /**
49      * Informs the {@link NitzStateMachine} that the network has become available.
50      */
handleNetworkAvailable()51     void handleNetworkAvailable();
52 
53     /**
54      * Informs the {@link NitzStateMachine} that the network has become unavailable. Any network
55      * state, i.e. NITZ, should be cleared.
56      */
handleNetworkUnavailable()57     void handleNetworkUnavailable();
58 
59     /**
60      * Informs the {@link NitzStateMachine} that any previously detected country supplied via
61      * {@link #handleCountryDetected(String)} is no longer valid.
62      */
handleCountryUnavailable()63     void handleCountryUnavailable();
64 
65     /**
66      * Handle a new NITZ signal being received.
67      */
handleNitzReceived(@onNull TimestampedValue<NitzData> nitzSignal)68     void handleNitzReceived(@NonNull TimestampedValue<NitzData> nitzSignal);
69 
70     /**
71      * Handle the user putting the device into or out of airplane mode
72      * @param on true if airplane mode has been turned on, false if it's been turned off.
73      */
handleAirplaneModeChanged(boolean on)74     void handleAirplaneModeChanged(boolean on);
75 
76     /**
77      * Dumps the current in-memory state to the supplied PrintWriter.
78      */
dumpState(PrintWriter pw)79     void dumpState(PrintWriter pw);
80 
81     /**
82      * Dumps the time / time zone logs to the supplied IndentingPrintWriter.
83      */
dumpLogs(FileDescriptor fd, IndentingPrintWriter ipw, String[] args)84     void dumpLogs(FileDescriptor fd, IndentingPrintWriter ipw, String[] args);
85 
86     /**
87      * A proxy over read-only device state that allows things like system properties, elapsed
88      * realtime clock to be faked for tests.
89      */
90     interface DeviceState {
91 
92         /**
93          * If time between NITZ updates is less than {@link #getNitzUpdateSpacingMillis()} the
94          * update may be ignored.
95          */
getNitzUpdateSpacingMillis()96         int getNitzUpdateSpacingMillis();
97 
98         /**
99          * If {@link #getNitzUpdateSpacingMillis()} hasn't been exceeded but update is >
100          * {@link #getNitzUpdateDiffMillis()} do the update
101          */
getNitzUpdateDiffMillis()102         int getNitzUpdateDiffMillis();
103 
104         /**
105          * Returns true if the {@code gsm.ignore-nitz} system property is set to "yes".
106          */
getIgnoreNitz()107         boolean getIgnoreNitz();
108 
109         /**
110          * Returns the same value as {@link SystemClock#elapsedRealtime()}.
111          */
elapsedRealtime()112         long elapsedRealtime();
113 
114         /**
115          * Returns the same value as {@link System#currentTimeMillis()}.
116          */
currentTimeMillis()117         long currentTimeMillis();
118     }
119 
120     /**
121      * The real implementation of {@link DeviceState}.
122      *
123      * {@hide}
124      */
125     class DeviceStateImpl implements DeviceState {
126         private static final int NITZ_UPDATE_SPACING_DEFAULT = 1000 * 60 * 10;
127         private final int mNitzUpdateSpacing;
128 
129         private static final int NITZ_UPDATE_DIFF_DEFAULT = 2000;
130         private final int mNitzUpdateDiff;
131 
132         private final ContentResolver mCr;
133 
DeviceStateImpl(Phone phone)134         public DeviceStateImpl(Phone phone) {
135             Context context = phone.getContext();
136             mCr = context.getContentResolver();
137             mNitzUpdateSpacing =
138                     SystemProperties.getInt("ro.nitz_update_spacing", NITZ_UPDATE_SPACING_DEFAULT);
139             mNitzUpdateDiff =
140                     SystemProperties.getInt("ro.nitz_update_diff", NITZ_UPDATE_DIFF_DEFAULT);
141         }
142 
143         @Override
getNitzUpdateSpacingMillis()144         public int getNitzUpdateSpacingMillis() {
145             return Settings.Global.getInt(mCr, Settings.Global.NITZ_UPDATE_SPACING,
146                     mNitzUpdateSpacing);
147         }
148 
149         @Override
getNitzUpdateDiffMillis()150         public int getNitzUpdateDiffMillis() {
151             return Settings.Global.getInt(mCr, Settings.Global.NITZ_UPDATE_DIFF, mNitzUpdateDiff);
152         }
153 
154         @Override
getIgnoreNitz()155         public boolean getIgnoreNitz() {
156             String ignoreNitz = SystemProperties.get("gsm.ignore-nitz");
157             return ignoreNitz != null && ignoreNitz.equals("yes");
158         }
159 
160         @Override
elapsedRealtime()161         public long elapsedRealtime() {
162             return SystemClock.elapsedRealtime();
163         }
164 
165         @Override
currentTimeMillis()166         public long currentTimeMillis() {
167             return System.currentTimeMillis();
168         }
169     }
170 }
171