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.Registrant; 22 import android.os.RegistrantList; 23 import android.telephony.AccessNetworkConstants; 24 import android.telephony.AnomalyReporter; 25 import android.telephony.NetworkRegistrationInfo; 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 static final String TAG = "DisplayInfoController"; 49 50 private final String mLogTag; 51 private final LocalLog mLocalLog = new LocalLog(128); 52 53 private static final Set<Pair<Integer, Integer>> VALID_DISPLAY_INFO_SET = Set.of( 54 // LTE 55 Pair.create(TelephonyManager.NETWORK_TYPE_LTE, 56 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA), 57 Pair.create(TelephonyManager.NETWORK_TYPE_LTE, 58 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO), 59 Pair.create(TelephonyManager.NETWORK_TYPE_LTE, 60 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA), 61 Pair.create(TelephonyManager.NETWORK_TYPE_LTE, 62 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED), 63 64 // NR 65 Pair.create(TelephonyManager.NETWORK_TYPE_NR, 66 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED) 67 ); 68 69 private final Phone mPhone; 70 private final NetworkTypeController mNetworkTypeController; 71 private final RegistrantList mTelephonyDisplayInfoChangedRegistrants = new RegistrantList(); 72 private TelephonyDisplayInfo mTelephonyDisplayInfo; 73 DisplayInfoController(Phone phone)74 public DisplayInfoController(Phone phone) { 75 mPhone = phone; 76 mLogTag = "DIC-" + mPhone.getPhoneId(); 77 mNetworkTypeController = new NetworkTypeController(phone, this); 78 mNetworkTypeController.sendMessage(NetworkTypeController.EVENT_UPDATE); 79 } 80 81 /** 82 * @return the current TelephonyDisplayInfo 83 */ getTelephonyDisplayInfo()84 public TelephonyDisplayInfo getTelephonyDisplayInfo() { 85 return mTelephonyDisplayInfo; 86 } 87 88 /** 89 * Update TelephonyDisplayInfo based on network type and override network type, received from 90 * NetworkTypeController. 91 */ updateTelephonyDisplayInfo()92 public void updateTelephonyDisplayInfo() { 93 NetworkRegistrationInfo nri = mPhone.getServiceState().getNetworkRegistrationInfo( 94 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 95 int dataNetworkType = nri == null ? TelephonyManager.NETWORK_TYPE_UNKNOWN 96 : nri.getAccessNetworkTechnology(); 97 TelephonyDisplayInfo newDisplayInfo = new TelephonyDisplayInfo(dataNetworkType, 98 mNetworkTypeController.getOverrideNetworkType()); 99 if (!newDisplayInfo.equals(mTelephonyDisplayInfo)) { 100 logl("TelephonyDisplayInfo changed from " + mTelephonyDisplayInfo + " to " 101 + newDisplayInfo); 102 validateDisplayInfo(newDisplayInfo); 103 mTelephonyDisplayInfo = newDisplayInfo; 104 mTelephonyDisplayInfoChangedRegistrants.notifyRegistrants(); 105 mPhone.notifyDisplayInfoChanged(mTelephonyDisplayInfo); 106 } 107 } 108 109 /** 110 * Validate the display info and trigger anomaly report if needed. 111 * 112 * @param displayInfo The display info to validate. 113 */ validateDisplayInfo(@onNull TelephonyDisplayInfo displayInfo)114 private void validateDisplayInfo(@NonNull TelephonyDisplayInfo displayInfo) { 115 try { 116 if (displayInfo.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA) { 117 throw new InvalidArgumentException("LTE_CA is not a valid network type."); 118 } 119 if (displayInfo.getNetworkType() < TelephonyManager.NETWORK_TYPE_UNKNOWN 120 && displayInfo.getNetworkType() > TelephonyManager.NETWORK_TYPE_NR) { 121 throw new InvalidArgumentException("Invalid network type " 122 + displayInfo.getNetworkType()); 123 } 124 if (displayInfo.getOverrideNetworkType() 125 != TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE 126 && !VALID_DISPLAY_INFO_SET.contains(Pair.create(displayInfo.getNetworkType(), 127 displayInfo.getOverrideNetworkType()))) { 128 throw new InvalidArgumentException("Invalid network type override " 129 + TelephonyDisplayInfo.overrideNetworkTypeToString( 130 displayInfo.getOverrideNetworkType()) 131 + " for " + TelephonyManager.getNetworkTypeName( 132 displayInfo.getNetworkType())); 133 } 134 } catch (InvalidArgumentException e) { 135 logel(e.getMessage()); 136 AnomalyReporter.reportAnomaly(UUID.fromString("3aa92a2c-94ed-46a0-a744-d6b1dfec2a55"), 137 e.getMessage(), mPhone.getCarrierId()); 138 } 139 } 140 141 /** 142 * Register for TelephonyDisplayInfo changed. 143 * @param h Handler to notify 144 * @param what msg.what when the message is delivered 145 * @param obj msg.obj when the message is delivered 146 */ registerForTelephonyDisplayInfoChanged(Handler h, int what, Object obj)147 public void registerForTelephonyDisplayInfoChanged(Handler h, int what, Object obj) { 148 Registrant r = new Registrant(h, what, obj); 149 mTelephonyDisplayInfoChangedRegistrants.add(r); 150 } 151 152 /** 153 * Unregister for TelephonyDisplayInfo changed. 154 * @param h Handler to notify 155 */ unregisterForTelephonyDisplayInfoChanged(Handler h)156 public void unregisterForTelephonyDisplayInfoChanged(Handler h) { 157 mTelephonyDisplayInfoChangedRegistrants.remove(h); 158 } 159 160 /** 161 * Log debug messages. 162 * @param s debug messages 163 */ log(@onNull String s)164 private void log(@NonNull String s) { 165 Rlog.d(mLogTag, s); 166 } 167 168 /** 169 * Log error messages. 170 * @param s error messages 171 */ loge(@onNull String s)172 private void loge(@NonNull String s) { 173 Rlog.e(mLogTag, s); 174 } 175 176 /** 177 * Log debug messages and also log into the local log. 178 * @param s debug messages 179 */ logl(@onNull String s)180 private void logl(@NonNull String s) { 181 log(s); 182 mLocalLog.log(s); 183 } 184 185 /** 186 * Log error messages and also log into the local log. 187 * @param s debug messages 188 */ logel(@onNull String s)189 private void logel(@NonNull String s) { 190 loge(s); 191 mLocalLog.log(s); 192 } 193 194 /** 195 * Dump the current state. 196 */ dump(FileDescriptor fd, PrintWriter printWriter, String[] args)197 public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) { 198 IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " "); 199 pw.println("DisplayInfoController:"); 200 pw.println(" mPhone=" + mPhone.getPhoneName()); 201 pw.println(" mTelephonyDisplayInfo=" + mTelephonyDisplayInfo.toString()); 202 pw.flush(); 203 pw.println("Local logs:"); 204 pw.increaseIndent(); 205 mLocalLog.dump(fd, pw, args); 206 pw.decreaseIndent(); 207 pw.println(" ***************************************"); 208 mNetworkTypeController.dump(fd, pw, args); 209 pw.flush(); 210 } 211 } 212