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 android.telephony.AccessNetworkConstants; 20 import android.telephony.Annotation.NetworkType; 21 import android.telephony.CellSignalStrength; 22 import android.telephony.NetworkRegistrationInfo; 23 import android.telephony.ServiceState; 24 import android.telephony.TelephonyManager; 25 26 import com.android.internal.telephony.Phone; 27 import com.android.internal.telephony.PhoneConstants; 28 import com.android.internal.telephony.ServiceStateTracker; 29 import com.android.internal.telephony.SubscriptionController; 30 import com.android.internal.telephony.TelephonyStatsLog; 31 import com.android.internal.telephony.data.DataStallRecoveryManager; 32 import com.android.internal.telephony.dataconnection.DcTracker; 33 34 /** Generates metrics related to data stall recovery events per phone ID for the pushed atom. */ 35 public class DataStallRecoveryStats { 36 /** 37 * Create and push new atom when there is a data stall recovery event 38 * 39 * @param recoveryAction Data stall recovery action 40 * @param phone 41 */ 42 43 /* Since the Enum has been extended in Android T, we are mapping it to the correct number. */ 44 private static final int RECOVERY_ACTION_RADIO_RESTART_MAPPING = 3; 45 private static final int RECOVERY_ACTION_RESET_MODEM_MAPPING = 4; 46 47 48 /** TODO: b/214044479 : Remove this function when new data design(Android T) start. */ onDataStallEvent( @cTracker.RecoveryAction int recoveryAction, Phone phone, boolean isRecovered, int durationMillis)49 public static void onDataStallEvent( 50 @DcTracker.RecoveryAction int recoveryAction, 51 Phone phone, 52 boolean isRecovered, 53 int durationMillis) { 54 if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) { 55 phone = phone.getDefaultPhone(); 56 } 57 58 int carrierId = phone.getCarrierId(); 59 int rat = getRat(phone); 60 int band = 61 (rat == TelephonyManager.NETWORK_TYPE_IWLAN) ? 0 : ServiceStateStats.getBand(phone); 62 // the number returned here matches the SignalStrength enum we have 63 int signalStrength = phone.getSignalStrength().getLevel(); 64 boolean isOpportunistic = getIsOpportunistic(phone); 65 boolean isMultiSim = SimSlotState.getCurrentState().numActiveSims > 1; 66 67 // Not use these fields in Android S, so we set below parameter for default value. 68 int recoveryReason = 0; 69 int otherSignalStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 70 int otherNetworkRegState = NetworkRegistrationInfo 71 .REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING; 72 int phoneNetworkRegState = NetworkRegistrationInfo 73 .REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING; 74 boolean isFirstValidation = false; 75 int phoneId = 0; 76 int durationMillisOfCurrentAction = 0; 77 TelephonyStatsLog.write( 78 TelephonyStatsLog.DATA_STALL_RECOVERY_REPORTED, 79 carrierId, 80 rat, 81 signalStrength, 82 recoveryAction, 83 isOpportunistic, 84 isMultiSim, 85 band, 86 isRecovered, 87 durationMillis, 88 recoveryReason, 89 otherSignalStrength, 90 otherNetworkRegState, 91 phoneNetworkRegState, 92 isFirstValidation, 93 phoneId, 94 durationMillisOfCurrentAction); 95 } 96 97 /** 98 * Called when data stall happened. 99 * 100 * @param recoveryAction The recovery action. 101 * @param phone The phone instance. 102 * @param isRecovered The data stall symptom recovered or not. 103 * @param durationMillis The duration from data stall symptom occurred. 104 * @param reason The recovered(data resume) reason. 105 * @param isFirstValidation The validation status if it's the first come after recovery. 106 */ onDataStallEvent( @ataStallRecoveryManager.RecoveryAction int recoveryAction, Phone phone, boolean isRecovered, int durationMillis, @DataStallRecoveryManager.RecoveredReason int reason, boolean isFirstValidation, int durationMillisOfCurrentAction)107 public static void onDataStallEvent( 108 @DataStallRecoveryManager.RecoveryAction int recoveryAction, 109 Phone phone, 110 boolean isRecovered, 111 int durationMillis, 112 @DataStallRecoveryManager.RecoveredReason int reason, 113 boolean isFirstValidation, 114 int durationMillisOfCurrentAction) { 115 if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) { 116 phone = phone.getDefaultPhone(); 117 } 118 119 int carrierId = phone.getCarrierId(); 120 int rat = getRat(phone); 121 int band = 122 (rat == TelephonyManager.NETWORK_TYPE_IWLAN) ? 0 : ServiceStateStats.getBand(phone); 123 // the number returned here matches the SignalStrength enum we have 124 int signalStrength = phone.getSignalStrength().getLevel(); 125 boolean isOpportunistic = getIsOpportunistic(phone); 126 boolean isMultiSim = SimSlotState.getCurrentState().numActiveSims > 1; 127 128 if (recoveryAction == DataStallRecoveryManager.RECOVERY_ACTION_RADIO_RESTART) { 129 recoveryAction = RECOVERY_ACTION_RADIO_RESTART_MAPPING; 130 } else if (recoveryAction == DataStallRecoveryManager.RECOVERY_ACTION_RESET_MODEM) { 131 recoveryAction = RECOVERY_ACTION_RESET_MODEM_MAPPING; 132 } 133 134 // collect info of the other device in case of DSDS 135 int otherSignalStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 136 // the number returned here matches the NetworkRegistrationState enum we have 137 int otherNetworkRegState = NetworkRegistrationInfo 138 .REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING; 139 // the number returned here matches the NetworkRegistrationState enum we have 140 int phoneNetworkRegState = NetworkRegistrationInfo 141 .REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING; 142 143 NetworkRegistrationInfo phoneRegInfo = phone.getServiceState() 144 .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS, 145 AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 146 if (phoneRegInfo != null) { 147 phoneNetworkRegState = phoneRegInfo.getRegistrationState(); 148 } 149 150 // reserve 0 for default value 151 int phoneId = phone.getPhoneId() + 1; 152 153 TelephonyStatsLog.write( 154 TelephonyStatsLog.DATA_STALL_RECOVERY_REPORTED, 155 carrierId, 156 rat, 157 signalStrength, 158 recoveryAction, 159 isOpportunistic, 160 isMultiSim, 161 band, 162 isRecovered, 163 durationMillis, 164 reason, 165 otherSignalStrength, 166 otherNetworkRegState, 167 phoneNetworkRegState, 168 isFirstValidation, 169 phoneId, 170 durationMillisOfCurrentAction); 171 } 172 173 /** Returns the RAT used for data (including IWLAN). */ getRat(Phone phone)174 private static @NetworkType int getRat(Phone phone) { 175 ServiceStateTracker serviceStateTracker = phone.getServiceStateTracker(); 176 ServiceState serviceState = 177 serviceStateTracker != null ? serviceStateTracker.getServiceState() : null; 178 return serviceState != null 179 ? serviceState.getDataNetworkType() 180 : TelephonyManager.NETWORK_TYPE_UNKNOWN; 181 } 182 getIsOpportunistic(Phone phone)183 private static boolean getIsOpportunistic(Phone phone) { 184 SubscriptionController subController = SubscriptionController.getInstance(); 185 return subController != null ? subController.isOpportunistic(phone.getSubId()) : false; 186 } 187 } 188