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