Loading src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java +6 −2 Original line number Diff line number Diff line Loading @@ -187,6 +187,7 @@ public class DataStallRecoveryManager extends Handler { private DataStallRecoveryManagerCallback mDataStallRecoveryManagerCallback; private final DataStallRecoveryStats mStats; /** * The data stall recovery manager callback. Note this is only used for passing information * internally in the data stack, should not be used externally. Loading Loading @@ -248,6 +249,8 @@ public class DataStallRecoveryManager extends Handler { updateDataStallRecoveryConfigs(); registerAllEvents(); mStats = new DataStallRecoveryStats(mPhone, dataNetworkController); } /** Register for all events that data stall monitor is interested. */ Loading Loading @@ -645,8 +648,9 @@ public class DataStallRecoveryManager extends Handler { && !mIsAttemptedAllSteps) || mLastAction == RECOVERY_ACTION_RESET_MODEM) ? (int) getDurationOfCurrentRecoveryMs() : 0; DataStallRecoveryStats.onDataStallEvent( mLastAction, mPhone, isValid, timeDuration, reason, mStats.uploadMetrics( mLastAction, isValid, timeDuration, reason, isFirstValidationAfterDoRecovery, timeDurationOfCurrentAction); logl( "data stall: " Loading src/java/com/android/internal/telephony/metrics/DataStallRecoveryStats.java +286 −88 Original line number Diff line number Diff line Loading @@ -16,138 +16,336 @@ package com.android.internal.telephony.metrics; import android.annotation.NonNull; import android.annotation.Nullable; import android.net.NetworkCapabilities; import android.os.Handler; import android.os.HandlerThread; 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 android.telephony.data.DataCallResponse; import android.telephony.data.DataCallResponse.LinkStatus; 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.TelephonyStatsLog; import com.android.internal.telephony.data.DataNetwork; import com.android.internal.telephony.data.DataNetworkController; import com.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback; import com.android.internal.telephony.data.DataStallRecoveryManager; import com.android.internal.telephony.subscription.SubscriptionInfoInternal; import com.android.internal.telephony.subscription.SubscriptionManagerService; import com.android.telephony.Rlog; /** Generates metrics related to data stall recovery events per phone ID for the pushed atom. */ import java.util.List; /** * 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 * Value indicating that link bandwidth is unspecified. * Copied from {@code NetworkCapabilities#LINK_BANDWIDTH_UNSPECIFIED} */ private static final int LINK_BANDWIDTH_UNSPECIFIED = 0; private static final String TAG = "DSRS-"; // Handler to upload metrics. private final @NonNull Handler mHandler; private final @NonNull String mTag; private final @NonNull Phone mPhone; // The interface name of the internet network. private @Nullable String mIfaceName = null; /* Metrics and stats data variables */ private int mPhoneId = 0; private int mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID; private int mSignalStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; private int mBand = 0; // The RAT used for data (including IWLAN). private @NetworkType int mRat = TelephonyManager.NETWORK_TYPE_UNKNOWN; private boolean mIsOpportunistic = false; private boolean mIsMultiSim = false; private int mNetworkRegState = NetworkRegistrationInfo .REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING; // Info of the other device in case of DSDS private int mOtherSignalStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; private int mOtherNetworkRegState = NetworkRegistrationInfo .REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING; // Link status of the data network private @LinkStatus int mInternetLinkStatus = DataCallResponse.LINK_STATUS_UNKNOWN; /* 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; // The link bandwidth of the data network private int mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; private int mLinkUpBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; /** * Called when data stall happened. * Constructs a new instance of {@link DataStallRecoveryStats}. */ public DataStallRecoveryStats(@NonNull final Phone phone, @NonNull final DataNetworkController dataNetworkController) { mTag = TAG + phone.getPhoneId(); mPhone = phone; HandlerThread handlerThread = new HandlerThread(mTag + "-thread"); handlerThread.start(); mHandler = new Handler(handlerThread.getLooper()); dataNetworkController.registerDataNetworkControllerCallback( new DataNetworkControllerCallback(mHandler::post) { @Override public void onInternetDataNetworkConnected( @NonNull List<DataNetwork> internetNetworks) { for (DataNetwork dataNetwork : internetNetworks) { mIfaceName = dataNetwork.getLinkProperties().getInterfaceName(); break; } } @Override public void onInternetDataNetworkDisconnected() { mIfaceName = null; } @Override public void onPhysicalLinkStatusChanged(@LinkStatus int status) { mInternetLinkStatus = status; } }); } /** * Create and push new atom when there is a data stall recovery event. * * @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. * @param action The recovery action. * @param isRecovered Whether the data stall has been recovered. * @param duration The duration from data stall occurred in milliseconds. * @param reason The reason for the recovery. * @param isFirstValidation Whether this is the first validation after recovery. * @param durationOfAction The duration of the current action in milliseconds. */ public static void onDataStallEvent( @DataStallRecoveryManager.RecoveryAction int recoveryAction, Phone phone, public void uploadMetrics( @DataStallRecoveryManager.RecoveryAction int action, boolean isRecovered, int durationMillis, int duration, @DataStallRecoveryManager.RecoveredReason int reason, boolean isFirstValidation, int durationMillisOfCurrentAction) { 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 int durationOfAction) { mHandler.post(() -> { // Update data stall stats log("Set recovery action to " + action); // Refreshes the metrics data. try { refreshMetricsData(); } catch (Exception e) { loge("The metrics data cannot be refreshed.", e); return; } /** * TODO: Extend TelephonyStatsLog.write to upload the TCP information and data * networking stats data. */ TelephonyStatsLog.write( TelephonyStatsLog.DATA_STALL_RECOVERY_REPORTED, mCarrierId, mRat, mSignalStrength, action, mIsOpportunistic, mIsMultiSim, mBand, isRecovered, duration, reason, mOtherSignalStrength, mOtherNetworkRegState, mNetworkRegState, isFirstValidation, mPhoneId, durationOfAction); log("Upload stats: " + "Action:" + action + ", Recovered:" + isRecovered + ", Duration:" + duration + ", Reason:" + reason + ", First validation:" + isFirstValidation + ", Duration of action:" + durationOfAction + ", " + this); }); } /** * Refreshes the metrics data. */ private void refreshMetricsData() { logd("Refreshes the metrics data."); // Update phone id/carrier id and signal strength mPhoneId = mPhone.getPhoneId() + 1; mCarrierId = mPhone.getCarrierId(); mSignalStrength = mPhone.getSignalStrength().getLevel(); // Update the bandwidth. updateBandwidths(); // Update the RAT and band. updateRatAndBand(); // Update the opportunistic state. mIsOpportunistic = getIsOpportunistic(mPhone); // Update the multi-SIM state. mIsMultiSim = SimSlotState.getCurrentState().numActiveSims > 1; // Update the network registration state. updateNetworkRegState(); // Update the DSDS information. updateDsdsInfo(); } /** * Updates the bandwidth for the current data network. */ private void updateBandwidths() { mLinkDownBandwidthKbps = mLinkUpBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; if (mIfaceName == null) { loge("Interface name is null"); return; } DataNetworkController dataNetworkController = mPhone.getDataNetworkController(); if (dataNetworkController == null) { loge("DataNetworkController is null"); return; } DataNetwork dataNetwork = dataNetworkController.getDataNetworkByInterface(mIfaceName); if (dataNetwork == null) { loge("DataNetwork is null"); return; } NetworkCapabilities networkCapabilities = dataNetwork.getNetworkCapabilities(); if (networkCapabilities == null) { loge("NetworkCapabilities is null"); return; } mLinkDownBandwidthKbps = networkCapabilities.getLinkDownstreamBandwidthKbps(); mLinkUpBandwidthKbps = networkCapabilities.getLinkUpstreamBandwidthKbps(); } private void updateRatAndBand() { mRat = TelephonyManager.NETWORK_TYPE_UNKNOWN; mBand = 0; ServiceState serviceState = mPhone.getServiceState(); if (serviceState == null) { loge("ServiceState is null"); return; } mRat = serviceState.getDataNetworkType(); mBand = (mRat == TelephonyManager.NETWORK_TYPE_IWLAN) ? 0 : ServiceStateStats.getBand(mPhone); } private static boolean getIsOpportunistic(@NonNull Phone phone) { SubscriptionInfoInternal subInfo = SubscriptionManagerService.getInstance() .getSubscriptionInfoInternal(phone.getSubId()); return subInfo != null && subInfo.isOpportunistic(); } private void updateNetworkRegState() { mNetworkRegState = NetworkRegistrationInfo .REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING; NetworkRegistrationInfo phoneRegInfo = mPhone.getServiceState() .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); if (phoneRegInfo != null) { mNetworkRegState = phoneRegInfo.getRegistrationState(); } } private void updateDsdsInfo() { mOtherSignalStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; mOtherNetworkRegState = NetworkRegistrationInfo .REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING; for (Phone otherPhone : PhoneFactory.getPhones()) { if (otherPhone.getPhoneId() == phone.getPhoneId()) continue; if (otherPhone.getPhoneId() == mPhone.getPhoneId()) continue; if (!getIsOpportunistic(otherPhone)) { otherSignalStrength = otherPhone.getSignalStrength().getLevel(); mOtherSignalStrength = otherPhone.getSignalStrength().getLevel(); NetworkRegistrationInfo regInfo = otherPhone.getServiceState() .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); if (regInfo != null) { otherNetworkRegState = regInfo.getRegistrationState(); mOtherNetworkRegState = 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(); private void log(@NonNull String s) { Rlog.i(mTag, s); } // reserve 0 for default value int phoneId = phone.getPhoneId() + 1; private void logd(@NonNull String s) { Rlog.d(mTag, s); } TelephonyStatsLog.write( TelephonyStatsLog.DATA_STALL_RECOVERY_REPORTED, carrierId, rat, signalStrength, recoveryAction, isOpportunistic, isMultiSim, band, isRecovered, durationMillis, reason, otherSignalStrength, otherNetworkRegState, phoneNetworkRegState, isFirstValidation, phoneId, durationMillisOfCurrentAction); private void loge(@NonNull String s) { Rlog.e(mTag, s); } /** 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 void loge(@NonNull String s, Throwable tr) { Rlog.e(mTag, s, tr); } private static boolean getIsOpportunistic(Phone phone) { SubscriptionInfoInternal subInfo = SubscriptionManagerService.getInstance() .getSubscriptionInfoInternal(phone.getSubId()); return subInfo != null && subInfo.isOpportunistic(); @Override public String toString() { return "DataStallRecoveryStats {" + "Phone id:" + mPhoneId + ", Signal strength:" + mSignalStrength + ", Band:" + mBand + ", RAT:" + mRat + ", Opportunistic:" + mIsOpportunistic + ", Multi-SIM:" + mIsMultiSim + ", Network reg state:" + mNetworkRegState + ", Other signal strength:" + mOtherSignalStrength + ", Other network reg state:" + mOtherNetworkRegState + ", Link status:" + mInternetLinkStatus + ", Link down bandwidth:" + mLinkDownBandwidthKbps + ", Link up bandwidth:" + mLinkUpBandwidthKbps + "}"; } } tests/telephonytests/src/com/android/internal/telephony/data/DataStallRecoveryManagerTest.java +4 −4 Original line number Diff line number Diff line Loading @@ -93,22 +93,22 @@ public class DataStallRecoveryManagerTest extends TelephonyTest { private void sendValidationStatusCallback(@ValidationStatus int status) { ArgumentCaptor<DataNetworkControllerCallback> dataNetworkControllerCallbackCaptor = ArgumentCaptor.forClass(DataNetworkControllerCallback.class); verify(mDataNetworkController) verify(mDataNetworkController, times(2)) .registerDataNetworkControllerCallback( dataNetworkControllerCallbackCaptor.capture()); DataNetworkControllerCallback dataNetworkControllerCallback = dataNetworkControllerCallbackCaptor.getValue(); dataNetworkControllerCallbackCaptor.getAllValues().get(0); dataNetworkControllerCallback.onInternetDataNetworkValidationStatusChanged(status); } private void sendOnInternetDataNetworkCallback(boolean isConnected) { ArgumentCaptor<DataNetworkControllerCallback> dataNetworkControllerCallbackCaptor = ArgumentCaptor.forClass(DataNetworkControllerCallback.class); verify(mDataNetworkController) verify(mDataNetworkController, times(2)) .registerDataNetworkControllerCallback( dataNetworkControllerCallbackCaptor.capture()); DataNetworkControllerCallback dataNetworkControllerCallback = dataNetworkControllerCallbackCaptor.getValue(); dataNetworkControllerCallbackCaptor.getAllValues().get(0); if (isConnected) { List<DataNetwork> dataprofile = new ArrayList<>(); Loading Loading
src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java +6 −2 Original line number Diff line number Diff line Loading @@ -187,6 +187,7 @@ public class DataStallRecoveryManager extends Handler { private DataStallRecoveryManagerCallback mDataStallRecoveryManagerCallback; private final DataStallRecoveryStats mStats; /** * The data stall recovery manager callback. Note this is only used for passing information * internally in the data stack, should not be used externally. Loading Loading @@ -248,6 +249,8 @@ public class DataStallRecoveryManager extends Handler { updateDataStallRecoveryConfigs(); registerAllEvents(); mStats = new DataStallRecoveryStats(mPhone, dataNetworkController); } /** Register for all events that data stall monitor is interested. */ Loading Loading @@ -645,8 +648,9 @@ public class DataStallRecoveryManager extends Handler { && !mIsAttemptedAllSteps) || mLastAction == RECOVERY_ACTION_RESET_MODEM) ? (int) getDurationOfCurrentRecoveryMs() : 0; DataStallRecoveryStats.onDataStallEvent( mLastAction, mPhone, isValid, timeDuration, reason, mStats.uploadMetrics( mLastAction, isValid, timeDuration, reason, isFirstValidationAfterDoRecovery, timeDurationOfCurrentAction); logl( "data stall: " Loading
src/java/com/android/internal/telephony/metrics/DataStallRecoveryStats.java +286 −88 Original line number Diff line number Diff line Loading @@ -16,138 +16,336 @@ package com.android.internal.telephony.metrics; import android.annotation.NonNull; import android.annotation.Nullable; import android.net.NetworkCapabilities; import android.os.Handler; import android.os.HandlerThread; 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 android.telephony.data.DataCallResponse; import android.telephony.data.DataCallResponse.LinkStatus; 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.TelephonyStatsLog; import com.android.internal.telephony.data.DataNetwork; import com.android.internal.telephony.data.DataNetworkController; import com.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback; import com.android.internal.telephony.data.DataStallRecoveryManager; import com.android.internal.telephony.subscription.SubscriptionInfoInternal; import com.android.internal.telephony.subscription.SubscriptionManagerService; import com.android.telephony.Rlog; /** Generates metrics related to data stall recovery events per phone ID for the pushed atom. */ import java.util.List; /** * 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 * Value indicating that link bandwidth is unspecified. * Copied from {@code NetworkCapabilities#LINK_BANDWIDTH_UNSPECIFIED} */ private static final int LINK_BANDWIDTH_UNSPECIFIED = 0; private static final String TAG = "DSRS-"; // Handler to upload metrics. private final @NonNull Handler mHandler; private final @NonNull String mTag; private final @NonNull Phone mPhone; // The interface name of the internet network. private @Nullable String mIfaceName = null; /* Metrics and stats data variables */ private int mPhoneId = 0; private int mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID; private int mSignalStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; private int mBand = 0; // The RAT used for data (including IWLAN). private @NetworkType int mRat = TelephonyManager.NETWORK_TYPE_UNKNOWN; private boolean mIsOpportunistic = false; private boolean mIsMultiSim = false; private int mNetworkRegState = NetworkRegistrationInfo .REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING; // Info of the other device in case of DSDS private int mOtherSignalStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; private int mOtherNetworkRegState = NetworkRegistrationInfo .REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING; // Link status of the data network private @LinkStatus int mInternetLinkStatus = DataCallResponse.LINK_STATUS_UNKNOWN; /* 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; // The link bandwidth of the data network private int mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; private int mLinkUpBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; /** * Called when data stall happened. * Constructs a new instance of {@link DataStallRecoveryStats}. */ public DataStallRecoveryStats(@NonNull final Phone phone, @NonNull final DataNetworkController dataNetworkController) { mTag = TAG + phone.getPhoneId(); mPhone = phone; HandlerThread handlerThread = new HandlerThread(mTag + "-thread"); handlerThread.start(); mHandler = new Handler(handlerThread.getLooper()); dataNetworkController.registerDataNetworkControllerCallback( new DataNetworkControllerCallback(mHandler::post) { @Override public void onInternetDataNetworkConnected( @NonNull List<DataNetwork> internetNetworks) { for (DataNetwork dataNetwork : internetNetworks) { mIfaceName = dataNetwork.getLinkProperties().getInterfaceName(); break; } } @Override public void onInternetDataNetworkDisconnected() { mIfaceName = null; } @Override public void onPhysicalLinkStatusChanged(@LinkStatus int status) { mInternetLinkStatus = status; } }); } /** * Create and push new atom when there is a data stall recovery event. * * @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. * @param action The recovery action. * @param isRecovered Whether the data stall has been recovered. * @param duration The duration from data stall occurred in milliseconds. * @param reason The reason for the recovery. * @param isFirstValidation Whether this is the first validation after recovery. * @param durationOfAction The duration of the current action in milliseconds. */ public static void onDataStallEvent( @DataStallRecoveryManager.RecoveryAction int recoveryAction, Phone phone, public void uploadMetrics( @DataStallRecoveryManager.RecoveryAction int action, boolean isRecovered, int durationMillis, int duration, @DataStallRecoveryManager.RecoveredReason int reason, boolean isFirstValidation, int durationMillisOfCurrentAction) { 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 int durationOfAction) { mHandler.post(() -> { // Update data stall stats log("Set recovery action to " + action); // Refreshes the metrics data. try { refreshMetricsData(); } catch (Exception e) { loge("The metrics data cannot be refreshed.", e); return; } /** * TODO: Extend TelephonyStatsLog.write to upload the TCP information and data * networking stats data. */ TelephonyStatsLog.write( TelephonyStatsLog.DATA_STALL_RECOVERY_REPORTED, mCarrierId, mRat, mSignalStrength, action, mIsOpportunistic, mIsMultiSim, mBand, isRecovered, duration, reason, mOtherSignalStrength, mOtherNetworkRegState, mNetworkRegState, isFirstValidation, mPhoneId, durationOfAction); log("Upload stats: " + "Action:" + action + ", Recovered:" + isRecovered + ", Duration:" + duration + ", Reason:" + reason + ", First validation:" + isFirstValidation + ", Duration of action:" + durationOfAction + ", " + this); }); } /** * Refreshes the metrics data. */ private void refreshMetricsData() { logd("Refreshes the metrics data."); // Update phone id/carrier id and signal strength mPhoneId = mPhone.getPhoneId() + 1; mCarrierId = mPhone.getCarrierId(); mSignalStrength = mPhone.getSignalStrength().getLevel(); // Update the bandwidth. updateBandwidths(); // Update the RAT and band. updateRatAndBand(); // Update the opportunistic state. mIsOpportunistic = getIsOpportunistic(mPhone); // Update the multi-SIM state. mIsMultiSim = SimSlotState.getCurrentState().numActiveSims > 1; // Update the network registration state. updateNetworkRegState(); // Update the DSDS information. updateDsdsInfo(); } /** * Updates the bandwidth for the current data network. */ private void updateBandwidths() { mLinkDownBandwidthKbps = mLinkUpBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; if (mIfaceName == null) { loge("Interface name is null"); return; } DataNetworkController dataNetworkController = mPhone.getDataNetworkController(); if (dataNetworkController == null) { loge("DataNetworkController is null"); return; } DataNetwork dataNetwork = dataNetworkController.getDataNetworkByInterface(mIfaceName); if (dataNetwork == null) { loge("DataNetwork is null"); return; } NetworkCapabilities networkCapabilities = dataNetwork.getNetworkCapabilities(); if (networkCapabilities == null) { loge("NetworkCapabilities is null"); return; } mLinkDownBandwidthKbps = networkCapabilities.getLinkDownstreamBandwidthKbps(); mLinkUpBandwidthKbps = networkCapabilities.getLinkUpstreamBandwidthKbps(); } private void updateRatAndBand() { mRat = TelephonyManager.NETWORK_TYPE_UNKNOWN; mBand = 0; ServiceState serviceState = mPhone.getServiceState(); if (serviceState == null) { loge("ServiceState is null"); return; } mRat = serviceState.getDataNetworkType(); mBand = (mRat == TelephonyManager.NETWORK_TYPE_IWLAN) ? 0 : ServiceStateStats.getBand(mPhone); } private static boolean getIsOpportunistic(@NonNull Phone phone) { SubscriptionInfoInternal subInfo = SubscriptionManagerService.getInstance() .getSubscriptionInfoInternal(phone.getSubId()); return subInfo != null && subInfo.isOpportunistic(); } private void updateNetworkRegState() { mNetworkRegState = NetworkRegistrationInfo .REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING; NetworkRegistrationInfo phoneRegInfo = mPhone.getServiceState() .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); if (phoneRegInfo != null) { mNetworkRegState = phoneRegInfo.getRegistrationState(); } } private void updateDsdsInfo() { mOtherSignalStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; mOtherNetworkRegState = NetworkRegistrationInfo .REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING; for (Phone otherPhone : PhoneFactory.getPhones()) { if (otherPhone.getPhoneId() == phone.getPhoneId()) continue; if (otherPhone.getPhoneId() == mPhone.getPhoneId()) continue; if (!getIsOpportunistic(otherPhone)) { otherSignalStrength = otherPhone.getSignalStrength().getLevel(); mOtherSignalStrength = otherPhone.getSignalStrength().getLevel(); NetworkRegistrationInfo regInfo = otherPhone.getServiceState() .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); if (regInfo != null) { otherNetworkRegState = regInfo.getRegistrationState(); mOtherNetworkRegState = 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(); private void log(@NonNull String s) { Rlog.i(mTag, s); } // reserve 0 for default value int phoneId = phone.getPhoneId() + 1; private void logd(@NonNull String s) { Rlog.d(mTag, s); } TelephonyStatsLog.write( TelephonyStatsLog.DATA_STALL_RECOVERY_REPORTED, carrierId, rat, signalStrength, recoveryAction, isOpportunistic, isMultiSim, band, isRecovered, durationMillis, reason, otherSignalStrength, otherNetworkRegState, phoneNetworkRegState, isFirstValidation, phoneId, durationMillisOfCurrentAction); private void loge(@NonNull String s) { Rlog.e(mTag, s); } /** 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 void loge(@NonNull String s, Throwable tr) { Rlog.e(mTag, s, tr); } private static boolean getIsOpportunistic(Phone phone) { SubscriptionInfoInternal subInfo = SubscriptionManagerService.getInstance() .getSubscriptionInfoInternal(phone.getSubId()); return subInfo != null && subInfo.isOpportunistic(); @Override public String toString() { return "DataStallRecoveryStats {" + "Phone id:" + mPhoneId + ", Signal strength:" + mSignalStrength + ", Band:" + mBand + ", RAT:" + mRat + ", Opportunistic:" + mIsOpportunistic + ", Multi-SIM:" + mIsMultiSim + ", Network reg state:" + mNetworkRegState + ", Other signal strength:" + mOtherSignalStrength + ", Other network reg state:" + mOtherNetworkRegState + ", Link status:" + mInternetLinkStatus + ", Link down bandwidth:" + mLinkDownBandwidthKbps + ", Link up bandwidth:" + mLinkUpBandwidthKbps + "}"; } }
tests/telephonytests/src/com/android/internal/telephony/data/DataStallRecoveryManagerTest.java +4 −4 Original line number Diff line number Diff line Loading @@ -93,22 +93,22 @@ public class DataStallRecoveryManagerTest extends TelephonyTest { private void sendValidationStatusCallback(@ValidationStatus int status) { ArgumentCaptor<DataNetworkControllerCallback> dataNetworkControllerCallbackCaptor = ArgumentCaptor.forClass(DataNetworkControllerCallback.class); verify(mDataNetworkController) verify(mDataNetworkController, times(2)) .registerDataNetworkControllerCallback( dataNetworkControllerCallbackCaptor.capture()); DataNetworkControllerCallback dataNetworkControllerCallback = dataNetworkControllerCallbackCaptor.getValue(); dataNetworkControllerCallbackCaptor.getAllValues().get(0); dataNetworkControllerCallback.onInternetDataNetworkValidationStatusChanged(status); } private void sendOnInternetDataNetworkCallback(boolean isConnected) { ArgumentCaptor<DataNetworkControllerCallback> dataNetworkControllerCallbackCaptor = ArgumentCaptor.forClass(DataNetworkControllerCallback.class); verify(mDataNetworkController) verify(mDataNetworkController, times(2)) .registerDataNetworkControllerCallback( dataNetworkControllerCallbackCaptor.capture()); DataNetworkControllerCallback dataNetworkControllerCallback = dataNetworkControllerCallbackCaptor.getValue(); dataNetworkControllerCallbackCaptor.getAllValues().get(0); if (isConnected) { List<DataNetwork> dataprofile = new ArrayList<>(); Loading