• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.os.Handler;
21 import android.os.Message;
22 import android.os.Registrant;
23 import android.os.RegistrantList;
24 import android.telephony.AnomalyReporter;
25 import android.telephony.ServiceState;
26 import android.telephony.TelephonyDisplayInfo;
27 import android.telephony.TelephonyManager;
28 import android.util.IndentingPrintWriter;
29 import android.util.LocalLog;
30 import android.util.Pair;
31 
32 import com.android.telephony.Rlog;
33 
34 import java.io.FileDescriptor;
35 import java.io.PrintWriter;
36 import java.util.Set;
37 import java.util.UUID;
38 
39 import javax.sip.InvalidArgumentException;
40 
41 /**
42  * The DisplayInfoController updates and broadcasts all changes to {@link TelephonyDisplayInfo}.
43  * It manages all the information necessary for display purposes. Clients can register for display
44  * info changes via {@link #registerForTelephonyDisplayInfoChanged} and obtain the current
45  * TelephonyDisplayInfo via {@link #getTelephonyDisplayInfo}.
46  */
47 public class DisplayInfoController extends Handler {
48     private final String mLogTag;
49     private final LocalLog mLocalLog = new LocalLog(128);
50 
51     private static final Set<Pair<Integer, Integer>> VALID_DISPLAY_INFO_SET = Set.of(
52             // LTE
53             Pair.create(TelephonyManager.NETWORK_TYPE_LTE,
54                     TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
55             Pair.create(TelephonyManager.NETWORK_TYPE_LTE,
56                     TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO),
57             Pair.create(TelephonyManager.NETWORK_TYPE_LTE,
58                     TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA),
59             Pair.create(TelephonyManager.NETWORK_TYPE_LTE,
60                     TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED),
61 
62             // NR
63             Pair.create(TelephonyManager.NETWORK_TYPE_NR,
64                     TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED)
65             );
66 
67     /** Event for service state changed (roaming). */
68     private static final int EVENT_SERVICE_STATE_CHANGED = 1;
69 
70     private final Phone mPhone;
71     private final NetworkTypeController mNetworkTypeController;
72     private final RegistrantList mTelephonyDisplayInfoChangedRegistrants = new RegistrantList();
73     private @NonNull TelephonyDisplayInfo mTelephonyDisplayInfo;
74     private @NonNull ServiceState mServiceState;
75 
DisplayInfoController(Phone phone)76     public DisplayInfoController(Phone phone) {
77         mPhone = phone;
78         mLogTag = "DIC-" + mPhone.getPhoneId();
79         mTelephonyDisplayInfo = new TelephonyDisplayInfo(
80                 TelephonyManager.NETWORK_TYPE_UNKNOWN,
81                 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
82         mNetworkTypeController = new NetworkTypeController(phone, this);
83         mNetworkTypeController.sendMessage(NetworkTypeController.EVENT_UPDATE);
84 
85         mServiceState = mPhone.getServiceStateTracker().getServiceState();
86         post(() -> {
87             mPhone.getServiceStateTracker()
88                     .registerForServiceStateChanged(this, EVENT_SERVICE_STATE_CHANGED, null);
89             updateTelephonyDisplayInfo();
90         });
91     }
92 
93     /**
94      * @return the current TelephonyDisplayInfo
95      */
getTelephonyDisplayInfo()96     public @NonNull TelephonyDisplayInfo getTelephonyDisplayInfo() {
97         return mTelephonyDisplayInfo;
98     }
99 
100     /**
101      * Update TelephonyDisplayInfo based on network type and override network type, received from
102      * NetworkTypeController.
103      */
updateTelephonyDisplayInfo()104     public void updateTelephonyDisplayInfo() {
105         TelephonyDisplayInfo newDisplayInfo = new TelephonyDisplayInfo(
106                 mNetworkTypeController.getDataNetworkType(),
107                 mNetworkTypeController.getOverrideNetworkType(),
108                 mServiceState.getRoaming());
109         if (!newDisplayInfo.equals(mTelephonyDisplayInfo)) {
110             logl("TelephonyDisplayInfo changed from " + mTelephonyDisplayInfo + " to "
111                     + newDisplayInfo);
112             validateDisplayInfo(newDisplayInfo);
113             mTelephonyDisplayInfo = newDisplayInfo;
114             mTelephonyDisplayInfoChangedRegistrants.notifyRegistrants();
115             mPhone.notifyDisplayInfoChanged(mTelephonyDisplayInfo);
116         }
117     }
118 
119     /**
120      * Validate the display info and trigger anomaly report if needed.
121      *
122      * @param displayInfo The display info to validate.
123      */
validateDisplayInfo(@onNull TelephonyDisplayInfo displayInfo)124     private void validateDisplayInfo(@NonNull TelephonyDisplayInfo displayInfo) {
125         try {
126             if (displayInfo.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA) {
127                 throw new InvalidArgumentException("LTE_CA is not a valid network type.");
128             }
129             if (displayInfo.getNetworkType() < TelephonyManager.NETWORK_TYPE_UNKNOWN
130                     && displayInfo.getNetworkType() > TelephonyManager.NETWORK_TYPE_NR) {
131                 throw new InvalidArgumentException("Invalid network type "
132                         + displayInfo.getNetworkType());
133             }
134             if (displayInfo.getOverrideNetworkType()
135                     != TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE
136                     && !VALID_DISPLAY_INFO_SET.contains(Pair.create(displayInfo.getNetworkType(),
137                     displayInfo.getOverrideNetworkType()))) {
138                 throw new InvalidArgumentException("Invalid network type override "
139                         + TelephonyDisplayInfo.overrideNetworkTypeToString(
140                                 displayInfo.getOverrideNetworkType())
141                         + " for " + TelephonyManager.getNetworkTypeName(
142                                 displayInfo.getNetworkType()));
143             }
144         } catch (InvalidArgumentException e) {
145             logel(e.getMessage());
146             AnomalyReporter.reportAnomaly(UUID.fromString("3aa92a2c-94ed-46a0-a744-d6b1dfec2a56"),
147                     e.getMessage(), mPhone.getCarrierId());
148         }
149     }
150 
151     /**
152      * Register for TelephonyDisplayInfo changed.
153      * @param h Handler to notify
154      * @param what msg.what when the message is delivered
155      * @param obj msg.obj when the message is delivered
156      */
registerForTelephonyDisplayInfoChanged(Handler h, int what, Object obj)157     public void registerForTelephonyDisplayInfoChanged(Handler h, int what, Object obj) {
158         Registrant r = new Registrant(h, what, obj);
159         mTelephonyDisplayInfoChangedRegistrants.add(r);
160     }
161 
162     /**
163      * Unregister for TelephonyDisplayInfo changed.
164      * @param h Handler to notify
165      */
unregisterForTelephonyDisplayInfoChanged(Handler h)166     public void unregisterForTelephonyDisplayInfoChanged(Handler h) {
167         mTelephonyDisplayInfoChangedRegistrants.remove(h);
168     }
169 
170     @Override
handleMessage(@onNull Message msg)171     public void handleMessage(@NonNull Message msg) {
172         switch (msg.what) {
173             case EVENT_SERVICE_STATE_CHANGED:
174                 mServiceState = mPhone.getServiceStateTracker().getServiceState();
175                 log("ServiceState updated, isRoaming=" + mServiceState.getRoaming());
176                 updateTelephonyDisplayInfo();
177                 break;
178         }
179     }
180 
181     /**
182      * Log debug messages.
183      * @param s debug messages
184      */
log(@onNull String s)185     private void log(@NonNull String s) {
186         Rlog.d(mLogTag, s);
187     }
188 
189     /**
190      * Log error messages.
191      * @param s error messages
192      */
loge(@onNull String s)193     private void loge(@NonNull String s) {
194         Rlog.e(mLogTag, s);
195     }
196 
197     /**
198      * Log debug messages and also log into the local log.
199      * @param s debug messages
200      */
logl(@onNull String s)201     private void logl(@NonNull String s) {
202         log(s);
203         mLocalLog.log(s);
204     }
205 
206     /**
207      * Log error messages and also log into the local log.
208      * @param s debug messages
209      */
logel(@onNull String s)210     private void logel(@NonNull String s) {
211         loge(s);
212         mLocalLog.log(s);
213     }
214 
215     /**
216      * Dump the current state.
217      */
dump(FileDescriptor fd, PrintWriter printWriter, String[] args)218     public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
219         IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
220         pw.println("DisplayInfoController:");
221         pw.println(" mPhone=" + mPhone.getPhoneName());
222         pw.println(" mTelephonyDisplayInfo=" + mTelephonyDisplayInfo.toString());
223         pw.flush();
224         pw.println("Local logs:");
225         pw.increaseIndent();
226         mLocalLog.dump(fd, pw, args);
227         pw.decreaseIndent();
228         pw.println(" ***************************************");
229         mNetworkTypeController.dump(fd, pw, args);
230         pw.flush();
231     }
232 }
233