blob: 6637cb50509580e5adb4d8a084da0b59da10bb17 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.telephony.metrics;
import android.telephony.AccessNetworkConstants;
import android.telephony.Annotation.NetworkType;
import android.telephony.CellSignalStrength;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.SubscriptionController;
import com.android.internal.telephony.TelephonyStatsLog;
import com.android.internal.telephony.data.DataStallRecoveryManager;
/** Generates metrics related to data stall recovery events per phone ID for the pushed atom. */
public class DataStallRecoveryStats {
/**
* Create and push new atom when there is a data stall recovery event
*
* @param recoveryAction Data stall recovery action
* @param phone
*/
/* Since the Enum has been extended in Android T, we are mapping it to the correct number. */
private static final int RECOVERY_ACTION_RADIO_RESTART_MAPPING = 3;
private static final int RECOVERY_ACTION_RESET_MODEM_MAPPING = 4;
/**
* Called when data stall happened.
*
* @param recoveryAction The recovery action.
* @param phone The phone instance.
* @param isRecovered The data stall symptom recovered or not.
* @param durationMillis The duration from data stall symptom occurred.
* @param reason The recovered(data resume) reason.
* @param isFirstValidation The validation status if it's the first come after recovery.
*/
public static void onDataStallEvent(
@DataStallRecoveryManager.RecoveryAction int recoveryAction,
Phone phone,
boolean isRecovered,
int durationMillis,
@DataStallRecoveryManager.RecoveredReason int reason,
boolean isFirstValidation) {
if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
phone = phone.getDefaultPhone();
}
int carrierId = phone.getCarrierId();
int rat = getRat(phone);
int band =
(rat == TelephonyManager.NETWORK_TYPE_IWLAN) ? 0 : ServiceStateStats.getBand(phone);
// the number returned here matches the SignalStrength enum we have
int signalStrength = phone.getSignalStrength().getLevel();
boolean isOpportunistic = getIsOpportunistic(phone);
boolean isMultiSim = SimSlotState.getCurrentState().numActiveSims > 1;
if (recoveryAction == DataStallRecoveryManager.RECOVERY_ACTION_RADIO_RESTART) {
recoveryAction = RECOVERY_ACTION_RADIO_RESTART_MAPPING;
} else if (recoveryAction == DataStallRecoveryManager.RECOVERY_ACTION_RESET_MODEM) {
recoveryAction = RECOVERY_ACTION_RESET_MODEM_MAPPING;
}
// collect info of the other device in case of DSDS
int otherSignalStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
// the number returned here matches the NetworkRegistrationState enum we have
int otherNetworkRegState = NetworkRegistrationInfo
.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING;
for (Phone otherPhone : PhoneFactory.getPhones()) {
if (otherPhone.getPhoneId() == phone.getPhoneId()) continue;
if (!getIsOpportunistic(otherPhone)) {
otherSignalStrength = otherPhone.getSignalStrength().getLevel();
NetworkRegistrationInfo regInfo = otherPhone.getServiceState()
.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
if (regInfo != null) {
otherNetworkRegState = regInfo.getRegistrationState();
}
break;
}
}
// the number returned here matches the NetworkRegistrationState enum we have
int phoneNetworkRegState = NetworkRegistrationInfo
.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING;
NetworkRegistrationInfo phoneRegInfo = phone.getServiceState()
.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
if (phoneRegInfo != null) {
phoneNetworkRegState = phoneRegInfo.getRegistrationState();
}
int phoneId = phone.getPhoneId();
TelephonyStatsLog.write(
TelephonyStatsLog.DATA_STALL_RECOVERY_REPORTED,
carrierId,
rat,
signalStrength,
recoveryAction,
isOpportunistic,
isMultiSim,
band,
isRecovered,
durationMillis,
reason,
otherSignalStrength,
otherNetworkRegState,
phoneNetworkRegState,
isFirstValidation,
phoneId);
}
/** Returns the RAT used for data (including IWLAN). */
private static @NetworkType int getRat(Phone phone) {
ServiceStateTracker serviceStateTracker = phone.getServiceStateTracker();
ServiceState serviceState =
serviceStateTracker != null ? serviceStateTracker.getServiceState() : null;
return serviceState != null
? serviceState.getDataNetworkType()
: TelephonyManager.NETWORK_TYPE_UNKNOWN;
}
private static boolean getIsOpportunistic(Phone phone) {
SubscriptionController subController = SubscriptionController.getInstance();
return subController != null ? subController.isOpportunistic(phone.getSubId()) : false;
}
}