Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a98ebe8b authored by Chi Zhang's avatar Chi Zhang Committed by Android (Google) Code Review
Browse files

Merge changes I18db3355,I5328b68c into sc-v2-dev

* changes:
  Use IMS registration for voice RAT stats.
  Fix band and RAT handling in various atoms.
parents 8732e8c3 88a2e928
Loading
Loading
Loading
Loading
+32 −13
Original line number Diff line number Diff line
@@ -91,7 +91,15 @@ public class DataCallSessionStats {
            loge("onSetupDataCallResponse: no DataCallSession atom has been initiated.");
            return;
        }
        mDataCallSession.ratAtEnd = ServiceState.rilRadioTechnologyToNetworkType(radioTechnology);

        @NetworkType int currentRat = ServiceState.rilRadioTechnologyToNetworkType(radioTechnology);
        if (currentRat != TelephonyManager.NETWORK_TYPE_UNKNOWN) {
            mDataCallSession.ratAtEnd = currentRat;
            mDataCallSession.bandAtEnd =
                    (currentRat == TelephonyManager.NETWORK_TYPE_IWLAN)
                            ? 0
                            : ServiceStateStats.getBand(mPhone);
        }

        // only set if apn hasn't been set during setup
        if (mDataCallSession.apnTypeBitmask == 0) {
@@ -106,6 +114,7 @@ public class DataCallSessionStats {
            // If setup has failed, then store the atom
            if (failureCause != DataFailCause.NONE) {
                mDataCallSession.failureCause = failureCause;
                mDataCallSession.oosAtEnd = getIsOos();
                mDataCallSession.setupFailed = true;
                mDataCallSession.ongoing = false;
                PhoneFactory.getMetricsCollector().unregisterOngoingDataCallStat(this);
@@ -147,14 +156,17 @@ public class DataCallSessionStats {
        }
    }

    /** Stores the atom when DataConnection reaches DISCONNECTED state.
    /**
     * Stores the atom when DataConnection reaches DISCONNECTED state.
     *
     * @param failureCause failure cause as per android.telephony.DataFailCause
     **/
     */
    public synchronized void onDataCallDisconnected(@DataFailureCause int failureCause) {
        // there should've been another call to initiate the atom,
        // so this method is being called out of order -> no atom will be saved
        // this also happens when DataConnection is created, which is expected
        if (mDataCallSession == null) {
            loge("onDataCallDisconnected: no DataCallSession atom has been initiated.");
            logi("onDataCallDisconnected: no DataCallSession atom has been initiated.");
            return;
        }
        mDataCallSession.failureCause = failureCause;
@@ -175,14 +187,17 @@ public class DataCallSessionStats {
     * registration state change.
     */
    public synchronized void onDrsOrRatChanged(@RilRadioTechnology int radioTechnology) {
        @NetworkType int currentRat =
                ServiceState.rilRadioTechnologyToNetworkType(radioTechnology);
        if (mDataCallSession != null
                && currentRat != TelephonyManager.NETWORK_TYPE_UNKNOWN
                && mDataCallSession.ratAtEnd != currentRat) {
        @NetworkType int currentRat = ServiceState.rilRadioTechnologyToNetworkType(radioTechnology);
        if (mDataCallSession != null && currentRat != TelephonyManager.NETWORK_TYPE_UNKNOWN) {
            if (mDataCallSession.ratAtEnd != currentRat) {
                mDataCallSession.ratSwitchCount++;
                mDataCallSession.ratAtEnd = currentRat;
            mDataCallSession.bandAtEnd = ServiceStateStats.getBand(mPhone, currentRat);
            }
            // band may have changed even if RAT was the same
            mDataCallSession.bandAtEnd =
                    (currentRat == TelephonyManager.NETWORK_TYPE_IWLAN)
                            ? 0
                            : ServiceStateStats.getBand(mPhone);
        }
    }

@@ -268,6 +283,10 @@ public class DataCallSessionStats {
                : false;
    }

    private void logi(String format, Object... args) {
        Rlog.i(TAG, "[" + mPhone.getPhoneId() + "]" + String.format(format, args));
    }

    private void loge(String format, Object... args) {
        Rlog.e(TAG, "[" + mPhone.getPhoneId() + "]" + String.format(format, args));
    }
+19 −6
Original line number Diff line number Diff line
@@ -35,22 +35,34 @@ public class DataStallRecoveryStats {
     * @param recoveryAction Data stall recovery action
     * @param phone
     */
    public static void onDataStallEvent(@DcTracker.RecoveryAction int recoveryAction,
            Phone phone, boolean isRecovered, int durationMillis) {
    public static void onDataStallEvent(
            @DcTracker.RecoveryAction int recoveryAction,
            Phone phone,
            boolean isRecovered,
            int durationMillis) {
        if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
            phone = phone.getDefaultPhone();
        }

        int carrierId = phone.getCarrierId();
        int rat = getRat(phone);
        int band = ServiceStateStats.getBand(phone, rat);
        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;

        TelephonyStatsLog.write(TelephonyStatsLog.DATA_STALL_RECOVERY_REPORTED, carrierId, rat,
                signalStrength, recoveryAction, isOpportunistic, isMultiSim, band, isRecovered,
        TelephonyStatsLog.write(
                TelephonyStatsLog.DATA_STALL_RECOVERY_REPORTED,
                carrierId,
                rat,
                signalStrength,
                recoveryAction,
                isOpportunistic,
                isMultiSim,
                band,
                isRecovered,
                durationMillis);
    }

@@ -59,7 +71,8 @@ public class DataStallRecoveryStats {
        ServiceStateTracker serviceStateTracker = phone.getServiceStateTracker();
        ServiceState serviceState =
                serviceStateTracker != null ? serviceStateTracker.getServiceState() : null;
        return serviceState != null ? serviceState.getDataNetworkType()
        return serviceState != null
                ? serviceState.getDataNetworkType()
                : TelephonyManager.NETWORK_TYPE_UNKNOWN;
    }

+31 −12
Original line number Diff line number Diff line
@@ -35,8 +35,6 @@ import android.os.SystemClock;
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.Annotation.NetworkType;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ProvisioningManager;
@@ -265,10 +263,24 @@ public class ImsStats {
            @ImsRegistrationTech int radioTech, MmTelCapabilities capabilities) {
        conclude();

        if (mLastRegistrationStats != null) {
            mLastRegistrationStats.rat = convertRegistrationTechToNetworkType(radioTech);
        boolean ratChanged = false;
        @NetworkType int newRat = convertRegistrationTechToNetworkType(radioTech);
        if (mLastRegistrationStats != null && mLastRegistrationStats.rat != newRat) {
            mLastRegistrationStats.rat = newRat;
            ratChanged = true;
        }

        boolean voiceAvailableNow = capabilities.isCapable(CAPABILITY_TYPE_VOICE);
        boolean voiceAvailabilityChanged =
                (mLastAvailableFeatures.isCapable(CAPABILITY_TYPE_VOICE) != voiceAvailableNow);
        mLastAvailableFeatures = capabilities;

        // Notify voice RAT change if 1. RAT changed while voice over IMS is available, or 2. voice
        // over IMS availability changed
        if ((ratChanged && voiceAvailableNow) || voiceAvailabilityChanged) {
            mPhone.getDefaultPhone().getServiceStateTracker().getServiceStateStats()
                    .onImsVoiceRegistrationChanged();
        }
    }

    /** Updates the stats when capable features changed. */
@@ -335,6 +347,20 @@ public class ImsStats {
        mLastAvailableFeatures = new MmTelCapabilities();
    }

    /**
     * Returns the current RAT used for IMS voice registration, or {@link
     * TelephonyManager#NETWORK_TYPE_UNKNOWN} if there isn't any.
     */
    @NetworkType
    @VisibleForTesting
    public synchronized int getImsVoiceRadioTech() {
        if (mLastRegistrationStats == null
                || !mLastAvailableFeatures.isCapable(CAPABILITY_TYPE_VOICE)) {
            return TelephonyManager.NETWORK_TYPE_UNKNOWN;
        }
        return mLastRegistrationStats.rat;
    }

    @NetworkType
    private int getRatAtEnd(@NetworkType int lastStateRat) {
        return lastStateRat == TelephonyManager.NETWORK_TYPE_IWLAN ? lastStateRat : getWwanPsRat();
@@ -354,14 +380,7 @@ public class ImsStats {

    @NetworkType
    private int getWwanPsRat() {
        ServiceState state = mPhone.getServiceStateTracker().getServiceState();
        final NetworkRegistrationInfo wwanRegInfo =
                state.getNetworkRegistrationInfo(
                        NetworkRegistrationInfo.DOMAIN_PS,
                        AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
        return wwanRegInfo != null
                ? wwanRegInfo.getAccessNetworkTechnology()
                : TelephonyManager.NETWORK_TYPE_UNKNOWN;
        return ServiceStateStats.getDataRat(mPhone.getServiceStateTracker().getServiceState());
    }

    private ImsRegistrationStats getDefaultImsRegistrationStats() {
+65 −15
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch;
import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState;
import com.android.telephony.Rlog;
@@ -58,6 +59,23 @@ public class ServiceStateStats {
        addServiceState(lastState, now);
    }

    /** Updates service state when IMS voice registration changes. */
    public void onImsVoiceRegistrationChanged() {
        final long now = getTimeMillis();
        TimestampedServiceState lastState =
                mLastState.getAndUpdate(
                        state -> {
                            if (state.mServiceState == null) {
                                return new TimestampedServiceState(null, now);
                            }
                            CellularServiceState newServiceState = copyOf(state.mServiceState);
                            newServiceState.voiceRat =
                                    getVoiceRat(mPhone, getServiceStateForPhone(mPhone));
                            return new TimestampedServiceState(newServiceState, now);
                        });
        addServiceState(lastState, now);
    }

    /** Updates the current service state. */
    public void onServiceStateChanged(ServiceState serviceState) {
        final long now = getTimeMillis();
@@ -132,24 +150,26 @@ public class ServiceStateStats {
    }

    /**
     * Returns the band used from the given phone and RAT, or {@code 0} if it is invalid or cannot
     * be determined.
     * Returns the band used from the given phone, or {@code 0} if it is invalid or cannot be
     * determined.
     */
    static int getBand(Phone phone, @NetworkType int rat) {
    static int getBand(Phone phone) {
        ServiceState serviceState = getServiceStateForPhone(phone);
        return getBand(serviceState, rat);
        return getBand(serviceState);
    }

    /**
     * Returns the band used from the given service state and RAT, or {@code 0} if it is invalid or
     * cannot be determined.
     * Returns the band used from the given service state, or {@code 0} if it is invalid or cannot
     * be determined.
     */
    static int getBand(@Nullable ServiceState serviceState, @NetworkType int rat) {
    static int getBand(@Nullable ServiceState serviceState) {
        if (serviceState == null) {
            Rlog.w(TAG, "getBand: serviceState=null");
            return 0; // Band unknown
        }
        int chNumber = serviceState.getChannelNumber();
        int band;
        @NetworkType int rat = getRat(serviceState);
        switch (rat) {
            case TelephonyManager.NETWORK_TYPE_GSM:
            case TelephonyManager.NETWORK_TYPE_GPRS:
@@ -168,10 +188,16 @@ public class ServiceStateStats {
                band = AccessNetworkUtils.getOperatingBandForEarfcn(chNumber);
                break;
            default:
                Rlog.w(TAG, "getBand: unknown WWAN RAT " + rat);
                band = 0;
                break;
        }
        return band == AccessNetworkUtils.INVALID_BAND ? 0 : band;
        if (band == AccessNetworkUtils.INVALID_BAND) {
            Rlog.w(TAG, "getBand: band invalid for rat=" + rat + " ch=" + chNumber);
            return 0;
        } else {
            return band;
        }
    }

    private static CellularServiceState copyOf(CellularServiceState state) {
@@ -200,15 +226,39 @@ public class ServiceStateStats {
        return state.getVoiceRegState() == ServiceState.STATE_POWER_OFF;
    }

    private static @NetworkType int getVoiceRat(Phone phone, ServiceState state) {
        boolean isWifiCall =
                phone.getImsPhone() != null
                        && phone.getImsPhone().isWifiCallingEnabled()
                        && state.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_IWLAN;
        return isWifiCall ? TelephonyManager.NETWORK_TYPE_IWLAN : state.getVoiceNetworkType();
    /**
     * Returns the current voice RAT from IMS registration if present, otherwise from the service
     * state.
     */
    static @NetworkType int getVoiceRat(Phone phone, @Nullable ServiceState state) {
        if (state == null) {
            return TelephonyManager.NETWORK_TYPE_UNKNOWN;
        }
        ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
        if (imsPhone != null) {
            @NetworkType int imsVoiceRat = imsPhone.getImsStats().getImsVoiceRadioTech();
            if (imsVoiceRat != TelephonyManager.NETWORK_TYPE_UNKNOWN) {
                return imsVoiceRat;
            }
        }
        return state.getVoiceNetworkType();
    }

    /**
     * Returns RAT used by WWAN.
     *
     * <p>Returns PS WWAN RAT, or CS WWAN RAT if PS WWAN RAT is unavailable.
     */
    private static @NetworkType int getRat(ServiceState state) {
        @NetworkType int rat = getDataRat(state);
        if (rat == TelephonyManager.NETWORK_TYPE_UNKNOWN) {
            rat = state.getVoiceNetworkType();
        }
        return rat;
    }

    private static @NetworkType int getDataRat(ServiceState state) {
    /** Returns PS (data) RAT used by WWAN. */
    static @NetworkType int getDataRat(ServiceState state) {
        final NetworkRegistrationInfo wwanRegInfo =
                state.getNetworkRegistrationInfo(
                        NetworkRegistrationInfo.DOMAIN_PS,
+15 −24
Original line number Diff line number Diff line
@@ -82,7 +82,7 @@ import java.util.stream.Collectors;
public class VoiceCallSessionStats {
    private static final String TAG = VoiceCallSessionStats.class.getSimpleName();

    /** Upper bounds of each call setup duration category in milliseconds. */
    // Upper bounds of each call setup duration category in milliseconds.
    private static final int CALL_SETUP_DURATION_UNKNOWN = 0;
    private static final int CALL_SETUP_DURATION_EXTREMELY_FAST = 400;
    private static final int CALL_SETUP_DURATION_ULTRA_FAST = 700;
@@ -100,8 +100,8 @@ public class VoiceCallSessionStats {
    /**
     * Threshold to calculate the main audio codec quality of the call.
     *
     * The audio codec quality was equal to or greater than the main audio codec quality for
     * at least 70% of the call.
     * <p>The audio codec quality was equal to or greater than the main audio codec quality for at
     * least 70% of the call.
     */
    private static final int MAIN_CODEC_QUALITY_THRESHOLD = 70;

@@ -121,9 +121,10 @@ public class VoiceCallSessionStats {
    private final SparseArray<VoiceCallSession> mCallProtos = new SparseArray<>();

    /**
     * Tracks usage of codecs for each call. The outer array is used to map each connection id to
     * the corresponding codec usage. The inner array is used to map timestamp (key) with the
     * codec in use (value).
     * Tracks usage of codecs for each call.
     *
     * <p>The outer array is used to map each connection id to the corresponding codec usage. The
     * inner array is used to map timestamp (key) with the codec in use (value).
     */
    private final SparseArray<LongSparseArray<Integer>> mCodecUsage = new SparseArray<>();

@@ -382,7 +383,7 @@ public class VoiceCallSessionStats {
        } else {
            int bearer = getBearer(conn);
            ServiceState serviceState = getServiceState();
            @NetworkType int rat = getRat(serviceState);
            @NetworkType int rat = ServiceStateStats.getVoiceRat(mPhone, serviceState);

            VoiceCallSession proto = new VoiceCallSession();

@@ -516,7 +517,7 @@ public class VoiceCallSessionStats {
            proto.setupFailed = false;
            // Track RAT when voice call is connected.
            ServiceState serviceState = getServiceState();
            proto.ratAtConnected = getRat(serviceState);
            proto.ratAtConnected = ServiceStateStats.getVoiceRat(mPhone, serviceState);
            // Reset list of codecs with the last codec at the present time. In this way, we
            // track codec quality only after call is connected and not while ringing.
            resetCodecList(conn);
@@ -524,8 +525,9 @@ public class VoiceCallSessionStats {
    }

    private void updateRatTracker(ServiceState state) {
        @NetworkType int rat = getRat(state);
        int band = ServiceStateStats.getBand(state, rat);
        @NetworkType int rat = ServiceStateStats.getVoiceRat(mPhone, state);
        int band =
                (rat == TelephonyManager.NETWORK_TYPE_IWLAN) ? 0 : ServiceStateStats.getBand(state);

        mRatUsage.add(mPhone.getCarrierId(), rat, getTimeMillis(), getConnectionIds());
        for (int i = 0; i < mCallProtos.size(); i++) {
@@ -573,17 +575,6 @@ public class VoiceCallSessionStats {
        }
    }

    private @NetworkType int getRat(@Nullable ServiceState state) {
        if (state == null) {
            return TelephonyManager.NETWORK_TYPE_UNKNOWN;
        }
        boolean isWifiCall =
                mPhone.getImsPhone() != null
                        && mPhone.getImsPhone().isWifiCallingEnabled()
                        && state.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_IWLAN;
        return isWifiCall ? TelephonyManager.NETWORK_TYPE_IWLAN : state.getVoiceNetworkType();
    }

    /** Returns the signal strength. */
    private int getSignalStrength(@NetworkType int rat) {
        if (rat == TelephonyManager.NETWORK_TYPE_IWLAN) {
@@ -603,8 +594,8 @@ public class VoiceCallSessionStats {
            int level = wifiManager.calculateSignalLevel(wifiInfo.getRssi());
            int max = wifiManager.getMaxSignalLevel();
            // Scale result into 0 to 4 range.
            result = VOICE_CALL_SESSION__SIGNAL_STRENGTH_AT_END__SIGNAL_STRENGTH_GREAT
                    * level / max;
            result =
                    VOICE_CALL_SESSION__SIGNAL_STRENGTH_AT_END__SIGNAL_STRENGTH_GREAT * level / max;
            logd("WiFi level: " + result + " (" + level + "/" + max + ")");
        }
        return result;
Loading