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.TelephonyManager.DATA_CONNECTED; 20 21 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS; 22 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS; 23 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_UNKNOWN; 24 import static com.android.internal.telephony.flags.Flags.dataRatMetricEnabled; 25 26 import android.annotation.NonNull; 27 import android.annotation.Nullable; 28 import android.os.SystemClock; 29 import android.telephony.AccessNetworkConstants; 30 import android.telephony.AccessNetworkUtils; 31 import android.telephony.Annotation.NetworkType; 32 import android.telephony.NetworkRegistrationInfo; 33 import android.telephony.ServiceState; 34 import android.telephony.ServiceState.RoamingType; 35 import android.telephony.SubscriptionManager; 36 import android.telephony.TelephonyManager; 37 import android.telephony.ims.stub.ImsRegistrationImplBase; 38 39 import com.android.internal.annotations.VisibleForTesting; 40 import com.android.internal.telephony.Phone; 41 import com.android.internal.telephony.PhoneFactory; 42 import com.android.internal.telephony.ServiceStateTracker; 43 import com.android.internal.telephony.TelephonyStatsLog; 44 import com.android.internal.telephony.data.DataNetwork; 45 import com.android.internal.telephony.data.DataNetworkController; 46 import com.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback; 47 import com.android.internal.telephony.imsphone.ImsPhone; 48 import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch; 49 import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState; 50 import com.android.internal.telephony.satellite.SatelliteController; 51 import com.android.telephony.Rlog; 52 53 import java.util.Set; 54 import java.util.concurrent.atomic.AtomicBoolean; 55 import java.util.concurrent.atomic.AtomicReference; 56 57 /** Tracks service state duration and switch metrics for each phone. */ 58 public class ServiceStateStats extends DataNetworkControllerCallback { 59 private static final String TAG = ServiceStateStats.class.getSimpleName(); 60 61 private final AtomicReference<TimestampedServiceState> mLastState = 62 new AtomicReference<>(new TimestampedServiceState(null, 0L)); 63 private final AtomicBoolean mOverrideVoiceService = new AtomicBoolean(false); 64 private final Phone mPhone; 65 private final PersistAtomsStorage mStorage; 66 private final DeviceStateHelper mDeviceStateHelper; 67 private boolean mExistAnyConnectedInternetPdn; 68 private int mCurrentDataRat = 69 TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_UNSPECIFIED; 70 ServiceStateStats(Phone phone)71 public ServiceStateStats(Phone phone) { 72 super(Runnable::run); 73 mPhone = phone; 74 mStorage = PhoneFactory.getMetricsCollector().getAtomsStorage(); 75 mDeviceStateHelper = PhoneFactory.getMetricsCollector().getDeviceStateHelper(); 76 } 77 78 /** Finalizes the durations of the current service state segment. */ conclude()79 public void conclude() { 80 final long now = getTimeMillis(); 81 TimestampedServiceState lastState = 82 mLastState.getAndUpdate( 83 state -> new TimestampedServiceState(state.mServiceState, now)); 84 addServiceState(lastState, now); 85 } 86 87 /** Updates service state when IMS voice registration changes. */ onImsVoiceRegistrationChanged()88 public void onImsVoiceRegistrationChanged() { 89 final long now = getTimeMillis(); 90 TimestampedServiceState lastState = 91 mLastState.getAndUpdate( 92 state -> { 93 if (state.mServiceState == null) { 94 return new TimestampedServiceState(null, now); 95 } 96 CellularServiceState newServiceState = copyOf(state.mServiceState); 97 newServiceState.voiceRat = 98 getVoiceRat(mPhone, getServiceStateForPhone(mPhone)); 99 newServiceState.isIwlanCrossSim = isCrossSimCallingRegistered(mPhone); 100 return new TimestampedServiceState(newServiceState, now); 101 }); 102 addServiceState(lastState, now); 103 } 104 105 /** Registers for internet pdn connected callback. */ registerDataNetworkControllerCallback()106 public void registerDataNetworkControllerCallback() { 107 mPhone.getDataNetworkController().registerDataNetworkControllerCallback(this); 108 } 109 110 /** Updates service state when internet pdn changed. */ 111 @Override onConnectedInternetDataNetworksChanged(@onNull Set<DataNetwork> internetNetworks)112 public void onConnectedInternetDataNetworksChanged(@NonNull Set<DataNetwork> internetNetworks) { 113 boolean existAnyConnectedInternetPdn = !internetNetworks.isEmpty(); 114 if (mExistAnyConnectedInternetPdn != existAnyConnectedInternetPdn) { 115 mExistAnyConnectedInternetPdn = existAnyConnectedInternetPdn; 116 onInternetDataNetworkChanged(mExistAnyConnectedInternetPdn); 117 } 118 } 119 120 /** Updates the current service state. */ onServiceStateChanged(ServiceState serviceState)121 public void onServiceStateChanged(ServiceState serviceState) { 122 final long now = getTimeMillis(); 123 if (isModemOff(serviceState)) { 124 // Finish the duration of last service state and mark modem off 125 addServiceState(mLastState.getAndSet(new TimestampedServiceState(null, now)), now); 126 } else { 127 SatelliteController satelliteController = SatelliteController.getInstance(); 128 CellularServiceState newState = new CellularServiceState(); 129 newState.voiceRat = getVoiceRat(mPhone, serviceState); 130 newState.dataRat = getRat(serviceState, NetworkRegistrationInfo.DOMAIN_PS); 131 newState.voiceRoamingType = 132 getNetworkRoamingState(serviceState, NetworkRegistrationInfo.DOMAIN_CS); 133 newState.dataRoamingType = 134 getNetworkRoamingState(serviceState, NetworkRegistrationInfo.DOMAIN_PS); 135 newState.isEndc = isEndc(serviceState); 136 newState.simSlotIndex = mPhone.getPhoneId(); 137 newState.isMultiSim = SimSlotState.isMultiSim(); 138 newState.carrierId = mPhone.getCarrierId(); 139 newState.isEmergencyOnly = isEmergencyOnly(serviceState); 140 newState.isInternetPdnUp = isInternetPdnUp(mPhone); 141 newState.foldState = mDeviceStateHelper.getFoldState(); 142 newState.overrideVoiceService = mOverrideVoiceService.get(); 143 newState.isDataEnabled = mPhone.getDataSettingsManager().isDataEnabled(); 144 newState.isIwlanCrossSim = isCrossSimCallingRegistered(mPhone); 145 newState.isNtn = satelliteController != null 146 && satelliteController.isInSatelliteModeForCarrierRoaming(mPhone); 147 TimestampedServiceState prevState = 148 mLastState.getAndSet(new TimestampedServiceState(newState, now)); 149 addServiceStateAndSwitch( 150 prevState, now, getDataServiceSwitch(prevState.mServiceState, newState)); 151 } 152 153 if (dataRatMetricEnabled()) { 154 writeDataRatAtom(serviceState); 155 } 156 } 157 158 /** Updates the fold state of the device for the current service state. */ onFoldStateChanged(int foldState)159 public void onFoldStateChanged(int foldState) { 160 final long now = getTimeMillis(); 161 CellularServiceState lastServiceState = mLastState.get().mServiceState; 162 if (lastServiceState == null || lastServiceState.foldState == foldState) { 163 // Not need to update the fold state if modem is off or if is the 164 // same fold state 165 return; 166 } else { 167 TimestampedServiceState lastState = 168 mLastState.getAndUpdate( 169 state -> { 170 CellularServiceState newServiceState = copyOf(state.mServiceState); 171 newServiceState.foldState = foldState; 172 return new TimestampedServiceState(newServiceState, now); 173 }); 174 addServiceState(lastState, now); 175 } 176 } 177 178 /** Updates override state for voice service state when voice calling capability changes */ onVoiceServiceStateOverrideChanged(boolean override)179 public void onVoiceServiceStateOverrideChanged(boolean override) { 180 if (override == mOverrideVoiceService.get()) { 181 return; 182 } 183 mOverrideVoiceService.set(override); 184 final long now = getTimeMillis(); 185 TimestampedServiceState lastState = 186 mLastState.getAndUpdate( 187 state -> { 188 if (state.mServiceState == null) { 189 return new TimestampedServiceState(null, now); 190 } 191 CellularServiceState newServiceState = copyOf(state.mServiceState); 192 newServiceState.overrideVoiceService = mOverrideVoiceService.get(); 193 return new TimestampedServiceState(newServiceState, now); 194 }); 195 addServiceState(lastState, now); 196 } 197 addServiceState(TimestampedServiceState prevState, long now)198 private void addServiceState(TimestampedServiceState prevState, long now) { 199 addServiceStateAndSwitch(prevState, now, null); 200 } 201 addServiceStateAndSwitch( TimestampedServiceState prevState, long now, @Nullable CellularDataServiceSwitch serviceSwitch)202 private void addServiceStateAndSwitch( 203 TimestampedServiceState prevState, 204 long now, 205 @Nullable CellularDataServiceSwitch serviceSwitch) { 206 if (prevState.mServiceState == null) { 207 // Skip duration when modem is off 208 return; 209 } 210 if (now >= prevState.mTimestamp) { 211 CellularServiceState state = copyOf(prevState.mServiceState); 212 state.totalTimeMillis = now - prevState.mTimestamp; 213 mStorage.addCellularServiceStateAndCellularDataServiceSwitch(state, serviceSwitch); 214 } else { 215 Rlog.e(TAG, "addServiceState: durationMillis<0"); 216 } 217 } 218 219 @Nullable getDataServiceSwitch( @ullable CellularServiceState prevState, CellularServiceState nextState)220 private CellularDataServiceSwitch getDataServiceSwitch( 221 @Nullable CellularServiceState prevState, CellularServiceState nextState) { 222 // Record switch only if multi-SIM state and carrier ID are the same and data RAT differs. 223 if (prevState != null 224 && prevState.isMultiSim == nextState.isMultiSim 225 && prevState.carrierId == nextState.carrierId 226 && prevState.dataRat != nextState.dataRat) { 227 CellularDataServiceSwitch serviceSwitch = new CellularDataServiceSwitch(); 228 serviceSwitch.ratFrom = prevState.dataRat; 229 serviceSwitch.ratTo = nextState.dataRat; 230 serviceSwitch.isMultiSim = nextState.isMultiSim; 231 serviceSwitch.simSlotIndex = nextState.simSlotIndex; 232 serviceSwitch.carrierId = nextState.carrierId; 233 serviceSwitch.switchCount = 1; 234 return serviceSwitch; 235 } else { 236 return null; 237 } 238 } 239 240 /** Returns the service state for the given phone, or {@code null} if it cannot be obtained. */ 241 @Nullable getServiceStateForPhone(Phone phone)242 private static ServiceState getServiceStateForPhone(Phone phone) { 243 ServiceStateTracker serviceStateTracker = phone.getServiceStateTracker(); 244 return serviceStateTracker != null ? serviceStateTracker.getServiceState() : null; 245 } 246 247 /** 248 * Returns the band used from the given phone, or {@code 0} if it is invalid or cannot be 249 * determined. 250 */ getBand(Phone phone)251 static int getBand(Phone phone) { 252 ServiceState serviceState = getServiceStateForPhone(phone); 253 return getBand(serviceState); 254 } 255 256 /** 257 * Returns the band used from the given service state, or {@code 0} if it is invalid or cannot 258 * be determined. 259 */ getBand(@ullable ServiceState serviceState)260 static int getBand(@Nullable ServiceState serviceState) { 261 if (serviceState == null) { 262 Rlog.w(TAG, "getBand: serviceState=null"); 263 return 0; // Band unknown 264 } 265 int chNumber = serviceState.getChannelNumber(); 266 int band; 267 @NetworkType int rat = getRat(serviceState, NetworkRegistrationInfo.DOMAIN_PS); 268 if (rat == TelephonyManager.NETWORK_TYPE_UNKNOWN) { 269 rat = serviceState.getVoiceNetworkType(); 270 } 271 switch (rat) { 272 case TelephonyManager.NETWORK_TYPE_GSM: 273 case TelephonyManager.NETWORK_TYPE_GPRS: 274 case TelephonyManager.NETWORK_TYPE_EDGE: 275 band = AccessNetworkUtils.getOperatingBandForArfcn(chNumber); 276 break; 277 case TelephonyManager.NETWORK_TYPE_UMTS: 278 case TelephonyManager.NETWORK_TYPE_HSDPA: 279 case TelephonyManager.NETWORK_TYPE_HSUPA: 280 case TelephonyManager.NETWORK_TYPE_HSPA: 281 case TelephonyManager.NETWORK_TYPE_HSPAP: 282 band = AccessNetworkUtils.getOperatingBandForUarfcn(chNumber); 283 break; 284 case TelephonyManager.NETWORK_TYPE_LTE: 285 case TelephonyManager.NETWORK_TYPE_LTE_CA: 286 band = AccessNetworkUtils.getOperatingBandForEarfcn(chNumber); 287 break; 288 case TelephonyManager.NETWORK_TYPE_NR: 289 band = AccessNetworkUtils.getOperatingBandForNrarfcn(chNumber); 290 break; 291 default: 292 Rlog.w(TAG, "getBand: unknown WWAN RAT " + rat); 293 band = 0; 294 break; 295 } 296 if (band == AccessNetworkUtils.INVALID_BAND) { 297 Rlog.w(TAG, "getBand: band invalid for rat=" + rat + " ch=" + chNumber); 298 return 0; 299 } else { 300 return band; 301 } 302 } 303 copyOf(CellularServiceState state)304 private static CellularServiceState copyOf(CellularServiceState state) { 305 // MessageNano does not support clone, have to copy manually 306 CellularServiceState copy = new CellularServiceState(); 307 copy.voiceRat = state.voiceRat; 308 copy.dataRat = state.dataRat; 309 copy.voiceRoamingType = state.voiceRoamingType; 310 copy.dataRoamingType = state.dataRoamingType; 311 copy.isEndc = state.isEndc; 312 copy.simSlotIndex = state.simSlotIndex; 313 copy.isMultiSim = state.isMultiSim; 314 copy.carrierId = state.carrierId; 315 copy.totalTimeMillis = state.totalTimeMillis; 316 copy.isEmergencyOnly = state.isEmergencyOnly; 317 copy.isInternetPdnUp = state.isInternetPdnUp; 318 copy.foldState = state.foldState; 319 copy.overrideVoiceService = state.overrideVoiceService; 320 copy.isDataEnabled = state.isDataEnabled; 321 copy.isIwlanCrossSim = state.isIwlanCrossSim; 322 copy.isNtn = state.isNtn; 323 return copy; 324 } 325 326 /** 327 * Returns {@code true} if modem radio is turned off (e.g. airplane mode). 328 * 329 * <p>Currently this is approximated by voice service state being {@code STATE_POWER_OFF}. 330 */ isModemOff(ServiceState state)331 private static boolean isModemOff(ServiceState state) { 332 // TODO(b/189335473): we should get this info from phone's radio power state, which is 333 // updated separately 334 return state.getVoiceRegState() == ServiceState.STATE_POWER_OFF; 335 } 336 337 /** 338 * Returns the current voice RAT from IMS registration if present, otherwise from the service 339 * state. 340 * 341 * <p>If the device is not in service, {@code TelephonyManager.NETWORK_TYPE_UNKNOWN} is returned 342 * despite that the device may have emergency service over a certain RAT. 343 */ getVoiceRat(Phone phone, @Nullable ServiceState state)344 static @NetworkType int getVoiceRat(Phone phone, @Nullable ServiceState state) { 345 return getVoiceRat(phone, state, VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_UNKNOWN); 346 } 347 348 /** 349 * Returns the current voice RAT according to the bearer. 350 * 351 * <p>If the device is not in service, {@code TelephonyManager.NETWORK_TYPE_UNKNOWN} is returned 352 * despite that the device may have emergency service over a certain RAT. 353 */ 354 @VisibleForTesting public getVoiceRat(Phone phone, @Nullable ServiceState state, int bearer)355 static @NetworkType int getVoiceRat(Phone phone, @Nullable ServiceState state, int bearer) { 356 if (state == null) { 357 return TelephonyManager.NETWORK_TYPE_UNKNOWN; 358 } 359 ImsPhone imsPhone = (ImsPhone) phone.getImsPhone(); 360 if (bearer != VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS && imsPhone != null) { 361 @NetworkType int imsVoiceRat = imsPhone.getImsStats().getImsVoiceRadioTech(); 362 if (imsVoiceRat != TelephonyManager.NETWORK_TYPE_UNKNOWN) { 363 // If IMS is registered over WWAN but WWAN PS is not in service, 364 // fallback to WWAN CS RAT 365 boolean isImsVoiceRatValid = 366 (imsVoiceRat == TelephonyManager.NETWORK_TYPE_IWLAN 367 || getRat(state, NetworkRegistrationInfo.DOMAIN_PS) 368 != TelephonyManager.NETWORK_TYPE_UNKNOWN); 369 if (isImsVoiceRatValid) { 370 return imsVoiceRat; 371 } 372 } 373 } 374 if (bearer == VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS) { 375 return TelephonyManager.NETWORK_TYPE_UNKNOWN; 376 } else { 377 return getRat(state, NetworkRegistrationInfo.DOMAIN_CS); 378 } 379 } 380 isCrossSimCallingRegistered(Phone phone)381 private boolean isCrossSimCallingRegistered(Phone phone) { 382 if (phone.getImsPhone() != null) { 383 return phone.getImsPhone().getImsRegistrationTech() 384 == ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM; 385 } 386 return false; 387 } 388 389 /** Returns RAT used by WWAN if WWAN is in service. */ getRat( ServiceState state, @NetworkRegistrationInfo.Domain int domain)390 public static @NetworkType int getRat( 391 ServiceState state, @NetworkRegistrationInfo.Domain int domain) { 392 final NetworkRegistrationInfo wwanRegInfo = 393 state.getNetworkRegistrationInfo( 394 domain, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 395 return wwanRegInfo != null && wwanRegInfo.isInService() 396 ? wwanRegInfo.getAccessNetworkTechnology() 397 : TelephonyManager.NETWORK_TYPE_UNKNOWN; 398 } 399 isEmergencyOnly(ServiceState state)400 private static boolean isEmergencyOnly(ServiceState state) { 401 NetworkRegistrationInfo regInfo = 402 state.getNetworkRegistrationInfo( 403 NetworkRegistrationInfo.DOMAIN_CS, 404 AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 405 return regInfo != null && !regInfo.isInService() && regInfo.isEmergencyEnabled(); 406 } 407 isEndc(ServiceState state)408 private static boolean isEndc(ServiceState state) { 409 if (getRat(state, NetworkRegistrationInfo.DOMAIN_PS) != TelephonyManager.NETWORK_TYPE_LTE) { 410 return false; 411 } 412 int nrState = state.getNrState(); 413 return nrState == NetworkRegistrationInfo.NR_STATE_CONNECTED 414 || nrState == NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED; 415 } 416 isInternetPdnUp(Phone phone)417 private static boolean isInternetPdnUp(Phone phone) { 418 DataNetworkController dataNetworkController = phone.getDataNetworkController(); 419 if (dataNetworkController != null) { 420 return dataNetworkController.getInternetDataNetworkState() == DATA_CONNECTED; 421 } 422 return false; 423 } 424 onInternetDataNetworkChanged(boolean internetPdnUp)425 private void onInternetDataNetworkChanged(boolean internetPdnUp) { 426 final long now = getTimeMillis(); 427 TimestampedServiceState lastState = 428 mLastState.getAndUpdate( 429 state -> { 430 if (state.mServiceState == null) { 431 return new TimestampedServiceState(null, now); 432 } 433 CellularServiceState newServiceState = copyOf(state.mServiceState); 434 newServiceState.isInternetPdnUp = internetPdnUp; 435 return new TimestampedServiceState(newServiceState, now); 436 }); 437 addServiceState(lastState, now); 438 } 439 getNetworkRoamingState( ServiceState ss, @NetworkRegistrationInfo.Domain int domain)440 private static @RoamingType int getNetworkRoamingState( 441 ServiceState ss, @NetworkRegistrationInfo.Domain int domain) { 442 final NetworkRegistrationInfo nri = 443 ss.getNetworkRegistrationInfo(domain, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 444 if (nri == null) { 445 // No registration for domain 446 return ServiceState.ROAMING_TYPE_NOT_ROAMING; 447 } 448 @RoamingType int roamingType = nri.getRoamingType(); 449 if (nri.isNetworkRoaming() && roamingType == ServiceState.ROAMING_TYPE_NOT_ROAMING) { 450 // Roaming is overridden, exact roaming type unknown. 451 return ServiceState.ROAMING_TYPE_UNKNOWN; 452 } 453 return roamingType; 454 } 455 456 /** Determines whether device is roaming, bypassing carrier overrides. */ isNetworkRoaming( ServiceState ss, @NetworkRegistrationInfo.Domain int domain)457 public static boolean isNetworkRoaming( 458 ServiceState ss, @NetworkRegistrationInfo.Domain int domain) { 459 if (ss == null) { 460 return false; 461 } 462 final NetworkRegistrationInfo nri = 463 ss.getNetworkRegistrationInfo(domain, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 464 return nri != null && nri.isNetworkRoaming(); 465 } 466 467 /** Determines whether device is roaming in any domain, bypassing carrier overrides. */ isNetworkRoaming(ServiceState ss)468 public static boolean isNetworkRoaming(ServiceState ss) { 469 return isNetworkRoaming(ss, NetworkRegistrationInfo.DOMAIN_CS) 470 || isNetworkRoaming(ss, NetworkRegistrationInfo.DOMAIN_PS); 471 } 472 473 /** Collect data Rat metric. */ writeDataRatAtom(@onNull ServiceState serviceState)474 private void writeDataRatAtom(@NonNull ServiceState serviceState) { 475 if (DataConnectionStateTracker.getActiveDataSubId() != mPhone.getSubId()) { 476 return; 477 } 478 NetworkRegistrationInfo wwanRegInfo = serviceState.getNetworkRegistrationInfo( 479 NetworkRegistrationInfo.DOMAIN_PS, 480 AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 481 if (wwanRegInfo == null) { 482 return; 483 } 484 int dataRat = wwanRegInfo.getAccessNetworkTechnology(); 485 int nrFrequency = serviceState.getNrFrequencyRange(); 486 int nrState = serviceState.getNrState(); 487 int translatedDataRat = 488 TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_UNSPECIFIED; 489 if (!SubscriptionManager.isValidSubscriptionId(mPhone.getSubId())) { 490 translatedDataRat = TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__NO_SIM; 491 } else if (dataRat == TelephonyManager.NETWORK_TYPE_EHRPD 492 || dataRat == TelephonyManager.NETWORK_TYPE_HSPAP 493 || dataRat == TelephonyManager.NETWORK_TYPE_UMTS 494 || dataRat == TelephonyManager.NETWORK_TYPE_HSDPA 495 || dataRat == TelephonyManager.NETWORK_TYPE_HSUPA 496 || dataRat == TelephonyManager.NETWORK_TYPE_HSPA 497 || dataRat == TelephonyManager.NETWORK_TYPE_EVDO_0 498 || dataRat == TelephonyManager.NETWORK_TYPE_EVDO_A 499 || dataRat == TelephonyManager.NETWORK_TYPE_EVDO_B) { 500 translatedDataRat = TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_3G; 501 } else if (dataRat == TelephonyManager.NETWORK_TYPE_1xRTT 502 || dataRat == TelephonyManager.NETWORK_TYPE_GPRS 503 || dataRat == TelephonyManager.NETWORK_TYPE_EDGE 504 || dataRat == TelephonyManager.NETWORK_TYPE_CDMA 505 || dataRat == TelephonyManager.NETWORK_TYPE_GSM) { 506 translatedDataRat = TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_2G; 507 } else if (dataRat == TelephonyManager.NETWORK_TYPE_NR) { 508 translatedDataRat = nrFrequency != ServiceState.FREQUENCY_RANGE_MMWAVE 509 ? TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_5G_SA_FR1 : 510 TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_5G_SA_FR2; 511 } else if (dataRat == TelephonyManager.NETWORK_TYPE_LTE) { 512 if (nrState == NetworkRegistrationInfo.NR_STATE_CONNECTED) { 513 translatedDataRat = nrFrequency != ServiceState.FREQUENCY_RANGE_MMWAVE 514 ? TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_5G_NSA_FR1 : 515 TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_5G_NSA_FR2; 516 } else if (nrState == NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED) { 517 translatedDataRat = 518 TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_5G_NSA_LTE; 519 } else { 520 translatedDataRat = 521 TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_4G_LTE; 522 } 523 } 524 525 if (translatedDataRat != mCurrentDataRat) { 526 TelephonyStatsLog.write(TelephonyStatsLog.DATA_RAT_STATE_CHANGED, translatedDataRat); 527 mCurrentDataRat = translatedDataRat; 528 } 529 } 530 getCurrentDataRat()531 int getCurrentDataRat() { 532 return mCurrentDataRat; 533 } 534 535 @VisibleForTesting getTimeMillis()536 protected long getTimeMillis() { 537 return SystemClock.elapsedRealtime(); 538 } 539 540 private static final class TimestampedServiceState { 541 private final CellularServiceState mServiceState; 542 private final long mTimestamp; // Start time of the service state segment 543 TimestampedServiceState(CellularServiceState serviceState, long timestamp)544 TimestampedServiceState(CellularServiceState serviceState, long timestamp) { 545 mServiceState = serviceState; 546 mTimestamp = timestamp; 547 } 548 } 549 } 550