diff options
author | 2024-04-03 21:23:20 +0000 | |
---|---|---|
committer | 2024-05-14 23:02:08 +0000 | |
commit | ab4b18ce6a662717d742c4c0264e90c94f1a3415 (patch) | |
tree | 430685fca7b3c580c47f940a46a069b7bb43c52b | |
parent | 88c9f84c3b3e992885f66fa4e63a8e45288e3fe8 (diff) |
Framework side implementation of carrier roaming satellite metrics.
Bug: 330256940
Test: atest MetricsCollectorTest, atest PersistantAtomsStorageTest,
atest SatelliteStatsTest
Manual Test: b/339865721#comment2
Change-Id: Iedb452e02a7d4218f7bab8437524caf8f00f38ab
14 files changed, 2766 insertions, 7 deletions
diff --git a/proto/src/persist_atoms.proto b/proto/src/persist_atoms.proto index fe181ae72d..6a3dcbd8a6 100644 --- a/proto/src/persist_atoms.proto +++ b/proto/src/persist_atoms.proto @@ -23,7 +23,7 @@ option java_outer_classname = "PersistAtomsProto"; // Holds atoms to store on persist storage in case of power cycle or process crash. // NOTE: using int64 rather than google.protobuf.Timestamp for timestamps simplifies implementation. -// Next id: 72 +// Next id: 80 message PersistAtoms { /* Aggregated RAT usage during the call. */ repeated VoiceCallRatUsage voice_call_rat_usage = 1; @@ -237,6 +237,30 @@ message PersistAtoms { /* Timestamp of last data_network_validation pull. */ optional int64 data_network_validation_pull_timestamp_millis = 71; + + /* Snapshot of carrier roaming satellite session. */ + repeated CarrierRoamingSatelliteSession carrier_roaming_satellite_session = 72; + + /* Timestamp of last carrier_roaming_satellite_session pull. */ + optional int64 carrier_roaming_satellite_session_pull_timestamp_millis = 73; + + /* Snapshot of carrier roaming satellite controller stats. */ + repeated CarrierRoamingSatelliteControllerStats carrier_roaming_satellite_controller_stats = 74; + + /* Timestamp of last carrier_roaming_satellite_controller_stats pull. */ + optional int64 carrier_roaming_satellite_controller_stats_pull_timestamp_millis = 75; + + /* Snapshot of satellite entitlement. */ + repeated SatelliteEntitlement satellite_entitlement = 76; + + /* Timestamp of last satellite_entitlement pull. */ + optional int64 satellite_entitlement_pull_timestamp_millis = 77; + + /* Snapshot of satellite config updater. */ + repeated SatelliteConfigUpdater satellite_config_updater = 78; + + /* Timestamp of last satellite_config_updater pull. */ + optional int64 satellite_config_updater_pull_timestamp_millis = 79; } // The canonical versions of the following enums live in: @@ -739,3 +763,47 @@ message DataNetworkValidation { optional bool handover_attempted = 6; optional int32 network_validation_count = 7; } + +message CarrierRoamingSatelliteSession { + optional int32 carrier_id = 1; + optional bool is_ntn_roaming_in_home_country = 2; + optional int32 total_satellite_mode_time_sec = 3; + optional int32 number_of_satellite_connections = 4; + optional int32 avg_duration_of_satellite_connection_sec = 5; + optional int32 satellite_connection_gap_min_sec = 6; + optional int32 satellite_connection_gap_avg_sec = 7; + optional int32 satellite_connection_gap_max_sec = 8; + optional int32 rsrp_avg = 9; + optional int32 rsrp_median = 10; + optional int32 rssnr_avg = 11; + optional int32 rssnr_median = 12; + optional int32 count_of_incoming_sms = 13; + optional int32 count_of_outgoing_sms = 14; + optional int32 count_of_incoming_mms = 15; + optional int32 count_of_outgoing_mms = 16; +} + +message CarrierRoamingSatelliteControllerStats { + optional int32 config_data_source = 1; + optional int32 count_of_entitlement_status_query_request = 2; + optional int32 count_of_satellite_config_update_request = 3; + optional int32 count_of_satellite_notification_displayed = 4; + optional int32 satellite_session_gap_min_sec = 5; + optional int32 satellite_session_gap_avg_sec = 6; + optional int32 satellite_session_gap_max_sec = 7; +} + +message SatelliteEntitlement { + optional int32 carrier_id = 1; + optional int32 result = 2; + optional int32 entitlement_status = 3; + optional bool is_retry = 4; + optional int32 count = 5; +} + +message SatelliteConfigUpdater { + optional int32 config_version = 1; + optional int32 oem_config_result = 2; + optional int32 carrier_config_result = 3; + optional int32 count = 4; +} diff --git a/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java b/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java index 85d5a353ef..85413f56ee 100644 --- a/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java +++ b/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java @@ -27,6 +27,8 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.satellite.SatelliteConfig; import com.android.internal.telephony.satellite.SatelliteConfigParser; +import com.android.internal.telephony.satellite.SatelliteConstants; +import com.android.internal.telephony.satellite.metrics.ConfigUpdaterMetricsStats; import com.android.internal.telephony.util.TelephonyUtils; import com.android.server.updates.ConfigUpdateInstallReceiver; @@ -57,6 +59,7 @@ public class TelephonyConfigUpdateInstallReceiver extends ConfigUpdateInstallRec private final Object mConfigParserLock = new Object(); @GuardedBy("mConfigParserLock") private ConfigParser mConfigParser; + @NonNull private final ConfigUpdaterMetricsStats mConfigUpdaterMetricsStats; public static TelephonyConfigUpdateInstallReceiver sReceiverAdaptorInstance = @@ -72,6 +75,7 @@ public class TelephonyConfigUpdateInstallReceiver extends ConfigUpdateInstallRec public TelephonyConfigUpdateInstallReceiver() { super(UPDATE_DIR, NEW_CONFIG_CONTENT_PATH, UPDATE_METADATA_PATH, VERSION); + mConfigUpdaterMetricsStats = ConfigUpdaterMetricsStats.getOrCreateInstance(); } /** @@ -97,6 +101,8 @@ public class TelephonyConfigUpdateInstallReceiver extends ConfigUpdateInstallRec SatelliteConfig satelliteConfig = (SatelliteConfig) parser.getConfig(); if (satelliteConfig == null) { Log.e(TAG, "satelliteConfig is null"); + mConfigUpdaterMetricsStats.reportOemAndCarrierConfigError( + SatelliteConstants.CONFIG_UPDATE_RESULT_NO_SATELLITE_DATA); return false; } @@ -109,12 +115,16 @@ public class TelephonyConfigUpdateInstallReceiver extends ConfigUpdateInstallRec for (String plmn : plmns) { if (!TelephonyUtils.isValidPlmn(plmn)) { Log.e(TAG, "found invalid plmn : " + plmn); + mConfigUpdaterMetricsStats.reportCarrierConfigError( + SatelliteConstants.CONFIG_UPDATE_RESULT_CARRIER_DATA_INVALID_PLMN); return false; } Set<Integer> serviceSet = plmnsServices.get(plmn); for (int service : serviceSet) { if (!TelephonyUtils.isValidService(service)) { Log.e(TAG, "found invalid service : " + service); + mConfigUpdaterMetricsStats.reportCarrierConfigError(SatelliteConstants + .CONFIG_UPDATE_RESULT_CARRIER_DATA_INVALID_SUPPORTED_SERVICES); return false; } } @@ -149,8 +159,11 @@ public class TelephonyConfigUpdateInstallReceiver extends ConfigUpdateInstallRec int previousVersion = getInstance().mConfigParser.mVersion; Log.d(TAG, "previous version is " + previousVersion + " | updated version is " + updatedVersion); + mConfigUpdaterMetricsStats.setConfigVersion(updatedVersion); if (updatedVersion <= previousVersion) { Log.e(TAG, "updatedVersion is smaller than previousVersion"); + mConfigUpdaterMetricsStats.reportOemAndCarrierConfigError( + SatelliteConstants.CONFIG_UPDATE_RESULT_INVALID_VERSION); return; } } @@ -167,6 +180,8 @@ public class TelephonyConfigUpdateInstallReceiver extends ConfigUpdateInstallRec if (!copySourceFileToTargetFile(NEW_CONFIG_CONTENT_PATH, VALID_CONFIG_CONTENT_PATH)) { Log.e(TAG, "fail to copy to the valid satellite carrier config data"); + mConfigUpdaterMetricsStats.reportOemAndCarrierConfigError( + SatelliteConstants.CONFIG_UPDATE_RESULT_IO_ERROR); } } @@ -231,6 +246,8 @@ public class TelephonyConfigUpdateInstallReceiver extends ConfigUpdateInstallRec public ConfigParser getNewConfigParser(String domain, @Nullable byte[] data) { if (data == null) { Log.d(TAG, "content data is null"); + mConfigUpdaterMetricsStats.reportOemAndCarrierConfigError( + SatelliteConstants.CONFIG_UPDATE_RESULT_NO_DATA); return null; } switch (domain) { @@ -238,6 +255,8 @@ public class TelephonyConfigUpdateInstallReceiver extends ConfigUpdateInstallRec return new SatelliteConfigParser(data); default: Log.e(TAG, "DOMAIN should be specified"); + mConfigUpdaterMetricsStats.reportOemAndCarrierConfigError( + SatelliteConstants.CONFIG_UPDATE_RESULT_INVALID_DOMAIN); return null; } } diff --git a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java index 10783992d3..f07cf60ca9 100644 --- a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java +++ b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java @@ -17,6 +17,8 @@ package com.android.internal.telephony.metrics; import static com.android.internal.telephony.TelephonyStatsLog.CARRIER_ID_TABLE_VERSION; +import static com.android.internal.telephony.TelephonyStatsLog.CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS; +import static com.android.internal.telephony.TelephonyStatsLog.CARRIER_ROAMING_SATELLITE_SESSION; import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_DATA_SERVICE_SWITCH; import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_SERVICE_STATE; import static com.android.internal.telephony.TelephonyStatsLog.DATA_CALL_SESSION; @@ -37,7 +39,9 @@ import static com.android.internal.telephony.TelephonyStatsLog.PER_SIM_STATUS; import static com.android.internal.telephony.TelephonyStatsLog.PRESENCE_NOTIFY_EVENT; import static com.android.internal.telephony.TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS; import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS; +import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_CONFIG_UPDATER; import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_CONTROLLER; +import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_ENTITLEMENT; import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_INCOMING_DATAGRAM; import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_OUTGOING_DATAGRAM; import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_PROVISION; @@ -70,6 +74,8 @@ import com.android.internal.telephony.TelephonyStatsLog; import com.android.internal.telephony.emergency.EmergencyNumberTracker; import com.android.internal.telephony.flags.FeatureFlags; import com.android.internal.telephony.imsphone.ImsPhone; +import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteControllerStats; +import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteSession; import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch; import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState; import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession; @@ -89,7 +95,9 @@ import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms; import com.android.internal.telephony.nano.PersistAtomsProto.PresenceNotifyEvent; import com.android.internal.telephony.nano.PersistAtomsProto.RcsAcsProvisioningStats; import com.android.internal.telephony.nano.PersistAtomsProto.RcsClientProvisioningStats; +import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteConfigUpdater; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteController; +import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteEntitlement; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteIncomingDatagram; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteOutgoingDatagram; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteProvision; @@ -178,14 +186,15 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { public MetricsCollector(Context context, @NonNull FeatureFlags featureFlags) { this(context, new PersistAtomsStorage(context), - new DeviceStateHelper(context), new VonrHelper(featureFlags), featureFlags); + new DeviceStateHelper(context), new VonrHelper(featureFlags), + new DefaultNetworkMonitor(context, featureFlags), featureFlags); } /** Allows dependency injection. Used during unit tests. */ @VisibleForTesting - public MetricsCollector( - Context context, PersistAtomsStorage storage, DeviceStateHelper deviceStateHelper, - VonrHelper vonrHelper, @NonNull FeatureFlags featureFlags) { + public MetricsCollector(Context context, PersistAtomsStorage storage, + DeviceStateHelper deviceStateHelper, VonrHelper vonrHelper, + DefaultNetworkMonitor defaultNetworkMonitor, @NonNull FeatureFlags featureFlags) { mStorage = storage; mDeviceStateHelper = deviceStateHelper; mStatsManager = (StatsManager) context.getSystemService(Context.STATS_MANAGER); @@ -229,6 +238,10 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { registerAtom(SATELLITE_PROVISION); registerAtom(SATELLITE_SOS_MESSAGE_RECOMMENDER); registerAtom(DATA_NETWORK_VALIDATION); + registerAtom(CARRIER_ROAMING_SATELLITE_SESSION); + registerAtom(CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS); + registerAtom(SATELLITE_ENTITLEMENT); + registerAtom(SATELLITE_CONFIG_UPDATER); Rlog.d(TAG, "registered"); } else { Rlog.e(TAG, "could not get StatsManager, atoms not registered"); @@ -325,6 +338,14 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { return pullSatelliteSosMessageRecommender(data); case DATA_NETWORK_VALIDATION: return pullDataNetworkValidation(data); + case CARRIER_ROAMING_SATELLITE_SESSION: + return pullCarrierRoamingSatelliteSession(data); + case CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS: + return pullCarrierRoamingSatelliteControllerStats(data); + case SATELLITE_ENTITLEMENT: + return pullSatelliteEntitlement(data); + case SATELLITE_CONFIG_UPDATER: + return pullSatelliteConfigUpdater(data); default: Rlog.e(TAG, String.format("unexpected atom ID %d", atomTag)); return StatsManager.PULL_SKIP; @@ -958,6 +979,59 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { } } + private int pullCarrierRoamingSatelliteSession(List<StatsEvent> data) { + CarrierRoamingSatelliteSession[] carrierRoamingSatelliteSessionAtoms = + mStorage.getCarrierRoamingSatelliteSessionStats(MIN_COOLDOWN_MILLIS); + if (carrierRoamingSatelliteSessionAtoms != null) { + Arrays.stream(carrierRoamingSatelliteSessionAtoms) + .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom))); + return StatsManager.PULL_SUCCESS; + } else { + Rlog.w(TAG, "CARRIER_ROAMING_SATELLITE_SESSION pull too frequent, skipping"); + return StatsManager.PULL_SKIP; + } + } + + private int pullCarrierRoamingSatelliteControllerStats(List<StatsEvent> data) { + CarrierRoamingSatelliteControllerStats[] carrierRoamingSatelliteControllerStatsAtoms = + mStorage.getCarrierRoamingSatelliteControllerStats(MIN_COOLDOWN_MILLIS); + if (carrierRoamingSatelliteControllerStatsAtoms != null) { + Arrays.stream(carrierRoamingSatelliteControllerStatsAtoms) + .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom))); + return StatsManager.PULL_SUCCESS; + } else { + Rlog.w(TAG, "CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS " + + "pull too frequent, skipping"); + return StatsManager.PULL_SKIP; + } + } + + private int pullSatelliteEntitlement(List<StatsEvent> data) { + SatelliteEntitlement[] satelliteEntitlementAtoms = + mStorage.getSatelliteEntitlementStats(MIN_COOLDOWN_MILLIS); + if (satelliteEntitlementAtoms != null) { + Arrays.stream(satelliteEntitlementAtoms) + .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom))); + return StatsManager.PULL_SUCCESS; + } else { + Rlog.w(TAG, "SATELLITE_ENTITLEMENT pull too frequent, skipping"); + return StatsManager.PULL_SKIP; + } + } + + private int pullSatelliteConfigUpdater(List<StatsEvent> data) { + SatelliteConfigUpdater[] satelliteConfigUpdaterAtoms = + mStorage.getSatelliteConfigUpdaterStats(MIN_COOLDOWN_MILLIS); + if (satelliteConfigUpdaterAtoms != null) { + Arrays.stream(satelliteConfigUpdaterAtoms) + .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom))); + return StatsManager.PULL_SUCCESS; + } else { + Rlog.w(TAG, "SATELLITE_CONFIG_UPDATER pull too frequent, skipping"); + return StatsManager.PULL_SKIP; + } + } + /** Registers a pulled atom ID {@code atomId}. */ private void registerAtom(int atomId) { mStatsManager.setPullAtomCallback(atomId, /* metadata= */ null, @@ -1448,6 +1522,57 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { stats.networkValidationCount); } + private static StatsEvent buildStatsEvent(CarrierRoamingSatelliteSession stats) { + return TelephonyStatsLog.buildStatsEvent( + CARRIER_ROAMING_SATELLITE_SESSION, + stats.carrierId, + stats.isNtnRoamingInHomeCountry, + stats.totalSatelliteModeTimeSec, + stats.numberOfSatelliteConnections, + stats.avgDurationOfSatelliteConnectionSec, + stats.satelliteConnectionGapMinSec, + stats.satelliteConnectionGapAvgSec, + stats.satelliteConnectionGapMaxSec, + stats.rsrpAvg, + stats.rsrpMedian, + stats.rssnrAvg, + stats.rssnrMedian, + stats.countOfIncomingSms, + stats.countOfOutgoingSms, + stats.countOfIncomingMms, + stats.countOfOutgoingMms); + } + + private static StatsEvent buildStatsEvent(CarrierRoamingSatelliteControllerStats stats) { + return TelephonyStatsLog.buildStatsEvent( + CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS, + stats.configDataSource, + stats.countOfEntitlementStatusQueryRequest, + stats.countOfSatelliteConfigUpdateRequest, + stats.countOfSatelliteNotificationDisplayed, + stats.satelliteSessionGapMinSec, + stats.satelliteSessionGapAvgSec, + stats.satelliteSessionGapMaxSec); + } + + private static StatsEvent buildStatsEvent(SatelliteEntitlement stats) { + return TelephonyStatsLog.buildStatsEvent( + SATELLITE_ENTITLEMENT, + stats.carrierId, + stats.result, + stats.entitlementStatus, + stats.isRetry, + stats.count); + } + + private static StatsEvent buildStatsEvent(SatelliteConfigUpdater stats) { + return TelephonyStatsLog.buildStatsEvent(SATELLITE_CONFIG_UPDATER, + stats.configVersion, + stats.oemConfigResult, + stats.carrierConfigResult, + stats.count); + } + /** Returns all phones in {@link PhoneFactory}, or an empty array if phones not made yet. */ static Phone[] getPhonesIfAny() { try { diff --git a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java index f55d968dd9..a3e70c9c38 100644 --- a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java +++ b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java @@ -30,6 +30,8 @@ import android.util.SparseIntArray; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.nano.PersistAtomsProto.CarrierIdMismatch; +import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteControllerStats; +import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteSession; import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch; import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState; import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession; @@ -49,7 +51,9 @@ import com.android.internal.telephony.nano.PersistAtomsProto.PersistAtoms; import com.android.internal.telephony.nano.PersistAtomsProto.PresenceNotifyEvent; import com.android.internal.telephony.nano.PersistAtomsProto.RcsAcsProvisioningStats; import com.android.internal.telephony.nano.PersistAtomsProto.RcsClientProvisioningStats; +import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteConfigUpdater; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteController; +import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteEntitlement; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteIncomingDatagram; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteOutgoingDatagram; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteProvision; @@ -173,6 +177,7 @@ public class PersistAtomsStorage { /** Maximum number of Satellite relevant stats to store between pulls. */ private final int mMaxNumSatelliteStats; private final int mMaxNumSatelliteControllerStats = 1; + private final int mMaxNumCarrierRoamingSatelliteSessionStats = 1; /** Maximum number of data network validation to store during pulls. */ private final int mMaxNumDataNetworkValidation; @@ -832,6 +837,63 @@ public class PersistAtomsStorage { saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS); } + /** Adds a new {@link CarrierRoamingSatelliteSession} to the storage. */ + public synchronized void addCarrierRoamingSatelliteSessionStats( + CarrierRoamingSatelliteSession stats) { + mAtoms.carrierRoamingSatelliteSession = insertAtRandomPlace( + mAtoms.carrierRoamingSatelliteSession, stats, + mMaxNumCarrierRoamingSatelliteSessionStats); + saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS); + } + + /** Adds a new {@link CarrierRoamingSatelliteControllerStats} to the storage. */ + public synchronized void addCarrierRoamingSatelliteControllerStats( + CarrierRoamingSatelliteControllerStats stats) { + // CarrierRoamingSatelliteController is a single data point + CarrierRoamingSatelliteControllerStats[] atomArray = + mAtoms.carrierRoamingSatelliteControllerStats; + if (atomArray == null || atomArray.length == 0) { + atomArray = new CarrierRoamingSatelliteControllerStats[] {new + CarrierRoamingSatelliteControllerStats()}; + } + + CarrierRoamingSatelliteControllerStats atom = atomArray[0]; + atom.configDataSource = stats.configDataSource; + atom.countOfEntitlementStatusQueryRequest += stats.countOfEntitlementStatusQueryRequest; + atom.countOfSatelliteConfigUpdateRequest += stats.countOfSatelliteConfigUpdateRequest; + atom.countOfSatelliteNotificationDisplayed += stats.countOfSatelliteNotificationDisplayed; + atom.satelliteSessionGapMinSec = stats.satelliteSessionGapMinSec; + atom.satelliteSessionGapAvgSec = stats.satelliteSessionGapAvgSec; + atom.satelliteSessionGapMaxSec = stats.satelliteSessionGapMaxSec; + + mAtoms.carrierRoamingSatelliteControllerStats = atomArray; + saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS); + } + + /** Adds a new {@link SatelliteEntitlement} to the storage. */ + public synchronized void addSatelliteEntitlementStats(SatelliteEntitlement stats) { + SatelliteEntitlement existingStats = find(stats); + if (existingStats != null) { + existingStats.count += 1; + } else { + mAtoms.satelliteEntitlement = insertAtRandomPlace(mAtoms.satelliteEntitlement, + stats, mMaxNumSatelliteStats); + } + saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS); + } + + /** Adds a new {@link SatelliteConfigUpdater} to the storage. */ + public synchronized void addSatelliteConfigUpdaterStats(SatelliteConfigUpdater stats) { + SatelliteConfigUpdater existingStats = find(stats); + if (existingStats != null) { + existingStats.count += 1; + } else { + mAtoms.satelliteConfigUpdater = insertAtRandomPlace(mAtoms.satelliteConfigUpdater, + stats, mMaxNumSatelliteStats); + } + saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS); + } + /** * Returns and clears the voice call sessions if last pulled longer than {@code * minIntervalMillis} ago, otherwise returns {@code null}. @@ -1508,6 +1570,84 @@ public class PersistAtomsStorage { } } + /** + * Returns and clears the {@link CarrierRoamingSatelliteSession} stats if last pulled + * longer than {@code minIntervalMillis} ago, otherwise returns {@code null}. + */ + @Nullable + public synchronized CarrierRoamingSatelliteSession[] getCarrierRoamingSatelliteSessionStats( + long minIntervalMillis) { + if (getWallTimeMillis() - mAtoms.carrierRoamingSatelliteSessionPullTimestampMillis + > minIntervalMillis) { + mAtoms.carrierRoamingSatelliteSessionPullTimestampMillis = getWallTimeMillis(); + CarrierRoamingSatelliteSession[] statsArray = mAtoms.carrierRoamingSatelliteSession; + mAtoms.carrierRoamingSatelliteSession = new CarrierRoamingSatelliteSession[0]; + saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS); + return statsArray; + } else { + return null; + } + } + + /** + * Returns and clears the {@link CarrierRoamingSatelliteControllerStats} stats if last pulled + * longer than {@code minIntervalMillis} ago, otherwise returns {@code null}. + */ + @Nullable + public synchronized CarrierRoamingSatelliteControllerStats[] + getCarrierRoamingSatelliteControllerStats(long minIntervalMillis) { + if (getWallTimeMillis() - mAtoms.carrierRoamingSatelliteControllerStatsPullTimestampMillis + > minIntervalMillis) { + mAtoms.carrierRoamingSatelliteControllerStatsPullTimestampMillis = getWallTimeMillis(); + CarrierRoamingSatelliteControllerStats[] statsArray = + mAtoms.carrierRoamingSatelliteControllerStats; + mAtoms.carrierRoamingSatelliteControllerStats = + new CarrierRoamingSatelliteControllerStats[0]; + saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS); + return statsArray; + } else { + return null; + } + } + + /** + * Returns and clears the {@link SatelliteEntitlement} stats if last pulled longer than {@code + * minIntervalMillis} ago, otherwise returns {@code null}. + */ + @Nullable + public synchronized SatelliteEntitlement[] getSatelliteEntitlementStats( + long minIntervalMillis) { + if (getWallTimeMillis() - mAtoms.satelliteEntitlementPullTimestampMillis + > minIntervalMillis) { + mAtoms.satelliteEntitlementPullTimestampMillis = getWallTimeMillis(); + SatelliteEntitlement[] statsArray = mAtoms.satelliteEntitlement; + mAtoms.satelliteEntitlement = new SatelliteEntitlement[0]; + saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS); + return statsArray; + } else { + return null; + } + } + + /** + * Returns and clears the {@link SatelliteConfigUpdater} stats if last pulled longer than {@code + * minIntervalMillis} ago, otherwise returns {@code null}. + */ + @Nullable + public synchronized SatelliteConfigUpdater[] getSatelliteConfigUpdaterStats( + long minIntervalMillis) { + if (getWallTimeMillis() - mAtoms.satelliteConfigUpdaterPullTimestampMillis + > minIntervalMillis) { + mAtoms.satelliteConfigUpdaterPullTimestampMillis = getWallTimeMillis(); + SatelliteConfigUpdater[] statsArray = mAtoms.satelliteConfigUpdater; + mAtoms.satelliteConfigUpdater = new SatelliteConfigUpdater[0]; + saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS); + return statsArray; + } else { + return null; + } + } + /** Saves {@link PersistAtoms} to a file in private storage immediately. */ public synchronized void flushAtoms() { saveAtomsToFile(0); @@ -1664,6 +1804,16 @@ public class PersistAtomsStorage { DataNetworkValidation.class, mMaxNumDataNetworkValidation ); + atoms.carrierRoamingSatelliteSession = sanitizeAtoms( + atoms.carrierRoamingSatelliteSession, CarrierRoamingSatelliteSession.class, + mMaxNumSatelliteStats); + atoms.carrierRoamingSatelliteControllerStats = sanitizeAtoms( + atoms.carrierRoamingSatelliteControllerStats, + CarrierRoamingSatelliteControllerStats.class, mMaxNumSatelliteControllerStats); + atoms.satelliteEntitlement = sanitizeAtoms(atoms.satelliteEntitlement, + SatelliteEntitlement.class, mMaxNumSatelliteStats); + atoms.satelliteConfigUpdater = sanitizeAtoms(atoms.satelliteConfigUpdater, + SatelliteConfigUpdater.class, mMaxNumSatelliteStats); // out of caution, sanitize also the timestamps atoms.voiceCallRatUsagePullTimestampMillis = @@ -1728,6 +1878,14 @@ public class PersistAtomsStorage { sanitizeTimestamp(atoms.satelliteSosMessageRecommenderPullTimestampMillis); atoms.dataNetworkValidationPullTimestampMillis = sanitizeTimestamp(atoms.dataNetworkValidationPullTimestampMillis); + atoms.carrierRoamingSatelliteSessionPullTimestampMillis = sanitizeTimestamp( + atoms.carrierRoamingSatelliteSessionPullTimestampMillis); + atoms.carrierRoamingSatelliteControllerStatsPullTimestampMillis = sanitizeTimestamp( + atoms.carrierRoamingSatelliteControllerStatsPullTimestampMillis); + atoms.satelliteEntitlementPullTimestampMillis = + sanitizeTimestamp(atoms.satelliteEntitlementPullTimestampMillis); + atoms.satelliteConfigUpdaterPullTimestampMillis = + sanitizeTimestamp(atoms.satelliteConfigUpdaterPullTimestampMillis); return atoms; } catch (NoSuchFileException e) { Rlog.d(TAG, "PersistAtoms file not found"); @@ -2179,6 +2337,35 @@ public class PersistAtomsStorage { return null; } + /** + * Returns SatelliteEntitlement atom that has same values or {@code null} if it does not exist. + */ + private @Nullable SatelliteEntitlement find(SatelliteEntitlement key) { + for (SatelliteEntitlement stats : mAtoms.satelliteEntitlement) { + if (stats.carrierId == key.carrierId + && stats.result == key.result + && stats.entitlementStatus == key.entitlementStatus + && stats.isRetry == key.isRetry) { + return stats; + } + } + return null; + } + + /** + * Returns SatelliteConfigUpdater atom that has same values + * or {@code null} if it does not exist. + */ + private @Nullable SatelliteConfigUpdater find(SatelliteConfigUpdater key) { + for (SatelliteConfigUpdater stats : mAtoms.satelliteConfigUpdater) { + if (stats.configVersion == key.configVersion + && stats.oemConfigResult == key.oemConfigResult + && stats.carrierConfigResult == key.carrierConfigResult) { + return stats; + } + } + return null; + } /** * Inserts a new element in a random position in an array with a maximum size. @@ -2437,6 +2624,10 @@ public class PersistAtomsStorage { atoms.satelliteProvisionPullTimestampMillis = currentTime; atoms.satelliteSosMessageRecommenderPullTimestampMillis = currentTime; atoms.dataNetworkValidationPullTimestampMillis = currentTime; + atoms.carrierRoamingSatelliteSessionPullTimestampMillis = currentTime; + atoms.carrierRoamingSatelliteControllerStatsPullTimestampMillis = currentTime; + atoms.satelliteEntitlementPullTimestampMillis = currentTime; + atoms.satelliteConfigUpdaterPullTimestampMillis = currentTime; Rlog.d(TAG, "created new PersistAtoms"); return atoms; diff --git a/src/java/com/android/internal/telephony/metrics/SatelliteStats.java b/src/java/com/android/internal/telephony/metrics/SatelliteStats.java index a9aab58ad8..2bf035eec4 100644 --- a/src/java/com/android/internal/telephony/metrics/SatelliteStats.java +++ b/src/java/com/android/internal/telephony/metrics/SatelliteStats.java @@ -19,14 +19,22 @@ package com.android.internal.telephony.metrics; import android.telephony.satellite.SatelliteManager; import com.android.internal.telephony.PhoneFactory; +import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteControllerStats; +import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteSession; +import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteConfigUpdater; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteController; +import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteEntitlement; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteIncomingDatagram; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteOutgoingDatagram; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteProvision; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteSession; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteSosMessageRecommender; +import com.android.internal.telephony.satellite.SatelliteConstants; import com.android.telephony.Rlog; +import java.util.ArrayList; +import java.util.List; + /** Tracks Satellite metrics for each phone */ public class SatelliteStats { private static final String TAG = SatelliteStats.class.getSimpleName(); @@ -1206,6 +1214,691 @@ public class SatelliteStats { } } + /** + * A data class to contain whole component of {@link CarrierRoamingSatelliteSession} atom. + * Refer to {@link #onCarrierRoamingSatelliteSessionMetrics( + * CarrierRoamingSatelliteSessionParams)}. + */ + public class CarrierRoamingSatelliteSessionParams { + private final int mCarrierId; + private final boolean mIsNtnRoamingInHomeCountry; + private final int mTotalSatelliteModeTimeSec; + private final int mNumberOfSatelliteConnections; + private final int mAvgDurationOfSatelliteConnectionSec; + private final int mSatelliteConnectionGapMinSec; + private final int mSatelliteConnectionGapAvgSec; + private final int mSatelliteConnectionGapMaxSec; + private final int mRsrpAvg; + private final int mRsrpMedian; + private final int mRssnrAvg; + private final int mRssnrMedian; + private final int mCountOfIncomingSms; + private final int mCountOfOutgoingSms; + private final int mCountOfIncomingMms; + private final int mCountOfOutgoingMms; + + private CarrierRoamingSatelliteSessionParams(Builder builder) { + this.mCarrierId = builder.mCarrierId; + this.mIsNtnRoamingInHomeCountry = builder.mIsNtnRoamingInHomeCountry; + this.mTotalSatelliteModeTimeSec = builder.mTotalSatelliteModeTimeSec; + this.mNumberOfSatelliteConnections = builder.mNumberOfSatelliteConnections; + this.mAvgDurationOfSatelliteConnectionSec = + builder.mAvgDurationOfSatelliteConnectionSec; + this.mSatelliteConnectionGapMinSec = builder.mSatelliteConnectionGapMinSec; + this.mSatelliteConnectionGapAvgSec = builder.mSatelliteConnectionGapAvgSec; + this.mSatelliteConnectionGapMaxSec = builder.mSatelliteConnectionGapMaxSec; + this.mRsrpAvg = builder.mRsrpAvg; + this.mRsrpMedian = builder.mRsrpMedian; + this.mRssnrAvg = builder.mRssnrAvg; + this.mRssnrMedian = builder.mRssnrMedian; + this.mCountOfIncomingSms = builder.mCountOfIncomingSms; + this.mCountOfOutgoingSms = builder.mCountOfOutgoingSms; + this.mCountOfIncomingMms = builder.mCountOfIncomingMms; + this.mCountOfOutgoingMms = builder.mCountOfOutgoingMms; + } + + public int getCarrierId() { + return mCarrierId; + } + + public boolean getIsNtnRoamingInHomeCountry() { + return mIsNtnRoamingInHomeCountry; + } + + public int getTotalSatelliteModeTimeSec() { + return mTotalSatelliteModeTimeSec; + } + + public int getNumberOfSatelliteConnections() { + return mNumberOfSatelliteConnections; + } + + public int getAvgDurationOfSatelliteConnectionSec() { + return mAvgDurationOfSatelliteConnectionSec; + } + + public int getSatelliteConnectionGapMinSec() { + return mSatelliteConnectionGapMinSec; + } + + public int getSatelliteConnectionGapAvgSec() { + return mSatelliteConnectionGapAvgSec; + } + + public int getSatelliteConnectionGapMaxSec() { + return mSatelliteConnectionGapMaxSec; + } + + public int getRsrpAvg() { + return mRsrpAvg; + } + + public int getRsrpMedian() { + return mRsrpMedian; + } + + public int getRssnrAvg() { + return mRssnrAvg; + } + + public int getRssnrMedian() { + return mRssnrMedian; + } + + public int getCountOfIncomingSms() { + return mCountOfIncomingSms; + } + + public int getCountOfOutgoingSms() { + return mCountOfOutgoingSms; + } + + public int getCountOfIncomingMms() { + return mCountOfIncomingMms; + } + + public int getCountOfOutgoingMms() { + return mCountOfOutgoingMms; + } + + /** + * A builder class to create {@link CarrierRoamingSatelliteSessionParams} data structure + * class + */ + public static class Builder { + private int mCarrierId = -1; + private boolean mIsNtnRoamingInHomeCountry = false; + private int mTotalSatelliteModeTimeSec = 0; + private int mNumberOfSatelliteConnections = 0; + private int mAvgDurationOfSatelliteConnectionSec = 0; + private int mSatelliteConnectionGapMinSec = 0; + private int mSatelliteConnectionGapAvgSec = 0; + private int mSatelliteConnectionGapMaxSec = 0; + private int mRsrpAvg = 0; + private int mRsrpMedian = 0; + private int mRssnrAvg = 0; + private int mRssnrMedian = 0; + private int mCountOfIncomingSms = 0; + private int mCountOfOutgoingSms = 0; + private int mCountOfIncomingMms = 0; + private int mCountOfOutgoingMms = 0; + + /** + * Sets carrierId value of {@link CarrierRoamingSatelliteSession} atom + * then returns Builder class + */ + public Builder setCarrierId(int carrierId) { + this.mCarrierId = carrierId; + return this; + } + + /** + * Sets isNtnRoamingInHomeCountry value of {@link CarrierRoamingSatelliteSession} atom + * then returns Builder class + */ + public Builder setIsNtnRoamingInHomeCountry(boolean isNtnRoamingInHomeCountry) { + this.mIsNtnRoamingInHomeCountry = isNtnRoamingInHomeCountry; + return this; + } + + /** + * Sets totalSatelliteModeTimeSec value of {@link CarrierRoamingSatelliteSession} atom + * then returns Builder class + */ + public Builder setTotalSatelliteModeTimeSec(int totalSatelliteModeTimeSec) { + this.mTotalSatelliteModeTimeSec = totalSatelliteModeTimeSec; + return this; + } + + + /** + * Sets numberOfSatelliteConnections value of {@link CarrierRoamingSatelliteSession} + * atom then returns Builder class + */ + public Builder setNumberOfSatelliteConnections(int numberOfSatelliteConnections) { + this.mNumberOfSatelliteConnections = numberOfSatelliteConnections; + return this; + } + + /** + * Sets avgDurationOfSatelliteConnectionSec value of + * {@link CarrierRoamingSatelliteSession} atom then returns Builder class + */ + public Builder setAvgDurationOfSatelliteConnectionSec( + int avgDurationOfSatelliteConnectionSec) { + this.mAvgDurationOfSatelliteConnectionSec = avgDurationOfSatelliteConnectionSec; + return this; + } + + /** + * Sets satelliteConnectionGapMinSec value of {@link CarrierRoamingSatelliteSession} + * atom then returns Builder class + */ + public Builder setSatelliteConnectionGapMinSec(int satelliteConnectionGapMinSec) { + this.mSatelliteConnectionGapMinSec = satelliteConnectionGapMinSec; + return this; + } + + /** + * Sets satelliteConnectionGapAvgSec value of {@link CarrierRoamingSatelliteSession} + * atom then returns Builder class + */ + public Builder setSatelliteConnectionGapAvgSec(int satelliteConnectionGapAvgSec) { + this.mSatelliteConnectionGapAvgSec = satelliteConnectionGapAvgSec; + return this; + } + + /** + * Sets satelliteConnectionGapMaxSec value of {@link CarrierRoamingSatelliteSession} + * atom then returns Builder class + */ + public Builder setSatelliteConnectionGapMaxSec(int satelliteConnectionGapMaxSec) { + this.mSatelliteConnectionGapMaxSec = satelliteConnectionGapMaxSec; + return this; + } + + /** + * Sets rsrpAvg value of {@link CarrierRoamingSatelliteSession} + * atom then returns Builder class + */ + public Builder setRsrpAvg(int rsrpAvg) { + this.mRsrpAvg = rsrpAvg; + return this; + } + + /** + * Sets rsrpMedian value of {@link CarrierRoamingSatelliteSession} + * atom then returns Builder class + */ + public Builder setRsrpMedian(int rsrpMedian) { + this.mRsrpMedian = rsrpMedian; + return this; + } + + /** + * Sets rssnrAvg value of {@link CarrierRoamingSatelliteSession} + * atom then returns Builder class + */ + public Builder setRssnrAvg(int rssnrAvg) { + this.mRssnrAvg = rssnrAvg; + return this; + } + + /** + * Sets rssnrMedian value of {@link CarrierRoamingSatelliteSession} + * atom then returns Builder class + */ + public Builder setRssnrMedian(int rssnrMedian) { + this.mRssnrMedian = rssnrMedian; + return this; + } + + + /** + * Sets countOfIncomingSms value of {@link CarrierRoamingSatelliteSession} + * atom then returns Builder class + */ + public Builder setCountOfIncomingSms(int countOfIncomingSms) { + this.mCountOfIncomingSms = countOfIncomingSms; + return this; + } + + /** + * Sets countOfOutgoingSms value of {@link CarrierRoamingSatelliteSession} + * atom then returns Builder class + */ + public Builder setCountOfOutgoingSms(int countOfOutgoingSms) { + this.mCountOfOutgoingSms = countOfOutgoingSms; + return this; + } + + /** + * Sets countOfIncomingMms value of {@link CarrierRoamingSatelliteSession} + * atom then returns Builder class + */ + public Builder setCountOfIncomingMms(int countOfIncomingMms) { + this.mCountOfIncomingMms = countOfIncomingMms; + return this; + } + + /** + * Sets countOfOutgoingMms value of {@link CarrierRoamingSatelliteSession} + * atom then returns Builder class + */ + public Builder setCountOfOutgoingMms(int countOfOutgoingMms) { + this.mCountOfOutgoingMms = countOfOutgoingMms; + return this; + } + + /** + * Returns CarrierRoamingSatelliteSessionParams, which contains whole component of + * {@link CarrierRoamingSatelliteSession} atom + */ + public CarrierRoamingSatelliteSessionParams build() { + return new SatelliteStats() + .new CarrierRoamingSatelliteSessionParams(Builder.this); + } + } + + @Override + public String toString() { + return "CarrierRoamingSatelliteSessionParams(" + + "carrierId=" + mCarrierId + + ", isNtnRoamingInHomeCountry=" + mIsNtnRoamingInHomeCountry + + ", totalSatelliteModeTimeSec=" + mTotalSatelliteModeTimeSec + + ", numberOfSatelliteConnections=" + mNumberOfSatelliteConnections + + ", avgDurationOfSatelliteConnectionSec=" + + mAvgDurationOfSatelliteConnectionSec + + ", satelliteConnectionGapMinSec=" + mSatelliteConnectionGapMinSec + + ", satelliteConnectionGapAvgSec=" + mSatelliteConnectionGapAvgSec + + ", satelliteConnectionGapMaxSec=" + mSatelliteConnectionGapMaxSec + + ", rsrpAvg=" + mRsrpAvg + + ", rsrpMedian=" + mRsrpMedian + + ", rssnrAvg=" + mRssnrAvg + + ", rssnrMedian=" + mRsrpMedian + + ", countOfIncomingSms=" + mCountOfIncomingSms + + ", countOfOutgoingSms=" + mCountOfOutgoingSms + + ", countOfIncomingMms=" + mCountOfIncomingMms + + ", countOfOutgoingMms=" + mCountOfOutgoingMms + + ")"; + } + } + + /** + * A data class to contain whole component of {@link CarrierRoamingSatelliteControllerStats} + * atom. Refer to {@link #onCarrierRoamingSatelliteControllerStatsMetrics( + * CarrierRoamingSatelliteControllerStatsParams)}. + */ + public class CarrierRoamingSatelliteControllerStatsParams { + private final int mConfigDataSource; + private final int mCountOfEntitlementStatusQueryRequest; + private final int mCountOfSatelliteConfigUpdateRequest; + private final int mCountOfSatelliteNotificationDisplayed; + private final int mSatelliteSessionGapMinSec; + private final int mSatelliteSessionGapAvgSec; + private final int mSatelliteSessionGapMaxSec; + + private CarrierRoamingSatelliteControllerStatsParams(Builder builder) { + this.mConfigDataSource = builder.mConfigDataSource; + this.mCountOfEntitlementStatusQueryRequest = + builder.mCountOfEntitlementStatusQueryRequest; + this.mCountOfSatelliteConfigUpdateRequest = + builder.mCountOfSatelliteConfigUpdateRequest; + this.mCountOfSatelliteNotificationDisplayed = + builder.mCountOfSatelliteNotificationDisplayed; + this.mSatelliteSessionGapMinSec = builder.mSatelliteSessionGapMinSec; + this.mSatelliteSessionGapAvgSec = builder.mSatelliteSessionGapAvgSec; + this.mSatelliteSessionGapMaxSec = builder.mSatelliteSessionGapMaxSec; + } + + public int getConfigDataSource() { + return mConfigDataSource; + } + + + public int getCountOfEntitlementStatusQueryRequest() { + return mCountOfEntitlementStatusQueryRequest; + } + + public int getCountOfSatelliteConfigUpdateRequest() { + return mCountOfSatelliteConfigUpdateRequest; + } + + public int getCountOfSatelliteNotificationDisplayed() { + return mCountOfSatelliteNotificationDisplayed; + } + + public int getSatelliteSessionGapMinSec() { + return mSatelliteSessionGapMinSec; + } + + public int getSatelliteSessionGapAvgSec() { + return mSatelliteSessionGapAvgSec; + } + + public int getSatelliteSessionGapMaxSec() { + return mSatelliteSessionGapMaxSec; + } + + /** + * A builder class to create {@link CarrierRoamingSatelliteControllerStatsParams} + * data structure class + */ + public static class Builder { + private int mConfigDataSource = SatelliteConstants.CONFIG_DATA_SOURCE_UNKNOWN; + private int mCountOfEntitlementStatusQueryRequest = 0; + private int mCountOfSatelliteConfigUpdateRequest = 0; + private int mCountOfSatelliteNotificationDisplayed = 0; + private int mSatelliteSessionGapMinSec = 0; + private int mSatelliteSessionGapAvgSec = 0; + private int mSatelliteSessionGapMaxSec = 0; + + /** + * Sets configDataSource value of {@link CarrierRoamingSatelliteControllerStats} atom + * then returns Builder class + */ + public Builder setConfigDataSource(int configDataSource) { + this.mConfigDataSource = configDataSource; + return this; + } + + /** + * Sets countOfEntitlementStatusQueryRequest value of + * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class + */ + public Builder setCountOfEntitlementStatusQueryRequest( + int countOfEntitlementStatusQueryRequest) { + this.mCountOfEntitlementStatusQueryRequest = countOfEntitlementStatusQueryRequest; + return this; + } + + /** + * Sets countOfSatelliteConfigUpdateRequest value of + * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class + */ + public Builder setCountOfSatelliteConfigUpdateRequest( + int countOfSatelliteConfigUpdateRequest) { + this.mCountOfSatelliteConfigUpdateRequest = countOfSatelliteConfigUpdateRequest; + return this; + } + + /** + * Sets countOfSatelliteNotificationDisplayed value of + * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class + */ + public Builder setCountOfSatelliteNotificationDisplayed( + int countOfSatelliteNotificationDisplayed) { + this.mCountOfSatelliteNotificationDisplayed = countOfSatelliteNotificationDisplayed; + return this; + } + + /** + * Sets satelliteSessionGapMinSec value of + * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class + */ + public Builder setSatelliteSessionGapMinSec(int satelliteSessionGapMinSec) { + this.mSatelliteSessionGapMinSec = satelliteSessionGapMinSec; + return this; + } + + /** + * Sets satelliteSessionGapAvgSec value of + * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class + */ + public Builder setSatelliteSessionGapAvgSec(int satelliteSessionGapAvgSec) { + this.mSatelliteSessionGapAvgSec = satelliteSessionGapAvgSec; + return this; + } + + /** + * Sets satelliteSessionGapMaxSec value of + * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class + */ + public Builder setSatelliteSessionGapMaxSec(int satelliteSessionGapMaxSec) { + this.mSatelliteSessionGapMaxSec = satelliteSessionGapMaxSec; + return this; + } + + /** + * Returns CarrierRoamingSatelliteControllerStatsParams, which contains whole component + * of {@link CarrierRoamingSatelliteControllerStats} atom + */ + public CarrierRoamingSatelliteControllerStatsParams build() { + return new SatelliteStats() + .new CarrierRoamingSatelliteControllerStatsParams(Builder.this); + } + } + + @Override + public String toString() { + return "CarrierRoamingSatelliteControllerStatsParams(" + + "configDataSource=" + mConfigDataSource + + ", countOfEntitlementStatusQueryRequest=" + + mCountOfEntitlementStatusQueryRequest + + ", countOfSatelliteConfigUpdateRequest=" + + mCountOfSatelliteConfigUpdateRequest + + ", countOfSatelliteNotificationDisplayed=" + + mCountOfSatelliteNotificationDisplayed + + ", satelliteSessionGapMinSec=" + mSatelliteSessionGapMinSec + + ", satelliteSessionGapAvgSec=" + mSatelliteSessionGapAvgSec + + ", satelliteSessionGapMaxSec=" + mSatelliteSessionGapMaxSec + + ")"; + } + } + + /** + * A data class to contain whole component of {@link SatelliteEntitlement} atom. + * Refer to {@link #onSatelliteEntitlementMetrics(SatelliteEntitlementParams)}. + */ + public class SatelliteEntitlementParams { + private final int mCarrierId; + private final int mResult; + private final int mEntitlementStatus; + private final boolean mIsRetry; + private final int mCount; + + private SatelliteEntitlementParams(Builder builder) { + this.mCarrierId = builder.mCarrierId; + this.mResult = builder.mResult; + this.mEntitlementStatus = builder.mEntitlementStatus; + this.mIsRetry = builder.mIsRetry; + this.mCount = builder.mCount; + } + + public int getCarrierId() { + return mCarrierId; + } + + public int getResult() { + return mResult; + } + + public int getEntitlementStatus() { + return mEntitlementStatus; + } + + public boolean getIsRetry() { + return mIsRetry; + } + + public int getCount() { + return mCount; + } + + /** + * A builder class to create {@link SatelliteEntitlementParams} data structure class + */ + public static class Builder { + private int mCarrierId = -1; + private int mResult = -1; + private int mEntitlementStatus = -1; + private boolean mIsRetry = false; + private int mCount = -1; + + /** + * Sets carrierId value of {@link SatelliteEntitlement} atom + * then returns Builder class + */ + public Builder setCarrierId(int carrierId) { + this.mCarrierId = carrierId; + return this; + } + + /** + * Sets result value of {@link SatelliteEntitlement} atom + * then returns Builder class + */ + public Builder setResult(int result) { + this.mResult = result; + return this; + } + + /** + * Sets entitlementStatus value of {@link SatelliteEntitlement} atom + * then returns Builder class + */ + public Builder setEntitlementStatus(int entitlementStatus) { + this.mEntitlementStatus = entitlementStatus; + return this; + } + + /** + * Sets isRetry value of {@link SatelliteEntitlement} atom + * then returns Builder class + */ + public Builder setIsRetry(boolean isRetry) { + this.mIsRetry = isRetry; + return this; + } + + /** + * Sets count value of {@link SatelliteEntitlement} atom + * then returns Builder class + */ + public Builder setCount(int count) { + this.mCount = count; + return this; + } + + /** + * Returns SatelliteEntitlementParams, which contains whole component of + * {@link SatelliteEntitlement} atom + */ + public SatelliteEntitlementParams build() { + return new SatelliteStats() + .new SatelliteEntitlementParams(Builder.this); + } + } + + @Override + public String toString() { + return "SatelliteEntitlementParams(" + + "carrierId=" + mCarrierId + + ", result=" + mResult + + ", entitlementStatus=" + mEntitlementStatus + + ", isRetry=" + mIsRetry + + ", count=" + mCount + ")"; + } + } + + /** + * A data class to contain whole component of {@link SatelliteConfigUpdater} atom. + * Refer to {@link #onSatelliteConfigUpdaterMetrics(SatelliteConfigUpdaterParams)}. + */ + public class SatelliteConfigUpdaterParams { + private final int mConfigVersion; + private final int mOemConfigResult; + private final int mCarrierConfigResult; + private final int mCount; + + private SatelliteConfigUpdaterParams(Builder builder) { + this.mConfigVersion = builder.mConfigVersion; + this.mOemConfigResult = builder.mOemConfigResult; + this.mCarrierConfigResult = builder.mCarrierConfigResult; + this.mCount = builder.mCount; + } + + public int getConfigVersion() { + return mConfigVersion; + } + + public int getOemConfigResult() { + return mOemConfigResult; + } + + public int getCarrierConfigResult() { + return mCarrierConfigResult; + } + + public int getCount() { + return mCount; + } + + /** + * A builder class to create {@link SatelliteConfigUpdaterParams} data structure class + */ + public static class Builder { + private int mConfigVersion = -1; + private int mOemConfigResult = -1; + private int mCarrierConfigResult = -1; + private int mCount = -1; + + /** + * Sets configVersion value of {@link SatelliteConfigUpdater} atom + * then returns Builder class + */ + public Builder setConfigVersion(int configVersion) { + this.mConfigVersion = configVersion; + return this; + } + + /** + * Sets oemConfigResult value of {@link SatelliteConfigUpdater} atom + * then returns Builder class + */ + public Builder setOemConfigResult(int oemConfigResult) { + this.mOemConfigResult = oemConfigResult; + return this; + } + + /** + * Sets carrierConfigResult value of {@link SatelliteConfigUpdater} atom + * then returns Builder class + */ + public Builder setCarrierConfigResult(int carrierConfigResult) { + this.mCarrierConfigResult = carrierConfigResult; + return this; + } + + /** + * Sets count value of {@link SatelliteConfigUpdater} atom + * then returns Builder class + */ + public Builder setCount(int count) { + this.mCount = count; + return this; + } + + /** + * Returns SatelliteConfigUpdaterParams, which contains whole component of + * {@link SatelliteConfigUpdater} atom + */ + public SatelliteConfigUpdaterParams build() { + return new SatelliteStats() + .new SatelliteConfigUpdaterParams(Builder.this); + } + } + + @Override + public String toString() { + return "SatelliteConfigUpdaterParams(" + + "configVersion=" + mConfigVersion + + ", oemConfigResult=" + mOemConfigResult + + ", carrierConfigResult=" + mCarrierConfigResult + + ", count=" + mCount + ")"; + } + } + /** Create a new atom or update an existing atom for SatelliteController metrics */ public synchronized void onSatelliteControllerMetrics(SatelliteControllerParams param) { SatelliteController proto = new SatelliteController(); @@ -1311,4 +2004,62 @@ public class SatelliteStats { proto.count = 1; mAtomsStorage.addSatelliteSosMessageRecommenderStats(proto); } + + /** Create a new atom for CarrierRoamingSatelliteSession metrics */ + public synchronized void onCarrierRoamingSatelliteSessionMetrics( + CarrierRoamingSatelliteSessionParams param) { + CarrierRoamingSatelliteSession proto = new CarrierRoamingSatelliteSession(); + proto.carrierId = param.getCarrierId(); + proto.isNtnRoamingInHomeCountry = param.getIsNtnRoamingInHomeCountry(); + proto.totalSatelliteModeTimeSec = param.getTotalSatelliteModeTimeSec(); + proto.numberOfSatelliteConnections = param.getNumberOfSatelliteConnections(); + proto.avgDurationOfSatelliteConnectionSec = param.getAvgDurationOfSatelliteConnectionSec(); + proto.satelliteConnectionGapMinSec = param.mSatelliteConnectionGapMinSec; + proto.satelliteConnectionGapAvgSec = param.mSatelliteConnectionGapAvgSec; + proto.satelliteConnectionGapMaxSec = param.mSatelliteConnectionGapMaxSec; + proto.rsrpAvg = param.mRsrpAvg; + proto.rsrpMedian = param.mRsrpMedian; + proto.rssnrAvg = param.mRssnrAvg; + proto.rssnrMedian = param.mRssnrMedian; + proto.countOfIncomingSms = param.mCountOfIncomingSms; + proto.countOfOutgoingSms = param.mCountOfOutgoingSms; + proto.countOfIncomingMms = param.mCountOfIncomingMms; + proto.countOfOutgoingMms = param.mCountOfOutgoingMms; + mAtomsStorage.addCarrierRoamingSatelliteSessionStats(proto); + } + + /** Create a new atom for CarrierRoamingSatelliteSession metrics */ + public synchronized void onCarrierRoamingSatelliteControllerStatsMetrics( + CarrierRoamingSatelliteControllerStatsParams param) { + CarrierRoamingSatelliteControllerStats proto = new CarrierRoamingSatelliteControllerStats(); + proto.configDataSource = param.mConfigDataSource; + proto.countOfEntitlementStatusQueryRequest = param.mCountOfEntitlementStatusQueryRequest; + proto.countOfSatelliteConfigUpdateRequest = param.mCountOfSatelliteConfigUpdateRequest; + proto.countOfSatelliteNotificationDisplayed = param.mCountOfSatelliteNotificationDisplayed; + proto.satelliteSessionGapMinSec = param.mSatelliteSessionGapMinSec; + proto.satelliteSessionGapAvgSec = param.mSatelliteSessionGapAvgSec; + proto.satelliteSessionGapMaxSec = param.mSatelliteSessionGapMaxSec; + mAtomsStorage.addCarrierRoamingSatelliteControllerStats(proto); + } + + /** Create a new atom for SatelliteEntitlement metrics */ + public synchronized void onSatelliteEntitlementMetrics(SatelliteEntitlementParams param) { + SatelliteEntitlement proto = new SatelliteEntitlement(); + proto.carrierId = param.getCarrierId(); + proto.result = param.getResult(); + proto.entitlementStatus = param.getEntitlementStatus(); + proto.isRetry = param.getIsRetry(); + proto.count = param.getCount(); + mAtomsStorage.addSatelliteEntitlementStats(proto); + } + + /** Create a new atom for SatelliteConfigUpdater metrics */ + public synchronized void onSatelliteConfigUpdaterMetrics(SatelliteConfigUpdaterParams param) { + SatelliteConfigUpdater proto = new SatelliteConfigUpdater(); + proto.configVersion = param.getConfigVersion(); + proto.oemConfigResult = param.getOemConfigResult(); + proto.carrierConfigResult = param.getCarrierConfigResult(); + proto.count = param.getCount(); + mAtomsStorage.addSatelliteConfigUpdaterStats(proto); + } } diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java b/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java new file mode 100644 index 0000000000..f88069f868 --- /dev/null +++ b/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2024 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.satellite; + +import android.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +public class SatelliteConstants { + public static final int CONFIG_DATA_SOURCE_UNKNOWN = 0; + public static final int CONFIG_DATA_SOURCE_ENTITLEMENT = 1; + public static final int CONFIG_DATA_SOURCE_CONFIG_UPDATER = 2; + public static final int CONFIG_DATA_SOURCE_CARRIER_CONFIG = 3; + public static final int CONFIG_DATA_SOURCE_DEVICE_CONFIG = 4; + + @IntDef(prefix = {"CONFIG_DATA_SOURCE_"}, value = { + CONFIG_DATA_SOURCE_UNKNOWN, + CONFIG_DATA_SOURCE_ENTITLEMENT, + CONFIG_DATA_SOURCE_CONFIG_UPDATER, + CONFIG_DATA_SOURCE_CARRIER_CONFIG, + CONFIG_DATA_SOURCE_DEVICE_CONFIG + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ConfigDataSource {} + + public static final int SATELLITE_ENTITLEMENT_STATUS_UNKNOWN = 0; + public static final int SATELLITE_ENTITLEMENT_STATUS_DISABLED = 1; + public static final int SATELLITE_ENTITLEMENT_STATUS_ENABLED = 2; + public static final int SATELLITE_ENTITLEMENT_STATUS_INCOMPATIBLE = 3; + public static final int SATELLITE_ENTITLEMENT_STATUS_PROVISIONING = 4; + + @IntDef(prefix = {"SATELLITE_ENTITLEMENT_STATUS_"}, value = { + SATELLITE_ENTITLEMENT_STATUS_UNKNOWN, + SATELLITE_ENTITLEMENT_STATUS_DISABLED, + SATELLITE_ENTITLEMENT_STATUS_ENABLED, + SATELLITE_ENTITLEMENT_STATUS_INCOMPATIBLE, + SATELLITE_ENTITLEMENT_STATUS_PROVISIONING + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SatelliteEntitlementStatus {} + + public static final int CONFIG_UPDATE_RESULT_UNKNOWN = 0; + public static final int CONFIG_UPDATE_RESULT_SUCCESS = 1; + public static final int CONFIG_UPDATE_RESULT_INVALID_DOMAIN = 2; + public static final int CONFIG_UPDATE_RESULT_INVALID_VERSION = 3; + public static final int CONFIG_UPDATE_RESULT_NO_DATA = 4; + public static final int CONFIG_UPDATE_RESULT_NO_SATELLITE_DATA = 5; + public static final int CONFIG_UPDATE_RESULT_PARSE_ERROR = 6; + public static final int CONFIG_UPDATE_RESULT_CARRIER_DATA_INVALID_PLMN = 7; + public static final int CONFIG_UPDATE_RESULT_CARRIER_DATA_INVALID_SUPPORTED_SERVICES = 8; + public static final int CONFIG_UPDATE_RESULT_DEVICE_DATA_INVALID_COUNTRY_CODE = 9; + public static final int CONFIG_UPDATE_RESULT_DEVICE_DATA_INVALID_S2_CELL_FILE = 10; + public static final int CONFIG_UPDATE_RESULT_IO_ERROR = 11; + + @IntDef(prefix = {"CONFIG_UPDATE_RESULT_"}, value = { + CONFIG_UPDATE_RESULT_UNKNOWN, + CONFIG_UPDATE_RESULT_SUCCESS, + CONFIG_UPDATE_RESULT_INVALID_DOMAIN, + CONFIG_UPDATE_RESULT_INVALID_VERSION, + CONFIG_UPDATE_RESULT_NO_DATA, + CONFIG_UPDATE_RESULT_NO_SATELLITE_DATA, + CONFIG_UPDATE_RESULT_PARSE_ERROR, + CONFIG_UPDATE_RESULT_CARRIER_DATA_INVALID_PLMN, + CONFIG_UPDATE_RESULT_CARRIER_DATA_INVALID_SUPPORTED_SERVICES, + CONFIG_UPDATE_RESULT_DEVICE_DATA_INVALID_COUNTRY_CODE, + CONFIG_UPDATE_RESULT_DEVICE_DATA_INVALID_S2_CELL_FILE, + CONFIG_UPDATE_RESULT_IO_ERROR + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ConfigUpdateResult {} +} diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java index 05051fa614..8582eaae1e 100644 --- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java +++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java @@ -117,6 +117,8 @@ import com.android.internal.telephony.configupdate.ConfigParser; import com.android.internal.telephony.configupdate.ConfigProviderAdaptor; import com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver; import com.android.internal.telephony.flags.FeatureFlags; +import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteControllerStats; +import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteSessionStats; import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats; import com.android.internal.telephony.satellite.metrics.ProvisionMetricsStats; import com.android.internal.telephony.satellite.metrics.SessionMetricsStats; @@ -220,6 +222,7 @@ public class SatelliteController extends Handler { @NonNull private final ControllerMetricsStats mControllerMetricsStats; @NonNull private final ProvisionMetricsStats mProvisionMetricsStats; @NonNull private SessionMetricsStats mSessionMetricsStats; + @NonNull private CarrierRoamingSatelliteControllerStats mCarrierRoamingSatelliteControllerStats; @NonNull private final SubscriptionManagerService mSubscriptionManagerService; private final CommandsInterface mCi; private ContentResolver mContentResolver; @@ -364,6 +367,10 @@ public class SatelliteController extends Handler { @GuardedBy("mSatelliteConnectedLock") @NonNull private final SparseBooleanArray mInitialized = new SparseBooleanArray(); + @GuardedBy("mSatelliteConnectedLock") + @NonNull private final Map<Integer, CarrierRoamingSatelliteSessionStats> + mCarrierRoamingSatelliteSessionStatsMap = new HashMap<>(); + /** * Key: Subscription ID; Value: set of * {@link android.telephony.NetworkRegistrationInfo.ServiceType} @@ -473,6 +480,8 @@ public class SatelliteController extends Handler { mControllerMetricsStats = ControllerMetricsStats.make(mContext); mProvisionMetricsStats = ProvisionMetricsStats.getOrCreateInstance(); mSessionMetricsStats = SessionMetricsStats.getInstance(); + mCarrierRoamingSatelliteControllerStats = + CarrierRoamingSatelliteControllerStats.getOrCreateInstance(); mSubscriptionManagerService = SubscriptionManagerService.getInstance(); // Create the DatagramController singleton, @@ -3614,6 +3623,8 @@ public class SatelliteController extends Handler { if (!entitlementPlmnList.isEmpty()) { mMergedPlmnListPerCarrier.put(subId, entitlementPlmnList); logd("mMergedPlmnListPerCarrier is updated by Entitlement"); + mCarrierRoamingSatelliteControllerStats.reportConfigDataSource( + SatelliteConstants.CONFIG_DATA_SOURCE_ENTITLEMENT); return; } } @@ -3627,6 +3638,8 @@ public class SatelliteController extends Handler { logd("mMergedPlmnListPerCarrier is updated by ConfigUpdater : " + String.join(",", plmnList)); mMergedPlmnListPerCarrier.put(subId, plmnList); + mCarrierRoamingSatelliteControllerStats.reportConfigDataSource( + SatelliteConstants.CONFIG_DATA_SOURCE_CONFIG_UPDATER); return; } } @@ -3637,6 +3650,8 @@ public class SatelliteController extends Handler { mSatelliteServicesSupportedByCarriers.get(subId).keySet().stream().toList(); logd("mMergedPlmnListPerCarrier is updated by carrier config: " + String.join(",", carrierPlmnList)); + mCarrierRoamingSatelliteControllerStats.reportConfigDataSource( + SatelliteConstants.CONFIG_DATA_SOURCE_CARRIER_CONFIG); } else { carrierPlmnList = new ArrayList<>(); logd("Empty mMergedPlmnListPerCarrier"); @@ -4113,7 +4128,15 @@ public class SatelliteController extends Handler { } synchronized (mSatelliteConnectedLock) { + CarrierRoamingSatelliteSessionStats sessionStats = + mCarrierRoamingSatelliteSessionStatsMap.get(subId); + if (serviceState.isUsingNonTerrestrialNetwork()) { + if (sessionStats != null && !mWasSatelliteConnectedViaCarrier.get(subId)) { + // Log satellite connection start + sessionStats.onConnectionStart(); + } + resetCarrierRoamingSatelliteModeParams(subId); mWasSatelliteConnectedViaCarrier.put(subId, true); @@ -4139,6 +4162,11 @@ public class SatelliteController extends Handler { sendMessageDelayed(obtainMessage(EVENT_NOTIFY_NTN_HYSTERESIS_TIMED_OUT, phone.getPhoneId()), getSatelliteConnectionHysteresisTimeMillis(subId)); + + if (sessionStats != null) { + // Log satellite connection end + sessionStats.onConnectionEnd(); + } } mWasSatelliteConnectedViaCarrier.put(subId, false); } @@ -4163,6 +4191,27 @@ public class SatelliteController extends Handler { if (!initialized) mInitialized.put(subId, true); mLastNotifiedNtnMode.put(subId, currNtnMode); phone.notifyCarrierRoamingNtnModeChanged(currNtnMode); + logCarrierRoamingSatelliteSessionStats(phone, lastNotifiedNtnMode, currNtnMode); + } + } + } + + private void logCarrierRoamingSatelliteSessionStats(@NonNull Phone phone, + boolean lastNotifiedNtnMode, boolean currNtnMode) { + synchronized (mSatelliteConnectedLock) { + int subId = phone.getSubId(); + if (!lastNotifiedNtnMode && currNtnMode) { + // Log satellite session start + CarrierRoamingSatelliteSessionStats sessionStats = + new CarrierRoamingSatelliteSessionStats(mContext, phone.getCarrierId()); + sessionStats.onSessionStart(); + mCarrierRoamingSatelliteSessionStatsMap.put(subId, sessionStats); + } else if (lastNotifiedNtnMode && !currNtnMode) { + // Log satellite session end + CarrierRoamingSatelliteSessionStats sessionStats = + mCarrierRoamingSatelliteSessionStatsMap.get(subId); + sessionStats.onSessionEnd(); + mCarrierRoamingSatelliteSessionStatsMap.remove(subId); } } } @@ -4523,6 +4572,8 @@ public class SatelliteController extends Handler { notificationManager.notifyAsUser(NOTIFICATION_TAG, NOTIFICATION_ID, notificationBuilder.build(), UserHandle.ALL); + + mCarrierRoamingSatelliteControllerStats.reportCountOfSatelliteNotificationDisplayed(); } private void resetCarrierRoamingSatelliteModeParams() { @@ -4536,7 +4587,6 @@ public class SatelliteController extends Handler { private void resetCarrierRoamingSatelliteModeParams(int subId) { if (!mFeatureFlags.carrierEnabledSatelliteFlag()) return; - logd("resetCarrierRoamingSatelliteModeParams subId:" + subId); synchronized (mSatelliteConnectedLock) { mLastSatelliteDisconnectedTimesMillis.put(subId, null); mSatModeCapabilitiesForCarrierRoaming.remove(subId); diff --git a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java new file mode 100644 index 0000000000..9524b754aa --- /dev/null +++ b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2024 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.satellite.metrics; + +import android.annotation.NonNull; +import android.util.Log; + +import com.android.internal.telephony.metrics.SatelliteStats; +import com.android.internal.telephony.satellite.SatelliteConstants; + +public class CarrierRoamingSatelliteControllerStats { + private static final String TAG = CarrierRoamingSatelliteControllerStats.class.getSimpleName(); + private static CarrierRoamingSatelliteControllerStats sInstance = null; + private static final int ADD_COUNT = 1; + + private SatelliteStats mSatelliteStats; + + private CarrierRoamingSatelliteControllerStats() { + mSatelliteStats = SatelliteStats.getInstance(); + } + + /** + * Returns the Singleton instance of CarrierRoamingSatelliteControllerStats class. + * If an instance of the Singleton class has not been created, + * it creates a new instance and returns it. Otherwise, it returns + * the existing instance. + * @return the Singleton instance of CarrierRoamingSatelliteControllerStats + */ + public static CarrierRoamingSatelliteControllerStats getOrCreateInstance() { + if (sInstance == null) { + logd("Create new CarrierRoamingSatelliteControllerStats."); + sInstance = new CarrierRoamingSatelliteControllerStats(); + } + return sInstance; + } + + /** Report config data source */ + public void reportConfigDataSource(@SatelliteConstants.ConfigDataSource int configDataSource) { + mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics( + new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder() + .setConfigDataSource(configDataSource) + .build()); + } + + /** Report count of entitlement status query request */ + public void reportCountOfEntitlementStatusQueryRequest() { + mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics( + new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder() + .setCountOfEntitlementStatusQueryRequest(ADD_COUNT) + .build()); + } + + /** Report count of satellite config update request */ + public void reportCountOfSatelliteConfigUpdateRequest() { + mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics( + new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder() + .setCountOfSatelliteConfigUpdateRequest(ADD_COUNT) + .build()); + } + + /** Report count of satellite notification displayed */ + public void reportCountOfSatelliteNotificationDisplayed() { + mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics( + new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder() + .setCountOfSatelliteNotificationDisplayed(ADD_COUNT) + .build()); + } + + private static void logd(@NonNull String log) { + Log.d(TAG, log); + } +} diff --git a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java new file mode 100644 index 0000000000..78c522231c --- /dev/null +++ b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2024 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.satellite.metrics; + +import android.annotation.NonNull; +import android.content.Context; +import android.telephony.TelephonyManager; +import android.util.Log; + +import com.android.internal.telephony.metrics.SatelliteStats; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class CarrierRoamingSatelliteSessionStats { + private static final String TAG = CarrierRoamingSatelliteSessionStats.class.getSimpleName(); + private final Context mContext; + + private int mCarrierId; + private boolean mIsNtnRoamingInHomeCountry; + private int mRsrpAvg; + private int mRsrpMedian; + private int mRssnrAvg; + private int mRssnrMedian; + private int mCountOfIncomingSms; + private int mCountOfOutgoingSms; + private int mCountOfIncomingMms; + private int mCountOfOutgoingMms; + + private int mSessionStartTimeSec; + private List<Long> mConnectionStartTimeList; + private List<Long> mConnectionEndTimeList; + + public CarrierRoamingSatelliteSessionStats(@NonNull Context context, int carrierId) { + logd("Create new CarrierRoamingSatelliteSessionStats."); + initializeParams(); + + mContext = context; + mCarrierId = carrierId; + } + + /** Log carrier roaming satellite session start */ + public void onSessionStart() { + mSessionStartTimeSec = getCurrentTimeInSec(); + onConnectionStart(); + } + + /** Log carrier roaming satellite connection start */ + public void onConnectionStart() { + mConnectionStartTimeList.add(getCurrentTime()); + } + + /** Log carrier roaming satellite session end */ + public void onSessionEnd() { + onConnectionEnd(); + reportMetrics(); + } + + /** Log carrier roaming satellite connection end */ + public void onConnectionEnd() { + mConnectionEndTimeList.add(getCurrentTime()); + } + + private void reportMetrics() { + int totalSatelliteModeTimeSec = mSessionStartTimeSec > 0 + ? getCurrentTimeInSec() - mSessionStartTimeSec : 0; + int numberOfSatelliteConnections = getNumberOfSatelliteConnections(); + int avgDurationOfSatelliteConnectionSec = getAvgDurationOfSatelliteConnection( + numberOfSatelliteConnections); + + List<Integer> connectionGapList = getSatelliteConnectionGapList( + numberOfSatelliteConnections); + int satelliteConnectionGapMinSec = 0; + int satelliteConnectionGapMaxSec = 0; + if (!connectionGapList.isEmpty()) { + satelliteConnectionGapMinSec = Collections.min(connectionGapList); + satelliteConnectionGapMaxSec = Collections.max(connectionGapList); + } + + SatelliteStats.CarrierRoamingSatelliteSessionParams params = + new SatelliteStats.CarrierRoamingSatelliteSessionParams.Builder() + .setCarrierId(mCarrierId) + .setIsNtnRoamingInHomeCountry(mIsNtnRoamingInHomeCountry) + .setTotalSatelliteModeTimeSec(totalSatelliteModeTimeSec) + .setNumberOfSatelliteConnections(numberOfSatelliteConnections) + .setAvgDurationOfSatelliteConnectionSec(avgDurationOfSatelliteConnectionSec) + .setSatelliteConnectionGapMinSec(satelliteConnectionGapMinSec) + .setSatelliteConnectionGapAvgSec(getAvgConnectionGapSec(connectionGapList)) + .setSatelliteConnectionGapMaxSec(satelliteConnectionGapMaxSec) + .setRsrpAvg(mRsrpAvg) + .setRsrpMedian(mRsrpMedian) + .setRssnrAvg(mRssnrAvg) + .setRssnrMedian(mRssnrMedian) + .setCountOfIncomingSms(mCountOfIncomingSms) + .setCountOfOutgoingSms(mCountOfOutgoingSms) + .setCountOfIncomingMms(mCountOfIncomingMms) + .setCountOfOutgoingMms(mCountOfOutgoingMms) + .build(); + SatelliteStats.getInstance().onCarrierRoamingSatelliteSessionMetrics(params); + logd("reportMetrics: " + params); + initializeParams(); + } + + private void initializeParams() { + mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID; + mIsNtnRoamingInHomeCountry = false; + mRsrpAvg = 0; + mRsrpMedian = 0; + mRssnrAvg = 0; + mRssnrMedian = 0; + mCountOfIncomingSms = 0; + mCountOfOutgoingSms = 0; + mCountOfIncomingMms = 0; + mCountOfOutgoingMms = 0; + + mSessionStartTimeSec = 0; + mConnectionStartTimeList = new ArrayList<>(); + mConnectionEndTimeList = new ArrayList<>(); + } + + private int getNumberOfSatelliteConnections() { + return Math.min(mConnectionStartTimeList.size(), mConnectionEndTimeList.size()); + } + + private int getAvgDurationOfSatelliteConnection(int numberOfSatelliteConnections) { + if (numberOfSatelliteConnections == 0) { + return 0; + } + + long totalConnectionsDuration = 0; + for (int i = 0; i < numberOfSatelliteConnections; i++) { + long endTime = mConnectionEndTimeList.get(i); + long startTime = mConnectionStartTimeList.get(i); + if (endTime >= startTime && startTime > 0) { + totalConnectionsDuration += endTime - startTime; + } + } + + long avgConnectionDuration = totalConnectionsDuration / numberOfSatelliteConnections; + return (int) (avgConnectionDuration / 1000L); + } + + private List<Integer> getSatelliteConnectionGapList(int numberOfSatelliteConnections) { + if (numberOfSatelliteConnections == 0) { + return new ArrayList<>(); + } + + List<Integer> connectionGapList = new ArrayList<>(); + for (int i = 1; i < numberOfSatelliteConnections; i++) { + long prevConnectionEndTime = mConnectionEndTimeList.get(i - 1); + long currentConnectionStartTime = mConnectionStartTimeList.get(i); + if (currentConnectionStartTime > prevConnectionEndTime && prevConnectionEndTime > 0) { + connectionGapList.add((int) ( + (currentConnectionStartTime - prevConnectionEndTime) / 1000)); + } + } + return connectionGapList; + } + + private int getAvgConnectionGapSec(@NonNull List<Integer> connectionGapList) { + if (connectionGapList.isEmpty()) { + return 0; + } + + int totalConnectionGap = 0; + for (int gap : connectionGapList) { + totalConnectionGap += gap; + } + + return (totalConnectionGap / connectionGapList.size()); + } + + private int getCurrentTimeInSec() { + return (int) (System.currentTimeMillis() / 1000); + } + + private long getCurrentTime() { + return System.currentTimeMillis(); + } + + private void logd(@NonNull String log) { + Log.d(TAG, log); + } + + private void loge(@NonNull String log) { + Log.e(TAG, log); + } +} diff --git a/src/java/com/android/internal/telephony/satellite/metrics/ConfigUpdaterMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/ConfigUpdaterMetricsStats.java new file mode 100644 index 0000000000..c379b83a70 --- /dev/null +++ b/src/java/com/android/internal/telephony/satellite/metrics/ConfigUpdaterMetricsStats.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2024 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.satellite.metrics; + +import android.annotation.NonNull; +import android.util.Log; + +import com.android.internal.telephony.metrics.SatelliteStats; +import com.android.internal.telephony.satellite.SatelliteConstants; + +public class ConfigUpdaterMetricsStats { + private static final String TAG = ConfigUpdaterMetricsStats.class.getSimpleName(); + private static ConfigUpdaterMetricsStats sInstance = null; + + private int mConfigVersion; + private int mOemConfigResult; + private int mCarrierConfigResult; + + private ConfigUpdaterMetricsStats() { + initializeConfigUpdaterParams(); + } + + /** + * Returns the Singleton instance of ConfigUpdaterMetricsStats class. + * If an instance of the Singleton class has not been created, + * it creates a new instance and returns it. Otherwise, it returns + * the existing instance. + * @return the Singleton instance of ConfigUpdaterMetricsStats + */ + public static ConfigUpdaterMetricsStats getOrCreateInstance() { + if (sInstance == null) { + logd("Create new ConfigUpdaterMetricsStats."); + sInstance = new ConfigUpdaterMetricsStats(); + } + return sInstance; + } + + /** Set config version for config updater metrics */ + public ConfigUpdaterMetricsStats setConfigVersion(int configVersion) { + mConfigVersion = configVersion; + return this; + } + + /** Set oem config result for config updater metrics */ + public ConfigUpdaterMetricsStats setOemConfigResult(int oemConfigResult) { + mOemConfigResult = oemConfigResult; + return this; + } + + /** Set carrier config result for config updater metrics */ + public ConfigUpdaterMetricsStats setCarrierConfigResult(int carrierConfigResult) { + mCarrierConfigResult = carrierConfigResult; + return this; + } + + /** Report metrics on oem config update error */ + public void reportOemConfigError(int error) { + mOemConfigResult = error; + reportConfigUpdaterMetrics(); + } + + /** Report metrics on carrier config update error */ + public void reportCarrierConfigError(int error) { + mCarrierConfigResult = error; + reportConfigUpdaterMetrics(); + } + + /** Report metrics on config update error */ + public void reportOemAndCarrierConfigError(int error) { + mOemConfigResult = error; + mCarrierConfigResult = error; + reportConfigUpdaterMetrics(); + } + + /** Report metrics on config update success */ + public void reportConfigUpdateSuccess() { + mOemConfigResult = SatelliteConstants.CONFIG_UPDATE_RESULT_SUCCESS; + mCarrierConfigResult = SatelliteConstants.CONFIG_UPDATE_RESULT_SUCCESS; + reportConfigUpdaterMetrics(); + } + + + /** Report config updater metrics atom to PersistAtomsStorage in telephony */ + private void reportConfigUpdaterMetrics() { + SatelliteStats.SatelliteConfigUpdaterParams configUpdaterParams = + new SatelliteStats.SatelliteConfigUpdaterParams.Builder() + .setConfigVersion(mConfigVersion) + .setOemConfigResult(mOemConfigResult) + .setCarrierConfigResult(mCarrierConfigResult) + .setCount(1) + .build(); + SatelliteStats.getInstance().onSatelliteConfigUpdaterMetrics(configUpdaterParams); + logd("reportConfigUpdaterMetrics: " + configUpdaterParams); + + CarrierRoamingSatelliteControllerStats.getOrCreateInstance() + .reportCountOfSatelliteConfigUpdateRequest(); + + initializeConfigUpdaterParams(); + } + + private void initializeConfigUpdaterParams() { + mConfigVersion = -1; + mOemConfigResult = SatelliteConstants.CONFIG_UPDATE_RESULT_UNKNOWN; + mCarrierConfigResult = SatelliteConstants.CONFIG_UPDATE_RESULT_UNKNOWN; + } + + private static void logd(@NonNull String log) { + Log.d(TAG, log); + } +} diff --git a/src/java/com/android/internal/telephony/satellite/metrics/EntitlementMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/EntitlementMetricsStats.java new file mode 100644 index 0000000000..4862188328 --- /dev/null +++ b/src/java/com/android/internal/telephony/satellite/metrics/EntitlementMetricsStats.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2024 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.satellite.metrics; + +import android.annotation.NonNull; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; +import android.util.Log; + +import com.android.internal.telephony.Phone; +import com.android.internal.telephony.PhoneFactory; +import com.android.internal.telephony.metrics.SatelliteStats; +import com.android.internal.telephony.satellite.SatelliteConstants; + +public class EntitlementMetricsStats { + private static final String TAG = EntitlementMetricsStats.class.getSimpleName(); + private static EntitlementMetricsStats sInstance = null; + private static final int RESULT_SUCCESS = 200; + + private int mSubId; + private int mResult; + private int mEntitlementStatus; + private boolean mIsRetry; + + private EntitlementMetricsStats() {} + + /** + * Returns the Singleton instance of EntitlementMetricsStats class. + * If an instance of the Singleton class has not been created, + * it creates a new instance and returns it. Otherwise, it returns + * the existing instance. + * @return the Singleton instance of EntitlementMetricsStats + */ + public static EntitlementMetricsStats getOrCreateInstance() { + if (sInstance == null) { + logd("Create new EntitlementMetricsStats."); + sInstance = new EntitlementMetricsStats(); + } + return sInstance; + } + + /** Report metrics on entitlement query request success */ + public void reportSuccess(int subId, + @SatelliteConstants.SatelliteEntitlementStatus int entitlementStatus, + boolean isRetry) { + mSubId = subId; + mResult = RESULT_SUCCESS; + mEntitlementStatus = entitlementStatus; + mIsRetry = isRetry; + reportEntitlementMetrics(); + } + + /** Report metrics on entitlement query request error */ + public void reportError(int subId, int result, boolean isRetry) { + mSubId = subId; + mResult = result; + mIsRetry = isRetry; + mEntitlementStatus = SatelliteConstants.SATELLITE_ENTITLEMENT_STATUS_UNKNOWN; + reportEntitlementMetrics(); + } + + /** Report entitlement metrics atom to PersistAtomsStorage in telephony */ + private void reportEntitlementMetrics() { + SatelliteStats.SatelliteEntitlementParams entitlementParams = + new SatelliteStats.SatelliteEntitlementParams.Builder() + .setCarrierId(getCarrierId(mSubId)) + .setResult(mResult) + .setEntitlementStatus(mEntitlementStatus) + .setIsRetry(mIsRetry) + .setCount(1) + .build(); + SatelliteStats.getInstance().onSatelliteEntitlementMetrics(entitlementParams); + logd("reportEntitlementMetrics: " + entitlementParams); + + CarrierRoamingSatelliteControllerStats.getOrCreateInstance() + .reportCountOfEntitlementStatusQueryRequest(); + } + + /** Returns the carrier ID of the given subscription id. */ + private int getCarrierId(int subId) { + int phoneId = SubscriptionManager.getPhoneId(subId); + Phone phone = PhoneFactory.getPhone(phoneId); + return phone != null ? phone.getCarrierId() : TelephonyManager.UNKNOWN_CARRIER_ID; + } + + private static void logd(@NonNull String log) { + Log.d(TAG, log); + } +} diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java index 35f1bb7240..04b45b396d 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java @@ -16,9 +16,13 @@ package com.android.internal.telephony.metrics; +import static com.android.internal.telephony.TelephonyStatsLog.CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS; +import static com.android.internal.telephony.TelephonyStatsLog.CARRIER_ROAMING_SATELLITE_SESSION; import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_DATA_SERVICE_SWITCH; import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_SERVICE_STATE; import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SHORT_CODE_SMS; +import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_CONFIG_UPDATER; +import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_ENTITLEMENT; import static com.android.internal.telephony.TelephonyStatsLog.SIM_SLOT_STATE; import static com.android.internal.telephony.TelephonyStatsLog.SUPPORTED_RADIO_ACCESS_FAMILY; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_RAT_USAGE; @@ -45,9 +49,13 @@ import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneFactory; import com.android.internal.telephony.TelephonyTest; import com.android.internal.telephony.flags.FeatureFlags; +import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteControllerStats; +import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteSession; import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch; import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState; import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingShortCodeSms; +import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteConfigUpdater; +import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteEntitlement; import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallRatUsage; import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallSession; import com.android.internal.telephony.uicc.IccCardStatus.CardState; @@ -115,7 +123,7 @@ public class MetricsCollectorTest extends TelephonyTest { mFeatureFlags = mock(FeatureFlags.class); mMetricsCollector = new MetricsCollector(mContext, mPersistAtomsStorage, - mDeviceStateHelper, mVonrHelper, mFeatureFlags); + mDeviceStateHelper, mVonrHelper, mDefaultNetworkMonitor, mFeatureFlags); doReturn(mSST).when(mSecondPhone).getServiceStateTracker(); doReturn(mServiceStateStats).when(mSST).getServiceStateStats(); } @@ -472,4 +480,178 @@ public class MetricsCollectorTest extends TelephonyTest { assertThat(actualAtoms).hasSize(4); assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS); } + + @Test + public void onPullAtom_carrierRoamingSatelliteSession_empty() { + doReturn(new CarrierRoamingSatelliteSession[0]).when(mPersistAtomsStorage) + .getCarrierRoamingSatelliteSessionStats(anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_SESSION, actualAtoms); + + assertThat(actualAtoms).hasSize(0); + assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS); + } + + @Test + public void onPullAtom_carrierRoamingSatelliteSession_tooFrequent() { + doReturn(null).when(mPersistAtomsStorage) + .getCarrierRoamingSatelliteSessionStats(anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_SESSION, actualAtoms); + + assertThat(actualAtoms).hasSize(0); + assertThat(result).isEqualTo(StatsManager.PULL_SKIP); + verify(mPersistAtomsStorage, times(1)) + .getCarrierRoamingSatelliteSessionStats(eq(MIN_COOLDOWN_MILLIS)); + verifyNoMoreInteractions(mPersistAtomsStorage); + } + + @Test + public void onPullAtom_carrierRoamingSatelliteSession_multipleAtoms() { + CarrierRoamingSatelliteSession carrierRoamingSatelliteSession = + new CarrierRoamingSatelliteSession(); + doReturn(new CarrierRoamingSatelliteSession[] {carrierRoamingSatelliteSession, + carrierRoamingSatelliteSession, carrierRoamingSatelliteSession, + carrierRoamingSatelliteSession}) + .when(mPersistAtomsStorage) + .getCarrierRoamingSatelliteSessionStats(anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_SESSION, actualAtoms); + + assertThat(actualAtoms).hasSize(4); + assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS); + } + + @Test + public void onPullAtom_carrierRoamingSatelliteControllerStats_empty() { + doReturn(new CarrierRoamingSatelliteControllerStats[0]).when(mPersistAtomsStorage) + .getCarrierRoamingSatelliteControllerStats(anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS, + actualAtoms); + + assertThat(actualAtoms).hasSize(0); + assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS); + } + + @Test + public void onPullAtom_carrierRoamingSatelliteControllerStats_multipleAtoms() { + CarrierRoamingSatelliteControllerStats carrierRoamingSatelliteControllerStats = + new CarrierRoamingSatelliteControllerStats(); + doReturn(new CarrierRoamingSatelliteControllerStats[] { + carrierRoamingSatelliteControllerStats}) + .when(mPersistAtomsStorage) + .getCarrierRoamingSatelliteControllerStats(anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS, + actualAtoms); + + assertThat(actualAtoms).hasSize(1); + assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS); + } + + @Test + public void onPullAtom_carrierRoamingSatelliteControllerStats_tooFrequent() { + doReturn(null).when(mPersistAtomsStorage) + .getCarrierRoamingSatelliteControllerStats(anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS, + actualAtoms); + + assertThat(actualAtoms).hasSize(0); + assertThat(result).isEqualTo(StatsManager.PULL_SKIP); + verify(mPersistAtomsStorage, times(1)) + .getCarrierRoamingSatelliteControllerStats(eq(MIN_COOLDOWN_MILLIS)); + verifyNoMoreInteractions(mPersistAtomsStorage); + } + + @Test + public void onPullAtom_satelliteEntitlement_empty() { + doReturn(new SatelliteEntitlement[0]).when(mPersistAtomsStorage) + .getSatelliteEntitlementStats(anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMetricsCollector.onPullAtom(SATELLITE_ENTITLEMENT, actualAtoms); + + assertThat(actualAtoms).hasSize(0); + assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS); + } + + @Test + public void onPullAtom_satelliteEntitlement_tooFrequent() { + doReturn(null).when(mPersistAtomsStorage).getSatelliteEntitlementStats( + anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMetricsCollector.onPullAtom(SATELLITE_ENTITLEMENT, actualAtoms); + + assertThat(actualAtoms).hasSize(0); + assertThat(result).isEqualTo(StatsManager.PULL_SKIP); + verify(mPersistAtomsStorage, times(1)) + .getSatelliteEntitlementStats(eq(MIN_COOLDOWN_MILLIS)); + verifyNoMoreInteractions(mPersistAtomsStorage); + } + + @Test + public void onPullAtom_satelliteEntitlement_multipleAtoms() { + SatelliteEntitlement satelliteEntitlement = new SatelliteEntitlement(); + doReturn(new SatelliteEntitlement[] {satelliteEntitlement, satelliteEntitlement, + satelliteEntitlement, satelliteEntitlement}) + .when(mPersistAtomsStorage) + .getSatelliteEntitlementStats(anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMetricsCollector.onPullAtom(SATELLITE_ENTITLEMENT, actualAtoms); + + assertThat(actualAtoms).hasSize(4); + assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS); + } + + @Test + public void onPullAtom_satelliteConfigUpdater_empty() { + doReturn(new SatelliteConfigUpdater[0]).when(mPersistAtomsStorage) + .getSatelliteConfigUpdaterStats(anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMetricsCollector.onPullAtom(SATELLITE_CONFIG_UPDATER, actualAtoms); + + assertThat(actualAtoms).hasSize(0); + assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS); + } + + @Test + public void onPullAtom_satelliteConfigUpdater_tooFrequent() { + doReturn(null).when(mPersistAtomsStorage).getSatelliteConfigUpdaterStats( + anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMetricsCollector.onPullAtom(SATELLITE_CONFIG_UPDATER, actualAtoms); + + assertThat(actualAtoms).hasSize(0); + assertThat(result).isEqualTo(StatsManager.PULL_SKIP); + verify(mPersistAtomsStorage, times(1)) + .getSatelliteConfigUpdaterStats(eq(MIN_COOLDOWN_MILLIS)); + verifyNoMoreInteractions(mPersistAtomsStorage); + } + + @Test + public void onPullAtom_satelliteConfigUpdater_multipleAtoms() { + SatelliteConfigUpdater satelliteConfigUpdater = new SatelliteConfigUpdater(); + doReturn(new SatelliteConfigUpdater[] {satelliteConfigUpdater, satelliteConfigUpdater, + satelliteConfigUpdater, satelliteConfigUpdater}) + .when(mPersistAtomsStorage) + .getSatelliteConfigUpdaterStats(anyLong()); + List<StatsEvent> actualAtoms = new ArrayList<>(); + + int result = mMetricsCollector.onPullAtom(SATELLITE_CONFIG_UPDATER, actualAtoms); + + assertThat(actualAtoms).hasSize(4); + assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS); + } } diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java index 16a4f0d864..092522b297 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java @@ -76,6 +76,8 @@ import androidx.test.filters.SmallTest; import com.android.internal.telephony.TelephonyStatsLog; import com.android.internal.telephony.TelephonyTest; +import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteControllerStats; +import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteSession; import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch; import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState; import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession; @@ -94,7 +96,9 @@ import com.android.internal.telephony.nano.PersistAtomsProto.PersistAtoms; import com.android.internal.telephony.nano.PersistAtomsProto.PresenceNotifyEvent; import com.android.internal.telephony.nano.PersistAtomsProto.RcsAcsProvisioningStats; import com.android.internal.telephony.nano.PersistAtomsProto.RcsClientProvisioningStats; +import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteConfigUpdater; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteController; +import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteEntitlement; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteIncomingDatagram; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteOutgoingDatagram; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteProvision; @@ -296,6 +300,22 @@ public class PersistAtomsStorageTest extends TelephonyTest { private DataNetworkValidation mDataNetworkValidationIwlan2; private DataNetworkValidation[] mDataNetworkValidations; + private CarrierRoamingSatelliteSession mCarrierRoamingSatelliteSession1; + private CarrierRoamingSatelliteSession mCarrierRoamingSatelliteSession2; + private CarrierRoamingSatelliteSession[] mCarrierRoamingSatelliteSessions; + + private CarrierRoamingSatelliteControllerStats mCarrierRoamingSatelliteControllerStats1; + private CarrierRoamingSatelliteControllerStats mCarrierRoamingSatelliteControllerStats2; + private CarrierRoamingSatelliteControllerStats[] mCarrierRoamingSatelliteControllerStats; + + private SatelliteEntitlement mSatelliteEntitlement1; + private SatelliteEntitlement mSatelliteEntitlement2; + private SatelliteEntitlement[] mSatelliteEntitlements; + + private SatelliteConfigUpdater mSatelliteConfigUpdater1; + private SatelliteConfigUpdater mSatelliteConfigUpdater2; + private SatelliteConfigUpdater[] mSatelliteConfigUpdaters; + private void makeTestData() { // MO call with SRVCC (LTE to UMTS) mCall1Proto = new VoiceCallSession(); @@ -1268,6 +1288,106 @@ public class PersistAtomsStorageTest extends TelephonyTest { new SatelliteSosMessageRecommender[] { mSatelliteSosMessageRecommender1, mSatelliteSosMessageRecommender2 }; + + mCarrierRoamingSatelliteSession1 = new CarrierRoamingSatelliteSession(); + mCarrierRoamingSatelliteSession1.carrierId = 1; + mCarrierRoamingSatelliteSession1.isNtnRoamingInHomeCountry = false; + mCarrierRoamingSatelliteSession1.totalSatelliteModeTimeSec = 60; + mCarrierRoamingSatelliteSession1.numberOfSatelliteConnections = 3; + mCarrierRoamingSatelliteSession1.avgDurationOfSatelliteConnectionSec = 20; + mCarrierRoamingSatelliteSession1.satelliteConnectionGapMinSec = 2; + mCarrierRoamingSatelliteSession1.satelliteConnectionGapAvgSec = 5; + mCarrierRoamingSatelliteSession1.satelliteConnectionGapMaxSec = 8; + mCarrierRoamingSatelliteSession1.rsrpAvg = 3; + mCarrierRoamingSatelliteSession1.rsrpMedian = 2; + mCarrierRoamingSatelliteSession1.rssnrAvg = 5; + mCarrierRoamingSatelliteSession1.rssnrMedian = 3; + mCarrierRoamingSatelliteSession1.countOfIncomingSms = 2; + mCarrierRoamingSatelliteSession1.countOfOutgoingSms = 4; + mCarrierRoamingSatelliteSession1.countOfIncomingMms = 1; + mCarrierRoamingSatelliteSession1.countOfOutgoingMms = 1; + + mCarrierRoamingSatelliteSession2 = new CarrierRoamingSatelliteSession(); + mCarrierRoamingSatelliteSession2.carrierId = 2; + mCarrierRoamingSatelliteSession2.isNtnRoamingInHomeCountry = true; + mCarrierRoamingSatelliteSession2.totalSatelliteModeTimeSec = 120; + mCarrierRoamingSatelliteSession2.numberOfSatelliteConnections = 5; + mCarrierRoamingSatelliteSession2.avgDurationOfSatelliteConnectionSec = 20; + mCarrierRoamingSatelliteSession2.satelliteConnectionGapMinSec = 2; + mCarrierRoamingSatelliteSession2.satelliteConnectionGapAvgSec = 5; + mCarrierRoamingSatelliteSession2.satelliteConnectionGapMaxSec = 8; + mCarrierRoamingSatelliteSession2.rsrpAvg = 3; + mCarrierRoamingSatelliteSession2.rsrpMedian = 2; + mCarrierRoamingSatelliteSession2.rssnrAvg = 8; + mCarrierRoamingSatelliteSession2.rssnrMedian = 15; + mCarrierRoamingSatelliteSession2.countOfIncomingSms = 2; + mCarrierRoamingSatelliteSession2.countOfOutgoingSms = 4; + mCarrierRoamingSatelliteSession2.countOfIncomingMms = 1; + mCarrierRoamingSatelliteSession2.countOfOutgoingMms = 1; + + mCarrierRoamingSatelliteSessions = new CarrierRoamingSatelliteSession[] { + mCarrierRoamingSatelliteSession1, mCarrierRoamingSatelliteSession2}; + + mCarrierRoamingSatelliteControllerStats1 = new CarrierRoamingSatelliteControllerStats(); + mCarrierRoamingSatelliteControllerStats1.configDataSource = + SatelliteProtoEnums.CONFIG_DATA_SOURCE_ENTITLEMENT; + mCarrierRoamingSatelliteControllerStats1.countOfEntitlementStatusQueryRequest = 2; + mCarrierRoamingSatelliteControllerStats1.countOfSatelliteConfigUpdateRequest = 1; + mCarrierRoamingSatelliteControllerStats1.countOfSatelliteNotificationDisplayed = 1; + mCarrierRoamingSatelliteControllerStats1.satelliteSessionGapMinSec = 2; + mCarrierRoamingSatelliteControllerStats1.satelliteSessionGapAvgSec = 3; + mCarrierRoamingSatelliteControllerStats1.satelliteSessionGapMaxSec = 4; + + mCarrierRoamingSatelliteControllerStats2 = new CarrierRoamingSatelliteControllerStats(); + mCarrierRoamingSatelliteControllerStats2.configDataSource = + SatelliteProtoEnums.CONFIG_DATA_SOURCE_CONFIG_UPDATER; + mCarrierRoamingSatelliteControllerStats2.countOfEntitlementStatusQueryRequest = 4; + mCarrierRoamingSatelliteControllerStats2.countOfSatelliteConfigUpdateRequest = 1; + mCarrierRoamingSatelliteControllerStats2.countOfSatelliteNotificationDisplayed = 1; + mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapMinSec = 5; + mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapAvgSec = 10; + mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapMaxSec = 15; + + // CarrierRoamingSatelliteController has one data point + mCarrierRoamingSatelliteControllerStats = new CarrierRoamingSatelliteControllerStats[] { + mCarrierRoamingSatelliteControllerStats1}; + + mSatelliteEntitlement1 = new SatelliteEntitlement(); + mSatelliteEntitlement1.carrierId = 1; + mSatelliteEntitlement1.result = 0; + mSatelliteEntitlement1.entitlementStatus = + SatelliteProtoEnums.SATELLITE_ENTITLEMENT_STATUS_ENABLED; + mSatelliteEntitlement1.isRetry = false; + mSatelliteEntitlement1.count = 1; + + mSatelliteEntitlement2 = new SatelliteEntitlement(); + mSatelliteEntitlement2.carrierId = 2; + mSatelliteEntitlement2.result = 1; + mSatelliteEntitlement2.entitlementStatus = + SatelliteProtoEnums.SATELLITE_ENTITLEMENT_STATUS_DISABLED; + mSatelliteEntitlement1.isRetry = true; + mSatelliteEntitlement2.count = 1; + + mSatelliteEntitlements = new SatelliteEntitlement[] {mSatelliteEntitlement1, + mSatelliteEntitlement2}; + + mSatelliteConfigUpdater1 = new SatelliteConfigUpdater(); + mSatelliteConfigUpdater1.configVersion = 1; + mSatelliteConfigUpdater1.oemConfigResult = SatelliteProtoEnums.CONFIG_UPDATE_RESULT_SUCCESS; + mSatelliteConfigUpdater1.carrierConfigResult = + SatelliteProtoEnums.CONFIG_UPDATE_RESULT_CARRIER_DATA_INVALID_PLMN; + mSatelliteConfigUpdater1.count = 1; + + mSatelliteConfigUpdater2 = new SatelliteConfigUpdater(); + mSatelliteConfigUpdater2.configVersion = 2; + mSatelliteConfigUpdater2.oemConfigResult = + SatelliteProtoEnums.CONFIG_UPDATE_RESULT_DEVICE_DATA_INVALID_COUNTRY_CODE; + mSatelliteConfigUpdater2.carrierConfigResult = + SatelliteProtoEnums.CONFIG_UPDATE_RESULT_SUCCESS; + mSatelliteConfigUpdater2.count = 1; + + mSatelliteConfigUpdaters = new SatelliteConfigUpdater[] {mSatelliteConfigUpdater1, + mSatelliteConfigUpdater2}; } private void generateTestDataNetworkValidationsData() { @@ -1494,6 +1614,18 @@ public class PersistAtomsStorageTest extends TelephonyTest { mDataNetworkValidationLte2 = null; mDataNetworkValidationIwlan1 = null; mDataNetworkValidationIwlan2 = null; + mCarrierRoamingSatelliteSession1 = null; + mCarrierRoamingSatelliteSession2 = null; + mCarrierRoamingSatelliteSessions = null; + mCarrierRoamingSatelliteControllerStats1 = null; + mCarrierRoamingSatelliteControllerStats2 = null; + mCarrierRoamingSatelliteControllerStats = null; + mSatelliteEntitlement1 = null; + mSatelliteEntitlement2 = null; + mSatelliteEntitlements = null; + mSatelliteConfigUpdater1 = null; + mSatelliteConfigUpdater2 = null; + mSatelliteConfigUpdaters = null; super.tearDown(); } @@ -4649,6 +4781,405 @@ public class PersistAtomsStorageTest extends TelephonyTest { } @Test + public void addCarrierRoamingSatelliteSessionStats_emptyProto() throws Exception { + createEmptyTestFile(); + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + mPersistAtomsStorage.addCarrierRoamingSatelliteSessionStats( + mCarrierRoamingSatelliteSession1); + mPersistAtomsStorage.incTimeMillis(100L); + + verifyCurrentStateSavedToFileOnce(); + CarrierRoamingSatelliteSession[] output = + mPersistAtomsStorage.getCarrierRoamingSatelliteSessionStats(0L); + assertProtoArrayEquals(new CarrierRoamingSatelliteSession[] { + mCarrierRoamingSatelliteSession1}, output); + } + + @Test + public void addCarrierRoamingSatelliteSessionStats_withExistingEntries() throws Exception { + createEmptyTestFile(); + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + mPersistAtomsStorage.addCarrierRoamingSatelliteSessionStats( + mCarrierRoamingSatelliteSession1); + mPersistAtomsStorage.addCarrierRoamingSatelliteSessionStats( + mCarrierRoamingSatelliteSession2); + mPersistAtomsStorage.incTimeMillis(100L); + + verifyCurrentStateSavedToFileOnce(); + CarrierRoamingSatelliteSession[] output = + mPersistAtomsStorage.getCarrierRoamingSatelliteSessionStats(0L); + assertProtoArrayEqualsIgnoringOrder( + new CarrierRoamingSatelliteSession[] {mCarrierRoamingSatelliteSession2}, output); + } + + @Test + public void addCarrierRoamingSatelliteSessionStats_tooManyEntries() throws Exception { + createEmptyTestFile(); + + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + + // Store atoms up to maximum number + 1 + int maxCount = 1 + 1; + for (int i = 0; i < maxCount; i++) { + mPersistAtomsStorage.addCarrierRoamingSatelliteSessionStats( + copyOf(mCarrierRoamingSatelliteSession1)); + mPersistAtomsStorage.incTimeMillis(100L); + } + + // Store 1 different atom + mPersistAtomsStorage.addCarrierRoamingSatelliteSessionStats( + mCarrierRoamingSatelliteSession2); + + verifyCurrentStateSavedToFileOnce(); + + CarrierRoamingSatelliteSession[] result = + mPersistAtomsStorage.getCarrierRoamingSatelliteSessionStats(0L); + + // First atom has count 0, the other has 1 + assertHasStatsAndCount(result, mCarrierRoamingSatelliteSession1, 0); + assertHasStatsAndCount(result, mCarrierRoamingSatelliteSession2, 1); + } + + @Test + public void getCarrierRoamingSatelliteSessionStats_tooFrequent() throws Exception { + createTestFile(START_TIME_MILLIS); + + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum + CarrierRoamingSatelliteSession[] output = + mPersistAtomsStorage.getCarrierRoamingSatelliteSessionStats(100L); + + // Should be denied + assertNull(output); + } + + @Test + public void getCarrierRoamingSatelliteSessionStats_withSavedAtoms() throws Exception { + createTestFile(START_TIME_MILLIS); + + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + mPersistAtomsStorage.incTimeMillis(100L); + CarrierRoamingSatelliteSession[] carrierRoamingSatelliteSessionStatsList1 = + mPersistAtomsStorage.getCarrierRoamingSatelliteSessionStats(50L); + mPersistAtomsStorage.incTimeMillis(100L); + CarrierRoamingSatelliteSession[] carrierRoamingSatelliteSessionStatsList2 = + mPersistAtomsStorage.getCarrierRoamingSatelliteSessionStats(50L); + + // First set of results should be equal to file contents. + CarrierRoamingSatelliteSession[] expectedList = new CarrierRoamingSatelliteSession[] { + mCarrierRoamingSatelliteSession1, mCarrierRoamingSatelliteSession2}; + assertProtoArrayEqualsIgnoringOrder(expectedList, carrierRoamingSatelliteSessionStatsList1); + // Second set of results should be empty. + assertProtoArrayEquals(new CarrierRoamingSatelliteSession[0], + carrierRoamingSatelliteSessionStatsList2); + // Corresponding pull timestamp should be updated and saved. + assertEquals(START_TIME_MILLIS + 200L, mPersistAtomsStorage + .getAtomsProto().carrierRoamingSatelliteSessionPullTimestampMillis); + InOrder inOrder = inOrder(mTestFileOutputStream); + assertEquals(START_TIME_MILLIS + 100L, + getAtomsWritten(inOrder).carrierRoamingSatelliteSessionPullTimestampMillis); + assertEquals(START_TIME_MILLIS + 200L, + getAtomsWritten(inOrder).carrierRoamingSatelliteSessionPullTimestampMillis); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void addCarrierRoamingSatelliteControllerStats_emptyProto() throws Exception { + createEmptyTestFile(); + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + mPersistAtomsStorage.addCarrierRoamingSatelliteControllerStats( + mCarrierRoamingSatelliteControllerStats1); + mPersistAtomsStorage.incTimeMillis(100L); + + verifyCurrentStateSavedToFileOnce(); + CarrierRoamingSatelliteControllerStats[] output = + mPersistAtomsStorage.getCarrierRoamingSatelliteControllerStats(0L); + assertProtoArrayEquals(new CarrierRoamingSatelliteControllerStats[] { + mCarrierRoamingSatelliteControllerStats1}, output); + } + + @Test + public void addCarrierRoamingSatelliteControllerStats_withExistingEntries() throws Exception { + createEmptyTestFile(); + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + mPersistAtomsStorage.addCarrierRoamingSatelliteControllerStats( + mCarrierRoamingSatelliteControllerStats1); + mPersistAtomsStorage.addCarrierRoamingSatelliteControllerStats( + mCarrierRoamingSatelliteControllerStats2); + mPersistAtomsStorage.incTimeMillis(100L); + + CarrierRoamingSatelliteControllerStats expected = + new CarrierRoamingSatelliteControllerStats(); + expected.configDataSource = mCarrierRoamingSatelliteControllerStats2.configDataSource; + expected.countOfEntitlementStatusQueryRequest = + mCarrierRoamingSatelliteControllerStats1.countOfEntitlementStatusQueryRequest + + mCarrierRoamingSatelliteControllerStats2 + .countOfEntitlementStatusQueryRequest; + expected.countOfSatelliteConfigUpdateRequest = + mCarrierRoamingSatelliteControllerStats1.countOfSatelliteConfigUpdateRequest + + mCarrierRoamingSatelliteControllerStats2 + .countOfSatelliteConfigUpdateRequest; + expected.countOfSatelliteNotificationDisplayed = + mCarrierRoamingSatelliteControllerStats1.countOfSatelliteNotificationDisplayed + + mCarrierRoamingSatelliteControllerStats2 + .countOfSatelliteNotificationDisplayed; + expected.satelliteSessionGapMinSec = + mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapMinSec; + expected.satelliteSessionGapAvgSec = + mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapAvgSec; + expected.satelliteSessionGapMaxSec = + mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapMaxSec; + + verifyCurrentStateSavedToFileOnce(); + CarrierRoamingSatelliteControllerStats[] output = + mPersistAtomsStorage.getCarrierRoamingSatelliteControllerStats(0L); + assertHasStats(output, expected); + } + + @Test + public void getCarrierRoamingSatelliteControllerStats_tooFrequent() throws Exception { + createTestFile(START_TIME_MILLIS); + + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum + CarrierRoamingSatelliteControllerStats[] output = + mPersistAtomsStorage.getCarrierRoamingSatelliteControllerStats(100L); + + // Should be denied + assertNull(output); + } + + + @Test + public void addSatelliteEntitlementStats_emptyProto() throws Exception { + createEmptyTestFile(); + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + mPersistAtomsStorage.addSatelliteEntitlementStats(mSatelliteEntitlement1); + mPersistAtomsStorage.incTimeMillis(100L); + + verifyCurrentStateSavedToFileOnce(); + SatelliteEntitlement[] output = + mPersistAtomsStorage.getSatelliteEntitlementStats(0L); + assertProtoArrayEquals(new SatelliteEntitlement[] {mSatelliteEntitlement1}, output); + } + + @Test + public void addSatelliteEntitlementStats_withExistingEntries() throws Exception { + createEmptyTestFile(); + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + mPersistAtomsStorage.addSatelliteEntitlementStats(mSatelliteEntitlement1); + mPersistAtomsStorage.addSatelliteEntitlementStats(mSatelliteEntitlement2); + mPersistAtomsStorage.incTimeMillis(100L); + + verifyCurrentStateSavedToFileOnce(); + SatelliteEntitlement[] output = + mPersistAtomsStorage.getSatelliteEntitlementStats(0L); + assertProtoArrayEqualsIgnoringOrder( + new SatelliteEntitlement[] { + mSatelliteEntitlement1, mSatelliteEntitlement2}, output); + } + + @Test + public void addSatelliteEntitlementStats_updateExistingEntries() throws Exception { + createTestFile(START_TIME_MILLIS); + + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + mPersistAtomsStorage.addSatelliteEntitlementStats(copyOf(mSatelliteEntitlement1)); + mPersistAtomsStorage.incTimeMillis(100L); + + // Count should be increased by 1. + verifyCurrentStateSavedToFileOnce(); + SatelliteEntitlement newSatelliteEntitlement1 = copyOf(mSatelliteEntitlement1); + newSatelliteEntitlement1.count = 2; + SatelliteEntitlement[] expectedList = new SatelliteEntitlement[] {newSatelliteEntitlement1, + mSatelliteEntitlement2}; + assertProtoArrayEqualsIgnoringOrder(expectedList, + mPersistAtomsStorage.getSatelliteEntitlementStats(0L)); + } + + @Test + public void addSatelliteEntitlementStats_tooManyEntries() throws Exception { + createEmptyTestFile(); + + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + + // Store atoms up to maximum number + 1 + int maxCount = 15 + 1; + for (int i = 0; i < maxCount; i++) { + mPersistAtomsStorage.addSatelliteEntitlementStats(mSatelliteEntitlement1); + mPersistAtomsStorage.incTimeMillis(100L); + } + + // Store 1 different atom + mPersistAtomsStorage.addSatelliteEntitlementStats(mSatelliteEntitlement2); + + verifyCurrentStateSavedToFileOnce(); + + SatelliteEntitlement[] result = + mPersistAtomsStorage.getSatelliteEntitlementStats(0L); + + // First atom has count 14, the other has 1 + assertHasStatsAndCount(result, mSatelliteEntitlement1, 16); + assertHasStatsAndCount(result, mSatelliteEntitlement2, 1); + } + + @Test + public void getSatelliteEntitlementStats_tooFrequent() throws Exception { + createTestFile(START_TIME_MILLIS); + + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum + SatelliteEntitlement[] output = + mPersistAtomsStorage.getSatelliteEntitlementStats(100L); + + // Should be denied + assertNull(output); + } + + @Test + public void getSatelliteEntitlementStats_withSavedAtoms() throws Exception { + createTestFile(START_TIME_MILLIS); + + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + mPersistAtomsStorage.incTimeMillis(100L); + SatelliteEntitlement[] satelliteEntitlementStatsList1 = + mPersistAtomsStorage.getSatelliteEntitlementStats(50L); + mPersistAtomsStorage.incTimeMillis(100L); + SatelliteEntitlement[] satelliteEntitlementStatsList2 = + mPersistAtomsStorage.getSatelliteEntitlementStats(50L); + + // First set of results should be equal to file contents. + SatelliteEntitlement[] expectedList = new SatelliteEntitlement[] { + mSatelliteEntitlement1, mSatelliteEntitlement2}; + assertProtoArrayEqualsIgnoringOrder(expectedList, satelliteEntitlementStatsList1); + // Second set of results should be empty. + assertProtoArrayEquals(new SatelliteEntitlement[0], satelliteEntitlementStatsList2); + // Corresponding pull timestamp should be updated and saved. + assertEquals(START_TIME_MILLIS + 200L, mPersistAtomsStorage + .getAtomsProto().satelliteEntitlementPullTimestampMillis); + InOrder inOrder = inOrder(mTestFileOutputStream); + assertEquals(START_TIME_MILLIS + 100L, + getAtomsWritten(inOrder).satelliteEntitlementPullTimestampMillis); + assertEquals(START_TIME_MILLIS + 200L, + getAtomsWritten(inOrder).satelliteEntitlementPullTimestampMillis); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void addSatelliteConfigUpdaterStats_emptyProto() throws Exception { + createEmptyTestFile(); + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + mPersistAtomsStorage.addSatelliteConfigUpdaterStats(mSatelliteConfigUpdater1); + mPersistAtomsStorage.incTimeMillis(100L); + + verifyCurrentStateSavedToFileOnce(); + SatelliteConfigUpdater[] output = + mPersistAtomsStorage.getSatelliteConfigUpdaterStats(0L); + assertProtoArrayEquals(new SatelliteConfigUpdater[] {mSatelliteConfigUpdater1}, output); + } + + @Test + public void addSatelliteConfigUpdaterStats_withExistingEntries() throws Exception { + createEmptyTestFile(); + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + mPersistAtomsStorage.addSatelliteConfigUpdaterStats(mSatelliteConfigUpdater1); + mPersistAtomsStorage.addSatelliteConfigUpdaterStats(mSatelliteConfigUpdater2); + mPersistAtomsStorage.incTimeMillis(100L); + + verifyCurrentStateSavedToFileOnce(); + SatelliteConfigUpdater[] output = + mPersistAtomsStorage.getSatelliteConfigUpdaterStats(0L); + assertProtoArrayEqualsIgnoringOrder(new SatelliteConfigUpdater[] { + mSatelliteConfigUpdater1, mSatelliteConfigUpdater2}, output); + } + + @Test + public void addSatelliteConfigUpdaterStats_updateExistingEntries() throws Exception { + createTestFile(START_TIME_MILLIS); + + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + mPersistAtomsStorage.addSatelliteConfigUpdaterStats(copyOf(mSatelliteConfigUpdater1)); + mPersistAtomsStorage.incTimeMillis(100L); + + // Count should be increased by 1. + verifyCurrentStateSavedToFileOnce(); + SatelliteConfigUpdater newSatelliteConfigUpdater1 = copyOf(mSatelliteConfigUpdater1); + newSatelliteConfigUpdater1.count = 2; + SatelliteConfigUpdater[] expectedList = new SatelliteConfigUpdater[] { + newSatelliteConfigUpdater1, mSatelliteConfigUpdater2}; + assertProtoArrayEqualsIgnoringOrder(expectedList, + mPersistAtomsStorage.getSatelliteConfigUpdaterStats(0L)); + } + + @Test + public void addSatelliteConfigUpdaterStats_tooManyEntries() throws Exception { + createEmptyTestFile(); + + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + + // Store atoms up to maximum number + 1 + int maxCount = 15 + 1; + for (int i = 0; i < maxCount; i++) { + mPersistAtomsStorage.addSatelliteConfigUpdaterStats(mSatelliteConfigUpdater1); + mPersistAtomsStorage.incTimeMillis(100L); + } + + // Store 1 different atom + mPersistAtomsStorage.addSatelliteConfigUpdaterStats(mSatelliteConfigUpdater2); + + verifyCurrentStateSavedToFileOnce(); + + SatelliteConfigUpdater[] result = + mPersistAtomsStorage.getSatelliteConfigUpdaterStats(0L); + + // First atom has count 14, the other has 1 + assertHasStatsAndCount(result, mSatelliteConfigUpdater1, 16); + assertHasStatsAndCount(result, mSatelliteConfigUpdater2, 1); + } + + @Test + public void getSatelliteConfigUpdaterStats_tooFrequent() throws Exception { + createTestFile(START_TIME_MILLIS); + + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum + SatelliteConfigUpdater[] output = + mPersistAtomsStorage.getSatelliteConfigUpdaterStats(100L); + + // Should be denied + assertNull(output); + } + + @Test + public void getSatelliteConfigUpdaterStats_withSavedAtoms() throws Exception { + createTestFile(START_TIME_MILLIS); + + mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext); + mPersistAtomsStorage.incTimeMillis(100L); + SatelliteConfigUpdater[] satelliteConfigUpdaterStatsList1 = + mPersistAtomsStorage.getSatelliteConfigUpdaterStats(50L); + mPersistAtomsStorage.incTimeMillis(100L); + SatelliteConfigUpdater[] satelliteConfigUpdaterStatsList2 = + mPersistAtomsStorage.getSatelliteConfigUpdaterStats(50L); + + // First set of results should be equal to file contents. + SatelliteConfigUpdater[] expectedList = new SatelliteConfigUpdater[] { + mSatelliteConfigUpdater1, mSatelliteConfigUpdater2}; + assertProtoArrayEqualsIgnoringOrder(expectedList, satelliteConfigUpdaterStatsList1); + // Second set of results should be empty. + assertProtoArrayEquals(new SatelliteConfigUpdater[0], satelliteConfigUpdaterStatsList2); + // Corresponding pull timestamp should be updated and saved. + assertEquals(START_TIME_MILLIS + 200L, mPersistAtomsStorage + .getAtomsProto().satelliteConfigUpdaterPullTimestampMillis); + InOrder inOrder = inOrder(mTestFileOutputStream); + assertEquals(START_TIME_MILLIS + 100L, + getAtomsWritten(inOrder).satelliteConfigUpdaterPullTimestampMillis); + assertEquals(START_TIME_MILLIS + 200L, + getAtomsWritten(inOrder).satelliteConfigUpdaterPullTimestampMillis); + inOrder.verifyNoMoreInteractions(); + } + + @Test @SmallTest public void addDataNetworkValidation_newEntry() throws Exception { createEmptyTestFile(); @@ -4806,6 +5337,14 @@ public class PersistAtomsStorageTest extends TelephonyTest { atoms.satelliteSosMessageRecommenderPullTimestampMillis = lastPullTimeMillis; atoms.dataNetworkValidation = mDataNetworkValidations; atoms.dataNetworkValidationPullTimestampMillis = lastPullTimeMillis; + atoms.carrierRoamingSatelliteSession = mCarrierRoamingSatelliteSessions; + atoms.carrierRoamingSatelliteSessionPullTimestampMillis = lastPullTimeMillis; + atoms.carrierRoamingSatelliteControllerStats = mCarrierRoamingSatelliteControllerStats; + atoms.carrierRoamingSatelliteControllerStatsPullTimestampMillis = lastPullTimeMillis; + atoms.satelliteEntitlement = mSatelliteEntitlements; + atoms.satelliteEntitlementPullTimestampMillis = lastPullTimeMillis; + atoms.satelliteConfigUpdater = mSatelliteConfigUpdaters; + atoms.satelliteConfigUpdaterPullTimestampMillis = lastPullTimeMillis; FileOutputStream stream = new FileOutputStream(mTestFile); stream.write(PersistAtoms.toByteArray(atoms)); stream.close(); @@ -4974,6 +5513,24 @@ public class PersistAtomsStorageTest extends TelephonyTest { return DataNetworkValidation.parseFrom(MessageNano.toByteArray(source)); } + private static CarrierRoamingSatelliteSession copyOf(CarrierRoamingSatelliteSession source) + throws Exception { + return CarrierRoamingSatelliteSession.parseFrom(MessageNano.toByteArray(source)); + } + + private static CarrierRoamingSatelliteControllerStats copyOf( + CarrierRoamingSatelliteControllerStats source) throws Exception { + return CarrierRoamingSatelliteControllerStats.parseFrom(MessageNano.toByteArray(source)); + } + + private static SatelliteEntitlement copyOf(SatelliteEntitlement source) throws Exception { + return SatelliteEntitlement.parseFrom(MessageNano.toByteArray(source)); + } + + private static SatelliteConfigUpdater copyOf(SatelliteConfigUpdater source) throws Exception { + return SatelliteConfigUpdater.parseFrom(MessageNano.toByteArray(source)); + } + private void assertAllPullTimestampEquals(long timestamp) { assertEquals( timestamp, @@ -5472,4 +6029,82 @@ public class PersistAtomsStorageTest extends TelephonyTest { } assertEquals(expectedCount, actualCount); } + + private static void assertHasStatsAndCount(CarrierRoamingSatelliteSession[] tested, + @Nullable CarrierRoamingSatelliteSession expectedStats, int expectedCount) { + assertNotNull(tested); + int actualCount = 0; + for (CarrierRoamingSatelliteSession stats : tested) { + if (stats.carrierId == expectedStats.carrierId + && stats.isNtnRoamingInHomeCountry == expectedStats.isNtnRoamingInHomeCountry + && stats.totalSatelliteModeTimeSec == expectedStats.totalSatelliteModeTimeSec + && stats.numberOfSatelliteConnections + == expectedStats.numberOfSatelliteConnections + && stats.avgDurationOfSatelliteConnectionSec + == expectedStats.avgDurationOfSatelliteConnectionSec + && stats.satelliteConnectionGapMinSec + == expectedStats.satelliteConnectionGapMinSec + && stats.satelliteConnectionGapAvgSec + == expectedStats.satelliteConnectionGapAvgSec + && stats.satelliteConnectionGapMaxSec + == expectedStats.satelliteConnectionGapMaxSec + && stats.rsrpAvg == expectedStats.rsrpAvg + && stats.rsrpMedian == expectedStats.rsrpMedian + && stats.rssnrAvg == expectedStats.rssnrAvg + && stats.rssnrMedian == expectedStats.rssnrMedian + && stats.countOfIncomingSms == expectedStats.countOfIncomingSms + && stats.countOfOutgoingSms == expectedStats.countOfOutgoingSms + && stats.countOfIncomingMms == expectedStats.countOfIncomingMms + && stats.countOfOutgoingMms == expectedStats.countOfOutgoingMms) { + actualCount++; + } + } + assertEquals(expectedCount, actualCount); + } + + private static void assertHasStats(CarrierRoamingSatelliteControllerStats[] tested, + @Nullable CarrierRoamingSatelliteControllerStats expectedStats) { + assertNotNull(tested); + assertEquals(tested[0].configDataSource, expectedStats.configDataSource); + assertEquals(tested[0].countOfEntitlementStatusQueryRequest, + expectedStats.countOfEntitlementStatusQueryRequest); + assertEquals(tested[0].countOfSatelliteConfigUpdateRequest, + expectedStats.countOfSatelliteConfigUpdateRequest); + assertEquals(tested[0].countOfSatelliteNotificationDisplayed, + expectedStats.countOfSatelliteNotificationDisplayed); + assertEquals(tested[0].satelliteSessionGapMinSec, expectedStats.satelliteSessionGapMinSec); + assertEquals(tested[0].satelliteSessionGapAvgSec, expectedStats.satelliteSessionGapAvgSec); + assertEquals(tested[0].satelliteSessionGapMaxSec, expectedStats.satelliteSessionGapMaxSec); + } + + private static void assertHasStatsAndCount( + SatelliteEntitlement[] tested, + @Nullable SatelliteEntitlement expectedStats, int expectedCount) { + assertNotNull(tested); + int actualCount = 0; + for (SatelliteEntitlement stats : tested) { + if (stats.carrierId == expectedStats.carrierId + && stats.result == expectedStats.result + && stats.entitlementStatus == expectedStats.entitlementStatus + && stats.isRetry == expectedStats.isRetry) { + actualCount = stats.count; + } + } + assertEquals(expectedCount, actualCount); + } + + private static void assertHasStatsAndCount( + SatelliteConfigUpdater[] tested, + @Nullable SatelliteConfigUpdater expectedStats, int expectedCount) { + assertNotNull(tested); + int actualCount = 0; + for (SatelliteConfigUpdater stats : tested) { + if (stats.configVersion == expectedStats.configVersion + && stats.oemConfigResult == expectedStats.oemConfigResult + && stats.carrierConfigResult == expectedStats.carrierConfigResult) { + actualCount = stats.count; + } + } + assertEquals(expectedCount, actualCount); + } } diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java index 9a84224c98..a7f1e01de6 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java @@ -24,7 +24,11 @@ import android.telephony.SatelliteProtoEnums; import android.telephony.TelephonyProtoEnums; import com.android.internal.telephony.TelephonyTest; +import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteControllerStats; +import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteSession; +import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteConfigUpdater; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteController; +import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteEntitlement; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteIncomingDatagram; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteOutgoingDatagram; import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteProvision; @@ -296,4 +300,136 @@ public class SatelliteStatsTest extends TelephonyTest { stats.isSatelliteAllowedInCurrentLocation); verifyNoMoreInteractions(mPersistAtomsStorage); } + + @Test + public void onCarrierRoamingSatelliteSessionMetrics_withAtoms() throws Exception { + SatelliteStats.CarrierRoamingSatelliteSessionParams param = + new SatelliteStats.CarrierRoamingSatelliteSessionParams.Builder() + .setCarrierId(100) + .setIsNtnRoamingInHomeCountry(true) + .setTotalSatelliteModeTimeSec(10 * 60) + .setNumberOfSatelliteConnections(5) + .setAvgDurationOfSatelliteConnectionSec(2 * 60) + .setSatelliteConnectionGapMinSec(30) + .setSatelliteConnectionGapAvgSec(300) + .setSatelliteConnectionGapMaxSec(500) + .setRsrpAvg(2) + .setRsrpMedian(3) + .setRssnrAvg(12) + .setRssnrMedian(18) + .setCountOfIncomingSms(6) + .setCountOfOutgoingSms(11) + .setCountOfIncomingMms(9) + .setCountOfOutgoingMms(14) + .build(); + + mSatelliteStats.onCarrierRoamingSatelliteSessionMetrics(param); + + ArgumentCaptor<CarrierRoamingSatelliteSession> captor = + ArgumentCaptor.forClass(CarrierRoamingSatelliteSession.class); + verify(mPersistAtomsStorage).addCarrierRoamingSatelliteSessionStats(captor.capture()); + CarrierRoamingSatelliteSession stats = captor.getValue(); + assertEquals(param.getCarrierId(), stats.carrierId); + assertEquals(param.getIsNtnRoamingInHomeCountry(), stats.isNtnRoamingInHomeCountry); + assertEquals(param.getTotalSatelliteModeTimeSec(), stats.totalSatelliteModeTimeSec); + assertEquals(param.getNumberOfSatelliteConnections(), stats.numberOfSatelliteConnections); + assertEquals(param.getAvgDurationOfSatelliteConnectionSec(), + stats.avgDurationOfSatelliteConnectionSec); + assertEquals(param.getSatelliteConnectionGapMinSec(), stats.satelliteConnectionGapMinSec); + assertEquals(param.getSatelliteConnectionGapAvgSec(), stats.satelliteConnectionGapAvgSec); + assertEquals(param.getSatelliteConnectionGapMaxSec(), stats.satelliteConnectionGapMaxSec); + assertEquals(param.getRsrpAvg(), stats.rsrpAvg); + assertEquals(param.getRsrpMedian(), stats.rsrpMedian); + assertEquals(param.getRssnrAvg(), stats.rssnrAvg); + assertEquals(param.getRssnrMedian(), stats.rssnrMedian); + assertEquals(param.getCountOfIncomingSms(), stats.countOfIncomingSms); + assertEquals(param.getCountOfOutgoingSms(), stats.countOfOutgoingSms); + assertEquals(param.getCountOfIncomingMms(), stats.countOfIncomingMms); + assertEquals(param.getCountOfOutgoingMms(), stats.countOfOutgoingMms); + + verifyNoMoreInteractions(mPersistAtomsStorage); + } + + @Test + public void onCarrierRoamingSatelliteControllerStatsMetrics_withAtoms() throws Exception { + SatelliteStats.CarrierRoamingSatelliteControllerStatsParams param = + new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder() + .setConfigDataSource(4) + .setCountOfEntitlementStatusQueryRequest(6) + .setCountOfSatelliteConfigUpdateRequest(2) + .setCountOfSatelliteNotificationDisplayed(1) + .setSatelliteSessionGapMinSec(15) + .setSatelliteSessionGapAvgSec(30) + .setSatelliteSessionGapMaxSec(45) + .build(); + + mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(param); + + ArgumentCaptor<CarrierRoamingSatelliteControllerStats> captor = + ArgumentCaptor.forClass(CarrierRoamingSatelliteControllerStats.class); + verify(mPersistAtomsStorage).addCarrierRoamingSatelliteControllerStats(captor.capture()); + CarrierRoamingSatelliteControllerStats stats = captor.getValue(); + assertEquals(param.getConfigDataSource(), stats.configDataSource); + assertEquals(param.getCountOfEntitlementStatusQueryRequest(), + stats.countOfEntitlementStatusQueryRequest); + assertEquals(param.getCountOfSatelliteConfigUpdateRequest(), + stats.countOfSatelliteConfigUpdateRequest); + assertEquals(param.getCountOfSatelliteNotificationDisplayed(), + stats.countOfSatelliteNotificationDisplayed); + assertEquals(param.getSatelliteSessionGapMinSec(), stats.satelliteSessionGapMinSec); + assertEquals(param.getSatelliteSessionGapAvgSec(), stats.satelliteSessionGapAvgSec); + assertEquals(param.getSatelliteSessionGapMaxSec(), stats.satelliteSessionGapMaxSec); + + verifyNoMoreInteractions(mPersistAtomsStorage); + } + + @Test + public void onSatelliteEntitlementMetrics_withAtoms() throws Exception { + SatelliteStats.SatelliteEntitlementParams param = + new SatelliteStats.SatelliteEntitlementParams.Builder() + .setCarrierId(10) + .setResult(500) + .setEntitlementStatus(2) + .setIsRetry(true) + .setCount(5) + .build(); + + mSatelliteStats.onSatelliteEntitlementMetrics(param); + + ArgumentCaptor<SatelliteEntitlement> captor = + ArgumentCaptor.forClass(SatelliteEntitlement.class); + verify(mPersistAtomsStorage).addSatelliteEntitlementStats(captor.capture()); + SatelliteEntitlement stats = captor.getValue(); + assertEquals(param.getCarrierId(), stats.carrierId); + assertEquals(param.getResult(), stats.result); + assertEquals(param.getEntitlementStatus(), stats.entitlementStatus); + assertEquals(param.getIsRetry(), stats.isRetry); + assertEquals(param.getCount(), stats.count); + + verifyNoMoreInteractions(mPersistAtomsStorage); + } + + @Test + public void onSatelliteConfigUpdaterMetrics_withAtoms() throws Exception { + SatelliteStats.SatelliteConfigUpdaterParams param = + new SatelliteStats.SatelliteConfigUpdaterParams.Builder() + .setConfigVersion(8) + .setOemConfigResult(9) + .setCarrierConfigResult(7) + .setCount(3) + .build(); + + mSatelliteStats.onSatelliteConfigUpdaterMetrics(param); + + ArgumentCaptor<SatelliteConfigUpdater> captor = + ArgumentCaptor.forClass(SatelliteConfigUpdater.class); + verify(mPersistAtomsStorage).addSatelliteConfigUpdaterStats(captor.capture()); + SatelliteConfigUpdater stats = captor.getValue(); + assertEquals(param.getConfigVersion(), stats.configVersion); + assertEquals(param.getOemConfigResult(), stats.oemConfigResult); + assertEquals(param.getCarrierConfigResult(), stats.carrierConfigResult); + assertEquals(param.getCount(), stats.count); + + verifyNoMoreInteractions(mPersistAtomsStorage); + } } |