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.metrics; 18 19 import static android.telephony.ims.RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED; 20 import static android.telephony.ims.RegistrationManager.REGISTRATION_STATE_REGISTERED; 21 import static android.telephony.ims.RegistrationManager.REGISTRATION_STATE_REGISTERING; 22 import static android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_SMS; 23 import static android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT; 24 import static android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO; 25 import static android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE; 26 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM; 27 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN; 28 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_LTE; 29 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_NONE; 30 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_NR; 31 import static android.text.format.DateUtils.SECOND_IN_MILLIS; 32 import static android.util.Patterns.EMAIL_ADDRESS; 33 34 import android.annotation.Nullable; 35 import android.os.SystemClock; 36 import android.telephony.AccessNetworkConstants; 37 import android.telephony.AccessNetworkConstants.TransportType; 38 import android.telephony.Annotation.NetworkType; 39 import android.telephony.NetworkRegistrationInfo; 40 import android.telephony.ServiceState; 41 import android.telephony.TelephonyManager; 42 import android.telephony.ims.ImsReasonInfo; 43 import android.telephony.ims.ImsRegistrationAttributes; 44 import android.telephony.ims.ProvisioningManager; 45 import android.telephony.ims.RegistrationManager.ImsRegistrationState; 46 import android.telephony.ims.feature.MmTelFeature.MmTelCapabilities; 47 import android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability; 48 import android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech; 49 50 import com.android.internal.annotations.VisibleForTesting; 51 import com.android.internal.telephony.Phone; 52 import com.android.internal.telephony.PhoneFactory; 53 import com.android.internal.telephony.imsphone.ImsPhone; 54 import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationStats; 55 import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationTermination; 56 import com.android.telephony.Rlog; 57 58 import java.util.regex.Pattern; 59 60 /** Tracks IMS registration metrics for each phone. */ 61 public class ImsStats { 62 private static final String TAG = ImsStats.class.getSimpleName(); 63 64 /** 65 * Minimal duration of the registration state. 66 * 67 * <p>Registration state (including changes in capable/available features) with duration shorter 68 * than this will be ignored as they are considered transient states. 69 */ 70 private static final long MIN_REGISTRATION_DURATION_MILLIS = 1L * SECOND_IN_MILLIS; 71 72 /** 73 * Maximum length of the extra message in the termination reason. 74 * 75 * <p>If the extra message is longer than this length, it will be truncated. 76 */ 77 private static final int MAX_EXTRA_MESSAGE_LENGTH = 128; 78 79 /** Pattern used to match UUIDs in IMS extra messages for filtering. */ 80 private static final Pattern PATTERN_UUID = 81 Pattern.compile( 82 "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"); 83 84 /** Replacement for UUIDs. */ 85 private static final String REPLACEMENT_UUID = "<UUID_REDACTED>"; 86 87 /** 88 * Pattern used to match URI (e.g. sip, tel) in IMS extra messages for filtering. 89 * 90 * <p>NOTE: this simple pattern aims to catch the most common URI schemes. It is not meant to be 91 * RFC-complaint. 92 */ 93 private static final Pattern PATTERN_URI = 94 Pattern.compile("([a-zA-Z]{2,}:)" + EMAIL_ADDRESS.pattern()); 95 96 /** Replacement for URI. */ 97 private static final String REPLACEMENT_URI = "$1<REDACTED>"; 98 99 /** 100 * Pattern used to match IPv4 addresses in IMS extra messages for filtering. 101 * 102 * <p>This is a copy of {@code android.util.Patterns.IP_ADDRESS}, which is deprecated and might 103 * be removed in the future. 104 */ 105 private static final Pattern PATTERN_IPV4 = 106 Pattern.compile( 107 "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]" 108 + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]" 109 + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}" 110 + "|[1-9][0-9]|[0-9]))"); 111 112 /** Replacement for IPv4 addresses. */ 113 private static final String REPLACEMENT_IPV4 = "<IPV4_REDACTED>"; 114 115 /** 116 * Pattern used to match IPv6 addresses in IMS extra messages for filtering. 117 * 118 * <p>NOTE: this pattern aims to catch the most common IPv6 addresses. It is not meant to be 119 * RFC-complaint or free of false positives. 120 */ 121 private static final Pattern PATTERN_IPV6 = 122 Pattern.compile( 123 // Full address 124 "([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}" 125 // Abbreviated address, e.g. 2001:4860:4860::8888 126 + "|([0-9a-fA-F]{1,4}:){1,6}(:[0-9a-fA-F]{1,4}){1,6}" 127 // Abbreviated network address, e.g. 2607:F8B0:: 128 + "|([0-9a-fA-F]{1,4}:){1,7}:" 129 // Abbreviated address, e.g. ::1 130 + "|:(:[0-9a-fA-F]{1,4}){1,7}"); 131 132 /** Replacement for IPv6 addresses. */ 133 private static final String REPLACEMENT_IPV6 = "<IPV6_REDACTED>"; 134 135 /** 136 * Pattern used to match potential IMEI values in IMS extra messages for filtering. 137 * 138 * <p>This includes segmented IMEI or IMEI/SV, as well as unsegmented IMEI/SV. 139 */ 140 private static final Pattern PATTERN_IMEI = 141 Pattern.compile( 142 "(^|[^0-9])(?:" 143 // IMEI, AABBBBBB-CCCCCC-D format; IMEI/SV, AABBBBBB-CCCCCC-EE format 144 + "[0-9]{8}-[0-9]{6}-[0-9][0-9]?" 145 // IMEI, AA-BBBBBB-CCCCCC-D format; IMEI/SV, AA-BBBBBB-CCCCCC-EE format 146 + "|[0-9]{2}-[0-9]{6}-[0-9]{6}-[0-9][0-9]?" 147 // IMEI/SV, unsegmented 148 + "|[0-9]{16}" 149 + ")($|[^0-9])"); 150 151 /** Replacement for IMEI. */ 152 private static final String REPLACEMENT_IMEI = "$1<IMEI_REDACTED>$2"; 153 154 /** 155 * Pattern used to match potential unsegmented IMEI/IMSI values in IMS extra messages for 156 * filtering. 157 */ 158 private static final Pattern PATTERN_UNSEGMENTED_IMEI_IMSI = 159 Pattern.compile("(^|[^0-9])[0-9]{15}($|[^0-9])"); 160 161 /** Replacement for unsegmented IMEI/IMSI. */ 162 private static final String REPLACEMENT_UNSEGMENTED_IMEI_IMSI = "$1<IMEI_IMSI_REDACTED>$2"; 163 164 /** 165 * Pattern used to match hostnames in IMS extra messages for filtering. 166 * 167 * <p>This pattern differs from {@link android.util.Patterns.DOMAIN_NAME} in a few ways: it 168 * requires the name to have at least 3 segments (shorter names are nearly always public or 169 * typos, i.e. missing space after period), does not check the validity of TLDs, and does not 170 * support punycodes in TLDs. 171 */ 172 private static final Pattern PATTERN_HOSTNAME = 173 Pattern.compile("([0-9a-zA-Z][0-9a-zA-Z_\\-]{0,61}[0-9a-zA-Z]\\.){2,}[a-zA-Z]{2,}"); 174 175 /** Replacement for hostnames. */ 176 private static final String REPLACEMENT_HOSTNAME = "<HOSTNAME_REDACTED>"; 177 178 /** 179 * Pattern used to match potential IDs in IMS extra messages for filtering. 180 * 181 * <p>This pattern target numbers that are potential IDs in unknown formats. It should be 182 * replaced after all other replacements are done to ensure complete and correct filtering. 183 * 184 * <p>Specifically, this pattern looks for any number (including hex) that is separated by dots 185 * or dashes has at least 6 significant digits, and any unsegmented numbers that has at least 5 186 * significant digits. 187 */ 188 private static final Pattern PATTERN_UNKNOWN_ID = 189 Pattern.compile( 190 "(^|[^0-9a-fA-F])(([-\\.]?0)*[1-9a-fA-F]([-\\.]?[0-9a-fA-F]){5,}" 191 + "|0*[1-9a-fA-F]([0-9a-fA-F]){4,})"); 192 193 /** Replacement for potential IDs. */ 194 private static final String REPLACEMENT_UNKNOWN_ID = "$1<ID_REDACTED>"; 195 196 private final ImsPhone mPhone; 197 private final PersistAtomsStorage mStorage; 198 199 @ImsRegistrationState private int mLastRegistrationState = REGISTRATION_STATE_NOT_REGISTERED; 200 201 private long mLastTimestamp; 202 private ImsRegistrationStats mLastRegistrationStats; 203 @TransportType int mLastTransportType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID; 204 // Available features are those reported by ImsService to be available for use. 205 private MmTelCapabilities mLastAvailableFeatures = new MmTelCapabilities(); 206 207 // Capable features (enabled by device/carrier). Theses are available before IMS is registered 208 // and not necessarily updated when RAT changes. 209 private final MmTelCapabilities mLastWwanCapableFeatures = new MmTelCapabilities(); 210 private final MmTelCapabilities mLastWlanCapableFeatures = new MmTelCapabilities(); 211 ImsStats(ImsPhone phone)212 public ImsStats(ImsPhone phone) { 213 mPhone = phone; 214 mStorage = PhoneFactory.getMetricsCollector().getAtomsStorage(); 215 216 mLastRegistrationStats = getDefaultImsRegistrationStats(); 217 updateImsRegistrationStats(); 218 mLastTimestamp = getTimeMillis(); 219 } 220 221 /** 222 * Finalizes the durations of the current IMS registration stats segment. 223 * 224 * <p>This method is also invoked whenever the registration state, feature capability, or 225 * feature availability changes. 226 */ conclude()227 public synchronized void conclude() { 228 long now = getTimeMillis(); 229 230 long duration = now - mLastTimestamp; 231 if (duration < MIN_REGISTRATION_DURATION_MILLIS) { 232 logw("conclude: discarding transient stats, duration=%d", duration); 233 } else { 234 ImsRegistrationStats stats = copyOfDimensionsOnly(mLastRegistrationStats); 235 236 if (stats.rat == TelephonyManager.NETWORK_TYPE_UNKNOWN) { 237 logw("conclude: discarding UNKNOWN RAT, duration=%d", duration); 238 mLastTimestamp = now; 239 return; 240 } 241 242 stats.registeredTimes = mLastRegistrationStats.registeredTimes; 243 // initialize registeredTimes after copying mLastRegistrationStats to be updated 244 mLastRegistrationStats.registeredTimes = 0; 245 246 switch (mLastRegistrationState) { 247 case REGISTRATION_STATE_REGISTERED: 248 stats.registeredMillis = duration; 249 250 stats.voiceAvailableMillis = 251 mLastAvailableFeatures.isCapable(CAPABILITY_TYPE_VOICE) ? duration : 0; 252 stats.videoAvailableMillis = 253 mLastAvailableFeatures.isCapable(CAPABILITY_TYPE_VIDEO) ? duration : 0; 254 stats.utAvailableMillis = 255 mLastAvailableFeatures.isCapable(CAPABILITY_TYPE_UT) ? duration : 0; 256 stats.smsAvailableMillis = 257 mLastAvailableFeatures.isCapable(CAPABILITY_TYPE_SMS) ? duration : 0; 258 259 MmTelCapabilities lastCapableFeatures = 260 stats.rat == TelephonyManager.NETWORK_TYPE_IWLAN 261 ? mLastWlanCapableFeatures 262 : mLastWwanCapableFeatures; 263 stats.voiceCapableMillis = 264 lastCapableFeatures.isCapable(CAPABILITY_TYPE_VOICE) ? duration : 0; 265 stats.videoCapableMillis = 266 lastCapableFeatures.isCapable(CAPABILITY_TYPE_VIDEO) ? duration : 0; 267 stats.utCapableMillis = 268 lastCapableFeatures.isCapable(CAPABILITY_TYPE_UT) ? duration : 0; 269 stats.smsCapableMillis = 270 lastCapableFeatures.isCapable(CAPABILITY_TYPE_SMS) ? duration : 0; 271 break; 272 case REGISTRATION_STATE_REGISTERING: 273 stats.registeringMillis = duration; 274 break; 275 case REGISTRATION_STATE_NOT_REGISTERED: 276 stats.unregisteredMillis = duration; 277 break; 278 } 279 mStorage.addImsRegistrationStats(stats); 280 } 281 282 mLastTimestamp = now; 283 } 284 285 /** Updates the stats when registered features changed. */ onImsCapabilitiesChanged( @msRegistrationTech int radioTech, MmTelCapabilities capabilities)286 public synchronized void onImsCapabilitiesChanged( 287 @ImsRegistrationTech int radioTech, MmTelCapabilities capabilities) { 288 conclude(); 289 290 boolean ratChanged = false; 291 @NetworkType int newRat = convertRegistrationTechToNetworkType(radioTech); 292 mLastTransportType = 293 (newRat == TelephonyManager.NETWORK_TYPE_IWLAN) 294 ? AccessNetworkConstants.TRANSPORT_TYPE_WLAN 295 : AccessNetworkConstants.TRANSPORT_TYPE_WWAN; 296 if (mLastRegistrationStats.rat != newRat) { 297 mLastRegistrationStats.rat = newRat; 298 ratChanged = true; 299 } 300 mLastRegistrationStats.isIwlanCrossSim = radioTech == REGISTRATION_TECH_CROSS_SIM; 301 302 boolean voiceAvailableNow = capabilities.isCapable(CAPABILITY_TYPE_VOICE); 303 boolean voiceAvailabilityChanged = 304 (mLastAvailableFeatures.isCapable(CAPABILITY_TYPE_VOICE) != voiceAvailableNow); 305 mLastAvailableFeatures = capabilities; 306 307 // Notify voice RAT change if 1. RAT changed while voice over IMS is available, or 2. voice 308 // over IMS availability changed 309 if ((ratChanged && voiceAvailableNow) || voiceAvailabilityChanged) { 310 mPhone.getDefaultPhone().getServiceStateTracker().getServiceStateStats() 311 .onImsVoiceRegistrationChanged(); 312 } 313 } 314 315 /** Updates the stats when capable features changed. */ onSetFeatureResponse( @mTelCapability int feature, @ImsRegistrationTech int network, int value)316 public synchronized void onSetFeatureResponse( 317 @MmTelCapability int feature, @ImsRegistrationTech int network, int value) { 318 MmTelCapabilities lastCapableFeatures = getLastCapableFeaturesForTech(network); 319 if (lastCapableFeatures != null) { 320 conclude(); 321 if (value == ProvisioningManager.PROVISIONING_VALUE_ENABLED) { 322 lastCapableFeatures.addCapabilities(feature); 323 } else { 324 lastCapableFeatures.removeCapabilities(feature); 325 } 326 } 327 } 328 329 /** Updates the stats when IMS registration is progressing. */ onImsRegistering(@ransportType int imsRadioTech)330 public synchronized void onImsRegistering(@TransportType int imsRadioTech) { 331 conclude(); 332 333 mLastTransportType = imsRadioTech; 334 updateImsRegistrationStats(); 335 mLastRegistrationStats.rat = convertTransportTypeToNetworkType(imsRadioTech); 336 mLastRegistrationState = REGISTRATION_STATE_REGISTERING; 337 } 338 339 /** Updates the stats when IMS registration succeeds. */ onImsRegistered(ImsRegistrationAttributes attributes)340 public synchronized void onImsRegistered(ImsRegistrationAttributes attributes) { 341 // Updates registered_times as soon as the UE is registered 342 if (mLastRegistrationState != REGISTRATION_STATE_REGISTERED) { 343 // RegistrationStats captures in every state. Changing REGISTERED state has to capture 344 // only once. 345 mLastRegistrationStats.registeredTimes = 1; 346 } 347 348 conclude(); 349 350 mLastTransportType = attributes.getTransportType(); 351 // NOTE: status can be unregistered (no registering phase) 352 if (mLastRegistrationState == REGISTRATION_STATE_NOT_REGISTERED) { 353 updateImsRegistrationStats(); 354 } 355 356 mLastRegistrationStats.rat = 357 convertTransportTypeToNetworkType(attributes.getTransportType()); 358 mLastRegistrationStats.isIwlanCrossSim = attributes.getRegistrationTechnology() 359 == REGISTRATION_TECH_CROSS_SIM; 360 mLastRegistrationState = REGISTRATION_STATE_REGISTERED; 361 } 362 363 /** Updates the stats and generates a termination atom when IMS registration fails/ends. */ onImsUnregistered(ImsReasonInfo reasonInfo)364 public synchronized void onImsUnregistered(ImsReasonInfo reasonInfo) { 365 conclude(); 366 367 // Generate end reason atom. 368 ImsRegistrationTermination termination = new ImsRegistrationTermination(); 369 if (mLastRegistrationState != REGISTRATION_STATE_NOT_REGISTERED) { 370 termination.carrierId = mLastRegistrationStats.carrierId; 371 termination.ratAtEnd = getRatAtEnd(mLastRegistrationStats.rat); 372 termination.isIwlanCrossSim = mLastRegistrationStats.isIwlanCrossSim; 373 } else { 374 // if the registration state is from unregistered to unregistered. 375 termination.carrierId = mPhone.getDefaultPhone().getCarrierId(); 376 } 377 termination.ratAtEnd = getRatAtEnd(mLastRegistrationStats.rat); 378 termination.isMultiSim = SimSlotState.isMultiSim(); 379 termination.setupFailed = (mLastRegistrationState != REGISTRATION_STATE_REGISTERED); 380 termination.reasonCode = reasonInfo.getCode(); 381 termination.extraCode = reasonInfo.getExtraCode(); 382 termination.extraMessage = filterExtraMessage(reasonInfo.getExtraMessage()); 383 termination.count = 1; 384 mStorage.addImsRegistrationTermination(termination); 385 386 // Reset state to unregistered. 387 mLastRegistrationState = REGISTRATION_STATE_NOT_REGISTERED; 388 mLastAvailableFeatures = new MmTelCapabilities(); 389 } 390 391 /** Updates the RAT when service state changes. */ onServiceStateChanged(ServiceState state)392 public synchronized void onServiceStateChanged(ServiceState state) { 393 conclude(); 394 395 @NetworkType int newRat = state.getDataNetworkType(); 396 MmTelCapabilities lastCapableFeatures = getLastCapableFeaturesForNetworkType(newRat); 397 398 if (lastCapableFeatures != null) { 399 mLastRegistrationStats.rat = newRat; 400 } else { 401 mLastRegistrationStats.rat = TelephonyManager.NETWORK_TYPE_UNKNOWN; 402 } 403 } 404 405 /** 406 * Returns the current RAT used for IMS voice registration, or {@link 407 * TelephonyManager#NETWORK_TYPE_UNKNOWN} if there isn't any. 408 */ 409 @NetworkType getImsVoiceRadioTech()410 public synchronized int getImsVoiceRadioTech() { 411 if (mLastRegistrationState == REGISTRATION_STATE_NOT_REGISTERED 412 || !mLastAvailableFeatures.isCapable(CAPABILITY_TYPE_VOICE)) { 413 return TelephonyManager.NETWORK_TYPE_UNKNOWN; 414 } 415 return mLastRegistrationStats.rat; 416 } 417 418 @NetworkType getRatAtEnd(@etworkType int lastStateRat)419 private int getRatAtEnd(@NetworkType int lastStateRat) { 420 return lastStateRat == TelephonyManager.NETWORK_TYPE_IWLAN ? lastStateRat : getWwanPsRat(); 421 } 422 423 @NetworkType convertTransportTypeToNetworkType(@ransportType int transportType)424 private int convertTransportTypeToNetworkType(@TransportType int transportType) { 425 switch (transportType) { 426 case AccessNetworkConstants.TRANSPORT_TYPE_WWAN: 427 return getWwanPsRat(); 428 case AccessNetworkConstants.TRANSPORT_TYPE_WLAN: 429 return TelephonyManager.NETWORK_TYPE_IWLAN; 430 default: 431 return TelephonyManager.NETWORK_TYPE_UNKNOWN; 432 } 433 } 434 435 @NetworkType getWwanPsRat()436 private int getWwanPsRat() { 437 return ServiceStateStats.getRat( 438 mPhone.getServiceStateTracker().getServiceState(), 439 NetworkRegistrationInfo.DOMAIN_PS); 440 } 441 getDefaultImsRegistrationStats()442 private ImsRegistrationStats getDefaultImsRegistrationStats() { 443 Phone phone = mPhone.getDefaultPhone(); 444 ImsRegistrationStats stats = new ImsRegistrationStats(); 445 stats.rat = TelephonyManager.NETWORK_TYPE_UNKNOWN; 446 return stats; 447 } 448 updateImsRegistrationStats()449 private void updateImsRegistrationStats() { 450 Phone phone = mPhone.getDefaultPhone(); 451 mLastRegistrationStats.carrierId = phone.getCarrierId(); 452 mLastRegistrationStats.simSlotIndex = phone.getPhoneId(); 453 } 454 455 @Nullable getLastCapableFeaturesForTech(@msRegistrationTech int radioTech)456 private MmTelCapabilities getLastCapableFeaturesForTech(@ImsRegistrationTech int radioTech) { 457 switch (radioTech) { 458 case REGISTRATION_TECH_NONE: 459 return null; 460 case REGISTRATION_TECH_IWLAN: 461 case REGISTRATION_TECH_CROSS_SIM: 462 return mLastWlanCapableFeatures; 463 default: 464 return mLastWwanCapableFeatures; 465 } 466 } 467 468 @Nullable getLastCapableFeaturesForNetworkType(@etworkType int netType)469 private MmTelCapabilities getLastCapableFeaturesForNetworkType(@NetworkType int netType) { 470 switch (netType) { 471 case TelephonyManager.NETWORK_TYPE_UNKNOWN: 472 return null; 473 case TelephonyManager.NETWORK_TYPE_IWLAN: 474 return mLastWlanCapableFeatures; 475 default: 476 return mLastWwanCapableFeatures; 477 } 478 } 479 480 @NetworkType convertRegistrationTechToNetworkType(@msRegistrationTech int radioTech)481 private int convertRegistrationTechToNetworkType(@ImsRegistrationTech int radioTech) { 482 switch (radioTech) { 483 case REGISTRATION_TECH_NONE: 484 return TelephonyManager.NETWORK_TYPE_UNKNOWN; 485 case REGISTRATION_TECH_LTE: 486 return TelephonyManager.NETWORK_TYPE_LTE; 487 case REGISTRATION_TECH_IWLAN: 488 case REGISTRATION_TECH_CROSS_SIM: 489 return TelephonyManager.NETWORK_TYPE_IWLAN; 490 case REGISTRATION_TECH_NR: 491 return TelephonyManager.NETWORK_TYPE_NR; 492 default: 493 loge("convertRegistrationTechToNetworkType: unknown radio tech %d", radioTech); 494 return getWwanPsRat(); 495 } 496 } 497 copyOfDimensionsOnly(ImsRegistrationStats source)498 private static ImsRegistrationStats copyOfDimensionsOnly(ImsRegistrationStats source) { 499 ImsRegistrationStats dest = new ImsRegistrationStats(); 500 501 dest.carrierId = source.carrierId; 502 dest.simSlotIndex = source.simSlotIndex; 503 dest.rat = source.rat; 504 dest.isIwlanCrossSim = source.isIwlanCrossSim; 505 506 return dest; 507 } 508 509 @VisibleForTesting getTimeMillis()510 protected long getTimeMillis() { 511 return SystemClock.elapsedRealtime(); 512 } 513 514 /** Filters IMS extra messages to ensure length limit and remove IDs. */ filterExtraMessage(@ullable String str)515 public static String filterExtraMessage(@Nullable String str) { 516 if (str == null) { 517 return ""; 518 } 519 520 str = PATTERN_UUID.matcher(str).replaceAll(REPLACEMENT_UUID); 521 str = PATTERN_URI.matcher(str).replaceAll(REPLACEMENT_URI); 522 str = PATTERN_HOSTNAME.matcher(str).replaceAll(REPLACEMENT_HOSTNAME); 523 str = PATTERN_IPV4.matcher(str).replaceAll(REPLACEMENT_IPV4); 524 str = PATTERN_IPV6.matcher(str).replaceAll(REPLACEMENT_IPV6); 525 str = PATTERN_IMEI.matcher(str).replaceAll(REPLACEMENT_IMEI); 526 str = PATTERN_UNSEGMENTED_IMEI_IMSI.matcher(str) 527 .replaceAll(REPLACEMENT_UNSEGMENTED_IMEI_IMSI); 528 str = PATTERN_UNKNOWN_ID.matcher(str).replaceAll(REPLACEMENT_UNKNOWN_ID); 529 530 return str.length() > MAX_EXTRA_MESSAGE_LENGTH 531 ? str.substring(0, MAX_EXTRA_MESSAGE_LENGTH) 532 : str; 533 } 534 logw(String format, Object... args)535 private void logw(String format, Object... args) { 536 Rlog.w(TAG, "[" + mPhone.getPhoneId() + "] " + String.format(format, args)); 537 } 538 loge(String format, Object... args)539 private void loge(String format, Object... args) { 540 Rlog.e(TAG, "[" + mPhone.getPhoneId() + "] " + String.format(format, args)); 541 } 542 } 543