diff options
87 files changed, 6779 insertions, 1852 deletions
diff --git a/flags/calling.aconfig b/flags/calling.aconfig index f12116915a..c1dc7e7a5f 100644 --- a/flags/calling.aconfig +++ b/flags/calling.aconfig @@ -17,4 +17,15 @@ flag { namespace: "telephony" description: "Used in DisconnectCause and TelephonyConnection if a non-emergency call fails on a device with no 2G, to guard whether a user can see an updated error message reminding the 2G is disabled and potentially disrupting their call connectivity" bug: "300142897" -}
\ No newline at end of file +} + +# OWNER=stevestatia TARGET=24Q4 +flag { + name: "remove_country_code_from_local_singapore_calls" + namespace: "telephony" + description: "Fix bug where the country code is being shown when merging in local Singapore numbers to conference calls." + bug:"284416645" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/flags/data.aconfig b/flags/data.aconfig index f93999b4b5..d956104784 100644 --- a/flags/data.aconfig +++ b/flags/data.aconfig @@ -25,10 +25,13 @@ flag { # OWNER=linggm TARGET=24Q3 flag { - name: "auto_data_switch_rat_ss" + name: "auto_data_switch_uses_data_enabled" namespace: "telephony" - description: "Whether switch for better rat and signal strength" - bug:"260928808" + description: "Separately consider the backup phone's data allowed and data enabled." + bug: "338552223" + metadata { + purpose: PURPOSE_BUGFIX + } } # OWNER=linggm TARGET=24Q2 diff --git a/flags/messaging.aconfig b/flags/messaging.aconfig index 364d6aaf8f..1030ba7c4f 100644 --- a/flags/messaging.aconfig +++ b/flags/messaging.aconfig @@ -27,4 +27,15 @@ flag { metadata { purpose: PURPOSE_BUGFIX } +} + +# OWNER=stevestatia TARGET=24Q3 +flag { + name: "unregister_sms_broadcast_receiver_from_cat_service" + namespace: "telephony" + description: "This flag will unregister the sms broadcast receiver in the CatService when the process is disposed." + bug: "338936403" + metadata { + purpose: PURPOSE_BUGFIX + } }
\ No newline at end of file diff --git a/flags/misc.aconfig b/flags/misc.aconfig index 6e9db00739..9d5cbd69be 100644 --- a/flags/misc.aconfig +++ b/flags/misc.aconfig @@ -1,6 +1,17 @@ package: "com.android.internal.telephony.flags" container: "system" +# OWNER=linggm TARGET=24Q3 +flag { + name: "combine_ril_death_handle" + namespace: "telephony" + description: "Upon radio service death, combine its handling to prevent race condition" + bug:"319612362" + metadata { + purpose: PURPOSE_BUGFIX + } +} + # OWNER=tjstuart TARGET=24Q3 flag { name: "do_not_override_precise_label" diff --git a/flags/subscription.aconfig b/flags/subscription.aconfig index 32e8f2df52..9a5dabc49d 100644 --- a/flags/subscription.aconfig +++ b/flags/subscription.aconfig @@ -65,3 +65,15 @@ flag { purpose: PURPOSE_BUGFIX } } + +# OWNER=songferngwang TARGET=24Q3 +flag { + name: "reset_primary_sim_default_values" + namespace: "telephony" + description: "Reset the default values to the remaining sim" + bug: "339394518" + + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/flags/uicc.aconfig b/flags/uicc.aconfig index 2d7b643cdf..2679cfe67f 100644 --- a/flags/uicc.aconfig +++ b/flags/uicc.aconfig @@ -17,7 +17,7 @@ flag { bug:"303780982" } -# OWNER=arunvoddu TARGET=24Q3 +# OWNER=arunvoddu TARGET=24Q4 flag { name: "carrier_restriction_status" is_exported: true @@ -50,3 +50,11 @@ flag { description: "This flag cleans up the OpenLogicalChannelRecord once SIM is removed" bug:"335046531" } + +# OWNER=arunvoddu TARGET=24Q4 +flag { + name: "set_carrier_restriction_status" + namespace: "telephony" + description: "This flag controls the visibility of the setCarrierRestrictionStatus API in carrierRestrictionRules class." + bug:"342411308" +} diff --git a/proto/src/persist_atoms.proto b/proto/src/persist_atoms.proto index fb1e9c2d0d..a7d523ca19 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: @@ -384,6 +408,7 @@ message DataCallSession { optional bool is_iwlan_cross_sim = 23; optional bool is_ntn = 24; optional bool is_satellite_transport = 25; + optional bool is_provisioning_profile = 26; } message CellularServiceState { @@ -697,6 +722,7 @@ message SatelliteSession { optional int32 count_of_incoming_datagram_success = 10; optional int32 count_of_incoming_datagram_failed = 11; optional bool is_demo_mode = 12; + optional int32 max_ntn_signal_strength_level = 13; } message SatelliteIncomingDatagram { @@ -741,3 +767,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/GsmCdmaCallTracker.java b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java index 9113514c75..26d4e1b84e 100644 --- a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java +++ b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java @@ -160,7 +160,7 @@ public class GsmCdmaCallTracker extends CallTracker { public GsmCdmaCallTracker(GsmCdmaPhone phone, FeatureFlags featureFlags) { super(featureFlags); - if (mFeatureFlags.minimalTelephonyCdmCheck() + if (TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags) && !phone.getContext().getPackageManager().hasSystemFeature( PackageManager.FEATURE_TELEPHONY_CALLING)) { throw new UnsupportedOperationException("GsmCdmaCallTracker requires calling"); diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java index c4d9a1740f..93a0c2fd35 100644 --- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java +++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java @@ -470,7 +470,7 @@ public class GsmCdmaPhone extends Phone { }; private boolean hasCalling() { - if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true; + if (!TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)) return true; return mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_TELEPHONY_CALLING); } @@ -3039,12 +3039,12 @@ public class GsmCdmaPhone extends Phone { @Override public void registerForCallWaiting(Handler h, int what, Object obj) { - mCT.registerForCallWaiting(h, what, obj); + if (mCT != null) mCT.registerForCallWaiting(h, what, obj); } @Override public void unregisterForCallWaiting(Handler h) { - mCT.unregisterForCallWaiting(h); + if (mCT != null) mCT.unregisterForCallWaiting(h); } /** diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java index eafb4ba038..03d56ed9af 100644 --- a/src/java/com/android/internal/telephony/InboundSmsHandler.java +++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java @@ -74,6 +74,7 @@ import com.android.internal.telephony.SmsConstants.MessageClass; import com.android.internal.telephony.analytics.TelephonyAnalytics; import com.android.internal.telephony.analytics.TelephonyAnalytics.SmsMmsAnalytics; import com.android.internal.telephony.metrics.TelephonyMetrics; +import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteSessionStats; import com.android.internal.telephony.util.NotificationChannelController; import com.android.internal.telephony.util.TelephonyUtils; import com.android.internal.util.HexDump; @@ -1104,6 +1105,9 @@ public abstract class InboundSmsHandler extends StateMachine { format, timestamps, block, tracker.getMessageId()); mPhone.getSmsStats().onIncomingSmsSuccess(is3gpp2(), tracker.getSource(), messageCount, block, tracker.getMessageId()); + CarrierRoamingSatelliteSessionStats sessionStats = + CarrierRoamingSatelliteSessionStats.getInstance(mPhone.getSubId()); + sessionStats.onIncomingSms(); if (mPhone != null) { TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics(); if (telephonyAnalytics != null) { diff --git a/src/java/com/android/internal/telephony/MultiSimSettingController.java b/src/java/com/android/internal/telephony/MultiSimSettingController.java index 83d58af7ed..a14ae89073 100644 --- a/src/java/com/android/internal/telephony/MultiSimSettingController.java +++ b/src/java/com/android/internal/telephony/MultiSimSettingController.java @@ -255,19 +255,19 @@ public class MultiSimSettingController extends Handler { } private boolean hasCalling() { - if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true; + if (!TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)) return true; return mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_TELEPHONY_CALLING); } private boolean hasData() { - if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true; + if (!TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)) return true; return mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_TELEPHONY_DATA); } private boolean hasMessaging() { - if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true; + if (!TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)) return true; return mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_TELEPHONY_MESSAGING); } @@ -645,8 +645,11 @@ public class MultiSimSettingController extends Handler { // Otherwise, if user just inserted their first SIM, or there's one primary and one // opportunistic subscription active (activeSubInfos.size() > 1), we automatically // set the primary to be default SIM and return. - if (mPrimarySubList.size() == 1 && (change != PRIMARY_SUB_REMOVED - || mActiveModemCount == 1)) { + boolean conditionForOnePrimarySim = + mFeatureFlags.resetPrimarySimDefaultValues() ? mPrimarySubList.size() == 1 + : mPrimarySubList.size() == 1 + && (change != PRIMARY_SUB_REMOVED || mActiveModemCount == 1); + if (conditionForOnePrimarySim) { int subId = mPrimarySubList.get(0); if (DBG) log("updateDefaultValues: to only primary sub " + subId); if (hasData()) mSubscriptionManagerService.setDefaultDataSubId(subId); diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java index 324e88142f..a9e21a3083 100644 --- a/src/java/com/android/internal/telephony/Phone.java +++ b/src/java/com/android/internal/telephony/Phone.java @@ -4915,15 +4915,15 @@ public abstract class Phone extends Handler implements PhoneInternalInterface { /** * @return The data network controller */ - public @Nullable DataNetworkController getDataNetworkController() { + public @NonNull DataNetworkController getDataNetworkController() { return mDataNetworkController; } /** * @return The data settings manager */ - public @Nullable DataSettingsManager getDataSettingsManager() { - if (mDataNetworkController == null) return null; + @NonNull + public DataSettingsManager getDataSettingsManager() { return mDataNetworkController.getDataSettingsManager(); } diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java index 803fb19185..d9c5c9cbd0 100644 --- a/src/java/com/android/internal/telephony/PhoneFactory.java +++ b/src/java/com/android/internal/telephony/PhoneFactory.java @@ -187,7 +187,7 @@ public class PhoneFactory { Rlog.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkModes[i])); sCommandsInterfaces[i] = new RIL(context, RadioAccessFamily.getRafFromNetworkType(networkModes[i]), - cdmaSubscription, i); + cdmaSubscription, i, featureFlags); } if (numPhones > 0) { @@ -312,7 +312,7 @@ public class PhoneFactory { for (int i = prevActiveModemCount; i < activeModemCount; i++) { sCommandsInterfaces[i] = new RIL(context, RadioAccessFamily.getRafFromNetworkType( RILConstants.PREFERRED_NETWORK_MODE), - cdmaSubscription, i); + cdmaSubscription, i, sFeatureFlags); sPhones[i] = createPhone(context, i); if (context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_TELEPHONY_IMS)) { diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java index 9cf5afb749..8abebe2ec6 100644 --- a/src/java/com/android/internal/telephony/RIL.java +++ b/src/java/com/android/internal/telephony/RIL.java @@ -88,6 +88,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.cdma.CdmaInformationRecords; import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo; import com.android.internal.telephony.emergency.EmergencyConstants; +import com.android.internal.telephony.flags.FeatureFlags; import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; import com.android.internal.telephony.imsphone.ImsCallInfo; import com.android.internal.telephony.metrics.ModemRestartStats; @@ -221,6 +222,8 @@ public class RIL extends BaseCommands implements CommandsInterface { public static final int MAX_SERVICE_IDX = HAL_SERVICE_IMS; + @NonNull private final FeatureFlags mFeatureFlags; + /** * An array of sets that records if services are disabled in the HAL for a specific phone ID * slot to avoid further getService requests for that service. See XXX_SERVICE for the indices. @@ -384,12 +387,27 @@ public class RIL extends BaseCommands implements CommandsInterface { case EVENT_AIDL_PROXY_DEAD: int aidlService = msg.arg1; long msgCookie = (long) msg.obj; - riljLog("handleMessage: EVENT_AIDL_PROXY_DEAD cookie = " + msgCookie - + ", service = " + serviceToString(aidlService) + ", cookie = " - + mServiceCookies.get(aidlService)); - if (msgCookie == mServiceCookies.get(aidlService).get()) { - mIsRadioProxyInitialized = false; - resetProxyAndRequestList(aidlService); + if (mFeatureFlags.combineRilDeathHandle()) { + if (msgCookie == mServiceCookies.get(aidlService).get()) { + riljLog("handleMessage: EVENT_AIDL_PROXY_DEAD cookie = " + msgCookie + + ", service = " + serviceToString(aidlService) + ", cookie = " + + mServiceCookies.get(aidlService)); + mIsRadioProxyInitialized = false; + resetProxyAndRequestList(aidlService); + // Remove duplicate death message to avoid duplicate reset. + mRilHandler.removeMessages(EVENT_AIDL_PROXY_DEAD); + } else { + riljLog("Ignore stale EVENT_AIDL_PROXY_DEAD for service " + + serviceToString(aidlService)); + } + } else { + riljLog("handleMessage: EVENT_AIDL_PROXY_DEAD cookie = " + msgCookie + + ", service = " + serviceToString(aidlService) + ", cookie = " + + mServiceCookies.get(aidlService)); + if (msgCookie == mServiceCookies.get(aidlService).get()) { + mIsRadioProxyInitialized = false; + resetProxyAndRequestList(aidlService); + } } break; } @@ -434,24 +452,33 @@ public class RIL extends BaseCommands implements CommandsInterface { public void serviceDied(long cookie) { // Deal with service going away riljLog("serviceDied"); - mRilHandler.sendMessage(mRilHandler.obtainMessage(EVENT_RADIO_PROXY_DEAD, - HAL_SERVICE_RADIO, 0 /* ignored arg2 */, cookie)); + if (mFeatureFlags.combineRilDeathHandle()) { + mRilHandler.sendMessageAtFrontOfQueue(mRilHandler.obtainMessage( + EVENT_RADIO_PROXY_DEAD, + HAL_SERVICE_RADIO, 0 /* ignored arg2 */, cookie)); + } else { + mRilHandler.sendMessage(mRilHandler.obtainMessage(EVENT_RADIO_PROXY_DEAD, + HAL_SERVICE_RADIO, 0 /* ignored arg2 */, cookie)); + } } } private final class BinderServiceDeathRecipient implements IBinder.DeathRecipient { private IBinder mBinder; private final int mService; + private long mLinkedFlags; BinderServiceDeathRecipient(int service) { mService = service; + mLinkedFlags = 0; } public void linkToDeath(IBinder service) throws RemoteException { if (service != null) { riljLog("Linked to death for service " + serviceToString(mService)); mBinder = service; - mBinder.linkToDeath(this, (int) mServiceCookies.get(mService).incrementAndGet()); + mLinkedFlags = mServiceCookies.get(mService).incrementAndGet(); + mBinder.linkToDeath(this, (int) mLinkedFlags); } else { riljLoge("Unable to link to death for service " + serviceToString(mService)); } @@ -459,32 +486,58 @@ public class RIL extends BaseCommands implements CommandsInterface { public synchronized void unlinkToDeath() { if (mBinder != null) { - mBinder.unlinkToDeath(this, 0); + mBinder.unlinkToDeath(this, (int) mLinkedFlags); mBinder = null; + mLinkedFlags = 0; } } @Override public void binderDied() { riljLog("Service " + serviceToString(mService) + " has died."); - mRilHandler.sendMessage(mRilHandler.obtainMessage(EVENT_AIDL_PROXY_DEAD, mService, - 0 /* ignored arg2 */, mServiceCookies.get(mService).get())); + if (mFeatureFlags.combineRilDeathHandle()) { + mRilHandler.sendMessageAtFrontOfQueue(mRilHandler.obtainMessage( + EVENT_AIDL_PROXY_DEAD, mService, 0 /* ignored arg2 */, + mLinkedFlags)); + } else { + mRilHandler.sendMessage(mRilHandler.obtainMessage(EVENT_AIDL_PROXY_DEAD, mService, + 0 /* ignored arg2 */, mLinkedFlags)); + } unlinkToDeath(); } } - private synchronized void resetProxyAndRequestList(int service) { + /** + * Reset services. If one of the AIDL service is reset, all the other AIDL services will be + * reset as well. + * @param service The service to reset. + */ + private synchronized void resetProxyAndRequestList(@HalService int service) { if (service == HAL_SERVICE_RADIO) { mRadioProxy = null; + // Increment the cookie so that death notification can be ignored + mServiceCookies.get(service).incrementAndGet(); } else { - mServiceProxies.get(service).clear(); + if (mFeatureFlags.combineRilDeathHandle()) { + // Reset all aidl services. + for (int i = MIN_SERVICE_IDX; i <= MAX_SERVICE_IDX; i++) { + if (i == HAL_SERVICE_RADIO) continue; + if (mServiceProxies.get(i) == null) { + // This should only happen in tests + riljLoge("Null service proxy for service " + serviceToString(i)); + continue; + } + mServiceProxies.get(i).clear(); + // Increment the cookie so that death notification can be ignored + mServiceCookies.get(i).incrementAndGet(); + } + } else { + mServiceProxies.get(service).clear(); + // Increment the cookie so that death notification can be ignored + mServiceCookies.get(service).incrementAndGet(); + } } - // Increment the cookie so that death notification can be ignored - mServiceCookies.get(service).incrementAndGet(); - - // TODO: If a service doesn't exist or is unimplemented, it shouldn't cause the radio to - // become unavailable for all other services setRadioState(TelephonyManager.RADIO_POWER_UNAVAILABLE, true /* forceNotifyRegistrants */); RILRequest.resetSerial(); @@ -494,7 +547,20 @@ public class RIL extends BaseCommands implements CommandsInterface { if (service == HAL_SERVICE_RADIO) { getRadioProxy(); } else { - getRadioServiceProxy(service); + if (mFeatureFlags.combineRilDeathHandle()) { + // Reset all aidl services. + for (int i = MIN_SERVICE_IDX; i <= MAX_SERVICE_IDX; i++) { + if (i == HAL_SERVICE_RADIO) continue; + if (mServiceProxies.get(i) == null) { + // This should only happen in tests + riljLoge("Null service proxy for service " + serviceToString(i)); + continue; + } + getRadioServiceProxy(i); + } + } else { + getRadioServiceProxy(service); + } } } @@ -512,10 +578,6 @@ public class RIL extends BaseCommands implements CommandsInterface { mMockModem = null; mMockModem = new MockModem(mContext, serviceName, mPhoneId); - if (mMockModem == null) { - riljLoge("MockModem create fail."); - return false; - } // Disable HIDL service if (mRadioProxy != null) { @@ -552,8 +614,14 @@ public class RIL extends BaseCommands implements CommandsInterface { if (serviceBound) { mIsRadioProxyInitialized = false; - for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) { - resetProxyAndRequestList(service); + if (mFeatureFlags.combineRilDeathHandle()) { + // Reset both hidl and aidl proxies. + resetProxyAndRequestList(HAL_SERVICE_RADIO); + resetProxyAndRequestList(HAL_SERVICE_DATA); + } else { + for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) { + resetProxyAndRequestList(service); + } } } } @@ -581,7 +649,15 @@ public class RIL extends BaseCommands implements CommandsInterface { mHalVersion.put(service, RADIO_HAL_VERSION_UNSUPPORTED); } } - resetProxyAndRequestList(service); + if (!mFeatureFlags.combineRilDeathHandle()) { + resetProxyAndRequestList(service); + } + } + if (mFeatureFlags.combineRilDeathHandle()) { + // Reset both hidl and aidl proxies. Must be after cleaning mocked halVersion, + // otherwise an aidl service will be incorrectly considered as disabled. + resetProxyAndRequestList(HAL_SERVICE_RADIO); + resetProxyAndRequestList(HAL_SERVICE_DATA); } } } @@ -739,9 +815,12 @@ public class RIL extends BaseCommands implements CommandsInterface { public synchronized RadioServiceProxy getRadioServiceProxy(int service) { if (!SubscriptionManager.isValidPhoneId(mPhoneId)) return mServiceProxies.get(service); if ((service >= HAL_SERVICE_IMS) && !isRadioServiceSupported(service)) { - riljLogw("getRadioServiceProxy: " + serviceToString(service) + " for " - + HIDL_SERVICE_NAME[mPhoneId] + " is not supported\n" - + android.util.Log.getStackTraceString(new RuntimeException())); + // Suppress the excessive logging for HAL_SERVICE_IMS when not supported. + if (service != HAL_SERVICE_IMS) { + riljLogw("getRadioServiceProxy: " + serviceToString(service) + " for " + + HIDL_SERVICE_NAME[mPhoneId] + " is not supported\n" + + android.util.Log.getStackTraceString(new RuntimeException())); + } return mServiceProxies.get(service); } if (!mIsCellularSupported) { @@ -990,16 +1069,33 @@ public class RIL extends BaseCommands implements CommandsInterface { @Override public synchronized void onSlotActiveStatusChange(boolean active) { mIsRadioProxyInitialized = false; - for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) { + if (mFeatureFlags.combineRilDeathHandle()) { if (active) { - // Try to connect to RIL services and set response functions. - if (service == HAL_SERVICE_RADIO) { - getRadioProxy(); - } else { - getRadioServiceProxy(service); + for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) { + // Try to connect to RIL services and set response functions. + if (service == HAL_SERVICE_RADIO) { + getRadioProxy(); + } else { + getRadioServiceProxy(service); + } } } else { - resetProxyAndRequestList(service); + // Reset both hidl and aidl proxies + resetProxyAndRequestList(HAL_SERVICE_RADIO); + resetProxyAndRequestList(HAL_SERVICE_DATA); + } + } else { + for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) { + if (active) { + // Try to connect to RIL services and set response functions. + if (service == HAL_SERVICE_RADIO) { + getRadioProxy(); + } else { + getRadioServiceProxy(service); + } + } else { + resetProxyAndRequestList(service); + } } } } @@ -1007,19 +1103,16 @@ public class RIL extends BaseCommands implements CommandsInterface { //***** Constructors @UnsupportedAppUsage - public RIL(Context context, int allowedNetworkTypes, int cdmaSubscription) { - this(context, allowedNetworkTypes, cdmaSubscription, null); - } - - @UnsupportedAppUsage - public RIL(Context context, int allowedNetworkTypes, int cdmaSubscription, Integer instanceId) { - this(context, allowedNetworkTypes, cdmaSubscription, instanceId, null); + public RIL(Context context, int allowedNetworkTypes, int cdmaSubscription, Integer instanceId, + @NonNull FeatureFlags flags) { + this(context, allowedNetworkTypes, cdmaSubscription, instanceId, null, flags); } @VisibleForTesting public RIL(Context context, int allowedNetworkTypes, int cdmaSubscription, Integer instanceId, - SparseArray<RadioServiceProxy> proxies) { + SparseArray<RadioServiceProxy> proxies, @NonNull FeatureFlags flags) { super(context); + mFeatureFlags = flags; if (RILJ_LOGD) { riljLog("RIL: init allowedNetworkTypes=" + allowedNetworkTypes + " cdmaSubscription=" + cdmaSubscription + ")"); @@ -1295,23 +1388,22 @@ public class RIL extends BaseCommands implements CommandsInterface { } else if (proxy instanceof RadioImsProxy) { service = HAL_SERVICE_IMS; } - - if (mHalVersion.get(service).less(version)) { - riljLoge(String.format("%s not supported on service %s < %s.", - request, serviceToString(service), version)); + if (proxy == null || proxy.isEmpty()) { + riljLoge(String.format("Unable to complete %s because service %s is not available.", + request, serviceToString(service))); if (result != null) { AsyncResult.forMessage(result, null, - CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED)); + CommandException.fromRilErrno(RADIO_NOT_AVAILABLE)); result.sendToTarget(); } return false; } - if (proxy == null || proxy.isEmpty()) { - riljLoge(String.format("Unable to complete %s because service %s is not available.", - request, serviceToString(service))); + if (mHalVersion.get(service).less(version)) { + riljLoge(String.format("%s not supported on service %s < %s.", + request, serviceToString(service), version)); if (result != null) { AsyncResult.forMessage(result, null, - CommandException.fromRilErrno(RADIO_NOT_AVAILABLE)); + CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED)); result.sendToTarget(); } return false; diff --git a/src/java/com/android/internal/telephony/SMSDispatcher.java b/src/java/com/android/internal/telephony/SMSDispatcher.java index 8764e02edc..70bddd1af6 100644 --- a/src/java/com/android/internal/telephony/SMSDispatcher.java +++ b/src/java/com/android/internal/telephony/SMSDispatcher.java @@ -89,6 +89,7 @@ import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails; import com.android.internal.telephony.analytics.TelephonyAnalytics; import com.android.internal.telephony.analytics.TelephonyAnalytics.SmsMmsAnalytics; import com.android.internal.telephony.cdma.sms.UserData; +import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteSessionStats; import com.android.internal.telephony.subscription.SubscriptionInfoInternal; import com.android.internal.telephony.subscription.SubscriptionManagerService; import com.android.internal.telephony.uicc.IccRecords; @@ -1066,6 +1067,9 @@ public abstract class SMSDispatcher extends Handler { tracker.isFromDefaultSmsApplication(mContext), tracker.getInterval(), mTelephonyManager.isEmergencyNumber(tracker.mDestAddress)); + CarrierRoamingSatelliteSessionStats sessionStats = + CarrierRoamingSatelliteSessionStats.getInstance(mPhone.getSubId()); + sessionStats.onOutgoingSms(); if (mPhone != null) { TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics(); if (telephonyAnalytics != null) { diff --git a/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java b/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java index 0a14ccd60d..0b427f8aa2 100644 --- a/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java +++ b/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java @@ -494,7 +494,7 @@ public class SimultaneousCallingTracker { l.onSimultaneousCallingSupportChanged(simultaneousCallSubscriptionIdMap); } } catch (Exception e) { - Log.w(LOG_TAG, "handleVideoCapabilitiesChanged: Exception = " + e); + Log.w(LOG_TAG, "handleSimultaneousCallingSupportChanged: Exception = " + e); } } diff --git a/src/java/com/android/internal/telephony/SmsController.java b/src/java/com/android/internal/telephony/SmsController.java index 32c7429335..59184d8ed1 100644 --- a/src/java/com/android/internal/telephony/SmsController.java +++ b/src/java/com/android/internal/telephony/SmsController.java @@ -302,16 +302,17 @@ public class SmsController extends ISmsImplBase { SubscriptionInfo info; try { info = getSubscriptionInfo(subId); + + if (isBluetoothSubscription(info)) { + sendBluetoothText(info, destAddr, text, sentIntent, deliveryIntent); + } else { + sendIccText(subId, callingPackage, destAddr, scAddr, text, sentIntent, + deliveryIntent, persistMessageForNonDefaultSmsApp, messageId, + skipShortCodeCheck); + } } finally { Binder.restoreCallingIdentity(token); } - - if (isBluetoothSubscription(info)) { - sendBluetoothText(info, destAddr, text, sentIntent, deliveryIntent); - } else { - sendIccText(subId, callingPackage, destAddr, scAddr, text, sentIntent, deliveryIntent, - persistMessageForNonDefaultSmsApp, messageId, skipShortCodeCheck); - } } private boolean isBluetoothSubscription(SubscriptionInfo info) { diff --git a/src/java/com/android/internal/telephony/SmsDispatchersController.java b/src/java/com/android/internal/telephony/SmsDispatchersController.java index 136e997218..bc1e1a8b3d 100644 --- a/src/java/com/android/internal/telephony/SmsDispatchersController.java +++ b/src/java/com/android/internal/telephony/SmsDispatchersController.java @@ -781,22 +781,16 @@ public class SmsDispatchersController extends Handler { if (isSmsDomainSelectionEnabled()) { TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); boolean isEmergency = tm.isEmergencyNumber(tracker.mDestAddress); - DomainSelectionConnectionHolder holder = getDomainSelectionConnection(isEmergency); - - // If the DomainSelectionConnection is not available, - // fallback to the legacy implementation. - if (holder != null && holder.getConnection() != null) { - // This may be invoked by another thread, so this operation is posted and - // handled through the execution flow of SmsDispatchersController. - SomeArgs args = SomeArgs.obtain(); - args.arg1 = holder; - args.arg2 = new PendingRequest(PendingRequest.TYPE_RETRY_SMS, tracker, - null, null, null, null, null, false, null, 0, null, null, false, - 0, false, 0, 0L, false); - args.arg3 = "sendRetrySms"; - sendMessage(obtainMessage(EVENT_REQUEST_DOMAIN_SELECTION, args)); - return; - } + // This may be invoked by another thread, so this operation is posted and + // handled through the execution flow of SmsDispatchersController. + SomeArgs args = SomeArgs.obtain(); + args.arg1 = getDomainSelectionConnectionHolder(isEmergency); + args.arg2 = new PendingRequest(PendingRequest.TYPE_RETRY_SMS, tracker, + null, null, null, null, null, false, null, 0, null, null, false, + 0, false, 0, 0L, false); + args.arg3 = "sendRetrySms"; + sendMessage(obtainMessage(EVENT_REQUEST_DOMAIN_SELECTION, args)); + return; } if (mImsSmsDispatcher.isAvailable()) { @@ -1007,52 +1001,23 @@ public class SmsDispatchersController extends Handler { * Returns a {@link DomainSelectionConnectionHolder} according to the flag specified. * * @param emergency The flag to indicate that the domain selection is for an emergency SMS. - * @return A {@link DomainSelectionConnectionHolder} instance or null. + * @return A {@link DomainSelectionConnectionHolder} instance. */ @VisibleForTesting @Nullable protected DomainSelectionConnectionHolder getDomainSelectionConnectionHolder( boolean emergency) { - return emergency ? mEmergencyDscHolder : mDscHolder; - } - - /** - * Returns a {@link DomainSelectionConnectionHolder} if the domain selection supports, - * return null otherwise. - * - * @param emergency The flag to indicate that the domain selection is for an emergency SMS. - * @return A {@link DomainSelectionConnectionHolder} that grabs the - * {@link DomainSelectionConnection} and its related information to use the domain - * selection architecture. - */ - private DomainSelectionConnectionHolder getDomainSelectionConnection(boolean emergency) { - DomainSelectionConnectionHolder holder = getDomainSelectionConnectionHolder(emergency); - DomainSelectionConnection connection = (holder != null) ? holder.getConnection() : null; - - if (connection == null) { - connection = mDomainSelectionResolverProxy.getDomainSelectionConnection( - mPhone, DomainSelectionService.SELECTOR_TYPE_SMS, emergency); - - if (connection == null) { - // Domain selection architecture is not supported. - // Use the legacy architecture. - return null; + if (emergency) { + if (mEmergencyDscHolder == null) { + mEmergencyDscHolder = new DomainSelectionConnectionHolder(emergency); } - } - - if (holder == null) { - holder = new DomainSelectionConnectionHolder(emergency); - - if (emergency) { - mEmergencyDscHolder = holder; - } else { - mDscHolder = holder; + return mEmergencyDscHolder; + } else { + if (mDscHolder == null) { + mDscHolder = new DomainSelectionConnectionHolder(emergency); } + return mDscHolder; } - - holder.setConnection(connection); - - return holder; } /** @@ -1102,6 +1067,8 @@ public class SmsDispatchersController extends Handler { * * @param holder The {@link DomainSelectionConnectionHolder} that contains the * {@link DomainSelectionConnection} and its related information. + * @param request The {@link PendingRequest} that stores the SMS request + * (data, text, multipart text) to be sent. * @param logTag The log string. */ private void requestDomainSelection(@NonNull DomainSelectionConnectionHolder holder, @@ -1111,6 +1078,21 @@ public class SmsDispatchersController extends Handler { // the domain selection by adding this request to the pending list. holder.addRequest(request); + if (holder.getConnection() == null) { + DomainSelectionConnection connection = + mDomainSelectionResolverProxy.getDomainSelectionConnection( + mPhone, DomainSelectionService.SELECTOR_TYPE_SMS, holder.isEmergency()); + if (connection == null) { + logd("requestDomainSelection: fallback for " + logTag); + // If the domain selection connection is not available, + // fallback to the legacy implementation. + sendAllPendingRequests(holder, NetworkRegistrationInfo.DOMAIN_UNKNOWN); + return; + } else { + holder.setConnection(connection); + } + } + if (!isDomainSelectionRequested) { if (VDBG) { logd("requestDomainSelection: " + logTag); @@ -1571,19 +1553,13 @@ public class SmsDispatchersController extends Handler { } if (isSmsDomainSelectionEnabled()) { - DomainSelectionConnectionHolder holder = getDomainSelectionConnection(false); - - // If the DomainSelectionConnection is not available, - // fallback to the legacy implementation. - if (holder != null && holder.getConnection() != null) { - sendSmsUsingDomainSelection(holder, - new PendingRequest(PendingRequest.TYPE_DATA, null, callingPackage, - destAddr, scAddr, asArrayList(sentIntent), - asArrayList(deliveryIntent), isForVvm, data, destPort, null, null, - false, 0, false, 0, 0L, false), - "sendData"); - return; - } + sendSmsUsingDomainSelection(getDomainSelectionConnectionHolder(false), + new PendingRequest(PendingRequest.TYPE_DATA, null, callingPackage, + destAddr, scAddr, asArrayList(sentIntent), + asArrayList(deliveryIntent), isForVvm, data, destPort, null, null, + false, 0, false, 0, 0L, false), + "sendData"); + return; } if (mImsSmsDispatcher.isAvailable()) { @@ -1812,20 +1788,14 @@ public class SmsDispatchersController extends Handler { if (isSmsDomainSelectionEnabled()) { TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); boolean isEmergency = tm.isEmergencyNumber(destAddr); - DomainSelectionConnectionHolder holder = getDomainSelectionConnection(isEmergency); - - // If the DomainSelectionConnection is not available, - // fallback to the legacy implementation. - if (holder != null && holder.getConnection() != null) { - sendSmsUsingDomainSelection(holder, - new PendingRequest(PendingRequest.TYPE_TEXT, null, callingPkg, - destAddr, scAddr, asArrayList(sentIntent), - asArrayList(deliveryIntent), isForVvm, null, 0, asArrayList(text), - messageUri, persistMessage, priority, expectMore, validityPeriod, - messageId, skipShortCodeCheck), - "sendText"); - return; - } + sendSmsUsingDomainSelection(getDomainSelectionConnectionHolder(isEmergency), + new PendingRequest(PendingRequest.TYPE_TEXT, null, callingPkg, + destAddr, scAddr, asArrayList(sentIntent), + asArrayList(deliveryIntent), isForVvm, null, 0, asArrayList(text), + messageUri, persistMessage, priority, expectMore, validityPeriod, + messageId, skipShortCodeCheck), + "sendText"); + return; } if (mImsSmsDispatcher.isAvailable() || mImsSmsDispatcher.isEmergencySmsSupport(destAddr)) { @@ -1961,19 +1931,13 @@ public class SmsDispatchersController extends Handler { if (isSmsDomainSelectionEnabled()) { TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); boolean isEmergency = tm.isEmergencyNumber(destAddr); - DomainSelectionConnectionHolder holder = getDomainSelectionConnection(isEmergency); - - // If the DomainSelectionConnection is not available, - // fallback to the legacy implementation. - if (holder != null && holder.getConnection() != null) { - sendSmsUsingDomainSelection(holder, - new PendingRequest(PendingRequest.TYPE_MULTIPART_TEXT, null, - callingPkg, destAddr, scAddr, sentIntents, deliveryIntents, false, - null, 0, parts, messageUri, persistMessage, priority, expectMore, - validityPeriod, messageId, false), - "sendMultipartText"); - return; - } + sendSmsUsingDomainSelection(getDomainSelectionConnectionHolder(isEmergency), + new PendingRequest(PendingRequest.TYPE_MULTIPART_TEXT, null, + callingPkg, destAddr, scAddr, sentIntents, deliveryIntents, false, + null, 0, parts, messageUri, persistMessage, priority, expectMore, + validityPeriod, messageId, false), + "sendMultipartText"); + return; } if (mImsSmsDispatcher.isAvailable()) { diff --git a/src/java/com/android/internal/telephony/TelephonyCapabilities.java b/src/java/com/android/internal/telephony/TelephonyCapabilities.java index 1b4a3a93e5..71d3b143b2 100644 --- a/src/java/com/android/internal/telephony/TelephonyCapabilities.java +++ b/src/java/com/android/internal/telephony/TelephonyCapabilities.java @@ -16,9 +16,12 @@ package com.android.internal.telephony; +import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; +import android.os.SystemProperties; +import com.android.internal.telephony.flags.FeatureFlags; import com.android.telephony.Rlog; /** @@ -194,4 +197,16 @@ public class TelephonyCapabilities { public static boolean canDistinguishDialingAndConnected(int phoneType) { return phoneType == PhoneConstants.PHONE_TYPE_GSM; } + + /** + * Returns true if Calling/Data/Messaging features should be checked on this device. + */ + public static boolean minimalTelephonyCdmCheck(@NonNull FeatureFlags featureFlags) { + // Check SDK version of the vendor partition. + final int vendorApiLevel = SystemProperties.getInt( + "ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT); + if (vendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) return false; + + return featureFlags.minimalTelephonyCdmCheck(); + } } diff --git a/src/java/com/android/internal/telephony/cat/CatService.java b/src/java/com/android/internal/telephony/cat/CatService.java index cadb02e0a9..4da1622ebf 100644 --- a/src/java/com/android/internal/telephony/cat/CatService.java +++ b/src/java/com/android/internal/telephony/cat/CatService.java @@ -284,6 +284,14 @@ public class CatService extends Handler implements AppInterface { CatLog.d(this, "Disposing CatService object"); mIccRecords.unregisterForRecordsLoaded(this); + if (sFlags.unregisterSmsBroadcastReceiverFromCatService()) { + try { + mContext.unregisterReceiver(mSmsBroadcastReceiver); + } catch (IllegalArgumentException e) { + CatLog.e(this, "mSmsBroadcastReceiver: was not registered" + e); + } + } + // Clean up stk icon if dispose is called broadcastCardStateAndIccRefreshResp(CardState.CARDSTATE_ABSENT, null); 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/data/AccessNetworksManager.java b/src/java/com/android/internal/telephony/data/AccessNetworksManager.java index 1d720ac886..bc684aff93 100644 --- a/src/java/com/android/internal/telephony/data/AccessNetworksManager.java +++ b/src/java/com/android/internal/telephony/data/AccessNetworksManager.java @@ -148,7 +148,9 @@ public class AccessNetworksManager extends Handler { @ApnType public final int apnType; // The qualified networks in preferred order. Each network is a AccessNetworkType. - public final @NonNull @RadioAccessNetworkType int[] qualifiedNetworks; + @NonNull + @RadioAccessNetworkType + public final int[] qualifiedNetworks; public QualifiedNetworks(@ApnType int apnType, @NonNull int[] qualifiedNetworks) { this.apnType = apnType; this.qualifiedNetworks = Arrays.stream(qualifiedNetworks) @@ -313,7 +315,7 @@ public class AccessNetworksManager extends Handler { /** * Called when QualifiedNetworksService requests network validation. - * + * <p> * Since the data network in the connected state corresponding to the given network * capability must be validated, a request is tossed to the data network controller. * @param networkCapability network capability @@ -429,7 +431,8 @@ public class AccessNetworksManager extends Handler { mPhone.getDataNetworkController().getDataRetryManager().registerCallback( new DataRetryManager.DataRetryManagerCallback(this::post) { @Override - public void onThrottleStatusChanged(List<ThrottleStatus> throttleStatuses) { + public void onThrottleStatusChanged( + @NonNull List<ThrottleStatus> throttleStatuses) { try { logl("onThrottleStatusChanged: " + throttleStatuses); if (mIQualifiedNetworksService != null) { @@ -471,7 +474,7 @@ public class AccessNetworksManager extends Handler { */ private void bindQualifiedNetworksService() { post(() -> { - Intent intent = null; + Intent intent; String packageName = getQualifiedNetworksServicePackageName(); String className = getQualifiedNetworksServiceClassName(); @@ -538,7 +541,7 @@ public class AccessNetworksManager extends Handler { b = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId(), CarrierConfigManager .KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_PACKAGE_OVERRIDE_STRING); - if (b != null && !b.isEmpty()) { + if (!b.isEmpty()) { // If carrier config overrides it, use the one from carrier config String carrierConfigPackageName = b.getString(CarrierConfigManager .KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_PACKAGE_OVERRIDE_STRING); @@ -569,7 +572,7 @@ public class AccessNetworksManager extends Handler { b = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId(), CarrierConfigManager .KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_CLASS_OVERRIDE_STRING); - if (b != null && !b.isEmpty()) { + if (!b.isEmpty()) { // If carrier config overrides it, use the one from carrier config String carrierConfigClassName = b.getString(CarrierConfigManager .KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_CLASS_OVERRIDE_STRING); @@ -585,7 +588,8 @@ public class AccessNetworksManager extends Handler { return className; } - private @NonNull List<QualifiedNetworks> getQualifiedNetworksList() { + @NonNull + private List<QualifiedNetworks> getQualifiedNetworksList() { List<QualifiedNetworks> qualifiedNetworksList = new ArrayList<>(); for (int i = 0; i < mAvailableNetworks.size(); i++) { qualifiedNetworksList.add(new QualifiedNetworks(mAvailableNetworks.keyAt(i), @@ -617,11 +621,13 @@ public class AccessNetworksManager extends Handler { /** * @return The available transports. */ - public @NonNull int[] getAvailableTransports() { + @NonNull + public int[] getAvailableTransports() { return mAvailableTransports; } - private static @TransportType int getTransportFromAccessNetwork(int accessNetwork) { + @TransportType + private static int getTransportFromAccessNetwork(int accessNetwork) { return accessNetwork == AccessNetworkType.IWLAN ? AccessNetworkConstants.TRANSPORT_TYPE_WLAN : AccessNetworkConstants.TRANSPORT_TYPE_WWAN; @@ -654,7 +660,8 @@ public class AccessNetworksManager extends Handler { * @param apnType APN type * @return The preferred transport. */ - public @TransportType int getPreferredTransport(@ApnType int apnType) { + @TransportType + public int getPreferredTransport(@ApnType int apnType) { return mPreferredTransports.get(apnType) == null ? AccessNetworkConstants.TRANSPORT_TYPE_WWAN : mPreferredTransports.get(apnType); } @@ -666,8 +673,8 @@ public class AccessNetworksManager extends Handler { * supported.) * @return The preferred transport. */ - public @TransportType int getPreferredTransportByNetworkCapability( - @NetCapability int networkCapability) { + @TransportType + public int getPreferredTransportByNetworkCapability(@NetCapability int networkCapability) { int apnType = DataUtils.networkCapabilityToApnType(networkCapability); // For non-APN type capabilities, always route to WWAN. if (apnType == ApnSetting.TYPE_NONE) { diff --git a/src/java/com/android/internal/telephony/data/AutoDataSwitchController.java b/src/java/com/android/internal/telephony/data/AutoDataSwitchController.java index 10371ab7f0..7486b6169f 100644 --- a/src/java/com/android/internal/telephony/data/AutoDataSwitchController.java +++ b/src/java/com/android/internal/telephony/data/AutoDataSwitchController.java @@ -473,6 +473,7 @@ public class AutoDataSwitchController extends Handler { @Override public void handleMessage(@NonNull Message msg) { AsyncResult ar; + Object obj; int phoneId; switch (msg.what) { case EVENT_SERVICE_STATE_CHANGED: @@ -491,33 +492,20 @@ public class AutoDataSwitchController extends Handler { onSignalStrengthChanged(phoneId); break; case EVENT_EVALUATE_AUTO_SWITCH: - if (sFeatureFlags.autoDataSwitchRatSs()) { - Object obj = mScheduledEventsToExtras.get(EVENT_EVALUATE_AUTO_SWITCH); - if (obj instanceof EvaluateEventExtra extra) { - mScheduledEventsToExtras.remove(EVENT_EVALUATE_AUTO_SWITCH); - onEvaluateAutoDataSwitch(extra.evaluateReason); - } - } else { - int reason = (int) msg.obj; - onEvaluateAutoDataSwitch(reason); + obj = mScheduledEventsToExtras.get(EVENT_EVALUATE_AUTO_SWITCH); + if (obj instanceof EvaluateEventExtra extra) { + mScheduledEventsToExtras.remove(EVENT_EVALUATE_AUTO_SWITCH); + onEvaluateAutoDataSwitch(extra.evaluateReason); } break; case EVENT_STABILITY_CHECK_PASSED: - if (sFeatureFlags.autoDataSwitchRatSs()) { - Object obj = mScheduledEventsToExtras.get(EVENT_STABILITY_CHECK_PASSED); - if (obj instanceof StabilityEventExtra extra) { - int targetPhoneId = extra.targetPhoneId; - boolean needValidation = extra.needValidation; - log("require validation on phone " + targetPhoneId - + (needValidation ? "" : " no") + " need to pass"); - mScheduledEventsToExtras.remove(EVENT_STABILITY_CHECK_PASSED); - mPhoneSwitcherCallback.onRequireValidation(targetPhoneId, needValidation); - } - } else { - int targetPhoneId = msg.arg1; - boolean needValidation = msg.arg2 == 1; + obj = mScheduledEventsToExtras.get(EVENT_STABILITY_CHECK_PASSED); + if (obj instanceof StabilityEventExtra extra) { + int targetPhoneId = extra.targetPhoneId; + boolean needValidation = extra.needValidation; log("require validation on phone " + targetPhoneId + (needValidation ? "" : " no") + " need to pass"); + mScheduledEventsToExtras.remove(EVENT_STABILITY_CHECK_PASSED); mPhoneSwitcherCallback.onRequireValidation(targetPhoneId, needValidation); } break; @@ -643,15 +631,9 @@ public class AutoDataSwitchController extends Handler { ? mAutoDataSwitchAvailabilityStabilityTimeThreshold << mAutoSwitchValidationFailedCount : 0; - if (sFeatureFlags.autoDataSwitchRatSs()) { - if (!mScheduledEventsToExtras.containsKey(EVENT_EVALUATE_AUTO_SWITCH)) { - scheduleEventWithTimer(EVENT_EVALUATE_AUTO_SWITCH, new EvaluateEventExtra(reason), - delayMs); - } - } else { - if (!hasMessages(EVENT_EVALUATE_AUTO_SWITCH)) { - sendMessageDelayed(obtainMessage(EVENT_EVALUATE_AUTO_SWITCH, reason), delayMs); - } + if (!mScheduledEventsToExtras.containsKey(EVENT_EVALUATE_AUTO_SWITCH)) { + scheduleEventWithTimer(EVENT_EVALUATE_AUTO_SWITCH, new EvaluateEventExtra(reason), + delayMs); } } @@ -700,12 +682,32 @@ public class AutoDataSwitchController extends Handler { return; } - if (!defaultDataPhone.isUserDataEnabled() || !backupDataPhone.isDataAllowed()) { - mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(DEFAULT_PHONE_INDEX, - EVALUATION_REASON_DATA_SETTINGS_CHANGED); - log(debugMessage.append(", immediately back to default as user turns off settings") - .toString()); - return; + DataEvaluation internetEvaluation; + if (sFeatureFlags.autoDataSwitchUsesDataEnabled()) { + if (!defaultDataPhone.isUserDataEnabled()) { + mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(DEFAULT_PHONE_INDEX, + EVALUATION_REASON_DATA_SETTINGS_CHANGED); + log(debugMessage.append( + ", immediately back to default as user turns off default").toString()); + return; + } else if (!(internetEvaluation = backupDataPhone.getDataNetworkController() + .getInternetEvaluation(false/*ignoreExistingNetworks*/)) + .isSubsetOf(DataEvaluation.DataDisallowedReason.NOT_IN_SERVICE)) { + mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone( + DEFAULT_PHONE_INDEX, EVALUATION_REASON_DATA_SETTINGS_CHANGED); + log(debugMessage.append( + ", immediately back to default because backup ") + .append(internetEvaluation).toString()); + return; + } + } else { + if (!defaultDataPhone.isUserDataEnabled() || !backupDataPhone.isDataAllowed()) { + mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(DEFAULT_PHONE_INDEX, + EVALUATION_REASON_DATA_SETTINGS_CHANGED); + log(debugMessage.append( + ", immediately back to default as user turns off settings").toString()); + return; + } } boolean backToDefault = false; @@ -915,12 +917,15 @@ public class AutoDataSwitchController extends Handler { } if (secondaryDataPhone != null) { - // check auto switch feature enabled - if (secondaryDataPhone.isDataAllowed()) { + // check internet data is allowed on the candidate + DataEvaluation internetEvaluation = secondaryDataPhone.getDataNetworkController() + .getInternetEvaluation(false/*ignoreExistingNetworks*/); + if (!internetEvaluation.containsDisallowedReasons()) { return new StabilityEventExtra(phoneId, isForPerformance, mRequirePingTestBeforeSwitch); } else { - debugMessage.append(", but candidate's data is not allowed"); + debugMessage.append(", but candidate's data is not allowed ") + .append(internetEvaluation); } } } @@ -932,8 +937,7 @@ public class AutoDataSwitchController extends Handler { * @return {@code true} If the feature of switching base on RAT and signal strength is enabled. */ private boolean isRatSignalStrengthBasedSwitchEnabled() { - return sFeatureFlags.autoDataSwitchRatSs() && mScoreTolerance >= 0 - && mAutoDataSwitchPerformanceStabilityTimeThreshold >= 0; + return mScoreTolerance >= 0 && mAutoDataSwitchPerformanceStabilityTimeThreshold >= 0; } /** @@ -953,39 +957,27 @@ public class AutoDataSwitchController extends Handler { */ private void startStabilityCheck(int targetPhoneId, boolean isForPerformance, boolean needValidation) { - String combinationIdentifier = targetPhoneId + "" + needValidation; - if (sFeatureFlags.autoDataSwitchRatSs()) { - StabilityEventExtra eventExtras = (StabilityEventExtra) - mScheduledEventsToExtras.getOrDefault(EVENT_STABILITY_CHECK_PASSED, - new StabilityEventExtra(INVALID_PHONE_INDEX, false /*need validation*/, - false /*isForPerformance*/)); - long delayMs = -1; - // Check if already scheduled one with that combination of extras. - if (eventExtras.targetPhoneId != targetPhoneId - || eventExtras.needValidation != needValidation - || eventExtras.isForPerformance != isForPerformance) { - eventExtras = - new StabilityEventExtra(targetPhoneId, isForPerformance, needValidation); - - // Reset with new timer. - delayMs = isForPerformance - ? mAutoDataSwitchPerformanceStabilityTimeThreshold - : mAutoDataSwitchAvailabilityStabilityTimeThreshold; - scheduleEventWithTimer(EVENT_STABILITY_CHECK_PASSED, eventExtras, delayMs); - } - log("startStabilityCheck: " - + (delayMs != -1 ? "scheduling " : "already scheduled ") - + eventExtras); - } else if (!hasEqualMessages(EVENT_STABILITY_CHECK_PASSED, combinationIdentifier)) { - removeMessages(EVENT_STABILITY_CHECK_PASSED); - sendMessageDelayed(obtainMessage(EVENT_STABILITY_CHECK_PASSED, targetPhoneId, - needValidation ? 1 : 0, - combinationIdentifier), - mAutoDataSwitchAvailabilityStabilityTimeThreshold); - log("startStabilityCheck: targetPhoneId=" + targetPhoneId - + " isForPerformance=" + isForPerformance - + " needValidation=" + needValidation); + StabilityEventExtra eventExtras = (StabilityEventExtra) + mScheduledEventsToExtras.getOrDefault(EVENT_STABILITY_CHECK_PASSED, + new StabilityEventExtra(INVALID_PHONE_INDEX, false /*need validation*/, + false /*isForPerformance*/)); + long delayMs = -1; + // Check if already scheduled one with that combination of extras. + if (eventExtras.targetPhoneId != targetPhoneId + || eventExtras.needValidation != needValidation + || eventExtras.isForPerformance != isForPerformance) { + eventExtras = + new StabilityEventExtra(targetPhoneId, isForPerformance, needValidation); + + // Reset with new timer. + delayMs = isForPerformance + ? mAutoDataSwitchPerformanceStabilityTimeThreshold + : mAutoDataSwitchAvailabilityStabilityTimeThreshold; + scheduleEventWithTimer(EVENT_STABILITY_CHECK_PASSED, eventExtras, delayMs); } + log("startStabilityCheck: " + + (delayMs != -1 ? "scheduling " : "already scheduled ") + + eventExtras); } /** @@ -1075,18 +1067,14 @@ public class AutoDataSwitchController extends Handler { private void cancelAnyPendingSwitch() { mSelectedTargetPhoneId = INVALID_PHONE_INDEX; resetFailedCount(); - if (sFeatureFlags.autoDataSwitchRatSs()) { - if (mScheduledEventsToExtras.containsKey(EVENT_STABILITY_CHECK_PASSED)) { - if (mEventsToAlarmListener.containsKey(EVENT_STABILITY_CHECK_PASSED)) { - mAlarmManager.cancel(mEventsToAlarmListener.get(EVENT_STABILITY_CHECK_PASSED)); - } else { - loge("cancelAnyPendingSwitch: EVENT_STABILITY_CHECK_PASSED listener is null"); - } - removeMessages(EVENT_STABILITY_CHECK_PASSED); - mScheduledEventsToExtras.remove(EVENT_STABILITY_CHECK_PASSED); + if (mScheduledEventsToExtras.containsKey(EVENT_STABILITY_CHECK_PASSED)) { + if (mEventsToAlarmListener.containsKey(EVENT_STABILITY_CHECK_PASSED)) { + mAlarmManager.cancel(mEventsToAlarmListener.get(EVENT_STABILITY_CHECK_PASSED)); + } else { + loge("cancelAnyPendingSwitch: EVENT_STABILITY_CHECK_PASSED listener is null"); } - } else { removeMessages(EVENT_STABILITY_CHECK_PASSED); + mScheduledEventsToExtras.remove(EVENT_STABILITY_CHECK_PASSED); } mPhoneSwitcherCallback.onRequireCancelAnyPendingAutoSwitchValidation(); } diff --git a/src/java/com/android/internal/telephony/data/DataConfigManager.java b/src/java/com/android/internal/telephony/data/DataConfigManager.java index 40039f25e2..4177cc4543 100644 --- a/src/java/com/android/internal/telephony/data/DataConfigManager.java +++ b/src/java/com/android/internal/telephony/data/DataConfigManager.java @@ -200,8 +200,8 @@ public class DataConfigManager extends Handler { private @interface DataConfigNetworkType {} /** Data config update callbacks. */ - private final @NonNull Set<DataConfigManagerCallback> mDataConfigManagerCallbacks = - new ArraySet<>(); + @NonNull + private final Set<DataConfigManagerCallback> mDataConfigManagerCallbacks = new ArraySet<>(); /** DeviceConfig key of anomaly report threshold for back to back ims release-request. */ private static final String KEY_ANOMALY_IMS_RELEASE_REQUEST = "anomaly_ims_release_request"; @@ -266,55 +266,77 @@ public class DataConfigManager extends Handler { */ private boolean mIsApnConfigAnomalyReportEnabled; - private @NonNull final Phone mPhone; - private @NonNull final String mLogTag; - - @NonNull private final FeatureFlags mFeatureFlags; - private @NonNull final CarrierConfigManager mCarrierConfigManager; - private @NonNull PersistableBundle mCarrierConfig = null; - private @NonNull Resources mResources = null; + @NonNull + private final Phone mPhone; + @NonNull + private final String mLogTag; + @NonNull + private final FeatureFlags mFeatureFlags; + @NonNull + private final CarrierConfigManager mCarrierConfigManager; + @NonNull + private PersistableBundle mCarrierConfig = null; + @NonNull + private Resources mResources = null; /** The network capability priority map */ - private @NonNull final Map<Integer, Integer> mNetworkCapabilityPriorityMap = - new ConcurrentHashMap<>(); + @NonNull + private final Map<Integer, Integer> mNetworkCapabilityPriorityMap = new ConcurrentHashMap<>(); /** The data setup retry rules */ - private @NonNull final List<DataSetupRetryRule> mDataSetupRetryRules = new ArrayList<>(); + @NonNull + private final List<DataSetupRetryRule> mDataSetupRetryRules = new ArrayList<>(); /** The data handover retry rules */ - private @NonNull final List<DataHandoverRetryRule> mDataHandoverRetryRules = new ArrayList<>(); + @NonNull + private final List<DataHandoverRetryRule> mDataHandoverRetryRules = new ArrayList<>(); /** The metered APN types for home network */ - private @NonNull final @ApnType Set<Integer> mMeteredApnTypes = new HashSet<>(); + @NonNull + @ApnType + private final Set<Integer> mMeteredApnTypes = new HashSet<>(); /** The metered APN types for roaming network */ - private @NonNull final @ApnType Set<Integer> mRoamingMeteredApnTypes = new HashSet<>(); + @NonNull + @ApnType + private final Set<Integer> mRoamingMeteredApnTypes = new HashSet<>(); /** The network types that only support single data networks */ - private @NonNull final @NetworkType List<Integer> mSingleDataNetworkTypeList = - new ArrayList<>(); - private @NonNull final @NetCapability Set<Integer> mCapabilitiesExemptFromSingleDataList = - new HashSet<>(); + @NonNull + @NetworkType + private final List<Integer> mSingleDataNetworkTypeList = new ArrayList<>(); + @NonNull + @NetCapability + private final Set<Integer> mCapabilitiesExemptFromSingleDataList = new HashSet<>(); /** The network types that support temporarily not metered */ - private @NonNull final @DataConfigNetworkType Set<String> mUnmeteredNetworkTypes = - new HashSet<>(); + @NonNull + @DataConfigNetworkType + private final Set<String> mUnmeteredNetworkTypes = new HashSet<>(); /** The network types that support temporarily not metered when roaming */ - private @NonNull final @DataConfigNetworkType Set<String> mRoamingUnmeteredNetworkTypes = - new HashSet<>(); + @NonNull + @DataConfigNetworkType + private final Set<String> mRoamingUnmeteredNetworkTypes = new HashSet<>(); /** A map of network types to the downlink and uplink bandwidth values for that network type */ - private @NonNull final @DataConfigNetworkType Map<String, DataNetwork.NetworkBandwidth> - mBandwidthMap = new ConcurrentHashMap<>(); - /** A map of network types to the TCP buffer sizes for that network type */ - private @NonNull final @DataConfigNetworkType Map<String, String> mTcpBufferSizeMap = + @NonNull + @DataConfigNetworkType + private final Map<String, DataNetwork.NetworkBandwidth> mBandwidthMap = new ConcurrentHashMap<>(); + /** A map of network types to the TCP buffer sizes for that network type */ + @NonNull + @DataConfigNetworkType + private final Map<String, String> mTcpBufferSizeMap = new ConcurrentHashMap<>(); /** Rules for handover between IWLAN and cellular network. */ - private @NonNull final List<HandoverRule> mHandoverRuleList = new ArrayList<>(); + @NonNull + private final List<HandoverRule> mHandoverRuleList = new ArrayList<>(); /** {@code True} keep IMS network in case of moving to non VOPS area; {@code false} otherwise.*/ private boolean mShouldKeepNetworkUpInNonVops = false; /** The set of network types that enable VOPS even in non VOPS area. */ - @NonNull private final @CarrierConfigManager.Ims.NetworkType List<Integer> - mEnabledVopsNetworkTypesInNonVops = new ArrayList<>(); + @NonNull + @CarrierConfigManager.Ims.NetworkType + private final List<Integer> mEnabledVopsNetworkTypesInNonVops = new ArrayList<>(); /** * A map of network types to the estimated downlink values by signal strength 0 - 4 for that * network type */ - private @NonNull final @DataConfigNetworkType Map<String, int[]> - mAutoDataSwitchNetworkTypeSignalMap = new ConcurrentHashMap<>(); + @NonNull + @DataConfigNetworkType + private final Map<String, int[]> mAutoDataSwitchNetworkTypeSignalMap = + new ConcurrentHashMap<>(); /** * Constructor @@ -554,14 +576,16 @@ public class DataConfigManager extends Handler { /** * @return The data setup retry rules from carrier config. */ - public @NonNull List<DataSetupRetryRule> getDataSetupRetryRules() { + @NonNull + public List<DataSetupRetryRule> getDataSetupRetryRules() { return Collections.unmodifiableList(mDataSetupRetryRules); } /** * @return The data handover retry rules from carrier config. */ - public @NonNull List<DataHandoverRetryRule> getDataHandoverRetryRules() { + @NonNull + public List<DataHandoverRetryRule> getDataHandoverRetryRules() { return Collections.unmodifiableList(mDataHandoverRetryRules); } @@ -604,7 +628,9 @@ public class DataConfigManager extends Handler { * * @return The metered network capabilities when connected to a home network. */ - public @NonNull @NetCapability Set<Integer> getMeteredNetworkCapabilities(boolean isRoaming) { + @NonNull + @NetCapability + public Set<Integer> getMeteredNetworkCapabilities(boolean isRoaming) { Set<Integer> meteredApnTypes = isRoaming ? mRoamingMeteredApnTypes : mMeteredApnTypes; Set<Integer> meteredCapabilities = meteredApnTypes.stream() .map(DataUtils::apnTypeToNetworkCapability) @@ -703,7 +729,9 @@ public class DataConfigManager extends Handler { /** * @return The list of {@link NetworkType} that only supports single data networks */ - public @NonNull @NetworkType List<Integer> getNetworkTypesOnlySupportSingleDataNetwork() { + @NonNull + @NetworkType + public List<Integer> getNetworkTypesOnlySupportSingleDataNetwork() { return Collections.unmodifiableList(mSingleDataNetworkTypeList); } @@ -711,7 +739,9 @@ public class DataConfigManager extends Handler { * @return The list of {@link android.net.NetworkCapabilities.NetCapability} that every of which * is exempt from the single PDN check. */ - public @NonNull @NetCapability Set<Integer> getCapabilitiesExemptFromSingleDataNetwork() { + @NonNull + @NetCapability + public Set<Integer> getCapabilitiesExemptFromSingleDataNetwork() { return Collections.unmodifiableSet(mCapabilitiesExemptFromSingleDataList); } @@ -844,7 +874,8 @@ public class DataConfigManager extends Handler { * @param displayInfo The {@link TelephonyDisplayInfo} to get the bandwidth for. * @return The pre-configured bandwidth estimate from carrier config. */ - public @NonNull DataNetwork.NetworkBandwidth getBandwidthForNetworkType( + @NonNull + public DataNetwork.NetworkBandwidth getBandwidthForNetworkType( @NonNull TelephonyDisplayInfo displayInfo) { DataNetwork.NetworkBandwidth bandwidth = mBandwidthMap.get( getDataConfigNetworkType(displayInfo)); @@ -931,7 +962,8 @@ public class DataConfigManager extends Handler { * Anomaly report thresholds for frequent setup data call failure. * @return EventFrequency to trigger the anomaly report */ - public @NonNull EventFrequency getAnomalySetupDataCallThreshold() { + @NonNull + public EventFrequency getAnomalySetupDataCallThreshold() { return mSetupDataCallAnomalyReportThreshold; } @@ -940,7 +972,8 @@ public class DataConfigManager extends Handler { * at {@link TelephonyNetworkAgent#onNetworkUnwanted} * @return EventFrequency to trigger the anomaly report */ - public @NonNull EventFrequency getAnomalyNetworkUnwantedThreshold() { + @NonNull + public EventFrequency getAnomalyNetworkUnwantedThreshold() { return mNetworkUnwantedAnomalyReportThreshold; } @@ -948,7 +981,8 @@ public class DataConfigManager extends Handler { * Anomaly report thresholds for back to back release-request of IMS. * @return EventFrequency to trigger the anomaly report */ - public @NonNull EventFrequency getAnomalyImsReleaseRequestThreshold() { + @NonNull + public EventFrequency getAnomalyImsReleaseRequestThreshold() { return mImsReleaseRequestAnomalyReportThreshold; } @@ -1119,7 +1153,8 @@ public class DataConfigManager extends Handler { * @return The TCP configuration string for the given display info or the default value from * {@code config_tcp_buffers} if unavailable. */ - public @NonNull String getTcpConfigString(@NonNull TelephonyDisplayInfo displayInfo) { + @NonNull + public String getTcpConfigString(@NonNull TelephonyDisplayInfo displayInfo) { String config = mTcpBufferSizeMap.get(getDataConfigNetworkType(displayInfo)); if (TextUtils.isEmpty(config)) { config = getDefaultTcpConfigString(); @@ -1130,7 +1165,8 @@ public class DataConfigManager extends Handler { /** * @return The fixed TCP buffer size configured based on the device's memory and performance. */ - public @NonNull String getDefaultTcpConfigString() { + @NonNull + public String getDefaultTcpConfigString() { return mResources.getString(com.android.internal.R.string.config_tcp_buffers); } @@ -1173,20 +1209,21 @@ public class DataConfigManager extends Handler { /** * @return The bandwidth estimation source. */ - public @DataNetwork.BandwidthEstimationSource int getBandwidthEstimateSource() { + @DataNetwork.BandwidthEstimationSource + public int getBandwidthEstimateSource() { String source = mResources.getString( com.android.internal.R.string.config_bandwidthEstimateSource); - switch (source) { - case BANDWIDTH_SOURCE_MODEM_STRING_VALUE: - return DataNetwork.BANDWIDTH_SOURCE_MODEM; - case BANDWIDTH_SOURCE_CARRIER_CONFIG_STRING_VALUE: - return DataNetwork.BANDWIDTH_SOURCE_CARRIER_CONFIG; - case BANDWIDTH_SOURCE_BANDWIDTH_ESTIMATOR_STRING_VALUE: - return DataNetwork.BANDWIDTH_SOURCE_BANDWIDTH_ESTIMATOR; - default: + return switch (source) { + case BANDWIDTH_SOURCE_MODEM_STRING_VALUE -> DataNetwork.BANDWIDTH_SOURCE_MODEM; + case BANDWIDTH_SOURCE_CARRIER_CONFIG_STRING_VALUE -> + DataNetwork.BANDWIDTH_SOURCE_CARRIER_CONFIG; + case BANDWIDTH_SOURCE_BANDWIDTH_ESTIMATOR_STRING_VALUE -> + DataNetwork.BANDWIDTH_SOURCE_BANDWIDTH_ESTIMATOR; + default -> { loge("Invalid bandwidth estimation source config: " + source); - return DataNetwork.BANDWIDTH_SOURCE_UNKNOWN; - } + yield DataNetwork.BANDWIDTH_SOURCE_UNKNOWN; + } + }; } /** @@ -1195,8 +1232,9 @@ public class DataConfigManager extends Handler { * @param displayInfo The {@link TelephonyDisplayInfo} used to determine the type. * @return The equivalent {@link DataConfigNetworkType}. */ - private static @NonNull @DataConfigNetworkType String getDataConfigNetworkType( - @NonNull TelephonyDisplayInfo displayInfo) { + @NonNull + @DataConfigNetworkType + private static String getDataConfigNetworkType(@NonNull TelephonyDisplayInfo displayInfo) { int networkType = displayInfo.getNetworkType(); switch (displayInfo.getOverrideNetworkType()) { case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED: @@ -1305,7 +1343,8 @@ public class DataConfigManager extends Handler { * * @see CarrierConfigManager#KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY */ - public @NonNull List<HandoverRule> getHandoverRules() { + @NonNull + public List<HandoverRule> getHandoverRules() { return Collections.unmodifiableList(mHandoverRuleList); } @@ -1323,52 +1362,33 @@ public class DataConfigManager extends Handler { * @param networkType The network type * @return The equivalent data config network type */ - private static @NonNull @DataConfigNetworkType String networkTypeToDataConfigNetworkType( + @NonNull + @DataConfigNetworkType + private static String networkTypeToDataConfigNetworkType( @NetworkType int networkType) { - switch (networkType) { - case TelephonyManager.NETWORK_TYPE_GPRS: - return DATA_CONFIG_NETWORK_TYPE_GPRS; - case TelephonyManager.NETWORK_TYPE_EDGE: - return DATA_CONFIG_NETWORK_TYPE_EDGE; - case TelephonyManager.NETWORK_TYPE_UMTS: - return DATA_CONFIG_NETWORK_TYPE_UMTS; - case TelephonyManager.NETWORK_TYPE_HSDPA: - return DATA_CONFIG_NETWORK_TYPE_HSDPA; - case TelephonyManager.NETWORK_TYPE_HSUPA: - return DATA_CONFIG_NETWORK_TYPE_HSUPA; - case TelephonyManager.NETWORK_TYPE_HSPA: - return DATA_CONFIG_NETWORK_TYPE_HSPA; - case TelephonyManager.NETWORK_TYPE_CDMA: - return DATA_CONFIG_NETWORK_TYPE_CDMA; - case TelephonyManager.NETWORK_TYPE_EVDO_0: - return DATA_CONFIG_NETWORK_TYPE_EVDO_0; - case TelephonyManager.NETWORK_TYPE_EVDO_A: - return DATA_CONFIG_NETWORK_TYPE_EVDO_A; - case TelephonyManager.NETWORK_TYPE_EVDO_B: - return DATA_CONFIG_NETWORK_TYPE_EVDO_B; - case TelephonyManager.NETWORK_TYPE_1xRTT: - return DATA_CONFIG_NETWORK_TYPE_1xRTT; - case TelephonyManager.NETWORK_TYPE_LTE: - return DATA_CONFIG_NETWORK_TYPE_LTE; - case TelephonyManager.NETWORK_TYPE_EHRPD: - return DATA_CONFIG_NETWORK_TYPE_EHRPD; - case TelephonyManager.NETWORK_TYPE_IDEN: - return DATA_CONFIG_NETWORK_TYPE_IDEN; - case TelephonyManager.NETWORK_TYPE_HSPAP: - return DATA_CONFIG_NETWORK_TYPE_HSPAP; - case TelephonyManager.NETWORK_TYPE_GSM: - return DATA_CONFIG_NETWORK_TYPE_GSM; - case TelephonyManager.NETWORK_TYPE_TD_SCDMA: - return DATA_CONFIG_NETWORK_TYPE_TD_SCDMA; - case TelephonyManager.NETWORK_TYPE_IWLAN: - return DATA_CONFIG_NETWORK_TYPE_IWLAN; - case TelephonyManager.NETWORK_TYPE_LTE_CA: - return DATA_CONFIG_NETWORK_TYPE_LTE_CA; - case TelephonyManager.NETWORK_TYPE_NR: - return DATA_CONFIG_NETWORK_TYPE_NR_SA; - default: - return ""; - } + return switch (networkType) { + case TelephonyManager.NETWORK_TYPE_GPRS -> DATA_CONFIG_NETWORK_TYPE_GPRS; + case TelephonyManager.NETWORK_TYPE_EDGE -> DATA_CONFIG_NETWORK_TYPE_EDGE; + case TelephonyManager.NETWORK_TYPE_UMTS -> DATA_CONFIG_NETWORK_TYPE_UMTS; + case TelephonyManager.NETWORK_TYPE_HSDPA -> DATA_CONFIG_NETWORK_TYPE_HSDPA; + case TelephonyManager.NETWORK_TYPE_HSUPA -> DATA_CONFIG_NETWORK_TYPE_HSUPA; + case TelephonyManager.NETWORK_TYPE_HSPA -> DATA_CONFIG_NETWORK_TYPE_HSPA; + case TelephonyManager.NETWORK_TYPE_CDMA -> DATA_CONFIG_NETWORK_TYPE_CDMA; + case TelephonyManager.NETWORK_TYPE_EVDO_0 -> DATA_CONFIG_NETWORK_TYPE_EVDO_0; + case TelephonyManager.NETWORK_TYPE_EVDO_A -> DATA_CONFIG_NETWORK_TYPE_EVDO_A; + case TelephonyManager.NETWORK_TYPE_EVDO_B -> DATA_CONFIG_NETWORK_TYPE_EVDO_B; + case TelephonyManager.NETWORK_TYPE_1xRTT -> DATA_CONFIG_NETWORK_TYPE_1xRTT; + case TelephonyManager.NETWORK_TYPE_LTE -> DATA_CONFIG_NETWORK_TYPE_LTE; + case TelephonyManager.NETWORK_TYPE_EHRPD -> DATA_CONFIG_NETWORK_TYPE_EHRPD; + case TelephonyManager.NETWORK_TYPE_IDEN -> DATA_CONFIG_NETWORK_TYPE_IDEN; + case TelephonyManager.NETWORK_TYPE_HSPAP -> DATA_CONFIG_NETWORK_TYPE_HSPAP; + case TelephonyManager.NETWORK_TYPE_GSM -> DATA_CONFIG_NETWORK_TYPE_GSM; + case TelephonyManager.NETWORK_TYPE_TD_SCDMA -> DATA_CONFIG_NETWORK_TYPE_TD_SCDMA; + case TelephonyManager.NETWORK_TYPE_IWLAN -> DATA_CONFIG_NETWORK_TYPE_IWLAN; + case TelephonyManager.NETWORK_TYPE_LTE_CA -> DATA_CONFIG_NETWORK_TYPE_LTE_CA; + case TelephonyManager.NETWORK_TYPE_NR -> DATA_CONFIG_NETWORK_TYPE_NR_SA; + default -> ""; + }; } /** @@ -1376,7 +1396,8 @@ public class DataConfigManager extends Handler { * * @see CarrierConfigManager#KEY_DATA_STALL_RECOVERY_TIMERS_LONG_ARRAY */ - public @NonNull long[] getDataStallRecoveryDelayMillis() { + @NonNull + public long[] getDataStallRecoveryDelayMillis() { return mCarrierConfig.getLongArray( CarrierConfigManager.KEY_DATA_STALL_RECOVERY_TIMERS_LONG_ARRAY); } @@ -1386,7 +1407,8 @@ public class DataConfigManager extends Handler { * * @see CarrierConfigManager#KEY_DATA_STALL_RECOVERY_SHOULD_SKIP_BOOL_ARRAY */ - public @NonNull boolean[] getDataStallRecoveryShouldSkipArray() { + @NonNull + public boolean[] getDataStallRecoveryShouldSkipArray() { return mCarrierConfig.getBooleanArray( CarrierConfigManager.KEY_DATA_STALL_RECOVERY_SHOULD_SKIP_BOOL_ARRAY); } @@ -1395,7 +1417,8 @@ public class DataConfigManager extends Handler { * @return The default preferred APN. An empty string if not configured. This is used for the * first time boot up where preferred APN is not set. */ - public @NonNull String getDefaultPreferredApn() { + @NonNull + public String getDefaultPreferredApn() { return TextUtils.emptyIfNull(mCarrierConfig.getString( CarrierConfigManager.KEY_DEFAULT_PREFERRED_APN_NAME_STRING)); } @@ -1414,7 +1437,9 @@ public class DataConfigManager extends Handler { * cases that we need to use "user-added" APN for initial attach. The regular way to configure * IA APN is by adding "IA" type to the APN in APN config. */ - public @NonNull @ApnType List<Integer> getAllowedInitialAttachApnTypes() { + @NonNull + @ApnType + public List<Integer> getAllowedInitialAttachApnTypes() { String[] apnTypesArray = mCarrierConfig.getStringArray( CarrierConfigManager.KEY_ALLOWED_INITIAL_ATTACH_APN_TYPES_STRING_ARRAY); if (apnTypesArray != null) { @@ -1461,7 +1486,8 @@ public class DataConfigManager extends Handler { /** * @return The capabilities that network will be forced to mark as cellular transport. */ - public @NetCapability Set<Integer> getForcedCellularTransportCapabilities() { + @NetCapability + public Set<Integer> getForcedCellularTransportCapabilities() { String[] forcedCellularTransportCapabilities = mResources.getStringArray( com.android.internal.R.array.config_force_cellular_transport_capabilities); diff --git a/src/java/com/android/internal/telephony/data/DataEvaluation.java b/src/java/com/android/internal/telephony/data/DataEvaluation.java index ae7023e2e1..f5eae91ef4 100644 --- a/src/java/com/android/internal/telephony/data/DataEvaluation.java +++ b/src/java/com/android/internal/telephony/data/DataEvaluation.java @@ -59,7 +59,7 @@ public class DataEvaluation { * * @param reason The reason for this evaluation. */ - public DataEvaluation(DataEvaluationReason reason) { + public DataEvaluation(@NonNull DataEvaluationReason reason) { mDataEvaluationReason = reason; } @@ -105,14 +105,16 @@ public class DataEvaluation { /** * @return List of data disallowed reasons. */ - public @NonNull List<DataDisallowedReason> getDataDisallowedReasons() { + @NonNull + public List<DataDisallowedReason> getDataDisallowedReasons() { return new ArrayList<>(mDataDisallowedReasons); } /** * @return The data allowed reason. */ - public @NonNull DataAllowedReason getDataAllowedReason() { + @NonNull + public DataAllowedReason getDataAllowedReason() { return mDataAllowedReason; } @@ -128,7 +130,8 @@ public class DataEvaluation { /** * @return The candidate data profile for setup data network. */ - public @Nullable DataProfile getCandidateDataProfile() { + @Nullable + public DataProfile getCandidateDataProfile() { return mCandidateDataProfile; } @@ -136,7 +139,7 @@ public class DataEvaluation { * @return {@code true} if the evaluation contains disallowed reasons. */ public boolean containsDisallowedReasons() { - return mDataDisallowedReasons.size() != 0; + return !mDataDisallowedReasons.isEmpty(); } /** @@ -422,7 +425,8 @@ public class DataEvaluation { @Override public String toString() { StringBuilder evaluationStr = new StringBuilder(); - evaluationStr.append("Data evaluation: evaluation reason:" + mDataEvaluationReason + ", "); + evaluationStr.append("Data evaluation: evaluation reason:") + .append(mDataEvaluationReason).append(", "); if (!mDataDisallowedReasons.isEmpty()) { evaluationStr.append("Data disallowed reasons:"); for (DataDisallowedReason reason : mDataDisallowedReasons) { @@ -432,8 +436,8 @@ public class DataEvaluation { evaluationStr.append("Data allowed reason:"); evaluationStr.append(" ").append(mDataAllowedReason); } - evaluationStr.append(", candidate profile=" + mCandidateDataProfile); - evaluationStr.append(", time=" + DataUtils.systemTimeToString(mEvaluatedTime)); + evaluationStr.append(", candidate profile=").append(mCandidateDataProfile); + evaluationStr.append(", time=").append(DataUtils.systemTimeToString(mEvaluatedTime)); return evaluationStr.toString(); } diff --git a/src/java/com/android/internal/telephony/data/DataNetwork.java b/src/java/com/android/internal/telephony/data/DataNetwork.java index 9e84a77a8d..57d242bd03 100644 --- a/src/java/com/android/internal/telephony/data/DataNetwork.java +++ b/src/java/com/android/internal/telephony/data/DataNetwork.java @@ -125,6 +125,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; +import java.util.ListIterator; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -136,11 +137,11 @@ import java.util.stream.Collectors; /** * DataNetwork class represents a single PDN (Packet Data Network). - * + * <p> * The life cycle of a data network starts from {@link ConnectingState}. If setup data request * succeeds, then it enters {@link ConnectedState}, otherwise it enters * {@link DisconnectedState}. - * + * <p> * When data network is in {@link ConnectingState}, it can enter {@link HandoverState} if handover * between IWLAN and cellular occurs. After handover completes or fails, it return back to * {@link ConnectedState}. When the data network is about to be disconnected, it first enters @@ -149,9 +150,9 @@ import java.util.stream.Collectors; * notifies data disconnected. Note that an unsolicited disconnected event from {@link DataService} * or any vendor HAL failure response can immediately move data network from {@link ConnectedState} * to {@link DisconnectedState}. {@link DisconnectedState} is the final state of a data network. - * + * <p> * State machine diagram: - * + * <p> * * ┌─────────┐ * │Handover │ @@ -504,10 +505,12 @@ public class DataNetwork extends StateMachine { private final DisconnectedState mDisconnectedState = new DisconnectedState(); /** The phone instance. */ - private final @NonNull Phone mPhone; + @NonNull + private final Phone mPhone; /** Feature flags */ - private final @NonNull FeatureFlags mFlags; + @NonNull + private final FeatureFlags mFlags; /** * The subscription id. This is assigned when the network is created, and not supposed to @@ -516,7 +519,8 @@ public class DataNetwork extends StateMachine { private final int mSubId; /** The network score of this network. */ - private @NonNull NetworkScore mNetworkScore; + @NonNull + private NetworkScore mNetworkScore; /** * Indicates that @@ -531,13 +535,15 @@ public class DataNetwork extends StateMachine { private boolean mEverConnected = false; /** RIL interface. */ - private final @NonNull CommandsInterface mRil; + @NonNull + private final CommandsInterface mRil; /** Local log. */ private final LocalLog mLocalLog = new LocalLog(128); /** The callback to receives data network state update. */ - private final @NonNull DataNetworkCallback mDataNetworkCallback; + @NonNull + private final DataNetworkCallback mDataNetworkCallback; /** The log tag. */ private String mLogTag; @@ -546,7 +552,8 @@ public class DataNetwork extends StateMachine { private final DataCallSessionStats mDataCallSessionStats; /** Metrics of per data network validation. */ - private final @NonNull DataNetworkValidationStats mDataNetworkValidationStats; + @NonNull + private final DataNetworkValidationStats mDataNetworkValidationStats; /** * The unique context id assigned by the data service in {@link DataCallResponse#getId()}. One @@ -570,71 +577,92 @@ public class DataNetwork extends StateMachine { * Data service managers for accessing {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN} and * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN} data services. */ - private final @NonNull SparseArray<DataServiceManager> mDataServiceManagers; + @NonNull + private final SparseArray<DataServiceManager> mDataServiceManagers; /** Access networks manager. */ - private final @NonNull AccessNetworksManager mAccessNetworksManager; + @NonNull + private final AccessNetworksManager mAccessNetworksManager; /** Data network controller. */ - private final @NonNull DataNetworkController mDataNetworkController; + @NonNull + private final DataNetworkController mDataNetworkController; /** Data network controller callback. */ - private final @NonNull DataNetworkController.DataNetworkControllerCallback + @NonNull + private final DataNetworkController.DataNetworkControllerCallback mDataNetworkControllerCallback; /** Data settings manager callback. */ - private @NonNull DataSettingsManagerCallback mDataSettingsManagerCallback; + @NonNull + private DataSettingsManagerCallback mDataSettingsManagerCallback; /** Data config manager. */ - private final @NonNull DataConfigManager mDataConfigManager; + @NonNull + private final DataConfigManager mDataConfigManager; /** VCN manager. */ - private final @Nullable VcnManager mVcnManager; + @Nullable + private final VcnManager mVcnManager; /** VCN policy changed listener. */ - private @Nullable VcnNetworkPolicyChangeListener mVcnPolicyChangeListener; + @Nullable + private VcnNetworkPolicyChangeListener mVcnPolicyChangeListener; /** The network agent associated with this data network. */ - private @NonNull TelephonyNetworkAgent mNetworkAgent; + @NonNull + private TelephonyNetworkAgent mNetworkAgent; /** QOS callback tracker. This is only created after network connected on WWAN. */ - private @Nullable QosCallbackTracker mQosCallbackTracker; + @Nullable + private QosCallbackTracker mQosCallbackTracker; /** NAT keepalive tracker. */ - private @Nullable KeepaliveTracker mKeepaliveTracker; + @Nullable + private KeepaliveTracker mKeepaliveTracker; /** The data profile used to establish this data network. */ - private @NonNull DataProfile mDataProfile; + @NonNull + private DataProfile mDataProfile; /** * The data profile used for data handover. Some carriers might use different data profile * between IWLAN and cellular. Only set before handover started. */ - private @Nullable DataProfile mHandoverDataProfile; + @Nullable + private DataProfile mHandoverDataProfile; /** The network capabilities of this data network. */ - private @NonNull NetworkCapabilities mNetworkCapabilities; + @NonNull + private NetworkCapabilities mNetworkCapabilities; /** The matched traffic descriptor returned from setup data call request. */ - private final @NonNull List<TrafficDescriptor> mTrafficDescriptors = new ArrayList<>(); + @NonNull + private final List<TrafficDescriptor> mTrafficDescriptors = new ArrayList<>(); /** The link properties of this data network. */ - private @NonNull LinkProperties mLinkProperties; + @NonNull + private LinkProperties mLinkProperties; /** The network slice info. */ - private @Nullable NetworkSliceInfo mNetworkSliceInfo; + @Nullable + private NetworkSliceInfo mNetworkSliceInfo; /** The link status (i.e. RRC state). */ - private @LinkStatus int mLinkStatus = DataCallResponse.LINK_STATUS_UNKNOWN; + @LinkStatus + private int mLinkStatus = DataCallResponse.LINK_STATUS_UNKNOWN; /** The network bandwidth. */ - private @NonNull NetworkBandwidth mNetworkBandwidth = new NetworkBandwidth(14, 14); + @NonNull + private NetworkBandwidth mNetworkBandwidth = new NetworkBandwidth(14, 14); /** The TCP buffer sizes config. */ - private @NonNull String mTcpBufferSizes; + @NonNull + private String mTcpBufferSizes; /** The telephony display info. */ - private @NonNull TelephonyDisplayInfo mTelephonyDisplayInfo; + @NonNull + private TelephonyDisplayInfo mTelephonyDisplayInfo; /** Whether {@link NetworkCapabilities#NET_CAPABILITY_TEMPORARILY_NOT_METERED} is supported. */ private boolean mTempNotMeteredSupported = false; @@ -646,7 +674,8 @@ public class DataNetwork extends StateMachine { private boolean mCongested = false; /** The network requests associated with this data network */ - private final @NonNull NetworkRequestList mAttachedNetworkRequestList = + @NonNull + private final NetworkRequestList mAttachedNetworkRequestList = new NetworkRequestList(); /** @@ -655,18 +684,21 @@ public class DataNetwork extends StateMachine { * {@link DataServiceCallback#onDataCallListChanged(List)}. The very first update must be * from {@link DataServiceCallback#onSetupDataCallComplete(int, DataCallResponse)}. */ - private @Nullable DataCallResponse mDataCallResponse = null; + @Nullable + private DataCallResponse mDataCallResponse = null; /** * The fail cause from either setup data failure or unsolicited disconnect reported by data * service. */ - private @DataFailureCause int mFailCause = DataFailCause.NONE; + @DataFailureCause + private int mFailCause = DataFailCause.NONE; /** * The tear down reason if the data call is voluntarily deactivated, not due to failure. */ - private @TearDownReason int mTearDownReason = TEAR_DOWN_REASON_NONE; + @TearDownReason + private int mTearDownReason = TEAR_DOWN_REASON_NONE; /** * The retry delay in milliseconds from setup data failure. @@ -686,12 +718,14 @@ public class DataNetwork extends StateMachine { * The current transport of the data network. For handover, the current transport will be set * after handover completes. */ - private @TransportType int mTransport; + @TransportType + private int mTransport; /** * The last known data network type. */ - private @NetworkType int mLastKnownDataNetworkType; + @NetworkType + private int mLastKnownDataNetworkType; /** * The last known roaming state of this data network. @@ -704,27 +738,33 @@ public class DataNetwork extends StateMachine { private final boolean mIsSatellite; /** The reason that why setting up this data network is allowed. */ - private final @NonNull DataAllowedReason mDataAllowedReason; + @NonNull + private final DataAllowedReason mDataAllowedReason; /** * PCO (Protocol Configuration Options) data received from the network. The first key is the * cid of the PCO data, the second key is the PCO id, the value is the PCO data. */ - private final @NonNull Map<Integer, Map<Integer, PcoData>> mPcoData = new ArrayMap<>(); + @NonNull + private final Map<Integer, Map<Integer, PcoData>> mPcoData = new ArrayMap<>(); /** The QOS bearer sessions. */ - private final @NonNull List<QosBearerSession> mQosBearerSessions = new ArrayList<>(); + @NonNull + private final List<QosBearerSession> mQosBearerSessions = new ArrayList<>(); /** The QOS for the Default Bearer, should be non-null on LTE and NR */ - private @Nullable Qos mDefaultQos; + @Nullable + private Qos mDefaultQos; /** * The UIDs of packages that have carrier privilege. */ - private @NonNull int[] mAdministratorUids = new int[0]; + @NonNull + private int[] mAdministratorUids = new int[0]; /** Carrier privileges callback to monitor administrator UID change. */ - private @Nullable TelephonyManager.CarrierPrivilegesCallback mCarrierPrivilegesCallback; + @Nullable + private TelephonyManager.CarrierPrivilegesCallback mCarrierPrivilegesCallback; /** * Carrier service package uid. This UID will not change through the life cycle of data network. @@ -734,36 +774,42 @@ public class DataNetwork extends StateMachine { /** * Link bandwidth estimator callback for receiving latest link bandwidth information. */ - private @Nullable LinkBandwidthEstimatorCallback mLinkBandwidthEstimatorCallback; + @Nullable + private LinkBandwidthEstimatorCallback mLinkBandwidthEstimatorCallback; /** * Data config callback for carrier config update. */ - private @Nullable DataConfigManagerCallback mDataConfigManagerCallback; + @Nullable + private DataConfigManagerCallback mDataConfigManagerCallback; /** * Network validation status for this data network. If the data service provider does not * support the network validation feature, should be UNSUPPORTED. */ - private @PreciseDataConnectionState.NetworkValidationStatus int mNetworkValidationStatus = + @PreciseDataConnectionState.NetworkValidationStatus + private int mNetworkValidationStatus = PreciseDataConnectionState.NETWORK_VALIDATION_UNSUPPORTED; /** * Callback used to respond to a network validation request to determine whether the request is * successfully submitted. If the request has been submitted, change it to null. */ - private @Nullable Consumer<Integer> mNetworkValidationResultCodeCallback; + @Nullable + private Consumer<Integer> mNetworkValidationResultCodeCallback; /** * Callback used to listen QNS preference changes. */ - private @Nullable AccessNetworksManagerCallback mAccessNetworksManagerCallback; + @Nullable + private AccessNetworksManagerCallback mAccessNetworksManagerCallback; /** * PreciseDataConnectionState, the most recently notified. If it has never been notified, it is * null. */ - private @Nullable PreciseDataConnectionState mPreciseDataConnectionState; + @Nullable + private PreciseDataConnectionState mPreciseDataConnectionState; /** * The network bandwidth. @@ -1004,23 +1050,36 @@ public class DataNetwork extends StateMachine { && transport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN; mDataAllowedReason = dataAllowedReason; dataProfile.setLastSetupTimestamp(SystemClock.elapsedRealtime()); - mAttachedNetworkRequestList.addAll(networkRequestList); for (int transportType : mAccessNetworksManager.getAvailableTransports()) { mCid.put(transportType, INVALID_CID); } mTelephonyDisplayInfo = mPhone.getDisplayInfoController().getTelephonyDisplayInfo(); mTcpBufferSizes = mDataConfigManager.getTcpConfigString(mTelephonyDisplayInfo); - for (TelephonyNetworkRequest networkRequest : networkRequestList) { - networkRequest.setAttachedNetwork(DataNetwork.this); - networkRequest.setState(TelephonyNetworkRequest.REQUEST_STATE_SATISFIED); - } - + // network capabilities infer connectivity transport and MMTEL from the requested + // capabilities. + // TODO: Ideally we shouldn't infer network capabilities base on the requested capabilities, + // but currently there are 2 hacks associated with getForcedCellularTransportCapabilities + // and IMS service requesting IMS|MMTEL that need to support. When we stop supporting these + // cases, we shouldn't consider the requests when determining the network capabilities. + mAttachedNetworkRequestList.addAll(networkRequestList); // Update the capabilities in the constructor is to make sure the data network has initial // capability immediately after created. Doing this connecting state creates the window that // DataNetworkController might check if existing data network's capability can satisfy the // next network request within this window. updateNetworkCapabilities(); + + // Remove the requests that can't use the initial capabilities + ListIterator<TelephonyNetworkRequest> iter = mAttachedNetworkRequestList.listIterator(); + while (iter.hasNext()) { + TelephonyNetworkRequest request = iter.next(); + if (request.canBeSatisfiedBy(mNetworkCapabilities)) { + request.setAttachedNetwork(DataNetwork.this); + request.setState(TelephonyNetworkRequest.REQUEST_STATE_SATISFIED); + } else { + iter.remove(); + } + } } /** @@ -1064,7 +1123,8 @@ public class DataNetwork extends StateMachine { * * @return The telephony network agent. */ - private @NonNull TelephonyNetworkAgent createNetworkAgent() { + @NonNull + private TelephonyNetworkAgent createNetworkAgent() { final NetworkAgentConfig.Builder configBuilder = new NetworkAgentConfig.Builder(); configBuilder.setLegacyType(ConnectivityManager.TYPE_MOBILE); configBuilder.setLegacyTypeName("MOBILE"); @@ -1097,13 +1157,8 @@ public class DataNetwork extends StateMachine { mPhone.getPhoneId()); final NetworkProvider provider = (null == factory) ? null : factory.getProvider(); - // Always prefer IWLAN network for MMS designated network. - // TODO(b/293656884) Proper use of primary transport to avoid conflicting with DSDA. - boolean isPreferred = mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN - && getApnTypeNetworkCapability() == NetworkCapabilities.NET_CAPABILITY_MMS; - - mNetworkScore = new NetworkScore.Builder().setTransportPrimary(isPreferred) - .setKeepConnectedReason(isHandoverInProgress() + mNetworkScore = new NetworkScore.Builder() + .setKeepConnectedReason(isHandoverInProgress() ? NetworkScore.KEEP_CONNECTED_FOR_HANDOVER : NetworkScore.KEEP_CONNECTED_NONE).build(); @@ -2522,21 +2577,24 @@ public class DataNetwork extends StateMachine { /** * @return The network capabilities of this data network. */ - public @NonNull NetworkCapabilities getNetworkCapabilities() { + @NonNull + public NetworkCapabilities getNetworkCapabilities() { return mNetworkCapabilities; } /** * @return The link properties of this data network. */ - public @NonNull LinkProperties getLinkProperties() { + @NonNull + public LinkProperties getLinkProperties() { return mLinkProperties; } /** * @return The data profile of this data network. */ - public @NonNull DataProfile getDataProfile() { + @NonNull + public DataProfile getDataProfile() { return mDataProfile; } @@ -2600,7 +2658,8 @@ public class DataNetwork extends StateMachine { * * @return The fail cause. {@link DataFailCause#NONE} if succeeds. */ - private @DataFailureCause int getFailCauseFromDataCallResponse( + @DataFailureCause + private int getFailCauseFromDataCallResponse( @DataServiceCallback.ResultCode int resultCode, @Nullable DataCallResponse response) { int failCause = DataFailCause.NONE; switch (resultCode) { @@ -2631,7 +2690,8 @@ public class DataNetwork extends StateMachine { * * @param response The data call response from data service. */ - private void updateDataNetwork(@NonNull DataCallResponse response) { + private void updateDataNetwork(@Nullable DataCallResponse response) { + if (response == null) return; mCid.put(mTransport, response.getId()); LinkProperties linkProperties = new LinkProperties(); @@ -2937,8 +2997,8 @@ public class DataNetwork extends StateMachine { * will be performed. {@code null} if the data network is already disconnected or being * disconnected. */ - public @Nullable Runnable tearDownWhenConditionMet(@TearDownReason int reason, - long timeoutMillis) { + @Nullable + public Runnable tearDownWhenConditionMet(@TearDownReason int reason, long timeoutMillis) { if (getCurrentState() == null || isDisconnected() || isDisconnecting()) { loge("tearDownWhenConditionMet: Not in the right state. State=" + getCurrentState()); return null; @@ -3201,7 +3261,8 @@ public class DataNetwork extends StateMachine { /** * @return The current network type reported by the network service. */ - private @NetworkType int getDataNetworkType() { + @NetworkType + private int getDataNetworkType() { return getDataNetworkType(mTransport); } @@ -3211,7 +3272,8 @@ public class DataNetwork extends StateMachine { * @param transport The transport. * @return The data network type. */ - private @NetworkType int getDataNetworkType(@TransportType int transport) { + @NetworkType + private int getDataNetworkType(@TransportType int transport) { // WLAN transport can't have network type other than IWLAN. Ideally service state tracker // should report the correct RAT, but sometimes race condition could happen that service // state is reset to out of service and RAT not updated to IWLAN yet. @@ -3231,7 +3293,8 @@ public class DataNetwork extends StateMachine { /** * @return The physical link status (i.e. RRC state). */ - public @LinkStatus int getLinkStatus() { + @LinkStatus + public int getLinkStatus() { return mLinkStatus; } @@ -3254,7 +3317,8 @@ public class DataNetwork extends StateMachine { /** * @return Network registration info on the current transport. */ - private @Nullable NetworkRegistrationInfo getNetworkRegistrationInfo() { + @Nullable + private NetworkRegistrationInfo getNetworkRegistrationInfo() { NetworkRegistrationInfo nri = mPhone.getServiceStateTracker().getServiceState() .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS, mTransport); if (nri == null) { @@ -3276,7 +3340,8 @@ public class DataNetwork extends StateMachine { * * @see #getPriority() */ - public @NetCapability int getApnTypeNetworkCapability() { + @NetCapability + public int getApnTypeNetworkCapability() { if (!mAttachedNetworkRequestList.isEmpty()) { // The highest priority network request is always at the top of list. return mAttachedNetworkRequestList.get(0).getApnTypeNetworkCapability(); @@ -3317,7 +3382,8 @@ public class DataNetwork extends StateMachine { /** * @return The attached network request list. */ - public @NonNull NetworkRequestList getAttachedNetworkRequestList() { + @NonNull + public NetworkRequestList getAttachedNetworkRequestList() { return mAttachedNetworkRequestList; } @@ -3366,11 +3432,13 @@ public class DataNetwork extends StateMachine { /** * @return The current transport of the data network. */ - public @TransportType int getTransport() { + @TransportType + public int getTransport() { return mTransport; } - private @DataState int getState() { + @DataState + private int getState() { IState state = getCurrentState(); if (state == null || isDisconnected()) { return TelephonyManager.DATA_DISCONNECTED; @@ -3429,7 +3497,7 @@ public class DataNetwork extends StateMachine { /** * Send the precise data connection state to the listener of * {@link android.telephony.TelephonyCallback.PreciseDataConnectionStateListener}. - * + * <p> * Note that notify only when {@link DataState} or {@link * PreciseDataConnectionState.NetworkValidationStatus} or {@link TelephonyNetworkAgent#getId} * changes. @@ -3449,7 +3517,7 @@ public class DataNetwork extends StateMachine { /** * Request the data network to handover to the target transport. - * + * <p> * This is the starting point of initiating IWLAN/cellular handover. It will first call * {@link DataServiceManager#startHandover(int, Message)} to notify source transport that * handover is about to start, and then call {@link DataServiceManager#setupDataCall(int, @@ -3660,7 +3728,8 @@ public class DataNetwork extends StateMachine { /** * @return The last known data network type of the data network. */ - public @NetworkType int getLastKnownDataNetworkType() { + @NetworkType + public int getLastKnownDataNetworkType() { return mLastKnownDataNetworkType; } @@ -3674,7 +3743,8 @@ public class DataNetwork extends StateMachine { /** * @return The PCO data received from the network. */ - public @NonNull Map<Integer, PcoData> getPcoData() { + @NonNull + public Map<Integer, PcoData> getPcoData() { if (mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN || mCid.get(mTransport) == INVALID_CID) { return Collections.emptyMap(); @@ -3794,7 +3864,8 @@ public class DataNetwork extends StateMachine { * @param reason Data deactivation reason. * @return The deactivation reason in string format. */ - public static @NonNull String tearDownReasonToString(@TearDownReason int reason) { + @NonNull + public static String tearDownReasonToString(@TearDownReason int reason) { return switch (reason) { case TEAR_DOWN_REASON_NONE -> "NONE"; case TEAR_DOWN_REASON_CONNECTIVITY_SERVICE_UNWANTED -> "CONNECTIVITY_SERVICE_UNWANTED"; @@ -3849,7 +3920,8 @@ public class DataNetwork extends StateMachine { * @param event The event * @return The event in string format. */ - private static @NonNull String eventToString(int event) { + @NonNull + private static String eventToString(int event) { return switch (event) { case EVENT_DATA_CONFIG_UPDATED -> "EVENT_DATA_CONFIG_UPDATED"; case EVENT_ATTACH_NETWORK_REQUEST -> "EVENT_ATTACH_NETWORK_REQUEST"; @@ -3897,7 +3969,8 @@ public class DataNetwork extends StateMachine { /** * @return The short name of the data network (e.g. DN-C-1) */ - public @NonNull String name() { + @NonNull + public String name() { return mLogTag; } diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java index 3104d9ef6f..008da1487e 100644 --- a/src/java/com/android/internal/telephony/data/DataNetworkController.java +++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java @@ -92,6 +92,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.SlidingWindowEventCounter; +import com.android.internal.telephony.TelephonyCapabilities; import com.android.internal.telephony.TelephonyComponentFactory; import com.android.internal.telephony.data.AccessNetworksManager.AccessNetworksManagerCallback; import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback; @@ -266,17 +267,26 @@ public class DataNetworkController extends Handler { private final String mLogTag; private final LocalLog mLocalLog = new LocalLog(128); - private final @NonNull DataConfigManager mDataConfigManager; - private final @NonNull DataSettingsManager mDataSettingsManager; - private final @NonNull DataProfileManager mDataProfileManager; - private final @NonNull DataStallRecoveryManager mDataStallRecoveryManager; - private final @NonNull AccessNetworksManager mAccessNetworksManager; - private final @NonNull DataRetryManager mDataRetryManager; - private final @NonNull ImsManager mImsManager; - private final @NonNull TelecomManager mTelecomManager; - private final @NonNull NetworkPolicyManager mNetworkPolicyManager; - private final @NonNull SparseArray<DataServiceManager> mDataServiceManagers = - new SparseArray<>(); + @NonNull + private final DataConfigManager mDataConfigManager; + @NonNull + private final DataSettingsManager mDataSettingsManager; + @NonNull + private final DataProfileManager mDataProfileManager; + @NonNull + private final DataStallRecoveryManager mDataStallRecoveryManager; + @NonNull + private final AccessNetworksManager mAccessNetworksManager; + @NonNull + private final DataRetryManager mDataRetryManager; + @NonNull + private final ImsManager mImsManager; + @NonNull + private final TelecomManager mTelecomManager; + @NonNull + private final NetworkPolicyManager mNetworkPolicyManager; + @NonNull + private final SparseArray<DataServiceManager> mDataServiceManagers = new SparseArray<>(); /** The subscription index associated with this data network controller. */ private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; @@ -284,35 +294,41 @@ public class DataNetworkController extends Handler { /** The current service state of the device. */ // Note that keeping a copy here instead of directly using ServiceStateTracker.getServiceState() // is intended for detecting the delta. - private @NonNull ServiceState mServiceState; + @NonNull + private ServiceState mServiceState; /** The list of SubscriptionPlans, updated when initialized and when plans are changed. */ - private final @NonNull List<SubscriptionPlan> mSubscriptionPlans = new ArrayList<>(); + @NonNull + private final List<SubscriptionPlan> mSubscriptionPlans = new ArrayList<>(); /** * The set of network types an unmetered override applies to, set by onSubscriptionOverride * and cleared when the device is rebooted or the override expires. */ - private final @NonNull @NetworkType Set<Integer> mUnmeteredOverrideNetworkTypes = - new ArraySet<>(); + @NonNull + @NetworkType + private final Set<Integer> mUnmeteredOverrideNetworkTypes = new ArraySet<>(); /** * The set of network types a congested override applies to, set by onSubscriptionOverride * and cleared when the device is rebooted or the override expires. */ - private final @NonNull @NetworkType Set<Integer> mCongestedOverrideNetworkTypes = - new ArraySet<>(); + @NonNull + @NetworkType + private final Set<Integer> mCongestedOverrideNetworkTypes = new ArraySet<>(); /** * The list of all network requests. */ - private final @NonNull NetworkRequestList mAllNetworkRequestList = new NetworkRequestList(); + @NonNull + private final NetworkRequestList mAllNetworkRequestList = new NetworkRequestList(); /** * The current data network list, including the ones that are connected, connecting, or * disconnecting. */ - private final @NonNull List<DataNetwork> mDataNetworkList = new ArrayList<>(); + @NonNull + private final List<DataNetwork> mDataNetworkList = new ArrayList<>(); /** {@code true} indicating at least one data network exists. */ private boolean mAnyDataNetworkExisting; @@ -320,27 +336,33 @@ public class DataNetworkController extends Handler { /** * Contain the last 10 data networks that were connected. This is for debugging purposes only. */ - private final @NonNull List<DataNetwork> mPreviousConnectedDataNetworkList = new ArrayList<>(); + @NonNull + private final List<DataNetwork> mPreviousConnectedDataNetworkList = new ArrayList<>(); /** * The internet data network state. Note that this is the best effort if more than one * data network supports internet. */ - private @DataState int mInternetDataNetworkState = TelephonyManager.DATA_DISCONNECTED; + @DataState + private int mInternetDataNetworkState = TelephonyManager.DATA_DISCONNECTED; /** All the current connected/handover internet networks. */ - @NonNull private Set<DataNetwork> mConnectedInternetNetworks = new HashSet<>(); + @NonNull + private Set<DataNetwork> mConnectedInternetNetworks = new HashSet<>(); /** * The IMS data network state. For now this is just for debugging purposes. */ - private @DataState int mImsDataNetworkState = TelephonyManager.DATA_DISCONNECTED; + @DataState + private int mImsDataNetworkState = TelephonyManager.DATA_DISCONNECTED; /** Overall aggregated link status from internet data networks. */ - private @LinkStatus int mInternetLinkStatus = DataCallResponse.LINK_STATUS_UNKNOWN; + @LinkStatus + private int mInternetLinkStatus = DataCallResponse.LINK_STATUS_UNKNOWN; /** Data network controller callbacks. */ - private final @NonNull Set<DataNetworkControllerCallback> mDataNetworkControllerCallbacks = + @NonNull + private final Set<DataNetworkControllerCallback> mDataNetworkControllerCallbacks = new ArraySet<>(); /** Indicates if packet switch data is restricted by the cellular network. */ @@ -356,48 +378,59 @@ public class DataNetworkController extends Handler { * Indicates if the data services are bound. Key if the transport type, and value is the boolean * indicating service is bound or not. */ - private final @NonNull SparseBooleanArray mDataServiceBound = new SparseBooleanArray(); + @NonNull + private final SparseBooleanArray mDataServiceBound = new SparseBooleanArray(); /** SIM state. */ - private @SimState int mSimState = TelephonyManager.SIM_STATE_UNKNOWN; + @SimState + private int mSimState = TelephonyManager.SIM_STATE_UNKNOWN; /** Data activity. */ - private @DataActivityType int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE; + @DataActivityType + private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE; /** * IMS state callbacks. Key is the IMS feature, value is the callback. */ - private final @NonNull SparseArray<ImsStateCallback> mImsStateCallbacks = new SparseArray<>(); + @NonNull + private final SparseArray<ImsStateCallback> mImsStateCallbacks = new SparseArray<>(); /** Registered IMS features. Unregistered IMS features are removed from the set. */ - private final @NonNull Set<Integer> mRegisteredImsFeatures = new ArraySet<>(); + @NonNull + private final Set<Integer> mRegisteredImsFeatures = new ArraySet<>(); /** IMS feature package names. Key is the IMS feature, value is the package name. */ - private final @NonNull SparseArray<String> mImsFeaturePackageName = new SparseArray<>(); + @NonNull + private final SparseArray<String> mImsFeaturePackageName = new SparseArray<>(); /** * Networks that are pending IMS de-registration. Key is the data network, value is the function * to tear down the network. */ - private final @NonNull Map<DataNetwork, Runnable> mPendingImsDeregDataNetworks = - new ArrayMap<>(); + @NonNull + private final Map<DataNetwork, Runnable> mPendingImsDeregDataNetworks = new ArrayMap<>(); /** * IMS feature registration callback. The key is the IMS feature, the value is the registration * callback. When new SIM inserted, the old callbacks associated with the old subscription index * will be unregistered. */ - private final @NonNull SparseArray<RegistrationManager.RegistrationCallback> + @NonNull + private final SparseArray<RegistrationManager.RegistrationCallback> mImsFeatureRegistrationCallbacks = new SparseArray<>(); /** The counter to detect back to back release/request IMS network. */ - private @NonNull SlidingWindowEventCounter mImsThrottleCounter; + @NonNull + private SlidingWindowEventCounter mImsThrottleCounter; /** Event counter for unwanted network within time window, is used to trigger anomaly report. */ - private @NonNull SlidingWindowEventCounter mNetworkUnwantedCounter; + @NonNull + private SlidingWindowEventCounter mNetworkUnwantedCounter; /** Event counter for WLAN setup data failure within time window to trigger anomaly report. */ - private @NonNull SlidingWindowEventCounter mSetupDataCallWlanFailureCounter; + @NonNull + private SlidingWindowEventCounter mSetupDataCallWlanFailureCounter; /** Event counter for WWAN setup data failure within time window to trigger anomaly report. */ - private @NonNull SlidingWindowEventCounter mSetupDataCallWwanFailureCounter; + @NonNull + private SlidingWindowEventCounter mSetupDataCallWwanFailureCounter; /** * The capabilities of the latest released IMS request. To detect back to back release/request @@ -408,7 +441,8 @@ public class DataNetworkController extends Handler { /** True after try to release an IMS network; False after try to request an IMS network. */ private boolean mLastImsOperationIsRelease; - private final @NonNull FeatureFlags mFeatureFlags; + @NonNull + private final FeatureFlags mFeatureFlags; /** The broadcast receiver. */ private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { @@ -429,7 +463,7 @@ public class DataNetworkController extends Handler { }; private boolean hasCalling() { - if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true; + if (!TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)) return true; return mPhone.getContext().getPackageManager().hasSystemFeature( PackageManager.FEATURE_TELEPHONY_CALLING); } @@ -437,7 +471,7 @@ public class DataNetworkController extends Handler { /** * The sorted network request list by priority. The highest priority network request stays at * the head of the list. The highest priority is 100, the lowest is 0. - * + * <p> * Note this list is not thread-safe. Do not access the list from different threads. */ @VisibleForTesting @@ -520,7 +554,8 @@ public class DataNetworkController extends Handler { * @return The first network request in the list that contains all the provided * capabilities. */ - public @Nullable TelephonyNetworkRequest get(@NonNull @NetCapability int[] netCaps) { + @Nullable + public TelephonyNetworkRequest get(@NonNull @NetCapability int[] netCaps) { int index = 0; while (index < size()) { TelephonyNetworkRequest networkRequest = get(index); @@ -529,7 +564,7 @@ public class DataNetworkController extends Handler { .boxed() .collect(Collectors.toSet()) .containsAll(Arrays.stream(netCaps).boxed() - .collect(Collectors.toList()))) { + .toList())) { return networkRequest; } index++; @@ -560,6 +595,16 @@ public class DataNetworkController extends Handler { } /** + * Print "capabilities - connectivity transport". e.g. INTERNET|NOT_RESTRICTED-SATELLITE + */ + @NonNull + public String toStringSimplified() { + return size() > 0 ? DataUtils.networkCapabilitiesToString(get(0).getCapabilities()) + + "-" + DataUtils.connectivityTransportsToString(get(0).getTransportTypes()) + : ""; + } + + /** * Dump the network request list. * * @param pw print writer. @@ -697,19 +742,26 @@ public class DataNetworkController extends Handler { private static final String RULE_TAG_ROAMING = "roaming"; /** Handover rule type. */ - public final @HandoverRuleType int type; + @HandoverRuleType + public final int type; /** The applicable source access networks for handover. */ - public final @NonNull @RadioAccessNetworkType Set<Integer> sourceAccessNetworks; + @NonNull + @RadioAccessNetworkType + public final Set<Integer> sourceAccessNetworks; /** The applicable target access networks for handover. */ - public final @NonNull @RadioAccessNetworkType Set<Integer> targetAccessNetworks; + @NonNull + @RadioAccessNetworkType + public final Set<Integer> targetAccessNetworks; /** * The network capabilities to any of which this handover rule applies. * If is empty, then capability is ignored as a rule matcher. */ - public final @NonNull @NetCapability Set<Integer> networkCapabilities; + @NonNull + @NetCapability + public final Set<Integer> networkCapabilities; /** {@code true} indicates this policy is only applicable when the device is roaming. */ public final boolean isOnlyForRoaming; @@ -1186,7 +1238,7 @@ public class DataNetworkController extends Handler { mSubscriptionPlans.clear(); mSubscriptionPlans.addAll(Arrays.asList(plans)); mDataNetworkControllerCallbacks.forEach(cb -> cb.invokeFromExecutor( - () -> cb.onSubscriptionPlanOverride())); + cb::onSubscriptionPlanOverride)); break; case EVENT_SUBSCRIPTION_OVERRIDE: int overrideMask = msg.arg1; @@ -1206,7 +1258,7 @@ public class DataNetworkController extends Handler { } } mDataNetworkControllerCallbacks.forEach(cb -> cb.invokeFromExecutor( - () -> cb.onSubscriptionPlanOverride())); + cb::onSubscriptionPlanOverride)); } else if (overrideMask == NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED) { log("Congested subscription override: override=" + override + ", networkTypes=" + Arrays.stream(networkTypes) @@ -1220,7 +1272,7 @@ public class DataNetworkController extends Handler { } } mDataNetworkControllerCallbacks.forEach(cb -> cb.invokeFromExecutor( - () -> cb.onSubscriptionPlanOverride())); + cb::onSubscriptionPlanOverride)); } else { loge("Unknown override mask: " + overrideMask); } @@ -1359,28 +1411,6 @@ public class DataNetworkController extends Handler { // When reaching here, it means this data network can satisfy all the network requests. logv("Found a compatible data network " + dataNetwork + ". Attaching " + requestList); - - // If WLAN preferred, see whether a more suitable data profile shall be used to satisfy - // a short-lived request that doesn't perform handover. - int capability = requestList.getFirst().getApnTypeNetworkCapability(); - int preferredTransport = mAccessNetworksManager - .getPreferredTransportByNetworkCapability(capability); - if (capability == NetworkCapabilities.NET_CAPABILITY_MMS - && preferredTransport != dataNetwork.getTransport() - && preferredTransport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) { - DataProfile candidate = mDataProfileManager - .getDataProfileForNetworkRequest(requestList.getFirst(), - TelephonyManager.NETWORK_TYPE_IWLAN, - mServiceState.isUsingNonTerrestrialNetwork(), - isEsimBootStrapProvisioningActivated(), - false/*ignorePermanentFailure*/); - if (candidate != null && !dataNetwork.getDataProfile().equals(candidate)) { - logv("But skipped because found better data profile " + candidate - + DataUtils.networkCapabilityToString(capability) + " preferred on " - + AccessNetworkConstants.transportTypeToString(preferredTransport)); - continue; - } - } return dataNetwork.attachNetworkRequests(requestList); } return false; @@ -1452,6 +1482,19 @@ public class DataNetworkController extends Handler { * still allowed in this case. */ public boolean isInternetDataAllowed(boolean ignoreExistingNetworks) { + return !getInternetEvaluation(ignoreExistingNetworks).containsDisallowedReasons(); + } + + /** + * @param ignoreExistingNetworks {@code true} to skip the existing network check. + * @return The internet evaluation result. + * For example, if SIM is absent, or airplane mode is on, then data is NOT allowed. + * This API does not reflect the currently internet data network status. It's possible there is + * no internet data due to weak cellular signal or network side issue, but internet data is + * still allowed in this case. + */ + @NonNull + public DataEvaluation getInternetEvaluation(boolean ignoreExistingNetworks) { TelephonyNetworkRequest internetRequest = new TelephonyNetworkRequest( new NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) @@ -1463,7 +1506,7 @@ public class DataNetworkController extends Handler { && mDataNetworkList.stream().anyMatch( dataNetwork -> internetRequest.canBeSatisfiedBy( dataNetwork.getNetworkCapabilities()))) { - return true; + return new DataEvaluation(DataEvaluationReason.EXTERNAL_QUERY); } // If no existing network can satisfy the request, then check if we can possibly setup @@ -1471,17 +1514,19 @@ public class DataNetworkController extends Handler { DataEvaluation evaluation = evaluateNetworkRequest(internetRequest, DataEvaluationReason.EXTERNAL_QUERY); - if (evaluation.containsOnly(DataDisallowedReason.ONLY_ALLOWED_SINGLE_NETWORK)) { + if (evaluation.containsOnly(DataDisallowedReason.ONLY_ALLOWED_SINGLE_NETWORK) + && internetRequest.getPriority() > mDataNetworkList.stream() + .map(DataNetwork::getPriority) + .max(Comparator.comparing(Integer::valueOf)) + .orElse(0)) { // If the only failed reason is only single network allowed, then check if the request // can trump the current network. - return internetRequest.getPriority() > mDataNetworkList.stream() - .map(DataNetwork::getPriority) - .max(Comparator.comparing(Integer::valueOf)) - .orElse(0); + evaluation.addDataAllowedReason(DataAllowedReason.NORMAL); } - return !evaluation.containsDisallowedReasons(); + return evaluation; } + /** * @return {@code true} if internet is unmetered. */ @@ -1510,7 +1555,8 @@ public class DataNetworkController extends Handler { * @return List of the reasons why internet data is not allowed. An empty list if internet * is allowed. */ - public @NonNull List<DataDisallowedReason> getInternetDataDisallowedReasons() { + @NonNull + public List<DataDisallowedReason> getInternetDataDisallowedReasons() { TelephonyNetworkRequest internetRequest = new TelephonyNetworkRequest( new NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) @@ -1528,7 +1574,8 @@ public class DataNetworkController extends Handler { * @param reason The reason for evaluation. * @return The data evaluation result. */ - private @NonNull DataEvaluation evaluateNetworkRequest( + @NonNull + private DataEvaluation evaluateNetworkRequest( @NonNull TelephonyNetworkRequest networkRequest, DataEvaluationReason reason) { DataEvaluation evaluation = new DataEvaluation(reason); int transport = mAccessNetworksManager.getPreferredTransportByNetworkCapability( @@ -1746,7 +1793,7 @@ public class DataNetworkController extends Handler { networkRequest.setEvaluation(evaluation); // EXTERNAL_QUERY generates too many log spam. if (reason != DataEvaluationReason.EXTERNAL_QUERY) { - log(evaluation.toString() + ", network type=" + log(evaluation + ", network type=" + TelephonyManager.getNetworkTypeName(getDataNetworkType(transport)) + ", reg state=" + NetworkRegistrationInfo.registrationStateToString( @@ -1820,7 +1867,8 @@ public class DataNetworkController extends Handler { * @return The grouped unsatisfied network requests. The network requests that have the same * network capabilities is grouped into one {@link NetworkRequestList}. */ - private @NonNull List<NetworkRequestList> getGroupedUnsatisfiedNetworkRequests() { + @NonNull + private List<NetworkRequestList> getGroupedUnsatisfiedNetworkRequests() { NetworkRequestList networkRequestList = new NetworkRequestList(); for (TelephonyNetworkRequest networkRequest : mAllNetworkRequestList) { if (networkRequest.getState() == TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED) { @@ -1841,8 +1889,7 @@ public class DataNetworkController extends Handler { log("Re-evaluating " + networkRequestLists.stream().mapToInt(List::size).sum() + " unsatisfied network requests in " + networkRequestLists.size() + " groups, " + networkRequestLists.stream().map( - requestList -> DataUtils.networkCapabilitiesToString( - requestList.get(0).getCapabilities())) + NetworkRequestList::toStringSimplified) .collect(Collectors.joining(", ")) + " due to " + reason); // Second, see if any existing network can satisfy those network requests. @@ -1875,7 +1922,8 @@ public class DataNetworkController extends Handler { * * @return The data evaluation result. */ - private @NonNull DataEvaluation evaluateDataNetwork(@NonNull DataNetwork dataNetwork, + @NonNull + private DataEvaluation evaluateDataNetwork(@NonNull DataNetwork dataNetwork, @NonNull DataEvaluationReason reason) { DataEvaluation evaluation = new DataEvaluation(reason); // Bypass all checks for emergency data network. @@ -2116,35 +2164,30 @@ public class DataNetworkController extends Handler { */ private boolean canConnectivityTransportSatisfyNetworkRequest( @NonNull TelephonyNetworkRequest networkRequest, @TransportType int transport) { + // Check if this is a IWLAN network request. + if (transport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) { + // If the request would result in bringing up network on IWLAN, then no + // need to check if the device is using satellite network. + return true; + } + // When the device is on satellite, only restricted network request can request network. if (mServiceState.isUsingNonTerrestrialNetwork() - && networkRequest.getNativeNetworkRequest().hasCapability( + && networkRequest.hasCapability( NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)) { return false; } // If the network request does not specify cellular or satellite, then it can be // satisfied when the device is either on cellular ot satellite. - if (!networkRequest.getNativeNetworkRequest().hasTransport( - NetworkCapabilities.TRANSPORT_CELLULAR) - && !networkRequest.getNativeNetworkRequest().hasTransport( - NetworkCapabilities.TRANSPORT_SATELLITE)) { - return true; - } - - // Check if this is a IWLAN network request. - if (networkRequest.getNativeNetworkRequest().hasTransport( - NetworkCapabilities.TRANSPORT_CELLULAR) - && transport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) { - // If the cellular request would result in bringing up network on IWLAN, then no - // need to check if the device is using satellite network. + if (!networkRequest.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) + && !networkRequest.hasTransport(NetworkCapabilities.TRANSPORT_SATELLITE)) { return true; } // As a short term solution, allowing some networks to be always marked as cellular // transport if certain capabilities are in the network request. - if (networkRequest.getNativeNetworkRequest().hasTransport( - NetworkCapabilities.TRANSPORT_CELLULAR) && Arrays.stream( + if (networkRequest.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) && Arrays.stream( networkRequest.getCapabilities()) .anyMatch(mDataConfigManager.getForcedCellularTransportCapabilities()::contains)) { return true; @@ -2154,11 +2197,9 @@ public class DataNetworkController extends Handler { // the network is satellite, then the request must specify satellite transport and // restricted. return (mServiceState.isUsingNonTerrestrialNetwork() - && networkRequest.getNativeNetworkRequest().hasTransport( - NetworkCapabilities.TRANSPORT_SATELLITE)) + && networkRequest.hasTransport(NetworkCapabilities.TRANSPORT_SATELLITE)) || (!mServiceState.isUsingNonTerrestrialNetwork() - && networkRequest.getNativeNetworkRequest().hasTransport( - NetworkCapabilities.TRANSPORT_CELLULAR)); + && networkRequest.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)); } /** @@ -2221,7 +2262,8 @@ public class DataNetworkController extends Handler { * * @see CarrierConfigManager#KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY */ - private @NonNull DataEvaluation evaluateDataNetworkHandover(@NonNull DataNetwork dataNetwork) { + @NonNull + private DataEvaluation evaluateDataNetworkHandover(@NonNull DataNetwork dataNetwork) { DataEvaluation dataEvaluation = new DataEvaluation(DataEvaluationReason.DATA_HANDOVER); if (!dataNetwork.isConnecting() && !dataNetwork.isConnected()) { dataEvaluation.addDataDisallowedReason(DataDisallowedReason.ILLEGAL_STATE); @@ -2279,10 +2321,7 @@ public class DataNetworkController extends Handler { sourceNetworkType); NetworkRegistrationInfo nri = mServiceState.getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); - boolean isWwanInService = false; - if (nri != null && nri.isInService()) { - isWwanInService = true; - } + boolean isWwanInService = nri != null && nri.isInService(); // If WWAN is inService, use the real roaming state reported by modem instead of // using the overridden roaming state, otherwise get last known roaming state stored // in data network. @@ -2344,7 +2383,8 @@ public class DataNetworkController extends Handler { * {@link #evaluateDataNetwork(DataNetwork, DataEvaluationReason)}. * @return The tear down reason. */ - private static @TearDownReason int getTearDownReason(@NonNull DataEvaluation dataEvaluation) { + @TearDownReason + private static int getTearDownReason(@NonNull DataEvaluation dataEvaluation) { if (dataEvaluation.containsDisallowedReasons()) { switch (dataEvaluation.getDataDisallowedReasons().get(0)) { case DATA_DISABLED: @@ -2545,14 +2585,14 @@ public class DataNetworkController extends Handler { RegistrationManager.RegistrationCallback callback = new RegistrationManager.RegistrationCallback() { @Override - public void onRegistered(ImsRegistrationAttributes attributes) { + public void onRegistered(@NonNull ImsRegistrationAttributes attributes) { log("IMS " + DataUtils.imsFeatureToString(imsFeature) + " registered. Attributes=" + attributes); mRegisteredImsFeatures.add(imsFeature); } @Override - public void onUnregistered(ImsReasonInfo info) { + public void onUnregistered(@NonNull ImsReasonInfo info) { log("IMS " + DataUtils.imsFeatureToString(imsFeature) + " deregistered. Info=" + info); mRegisteredImsFeatures.remove(imsFeature); @@ -2760,8 +2800,8 @@ public class DataNetworkController extends Handler { * @param dataProfile The data profile. * @return The network requests list. */ - private @NonNull NetworkRequestList findSatisfiableNetworkRequests( - @NonNull DataProfile dataProfile) { + @NonNull + private NetworkRequestList findSatisfiableNetworkRequests(@NonNull DataProfile dataProfile) { return new NetworkRequestList(mAllNetworkRequestList.stream() .filter(request -> request.getState() == TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED) @@ -3060,8 +3100,18 @@ public class DataNetworkController extends Handler { List<NetworkRequestList> groupRequestLists = getGroupedUnsatisfiedNetworkRequests(); dataSetupRetryEntry.networkRequestList.stream() .filter(request -> groupRequestLists.stream() - .anyMatch(groupRequestList -> groupRequestList - .get(request.getCapabilities()) != null)) + .anyMatch(groupRequestList -> { + // The unsatisfied request has all the requested capabilities. + if (groupRequestList.get(request.getCapabilities()) == null) { + return false; + } + TelephonyNetworkRequest leading = groupRequestList.getFirst(); + // The unsatisfied request covers all the requested transports. + return leading.getTransportTypes().length == 0 + || request.getTransportTypes().length == 0 + || Arrays.stream(request.getTransportTypes()) + .allMatch(leading::hasTransport); + })) .forEach(requestList::add); } if (requestList.isEmpty()) { @@ -3701,17 +3751,13 @@ public class DataNetworkController extends Handler { DataSpecificRegistrationInfo newDsri = newNri.getDataSpecificInfo(); if (newDsri == null) return false; - if ((oldDsri == null || oldDsri.getVopsSupportInfo() == null + // If previously VoPS was supported (or does not exist), and now the network reports + // VoPS not supported, we should evaluate existing data networks to see if they need + // to be torn down. + return (oldDsri == null || oldDsri.getVopsSupportInfo() == null || oldDsri.getVopsSupportInfo().isVopsSupported()) && (newDsri.getVopsSupportInfo() != null && !newDsri.getVopsSupportInfo() - .isVopsSupported())) { - // If previously VoPS was supported (or does not exist), and now the network reports - // VoPS not supported, we should evaluate existing data networks to see if they need - // to be torn down. - return true; - } - - return false; + .isVopsSupported()); } /** @@ -3758,17 +3804,13 @@ public class DataNetworkController extends Handler { DataSpecificRegistrationInfo newDsri = newPsNri.getDataSpecificInfo(); if (oldDsri == null) return false; - if ((newDsri == null || newDsri.getVopsSupportInfo() == null + // If previously VoPS was not supported, and now the network reports + // VoPS supported (or does not report), we should evaluate the unsatisfied network + // request to see if the can be satisfied again. + return (newDsri == null || newDsri.getVopsSupportInfo() == null || newDsri.getVopsSupportInfo().isVopsSupported()) && (oldDsri.getVopsSupportInfo() != null && !oldDsri.getVopsSupportInfo() - .isVopsSupported())) { - // If previously VoPS was not supported, and now the network reports - // VoPS supported (or does not report), we should evaluate the unsatisfied network - // request to see if the can be satisfied again. - return true; - } - - return false; + .isVopsSupported()); } /** @@ -3879,28 +3921,32 @@ public class DataNetworkController extends Handler { /** * @return Data config manager instance. */ - public @NonNull DataConfigManager getDataConfigManager() { + @NonNull + public DataConfigManager getDataConfigManager() { return mDataConfigManager; } /** * @return Data profile manager instance. */ - public @NonNull DataProfileManager getDataProfileManager() { + @NonNull + public DataProfileManager getDataProfileManager() { return mDataProfileManager; } /** * @return Data settings manager instance. */ - public @NonNull DataSettingsManager getDataSettingsManager() { + @NonNull + public DataSettingsManager getDataSettingsManager() { return mDataSettingsManager; } /** * @return Data retry manager instance. */ - public @NonNull DataRetryManager getDataRetryManager() { + @NonNull + public DataRetryManager getDataRetryManager() { return mDataRetryManager; } @@ -3908,7 +3954,8 @@ public class DataNetworkController extends Handler { * @return The list of SubscriptionPlans */ @VisibleForTesting - public @NonNull List<SubscriptionPlan> getSubscriptionPlans() { + @NonNull + public List<SubscriptionPlan> getSubscriptionPlans() { return mSubscriptionPlans; } @@ -3916,7 +3963,9 @@ public class DataNetworkController extends Handler { * @return The set of network types an unmetered override applies to */ @VisibleForTesting - public @NonNull @NetworkType Set<Integer> getUnmeteredOverrideNetworkTypes() { + @NonNull + @NetworkType + public Set<Integer> getUnmeteredOverrideNetworkTypes() { return mUnmeteredOverrideNetworkTypes; } @@ -3924,7 +3973,9 @@ public class DataNetworkController extends Handler { * @return The set of network types a congested override applies to */ @VisibleForTesting - public @NonNull @NetworkType Set<Integer> getCongestedOverrideNetworkTypes() { + @NonNull + @NetworkType + public Set<Integer> getCongestedOverrideNetworkTypes() { return mCongestedOverrideNetworkTypes; } @@ -3934,7 +3985,8 @@ public class DataNetworkController extends Handler { * @param transport The transport. * @return The current network type. */ - private @NetworkType int getDataNetworkType(@TransportType int transport) { + @NetworkType + private int getDataNetworkType(@TransportType int transport) { NetworkRegistrationInfo nri = mServiceState.getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, transport); if (nri != null) { @@ -3950,8 +4002,8 @@ public class DataNetworkController extends Handler { * @param transport The transport. * @return The registration state. */ - private @RegistrationState int getDataRegistrationState(@NonNull ServiceState ss, - @TransportType int transport) { + @RegistrationState + private int getDataRegistrationState(@NonNull ServiceState ss, @TransportType int transport) { NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, transport); if (nri != null) { @@ -3963,7 +4015,8 @@ public class DataNetworkController extends Handler { /** * @return The data activity. Note this is only updated when screen is on. */ - public @DataActivityType int getDataActivity() { + @DataActivityType + public int getDataActivity() { return mDataActivity; } @@ -4109,14 +4162,16 @@ public class DataNetworkController extends Handler { * * @return The data network state. */ - public @DataState int getInternetDataNetworkState() { + @DataState + public int getInternetDataNetworkState() { return mInternetDataNetworkState; } /** * @return List of bound data service packages name on WWAN and WLAN. */ - public @NonNull List<String> getDataServicePackages() { + @NonNull + public List<String> getDataServicePackages() { List<String> packages = new ArrayList<>(); for (int i = 0; i < mDataServiceManagers.size(); i++) { packages.add(mDataServiceManagers.valueAt(i).getDataServicePackageName()); @@ -4126,8 +4181,8 @@ public class DataNetworkController extends Handler { /** * Request network validation. - * - * Nnetwork validation request is sent to the DataNetwork that matches the network capability + * <p> + * Network validation request is sent to the DataNetwork that matches the network capability * in the list of DataNetwork owned by the DNC. * * @param capability network capability {@link NetCapability} diff --git a/src/java/com/android/internal/telephony/data/DataProfileManager.java b/src/java/com/android/internal/telephony/data/DataProfileManager.java index 2a2a792b97..c50d50a2bc 100644 --- a/src/java/com/android/internal/telephony/data/DataProfileManager.java +++ b/src/java/com/android/internal/telephony/data/DataProfileManager.java @@ -82,43 +82,51 @@ public class DataProfileManager extends Handler { private final LocalLog mLocalLog = new LocalLog(128); /** Data network controller. */ - private final @NonNull DataNetworkController mDataNetworkController; + @NonNull + private final DataNetworkController mDataNetworkController; /** Data config manager. */ - private final @NonNull DataConfigManager mDataConfigManager; + @NonNull + private final DataConfigManager mDataConfigManager; /** Cellular data service. */ - private final @NonNull DataServiceManager mWwanDataServiceManager; + @NonNull + private final DataServiceManager mWwanDataServiceManager; /** * All data profiles for the current carrier. Note only data profiles loaded from the APN * database will be stored here. The on-demand data profiles (generated dynamically, for * example, enterprise data profiles with differentiator) are not stored here. */ - private final @NonNull List<DataProfile> mAllDataProfiles = new ArrayList<>(); + @NonNull + private final List<DataProfile> mAllDataProfiles = new ArrayList<>(); /** The data profile used for initial attach. */ - private @Nullable DataProfile mInitialAttachDataProfile = null; + @Nullable + private DataProfile mInitialAttachDataProfile = null; /** The preferred data profile used for internet. */ - private @Nullable DataProfile mPreferredDataProfile = null; + @Nullable + private DataProfile mPreferredDataProfile = null; /** The last data profile that's successful for internet connection by subscription id. */ - private final @NonNull LruCache<Integer, DataProfile> mLastInternetDataProfiles = - new LruCache<>(256); + @NonNull + private final LruCache<Integer, DataProfile> mLastInternetDataProfiles = new LruCache<>(256); /** Preferred data profile set id. */ private int mPreferredDataProfileSetId = Telephony.Carriers.NO_APN_SET_ID; /** Data profile manager callbacks. */ - private final @NonNull Set<DataProfileManagerCallback> mDataProfileManagerCallbacks = - new ArraySet<>(); + @NonNull + private final Set<DataProfileManagerCallback> mDataProfileManagerCallbacks = new ArraySet<>(); /** SIM state. */ - private @SimState int mSimState = TelephonyManager.SIM_STATE_UNKNOWN; + @SimState + private int mSimState = TelephonyManager.SIM_STATE_UNKNOWN; /** Feature flags controlling which feature is enabled. */ - private final @NonNull FeatureFlags mFeatureFlags; + @NonNull + private final FeatureFlags mFeatureFlags; /** * Data profile manager callback. This should be only used by {@link DataNetworkController}. @@ -477,7 +485,8 @@ public class DataProfileManager extends Handler { * * @return The preferred data profile. */ - private @Nullable DataProfile getPreferredDataProfileFromDb() { + @Nullable + private DataProfile getPreferredDataProfileFromDb() { Cursor cursor = mPhone.getContext().getContentResolver().query( Uri.withAppendedPath(Telephony.Carriers.PREFERRED_APN_URI, String.valueOf(mPhone.getSubId())), null, null, null, @@ -502,7 +511,8 @@ public class DataProfileManager extends Handler { /** * @return The preferred data profile from carrier config. */ - private @Nullable DataProfile getPreferredDataProfileFromConfig() { + @Nullable + private DataProfile getPreferredDataProfileFromConfig() { // Check if there is configured default preferred data profile. String defaultPreferredApn = mDataConfigManager.getDefaultPreferredApn(); if (!TextUtils.isEmpty(defaultPreferredApn)) { @@ -586,10 +596,10 @@ public class DataProfileManager extends Handler { /** * Update the data profile used for initial attach. - * + * <p> * Note that starting from Android 13 only APNs that supports "IA" type will be used for * initial attach. Please update APN configuration file if needed. - * + * <p> * Some carriers might explicitly require that using "user-added" APN for initial * attach. In this case, exception can be configured through * {@link CarrierConfigManager#KEY_ALLOWED_INITIAL_ATTACH_APN_TYPES_STRING_ARRAY}. @@ -642,7 +652,8 @@ public class DataProfileManager extends Handler { * @param apnTypeBitmask APN type * @return The APN setting */ - private @NonNull ApnSetting buildDefaultApnSetting(@NonNull String entry, + @NonNull + private ApnSetting buildDefaultApnSetting(@NonNull String entry, @NonNull String apn, @Annotation.ApnType int apnTypeBitmask) { return new ApnSetting.Builder() .setEntryName(entry) @@ -665,7 +676,8 @@ public class DataProfileManager extends Handler { * This should be set to true for condition-based retry/setup. * @return The data profile. {@code null} if can't find any satisfiable data profile. */ - public @Nullable DataProfile getDataProfileForNetworkRequest( + @Nullable + public DataProfile getDataProfileForNetworkRequest( @NonNull TelephonyNetworkRequest networkRequest, @NetworkType int networkType, boolean isNtn, boolean isEsimBootstrapProvisioning, boolean ignorePermanentFailure) { ApnSetting apnSetting = null; @@ -736,7 +748,8 @@ public class DataProfileManager extends Handler { * This should be set to true for condition-based retry/setup. * @return The APN setting. {@code null} if can't find any satisfiable data profile. */ - private @Nullable ApnSetting getApnSettingForNetworkRequest( + @Nullable + private ApnSetting getApnSettingForNetworkRequest( @NonNull TelephonyNetworkRequest networkRequest, @NetworkType int networkType, boolean isNtn, boolean isEsimBootStrapProvisioning, boolean ignorePermanentFailure) { if (!networkRequest.hasAttribute( @@ -996,7 +1009,8 @@ public class DataProfileManager extends Handler { * * @return The merged data profile. {@code null} if merging is not possible. */ - private static @Nullable DataProfile mergeDataProfiles( + @Nullable + private static DataProfile mergeDataProfiles( @NonNull DataProfile dp1, @NonNull DataProfile dp2) { Objects.requireNonNull(dp1); Objects.requireNonNull(dp2); diff --git a/src/java/com/android/internal/telephony/data/DataRetryManager.java b/src/java/com/android/internal/telephony/data/DataRetryManager.java index 7454d01d3c..d35e9e87ea 100644 --- a/src/java/com/android/internal/telephony/data/DataRetryManager.java +++ b/src/java/com/android/internal/telephony/data/DataRetryManager.java @@ -150,53 +150,67 @@ public class DataRetryManager extends Handler { private static final int RESET_REASON_TAC_CHANGED = 6; /** The phone instance. */ - private final @NonNull Phone mPhone; + @NonNull + private final Phone mPhone; /** Featureflags. */ - private final @NonNull FeatureFlags mFlags; + @NonNull + private final FeatureFlags mFlags; /** The RIL instance. */ - private final @NonNull CommandsInterface mRil; + @NonNull + private final CommandsInterface mRil; /** Logging tag. */ - private final @NonNull String mLogTag; + @NonNull + private final String mLogTag; /** Local log. */ - private final @NonNull LocalLog mLocalLog = new LocalLog(128); + @NonNull + private final LocalLog mLocalLog = new LocalLog(128); /** Alarm Manager used to schedule long set up or handover retries. */ - private final @NonNull AlarmManager mAlarmManager; + @NonNull + private final AlarmManager mAlarmManager; /** * The data retry callback. This is only used to notify {@link DataNetworkController} to retry * setup data network. */ - private @NonNull Set<DataRetryManagerCallback> mDataRetryManagerCallbacks = new ArraySet<>(); + @NonNull + private final Set<DataRetryManagerCallback> mDataRetryManagerCallbacks = new ArraySet<>(); /** Data service managers. */ - private @NonNull SparseArray<DataServiceManager> mDataServiceManagers; + @NonNull + private final SparseArray<DataServiceManager> mDataServiceManagers; /** Data config manager instance. */ - private final @NonNull DataConfigManager mDataConfigManager; + @NonNull + private final DataConfigManager mDataConfigManager; /** Data profile manager. */ - private final @NonNull DataProfileManager mDataProfileManager; + @NonNull + private final DataProfileManager mDataProfileManager; /** Data setup retry rule list. */ - private @NonNull List<DataSetupRetryRule> mDataSetupRetryRuleList = new ArrayList<>(); + @NonNull + private List<DataSetupRetryRule> mDataSetupRetryRuleList = new ArrayList<>(); /** Data handover retry rule list. */ - private @NonNull List<DataHandoverRetryRule> mDataHandoverRetryRuleList = new ArrayList<>(); + @NonNull + private List<DataHandoverRetryRule> mDataHandoverRetryRuleList = new ArrayList<>(); /** Data retry entries. */ - private final @NonNull List<DataRetryEntry> mDataRetryEntries = new ArrayList<>(); + @NonNull + private final List<DataRetryEntry> mDataRetryEntries = new ArrayList<>(); /** * Data throttling entries. Note this only stores throttling requested by networks. We intended * not to store frameworks-initiated throttling because they are not explicit/strong throttling * requests. */ - private final @NonNull List<DataThrottlingEntry> mDataThrottlingEntries = new ArrayList<>(); + @NonNull + private final List<DataThrottlingEntry> mDataThrottlingEntries = new ArrayList<>(); /** * Represent a single data setup/handover throttling reported by networks. @@ -205,31 +219,37 @@ public class DataRetryManager extends Handler { /** * The data profile that is being throttled for setup/handover retry. */ - public final @NonNull DataProfile dataProfile; + @NonNull + public final DataProfile dataProfile; /** * The associated network request list when throttling happened. Should be {@code null} when * retry type is {@link ThrottleStatus#RETRY_TYPE_HANDOVER}. */ - public final @Nullable NetworkRequestList networkRequestList; + @Nullable + public final NetworkRequestList networkRequestList; /** * The data network that is being throttled for handover retry. Should be * {@code null} when retryType is {@link ThrottleStatus#RETRY_TYPE_NEW_CONNECTION}. */ - public final @Nullable DataNetwork dataNetwork; + @Nullable + public final DataNetwork dataNetwork; /** The transport that the data profile has been throttled on. */ - public final @TransportType int transport; + @TransportType + public final int transport; /** The retry type when throttling expires. */ - public final @RetryType int retryType; + @RetryType + public final int retryType; /** * The expiration time of data throttling. This is the time retrieved from * {@link SystemClock#elapsedRealtime()}. */ - public final @ElapsedRealtimeLong long expirationTimeMillis; + @ElapsedRealtimeLong + public final long expirationTimeMillis; /** * Constructor. @@ -257,7 +277,8 @@ public class DataRetryManager extends Handler { } @Override - public @NonNull String toString() { + @NonNull + public String toString() { return "[DataThrottlingEntry: dataProfile=" + dataProfile + ", request list=" + networkRequestList + ", dataNetwork=" + dataNetwork + ", transport=" + AccessNetworkConstants.transportTypeToString(transport) + ", expiration time=" @@ -293,13 +314,17 @@ public class DataRetryManager extends Handler { * capabilities specified here, then retry will happen. Empty set indicates the retry rule * is not using network capabilities. */ - protected @NonNull @NetCapability Set<Integer> mNetworkCapabilities = new ArraySet<>(); + @NonNull + @NetCapability + protected Set<Integer> mNetworkCapabilities = new ArraySet<>(); /** * The fail causes. If data setup failed with certain fail causes, then retry will happen. * Empty set indicates the retry rule is not using the fail causes. */ - protected @NonNull @DataFailureCause Set<Integer> mFailCauses = new ArraySet<>(); + @NonNull + @DataFailureCause + protected Set<Integer> mFailCauses = new ArraySet<>(); public DataRetryRule(@NonNull String ruleString) { if (TextUtils.isEmpty(ruleString)) { @@ -353,7 +378,8 @@ public class DataRetryManager extends Handler { * @return The data network setup retry intervals in milliseconds. If this is empty, then * {@link #getMaxRetries()} must return 0. */ - public @NonNull List<Long> getRetryIntervalsMillis() { + @NonNull + public List<Long> getRetryIntervalsMillis() { return mRetryIntervalsMillis; } @@ -372,43 +398,44 @@ public class DataRetryManager extends Handler { * happen. Empty set indicates the retry rule is not using the fail causes. */ @VisibleForTesting - public @NonNull @DataFailureCause Set<Integer> getFailCauses() { + @NonNull + @DataFailureCause + public Set<Integer> getFailCauses() { return mFailCauses; } } /** * Represent a rule for data setup retry. - * + * <p> * The syntax of the retry rule: * 1. Retry based on {@link NetworkCapabilities}. Note that only APN-type network capabilities * are supported. If the capabilities are not specified, then the retry rule only applies * to the current failed APN used in setup data call request. * "capabilities=[netCaps1|netCaps2|...], [retry_interval=n1|n2|n3|n4...], [maximum_retries=n]" - * + * <p> * 2. Retry based on {@link DataFailCause} * "fail_causes=[cause1|cause2|cause3|..], [retry_interval=n1|n2|n3|n4...], [maximum_retries=n]" - * + * <p> * 3. Retry based on {@link NetworkCapabilities} and {@link DataFailCause}. Note that only * APN-type network capabilities are supported. * "capabilities=[netCaps1|netCaps2|...], fail_causes=[cause1|cause2|cause3|...], * [retry_interval=n1|n2|n3|n4...], [maximum_retries=n]" - * + * <p> * 4. Permanent fail causes (no timer-based retry) on the current failed APN. Retry interval * is specified for retrying the next available APN. * "permanent_fail_causes=8|27|28|29|30|32|33|35|50|51|111|-5|-6|65537|65538|-3|65543|65547| * 2252|2253|2254, retry_interval=2500" - * + * <p> * For example, * "capabilities=eims, retry_interval=1000, maximum_retries=20" means if the attached * network request is emergency, then retry data network setup every 1 second for up to 20 * times. - * + * <p> * "capabilities=internet|enterprise|dun|ims|fota, retry_interval=2500|3000|" * "5000|10000|15000|20000|40000|60000|120000|240000|600000|1200000|1800000" * "1800000, maximum_retries=20" means for those capabilities, retry happens in 2.5s, 3s, 5s, * 10s, 15s, 20s, 40s, 1m, 2m, 4m, 10m, 20m, 30m, 30m, 30m, until reaching 20 retries. - * */ public static class DataSetupRetryRule extends DataRetryRule { private static final String RULE_TAG_PERMANENT_FAIL_CAUSES = "permanent_fail_causes"; @@ -469,7 +496,9 @@ public class DataRetryManager extends Handler { * capabilities. */ @VisibleForTesting - public @NonNull @NetCapability Set<Integer> getNetworkCapabilities() { + @NonNull + @NetCapability + public Set<Integer> getNetworkCapabilities() { return mNetworkCapabilities; } @@ -510,22 +539,22 @@ public class DataRetryManager extends Handler { /** * Represent a handover data network retry rule. - * + * <p> * The syntax of the retry rule: * 1. Retry when handover fails. * "retry_interval=[n1|n2|n3|...], [maximum_retries=n]" - * + * <p> * For example, * "retry_interval=1000|3000|5000, maximum_retries=10" means handover retry will happen in 1s, * 3s, 5s, 5s, 5s....up to 10 times. - * + * <p> * 2. Retry when handover fails with certain fail causes. * "retry_interval=[n1|n2|n3|...], fail_causes=[cause1|cause2|cause3|...], [maximum_retries=n] - * + * <p> * For example, * "retry_interval=1000, maximum_retries=3, fail_causes=5" means handover retry every 1 second * for up to 3 times when handover fails with the cause 5. - * + * <p> * "maximum_retries=0, fail_causes=6|10|67" means handover retry should not happen for those * causes. */ @@ -573,7 +602,8 @@ public class DataRetryManager extends Handler { public @interface DataRetryState {} /** The rule used for this data retry. {@code null} if the retry is requested by network. */ - public final @Nullable DataRetryRule appliedDataRetryRule; + @Nullable + public final DataRetryRule appliedDataRetryRule; /** The retry delay in milliseconds. */ public final long retryDelayMillis; @@ -582,13 +612,15 @@ public class DataRetryManager extends Handler { * Retry elapsed time. This is the system elapsed time retrieved from * {@link SystemClock#elapsedRealtime()}. */ - public final @ElapsedRealtimeLong long retryElapsedTime; + @ElapsedRealtimeLong + public final long retryElapsedTime; /** The retry state. */ protected int mRetryState = RETRY_STATE_NOT_RETRIED; /** Timestamp when a state is set. For debugging purposes only. */ - protected @ElapsedRealtimeLong long mRetryStateTimestamp = 0; + @ElapsedRealtimeLong + protected long mRetryStateTimestamp; /** * Constructor @@ -617,7 +649,8 @@ public class DataRetryManager extends Handler { /** * @return Get the retry state. */ - public @DataRetryState int getState() { + @DataRetryState + public int getState() { return mRetryState; } @@ -649,7 +682,8 @@ public class DataRetryManager extends Handler { protected long mRetryDelayMillis = TimeUnit.SECONDS.toMillis(5); /** The applied data retry rule. */ - protected @Nullable DataRetryRule mAppliedDataRetryRule; + @Nullable + protected DataRetryRule mAppliedDataRetryRule; /** * Set the data retry delay. @@ -657,7 +691,8 @@ public class DataRetryManager extends Handler { * @param retryDelayMillis The retry delay in milliseconds. * @return This builder. */ - public @NonNull T setRetryDelay(long retryDelayMillis) { + @NonNull + public T setRetryDelay(long retryDelayMillis) { mRetryDelayMillis = retryDelayMillis; return (T) this; } @@ -668,7 +703,8 @@ public class DataRetryManager extends Handler { * @param dataRetryRule The rule that used for this data retry. * @return This builder. */ - public @NonNull T setAppliedRetryRule(@NonNull DataRetryRule dataRetryRule) { + @NonNull + public T setAppliedRetryRule(@NonNull DataRetryRule dataRetryRule) { mAppliedDataRetryRule = dataRetryRule; return (T) this; } @@ -703,16 +739,20 @@ public class DataRetryManager extends Handler { public @interface SetupRetryType {} /** Setup retry type. Could be retry by same data profile or same capability. */ - public final @SetupRetryType int setupRetryType; + @SetupRetryType + public final int setupRetryType; /** The network requests to satisfy when retry happens. */ - public final @NonNull NetworkRequestList networkRequestList; + @NonNull + public final NetworkRequestList networkRequestList; /** The data profile that will be used for retry. */ - public final @Nullable DataProfile dataProfile; + @Nullable + public final DataProfile dataProfile; /** The transport to retry data setup. */ - public final @TransportType int transport; + @TransportType + public final int transport; /** * Constructor @@ -743,11 +783,12 @@ public class DataRetryManager extends Handler { * @return Retry type in string format. */ private static String retryTypeToString(@SetupRetryType int setupRetryType) { - switch (setupRetryType) { - case RETRY_TYPE_DATA_PROFILE: return "BY_PROFILE"; - case RETRY_TYPE_NETWORK_REQUESTS: return "BY_NETWORK_REQUESTS"; - default: return "Unknown(" + setupRetryType + ")"; - } + return switch (setupRetryType) { + case RETRY_TYPE_DATA_PROFILE -> "BY_PROFILE"; + case RETRY_TYPE_NETWORK_REQUESTS -> "BY_NETWORK_REQUESTS"; + case RETRY_TYPE_UNKNOWN -> "UNKNOWN"; + default -> "Unknown(" + setupRetryType + ")"; + }; } @Override @@ -768,16 +809,20 @@ public class DataRetryManager extends Handler { */ public static class Builder<T extends Builder<T>> extends DataRetryEntry.Builder<T> { /** Data setup retry type. Could be retry by same data profile or same capabilities. */ - private @SetupRetryType int mSetupRetryType = RETRY_TYPE_UNKNOWN; + @SetupRetryType + private int mSetupRetryType = RETRY_TYPE_UNKNOWN; /** The network requests to satisfy when retry happens. */ - private @NonNull NetworkRequestList mNetworkRequestList; + @NonNull + private NetworkRequestList mNetworkRequestList; /** The data profile that will be used for retry. */ - private @Nullable DataProfile mDataProfile; + @Nullable + private DataProfile mDataProfile; /** The transport to retry data setup. */ - private @TransportType int mTransport = AccessNetworkConstants.TRANSPORT_TYPE_INVALID; + @TransportType + private int mTransport = AccessNetworkConstants.TRANSPORT_TYPE_INVALID; /** * Set the data retry type. @@ -786,7 +831,8 @@ public class DataRetryManager extends Handler { * capabilities. * @return This builder. */ - public @NonNull Builder<T> setSetupRetryType(@SetupRetryType int setupRetryType) { + @NonNull + public Builder<T> setSetupRetryType(@SetupRetryType int setupRetryType) { mSetupRetryType = setupRetryType; return this; } @@ -797,7 +843,8 @@ public class DataRetryManager extends Handler { * @param networkRequestList The network requests to satisfy when retry happens. * @return This builder. */ - public @NonNull Builder<T> setNetworkRequestList( + @NonNull + public Builder<T> setNetworkRequestList( @NonNull NetworkRequestList networkRequestList) { mNetworkRequestList = networkRequestList; return this; @@ -809,7 +856,8 @@ public class DataRetryManager extends Handler { * @param dataProfile The data profile that will be used for retry. * @return This builder. */ - public @NonNull Builder<T> setDataProfile(@NonNull DataProfile dataProfile) { + @NonNull + public Builder<T> setDataProfile(@NonNull DataProfile dataProfile) { mDataProfile = dataProfile; return this; } @@ -820,7 +868,8 @@ public class DataRetryManager extends Handler { * @param transport The transport to retry data setup. * @return This builder. */ - public @NonNull Builder<T> setTransport(@TransportType int transport) { + @NonNull + public Builder<T> setTransport(@TransportType int transport) { mTransport = transport; return this; } @@ -830,7 +879,8 @@ public class DataRetryManager extends Handler { * * @return The instance of {@link DataSetupRetryEntry}. */ - public @NonNull DataSetupRetryEntry build() { + @NonNull + public DataSetupRetryEntry build() { if (mNetworkRequestList == null) { throw new IllegalArgumentException("network request list is not specified."); } @@ -854,7 +904,8 @@ public class DataRetryManager extends Handler { */ public static class DataHandoverRetryEntry extends DataRetryEntry { /** The data network to be retried for handover. */ - public final @NonNull DataNetwork dataNetwork; + @NonNull + public final DataNetwork dataNetwork; /** * Constructor. @@ -886,7 +937,8 @@ public class DataRetryManager extends Handler { */ public static class Builder<T extends Builder<T>> extends DataRetryEntry.Builder<T> { /** The data network to be retried for handover. */ - public @NonNull DataNetwork mDataNetwork; + @NonNull + public DataNetwork mDataNetwork; /** * Set the data retry type. @@ -895,7 +947,8 @@ public class DataRetryManager extends Handler { * * @return This builder. */ - public @NonNull Builder<T> setDataNetwork(@NonNull DataNetwork dataNetwork) { + @NonNull + public Builder<T> setDataNetwork(@NonNull DataNetwork dataNetwork) { mDataNetwork = dataNetwork; return this; } @@ -905,7 +958,8 @@ public class DataRetryManager extends Handler { * * @return The instance of {@link DataHandoverRetryEntry}. */ - public @NonNull DataHandoverRetryEntry build() { + @NonNull + public DataHandoverRetryEntry build() { return new DataHandoverRetryEntry(mDataNetwork, (DataHandoverRetryRule) mAppliedDataRetryRule, mRetryDelayMillis); } @@ -1865,7 +1919,8 @@ public class DataRetryManager extends Handler { * @param reason The reason * @return The reason in string format. */ - private static @NonNull String resetReasonToString(int reason) { + @NonNull + private static String resetReasonToString(int reason) { return switch (reason) { case RESET_REASON_DATA_PROFILES_CHANGED -> "DATA_PROFILES_CHANGED"; case RESET_REASON_RADIO_ON -> "RADIO_ON"; diff --git a/src/java/com/android/internal/telephony/data/DataSettingsManager.java b/src/java/com/android/internal/telephony/data/DataSettingsManager.java index 51e5b7d8f1..fb112d92b2 100644 --- a/src/java/com/android/internal/telephony/data/DataSettingsManager.java +++ b/src/java/com/android/internal/telephony/data/DataSettingsManager.java @@ -47,6 +47,7 @@ import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.PhoneFactory; import com.android.internal.telephony.SettingsObserver; +import com.android.internal.telephony.TelephonyCapabilities; import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback; import com.android.internal.telephony.flags.FeatureFlags; import com.android.internal.telephony.metrics.DeviceTelephonyPropertiesStats; @@ -91,7 +92,8 @@ public class DataSettingsManager extends Handler { private static final int EVENT_INITIALIZE = 11; private final Phone mPhone; - private final @NonNull FeatureFlags mFeatureFlags; + @NonNull + private final FeatureFlags mFeatureFlags; private final ContentResolver mResolver; private final SettingsObserver mSettingsObserver; private final String mLogTag; @@ -100,11 +102,12 @@ public class DataSettingsManager extends Handler { private int mSubId; /** Data config manager */ - private final @NonNull DataConfigManager mDataConfigManager; + @NonNull + private final DataConfigManager mDataConfigManager; /** Data settings manager callbacks. */ - private final @NonNull Set<DataSettingsManagerCallback> mDataSettingsManagerCallbacks = - new ArraySet<>(); + @NonNull + private final Set<DataSettingsManagerCallback> mDataSettingsManagerCallbacks = new ArraySet<>(); /** Mapping of {@link TelephonyManager.DataEnabledReason} to data enabled values. */ private final Map<Integer, Boolean> mDataEnabledSettings = new ArrayMap<>(); @@ -271,7 +274,7 @@ public class DataSettingsManager extends Handler { } private boolean hasCalling() { - if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true; + if (!TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)) return true; return mPhone.getContext().getPackageManager().hasSystemFeature( PackageManager.FEATURE_TELEPHONY_CALLING); } @@ -718,8 +721,9 @@ public class DataSettingsManager extends Handler { * @param policies New mobile data policies in String format. * @return A Set of parsed mobile data policies. */ - public @NonNull @MobileDataPolicy Set<Integer> getMobileDataPolicyEnabled( - @NonNull String policies) { + @NonNull + @MobileDataPolicy + public Set<Integer> getMobileDataPolicyEnabled(@NonNull String policies) { Set<Integer> mobileDataPolicies = new HashSet<>(); String[] rulesString = policies.trim().split("\\s*,\\s*"); for (String rule : rulesString) { @@ -741,7 +745,8 @@ public class DataSettingsManager extends Handler { * @return Parsed mobile data policy. {@link #INVALID_MOBILE_DATA_POLICY} if string can't be * parsed into a mobile data policy. */ - private @MobileDataPolicy int parsePolicyFrom(@NonNull String policy) { + @MobileDataPolicy + private int parsePolicyFrom(@NonNull String policy) { int dataPolicy; try { // parse as new override policy @@ -810,20 +815,14 @@ public class DataSettingsManager extends Handler { private static String dataEnabledChangedReasonToString( @TelephonyManager.DataEnabledChangedReason int reason) { - switch (reason) { - case TelephonyManager.DATA_ENABLED_REASON_USER: - return "USER"; - case TelephonyManager.DATA_ENABLED_REASON_POLICY: - return "POLICY"; - case TelephonyManager.DATA_ENABLED_REASON_CARRIER: - return "CARRIER"; - case TelephonyManager.DATA_ENABLED_REASON_THERMAL: - return "THERMAL"; - case TelephonyManager.DATA_ENABLED_REASON_OVERRIDE: - return "OVERRIDE"; - default: - return "UNKNOWN"; - } + return switch (reason) { + case TelephonyManager.DATA_ENABLED_REASON_USER -> "USER"; + case TelephonyManager.DATA_ENABLED_REASON_POLICY -> "POLICY"; + case TelephonyManager.DATA_ENABLED_REASON_CARRIER -> "CARRIER"; + case TelephonyManager.DATA_ENABLED_REASON_THERMAL -> "THERMAL"; + case TelephonyManager.DATA_ENABLED_REASON_OVERRIDE -> "OVERRIDE"; + default -> "UNKNOWN"; + }; } @Override diff --git a/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java b/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java index ec6b40f1ab..b9b60a0bc7 100644 --- a/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java +++ b/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java @@ -140,24 +140,33 @@ public class DataStallRecoveryManager extends Handler { /** Event for duration milliseconds changed. */ private static final int EVENT_CONTENT_DSRM_DURATION_MILLIS_CHANGED = 5; - private final @NonNull Phone mPhone; - private final @NonNull String mLogTag; - private final @NonNull LocalLog mLocalLog = new LocalLog(128); - private final @NonNull FeatureFlags mFeatureFlags; + @NonNull + private final Phone mPhone; + @NonNull + private final String mLogTag; + @NonNull + private final LocalLog mLocalLog = new LocalLog(128); + @NonNull + private final FeatureFlags mFeatureFlags; /** Data network controller */ - private final @NonNull DataNetworkController mDataNetworkController; + @NonNull + private final DataNetworkController mDataNetworkController; /** Data config manager */ - private final @NonNull DataConfigManager mDataConfigManager; + @NonNull + private final DataConfigManager mDataConfigManager; /** Cellular data service */ - private final @NonNull DataServiceManager mWwanDataServiceManager; + @NonNull + private final DataServiceManager mWwanDataServiceManager; /** The data stall recovery action. */ - private @RecoveryAction int mRecoveryAction; + @RecoveryAction + private int mRecoveryAction; /** The elapsed real time of last recovery attempted */ - private @ElapsedRealtimeLong long mTimeLastRecoveryStartMs; + @ElapsedRealtimeLong + private long mTimeLastRecoveryStartMs; /** Whether current network is good or not */ private boolean mIsValidNetwork; /** Whether data stall recovery is triggered or not */ @@ -168,11 +177,14 @@ public class DataStallRecoveryManager extends Handler { private boolean mLastActionReported; /** The real time for data stall start. */ @VisibleForTesting - public @ElapsedRealtimeLong long mDataStallStartMs; + @ElapsedRealtimeLong + public long mDataStallStartMs; /** Last data stall recovery action. */ - private @RecoveryAction int mLastAction; + @RecoveryAction + private int mLastAction; /** Last radio power state. */ - private @RadioPowerState int mRadioPowerState; + @RadioPowerState + private int mRadioPowerState; /** Whether the NetworkCheckTimer start. */ private boolean mNetworkCheckTimerStarted = false; /** Whether radio state changed during data stall. */ @@ -186,15 +198,18 @@ public class DataStallRecoveryManager extends Handler { /** Whether internet network that require validation is connected. */ private boolean mIsInternetNetworkConnected; /** The durations for current recovery action */ - private @ElapsedRealtimeLong long mTimeElapsedOfCurrentAction; + @ElapsedRealtimeLong + private long mTimeElapsedOfCurrentAction; /** Tracks the total number of validation duration a data stall */ private int mValidationCount; /** Tracks the number of validation for current action during a data stall */ private int mActionValidationCount; /** The array for the timers between recovery actions. */ - private @NonNull long[] mDataStallRecoveryDelayMillisArray; + @NonNull + private long[] mDataStallRecoveryDelayMillisArray; /** The boolean array for the flags. They are used to skip the recovery actions if needed. */ - private @NonNull boolean[] mSkipRecoveryActionArray; + @NonNull + private boolean[] mSkipRecoveryActionArray; /** * The content URI for the DSRM recovery actions. @@ -563,7 +578,7 @@ public class DataStallRecoveryManager extends Handler { if (isValid) { if (mFeatureFlags.dsrsDiagnosticsEnabled()) { // Broadcast intent that data stall recovered. - broadcastDataStallDetected(getRecoveryAction()); + broadcastDataStallDetected(mLastAction); } reset(); } else if (isRecoveryNeeded(true)) { @@ -684,7 +699,7 @@ public class DataStallRecoveryManager extends Handler { // Get the information for DSRS state final boolean isRecovered = !mDataStalled; final int duration = (int) (SystemClock.elapsedRealtime() - mDataStallStartMs); - final @RecoveredReason int reason = getRecoveredReason(mIsValidNetwork); + @RecoveredReason final int reason = getRecoveredReason(mIsValidNetwork); final int durationOfAction = (int) getDurationOfCurrentRecoveryMs(); if (mFeatureFlags.dsrsDiagnosticsEnabled()) { log("mValidationCount=" + mValidationCount @@ -712,7 +727,7 @@ public class DataStallRecoveryManager extends Handler { private void cleanUpDataNetwork() { log("cleanUpDataNetwork: notify clean up data network"); mDataStallRecoveryManagerCallback.invokeFromExecutor( - () -> mDataStallRecoveryManagerCallback.onDataStallReestablishInternet()); + mDataStallRecoveryManagerCallback::onDataStallReestablishInternet); } /** Recovery Action: RECOVERY_ACTION_RADIO_RESTART */ @@ -817,7 +832,7 @@ public class DataStallRecoveryManager extends Handler { private void setNetworkValidationState(boolean isValid) { boolean isLogNeeded = false; int timeDuration = 0; - int timeDurationOfCurrentAction = 0; + int timeDurationOfCurrentAction; boolean isFirstDataStall = false; boolean isFirstValidationAfterDoRecovery = false; @RecoveredReason int reason = getRecoveredReason(isValid); @@ -891,9 +906,6 @@ public class DataStallRecoveryManager extends Handler { if (mLastAction <= RECOVERY_ACTION_CLEANUP) { ret = RECOVERED_REASON_MODEM; } - if (mLastAction > RECOVERY_ACTION_CLEANUP) { - ret = RECOVERED_REASON_DSRM; - } if (mIsAirPlaneModeEnableDuringDataStall) { ret = RECOVERED_REASON_USER; } @@ -953,7 +965,8 @@ public class DataStallRecoveryManager extends Handler { * @param reason The recovered reason. * @return The recovered reason in string format. */ - private static @NonNull String recoveredReasonToString(@RecoveredReason int reason) { + @NonNull + private static String recoveredReasonToString(@RecoveredReason int reason) { return switch (reason) { case RECOVERED_REASON_NONE -> "RECOVERED_REASON_NONE"; case RECOVERED_REASON_DSRM -> "RECOVERED_REASON_DSRM"; @@ -969,17 +982,14 @@ public class DataStallRecoveryManager extends Handler { * @param state The radio power state * @return The radio power state in string format. */ - private static @NonNull String radioPowerStateToString(@RadioPowerState int state) { - switch (state) { - case TelephonyManager.RADIO_POWER_OFF: - return "RADIO_POWER_OFF"; - case TelephonyManager.RADIO_POWER_ON: - return "RADIO_POWER_ON"; - case TelephonyManager.RADIO_POWER_UNAVAILABLE: - return "RADIO_POWER_UNAVAILABLE"; - default: - return "Unknown(" + state + ")"; - } + @NonNull + private static String radioPowerStateToString(@RadioPowerState int state) { + return switch (state) { + case TelephonyManager.RADIO_POWER_OFF -> "RADIO_POWER_OFF"; + case TelephonyManager.RADIO_POWER_ON -> "RADIO_POWER_ON"; + case TelephonyManager.RADIO_POWER_UNAVAILABLE -> "RADIO_POWER_UNAVAILABLE"; + default -> "Unknown(" + state + ")"; + }; } /** @@ -988,7 +998,8 @@ public class DataStallRecoveryManager extends Handler { * @param action The recovery action * @return The recovery action in string format. */ - private static @NonNull String recoveryActionToString(@RecoveryAction int action) { + @NonNull + private static String recoveryActionToString(@RecoveryAction int action) { return switch (action) { case RECOVERY_ACTION_GET_DATA_CALL_LIST -> "RECOVERY_ACTION_GET_DATA_CALL_LIST"; case RECOVERY_ACTION_CLEANUP -> "RECOVERY_ACTION_CLEANUP"; diff --git a/src/java/com/android/internal/telephony/data/DataUtils.java b/src/java/com/android/internal/telephony/data/DataUtils.java index 49e54e788a..8b959130fd 100644 --- a/src/java/com/android/internal/telephony/data/DataUtils.java +++ b/src/java/com/android/internal/telephony/data/DataUtils.java @@ -27,6 +27,7 @@ import android.telephony.AccessNetworkConstants; import android.telephony.AccessNetworkConstants.AccessNetworkType; import android.telephony.AccessNetworkConstants.RadioAccessNetworkType; import android.telephony.AccessNetworkConstants.TransportType; +import android.telephony.Annotation.ConnectivityTransport; import android.telephony.Annotation.DataActivityType; import android.telephony.Annotation.NetCapability; import android.telephony.Annotation.NetworkType; @@ -69,32 +70,30 @@ public class DataUtils { * @param capabilityString The capability in string format * @return The network capability. -1 if not found. */ - public static @NetCapability int getNetworkCapabilityFromString( - @NonNull String capabilityString) { - switch (capabilityString.toUpperCase(Locale.ROOT)) { - case "MMS": return NetworkCapabilities.NET_CAPABILITY_MMS; - case "SUPL": return NetworkCapabilities.NET_CAPABILITY_SUPL; - case "DUN": return NetworkCapabilities.NET_CAPABILITY_DUN; - case "FOTA": return NetworkCapabilities.NET_CAPABILITY_FOTA; - case "IMS": return NetworkCapabilities.NET_CAPABILITY_IMS; - case "CBS": return NetworkCapabilities.NET_CAPABILITY_CBS; - case "XCAP": return NetworkCapabilities.NET_CAPABILITY_XCAP; - case "EIMS": return NetworkCapabilities.NET_CAPABILITY_EIMS; - case "INTERNET": return NetworkCapabilities.NET_CAPABILITY_INTERNET; - case "MCX": return NetworkCapabilities.NET_CAPABILITY_MCX; - case "VSIM": return NetworkCapabilities.NET_CAPABILITY_VSIM; - case "BIP" : return NetworkCapabilities.NET_CAPABILITY_BIP; - case "ENTERPRISE": return NetworkCapabilities.NET_CAPABILITY_ENTERPRISE; - case "PRIORITIZE_BANDWIDTH": - return NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH; - case "PRIORITIZE_LATENCY": - return NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY; - case "RCS": - return NetworkCapabilities.NET_CAPABILITY_RCS; - default: + @NetCapability + public static int getNetworkCapabilityFromString(@NonNull String capabilityString) { + return switch (capabilityString.toUpperCase(Locale.ROOT)) { + case "MMS" -> NetworkCapabilities.NET_CAPABILITY_MMS; + case "SUPL" -> NetworkCapabilities.NET_CAPABILITY_SUPL; + case "DUN" -> NetworkCapabilities.NET_CAPABILITY_DUN; + case "FOTA" -> NetworkCapabilities.NET_CAPABILITY_FOTA; + case "IMS" -> NetworkCapabilities.NET_CAPABILITY_IMS; + case "CBS" -> NetworkCapabilities.NET_CAPABILITY_CBS; + case "XCAP" -> NetworkCapabilities.NET_CAPABILITY_XCAP; + case "EIMS" -> NetworkCapabilities.NET_CAPABILITY_EIMS; + case "INTERNET" -> NetworkCapabilities.NET_CAPABILITY_INTERNET; + case "MCX" -> NetworkCapabilities.NET_CAPABILITY_MCX; + case "VSIM" -> NetworkCapabilities.NET_CAPABILITY_VSIM; + case "BIP" -> NetworkCapabilities.NET_CAPABILITY_BIP; + case "ENTERPRISE" -> NetworkCapabilities.NET_CAPABILITY_ENTERPRISE; + case "PRIORITIZE_BANDWIDTH" -> NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH; + case "PRIORITIZE_LATENCY" -> NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY; + case "RCS" -> NetworkCapabilities.NET_CAPABILITY_RCS; + default -> { loge("Illegal network capability: " + capabilityString); - return -1; - } + yield -1; + } + }; } /** @@ -105,7 +104,8 @@ public class DataUtils { * @param capabilitiesString capability strings joined by {@code |} * @return Set of capabilities */ - public static @NetCapability Set<Integer> getNetworkCapabilitiesFromString( + @NetCapability + public static Set<Integer> getNetworkCapabilitiesFromString( @NonNull String capabilitiesString) { // e.g. "IMS|" is not allowed if (!capabilitiesString.matches("(\\s*[a-zA-Z_]+\\s*)(\\|\\s*[a-zA-Z_]+\\s*)*")) { @@ -119,69 +119,107 @@ public class DataUtils { /** * Convert a network capability to string. - * + * <p> * This is for debugging and logging purposes only. * * @param netCap Network capability. * @return Network capability in string format. */ - public static @NonNull String networkCapabilityToString(@NetCapability int netCap) { - switch (netCap) { - case NetworkCapabilities.NET_CAPABILITY_MMS: return "MMS"; - case NetworkCapabilities.NET_CAPABILITY_SUPL: return "SUPL"; - case NetworkCapabilities.NET_CAPABILITY_DUN: return "DUN"; - case NetworkCapabilities.NET_CAPABILITY_FOTA: return "FOTA"; - case NetworkCapabilities.NET_CAPABILITY_IMS: return "IMS"; - case NetworkCapabilities.NET_CAPABILITY_CBS: return "CBS"; - case NetworkCapabilities.NET_CAPABILITY_WIFI_P2P: return "WIFI_P2P"; - case NetworkCapabilities.NET_CAPABILITY_IA: return "IA"; - case NetworkCapabilities.NET_CAPABILITY_RCS: return "RCS"; - case NetworkCapabilities.NET_CAPABILITY_XCAP: return "XCAP"; - case NetworkCapabilities.NET_CAPABILITY_EIMS: return "EIMS"; - case NetworkCapabilities.NET_CAPABILITY_NOT_METERED: return "NOT_METERED"; - case NetworkCapabilities.NET_CAPABILITY_INTERNET: return "INTERNET"; - case NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED: return "NOT_RESTRICTED"; - case NetworkCapabilities.NET_CAPABILITY_TRUSTED: return "TRUSTED"; - case NetworkCapabilities.NET_CAPABILITY_NOT_VPN: return "NOT_VPN"; - case NetworkCapabilities.NET_CAPABILITY_VALIDATED: return "VALIDATED"; - case NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL: return "CAPTIVE_PORTAL"; - case NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING: return "NOT_ROAMING"; - case NetworkCapabilities.NET_CAPABILITY_FOREGROUND: return "FOREGROUND"; - case NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED: return "NOT_CONGESTED"; - case NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED: return "NOT_SUSPENDED"; - case NetworkCapabilities.NET_CAPABILITY_OEM_PAID: return "OEM_PAID"; - case NetworkCapabilities.NET_CAPABILITY_MCX: return "MCX"; - case NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY: - return "PARTIAL_CONNECTIVITY"; - case NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED: - return "TEMPORARILY_NOT_METERED"; - case NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE: return "OEM_PRIVATE"; - case NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL: return "VEHICLE_INTERNAL"; - case NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED: return "NOT_VCN_MANAGED"; - case NetworkCapabilities.NET_CAPABILITY_ENTERPRISE: return "ENTERPRISE"; - case NetworkCapabilities.NET_CAPABILITY_VSIM: return "VSIM"; - case NetworkCapabilities.NET_CAPABILITY_BIP: return "BIP"; - case NetworkCapabilities.NET_CAPABILITY_HEAD_UNIT: return "HEAD_UNIT"; - case NetworkCapabilities.NET_CAPABILITY_MMTEL: return "MMTEL"; - case NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY: - return "PRIORITIZE_LATENCY"; - case NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH: - return "PRIORITIZE_BANDWIDTH"; - default: + @NonNull + public static String networkCapabilityToString(@NetCapability int netCap) { + return switch (netCap) { + case NetworkCapabilities.NET_CAPABILITY_MMS -> "MMS"; + case NetworkCapabilities.NET_CAPABILITY_SUPL -> "SUPL"; + case NetworkCapabilities.NET_CAPABILITY_DUN -> "DUN"; + case NetworkCapabilities.NET_CAPABILITY_FOTA -> "FOTA"; + case NetworkCapabilities.NET_CAPABILITY_IMS -> "IMS"; + case NetworkCapabilities.NET_CAPABILITY_CBS -> "CBS"; + case NetworkCapabilities.NET_CAPABILITY_WIFI_P2P -> "WIFI_P2P"; + case NetworkCapabilities.NET_CAPABILITY_IA -> "IA"; + case NetworkCapabilities.NET_CAPABILITY_RCS -> "RCS"; + case NetworkCapabilities.NET_CAPABILITY_XCAP -> "XCAP"; + case NetworkCapabilities.NET_CAPABILITY_EIMS -> "EIMS"; + case NetworkCapabilities.NET_CAPABILITY_NOT_METERED -> "NOT_METERED"; + case NetworkCapabilities.NET_CAPABILITY_INTERNET -> "INTERNET"; + case NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED -> "NOT_RESTRICTED"; + case NetworkCapabilities.NET_CAPABILITY_TRUSTED -> "TRUSTED"; + case NetworkCapabilities.NET_CAPABILITY_NOT_VPN -> "NOT_VPN"; + case NetworkCapabilities.NET_CAPABILITY_VALIDATED -> "VALIDATED"; + case NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL -> "CAPTIVE_PORTAL"; + case NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING -> "NOT_ROAMING"; + case NetworkCapabilities.NET_CAPABILITY_FOREGROUND -> "FOREGROUND"; + case NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED -> "NOT_CONGESTED"; + case NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED -> "NOT_SUSPENDED"; + case NetworkCapabilities.NET_CAPABILITY_OEM_PAID -> "OEM_PAID"; + case NetworkCapabilities.NET_CAPABILITY_MCX -> "MCX"; + case NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY -> "PARTIAL_CONNECTIVITY"; + case NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED -> + "TEMPORARILY_NOT_METERED"; + case NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE -> "OEM_PRIVATE"; + case NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL -> "VEHICLE_INTERNAL"; + case NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED -> "NOT_VCN_MANAGED"; + case NetworkCapabilities.NET_CAPABILITY_ENTERPRISE -> "ENTERPRISE"; + case NetworkCapabilities.NET_CAPABILITY_VSIM -> "VSIM"; + case NetworkCapabilities.NET_CAPABILITY_BIP -> "BIP"; + case NetworkCapabilities.NET_CAPABILITY_HEAD_UNIT -> "HEAD_UNIT"; + case NetworkCapabilities.NET_CAPABILITY_MMTEL -> "MMTEL"; + case NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY -> "PRIORITIZE_LATENCY"; + case NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH -> "PRIORITIZE_BANDWIDTH"; + default -> { loge("Unknown network capability(" + netCap + ")"); - return "Unknown(" + netCap + ")"; - } + yield "Unknown(" + netCap + ")"; + } + }; } /** - * Convert network capabilities to string. + * Concat an array of {@link NetworkCapabilities.Transport} in string format. * + * @param transports an array of connectivity transports + * @return a string of the array of transports. + */ + @NonNull + public static String connectivityTransportsToString( + @NonNull @ConnectivityTransport int[] transports) { + return Arrays.stream(transports).mapToObj(DataUtils::connectivityTransportToString) + .collect(Collectors.joining("|")); + } + + /** + * Convert a {@link NetworkCapabilities.Transport} to a string. + * + * @param transport the connectivity transport + * @return the transport in string + */ + @NonNull + public static String connectivityTransportToString( + @ConnectivityTransport int transport) { + return switch (transport) { + case NetworkCapabilities.TRANSPORT_CELLULAR -> "CELLULAR"; + case NetworkCapabilities.TRANSPORT_WIFI -> "WIFI"; + case NetworkCapabilities.TRANSPORT_BLUETOOTH -> "BLUETOOTH"; + case NetworkCapabilities.TRANSPORT_ETHERNET -> "ETHERNET"; + case NetworkCapabilities.TRANSPORT_VPN -> "VPN"; + case NetworkCapabilities.TRANSPORT_WIFI_AWARE -> "WIFI_AWARE"; + case NetworkCapabilities.TRANSPORT_LOWPAN -> "LOWPAN"; + case NetworkCapabilities.TRANSPORT_TEST -> "TEST"; + case NetworkCapabilities.TRANSPORT_USB -> "USB"; + case NetworkCapabilities.TRANSPORT_THREAD -> "THREAD"; + case NetworkCapabilities.TRANSPORT_SATELLITE -> "SATELLITE"; + default -> "Unknown(" + transport + ")"; + }; + } + + /** + * Convert network capabilities to string. + * <p> * This is for debugging and logging purposes only. * * @param netCaps Network capabilities. * @return Network capabilities in string format. */ - public static @NonNull String networkCapabilitiesToString( + @NonNull + public static String networkCapabilitiesToString( @NetCapability @Nullable Collection<Integer> netCaps) { if (netCaps == null || netCaps.isEmpty()) return ""; return "[" + netCaps.stream() @@ -191,13 +229,14 @@ public class DataUtils { /** * Convert network capabilities to string. - * + * <p> * This is for debugging and logging purposes only. * * @param netCaps Network capabilities. * @return Network capabilities in string format. */ - public static @NonNull String networkCapabilitiesToString(@NetCapability int[] netCaps) { + @NonNull + public static String networkCapabilitiesToString(@NetCapability int[] netCaps) { if (netCaps == null) return ""; return "[" + Arrays.stream(netCaps) .mapToObj(DataUtils::networkCapabilityToString) @@ -210,14 +249,16 @@ public class DataUtils { * @param status The validation status. * @return The validation status in string format. */ - public static @NonNull String validationStatusToString(@ValidationStatus int status) { - switch (status) { - case NetworkAgent.VALIDATION_STATUS_VALID: return "VALID"; - case NetworkAgent.VALIDATION_STATUS_NOT_VALID: return "INVALID"; - default: + @NonNull + public static String validationStatusToString(@ValidationStatus int status) { + return switch (status) { + case NetworkAgent.VALIDATION_STATUS_VALID -> "VALID"; + case NetworkAgent.VALIDATION_STATUS_NOT_VALID -> "INVALID"; + default -> { loge("Unknown validation status(" + status + ")"); - return "UNKNOWN(" + status + ")"; - } + yield "UNKNOWN(" + status + ")"; + } + }; } /** @@ -226,41 +267,26 @@ public class DataUtils { * @param networkCapability Network capability. * @return APN type. */ - public static @ApnType int networkCapabilityToApnType(@NetCapability int networkCapability) { - switch (networkCapability) { - case NetworkCapabilities.NET_CAPABILITY_MMS: - return ApnSetting.TYPE_MMS; - case NetworkCapabilities.NET_CAPABILITY_SUPL: - return ApnSetting.TYPE_SUPL; - case NetworkCapabilities.NET_CAPABILITY_DUN: - return ApnSetting.TYPE_DUN; - case NetworkCapabilities.NET_CAPABILITY_FOTA: - return ApnSetting.TYPE_FOTA; - case NetworkCapabilities.NET_CAPABILITY_IMS: - return ApnSetting.TYPE_IMS; - case NetworkCapabilities.NET_CAPABILITY_CBS: - return ApnSetting.TYPE_CBS; - case NetworkCapabilities.NET_CAPABILITY_XCAP: - return ApnSetting.TYPE_XCAP; - case NetworkCapabilities.NET_CAPABILITY_EIMS: - return ApnSetting.TYPE_EMERGENCY; - case NetworkCapabilities.NET_CAPABILITY_INTERNET: - return ApnSetting.TYPE_DEFAULT; - case NetworkCapabilities.NET_CAPABILITY_MCX: - return ApnSetting.TYPE_MCX; - case NetworkCapabilities.NET_CAPABILITY_IA: - return ApnSetting.TYPE_IA; - case NetworkCapabilities.NET_CAPABILITY_ENTERPRISE: - return ApnSetting.TYPE_ENTERPRISE; - case NetworkCapabilities.NET_CAPABILITY_VSIM: - return ApnSetting.TYPE_VSIM; - case NetworkCapabilities.NET_CAPABILITY_BIP: - return ApnSetting.TYPE_BIP; - case NetworkCapabilities.NET_CAPABILITY_RCS: - return ApnSetting.TYPE_RCS; - default: - return ApnSetting.TYPE_NONE; - } + @ApnType + public static int networkCapabilityToApnType(@NetCapability int networkCapability) { + return switch (networkCapability) { + case NetworkCapabilities.NET_CAPABILITY_MMS -> ApnSetting.TYPE_MMS; + case NetworkCapabilities.NET_CAPABILITY_SUPL -> ApnSetting.TYPE_SUPL; + case NetworkCapabilities.NET_CAPABILITY_DUN -> ApnSetting.TYPE_DUN; + case NetworkCapabilities.NET_CAPABILITY_FOTA -> ApnSetting.TYPE_FOTA; + case NetworkCapabilities.NET_CAPABILITY_IMS -> ApnSetting.TYPE_IMS; + case NetworkCapabilities.NET_CAPABILITY_CBS -> ApnSetting.TYPE_CBS; + case NetworkCapabilities.NET_CAPABILITY_XCAP -> ApnSetting.TYPE_XCAP; + case NetworkCapabilities.NET_CAPABILITY_EIMS -> ApnSetting.TYPE_EMERGENCY; + case NetworkCapabilities.NET_CAPABILITY_INTERNET -> ApnSetting.TYPE_DEFAULT; + case NetworkCapabilities.NET_CAPABILITY_MCX -> ApnSetting.TYPE_MCX; + case NetworkCapabilities.NET_CAPABILITY_IA -> ApnSetting.TYPE_IA; + case NetworkCapabilities.NET_CAPABILITY_ENTERPRISE -> ApnSetting.TYPE_ENTERPRISE; + case NetworkCapabilities.NET_CAPABILITY_VSIM -> ApnSetting.TYPE_VSIM; + case NetworkCapabilities.NET_CAPABILITY_BIP -> ApnSetting.TYPE_BIP; + case NetworkCapabilities.NET_CAPABILITY_RCS -> ApnSetting.TYPE_RCS; + default -> ApnSetting.TYPE_NONE; + }; } /** @@ -269,41 +295,26 @@ public class DataUtils { * @param apnType APN type. * @return Network capability. */ - public static @NetCapability int apnTypeToNetworkCapability(@ApnType int apnType) { - switch (apnType) { - case ApnSetting.TYPE_MMS: - return NetworkCapabilities.NET_CAPABILITY_MMS; - case ApnSetting.TYPE_SUPL: - return NetworkCapabilities.NET_CAPABILITY_SUPL; - case ApnSetting.TYPE_DUN: - return NetworkCapabilities.NET_CAPABILITY_DUN; - case ApnSetting.TYPE_FOTA: - return NetworkCapabilities.NET_CAPABILITY_FOTA; - case ApnSetting.TYPE_IMS: - return NetworkCapabilities.NET_CAPABILITY_IMS; - case ApnSetting.TYPE_CBS: - return NetworkCapabilities.NET_CAPABILITY_CBS; - case ApnSetting.TYPE_XCAP: - return NetworkCapabilities.NET_CAPABILITY_XCAP; - case ApnSetting.TYPE_EMERGENCY: - return NetworkCapabilities.NET_CAPABILITY_EIMS; - case ApnSetting.TYPE_DEFAULT: - return NetworkCapabilities.NET_CAPABILITY_INTERNET; - case ApnSetting.TYPE_MCX: - return NetworkCapabilities.NET_CAPABILITY_MCX; - case ApnSetting.TYPE_IA: - return NetworkCapabilities.NET_CAPABILITY_IA; - case ApnSetting.TYPE_BIP: - return NetworkCapabilities.NET_CAPABILITY_BIP; - case ApnSetting.TYPE_VSIM: - return NetworkCapabilities.NET_CAPABILITY_VSIM; - case ApnSetting.TYPE_ENTERPRISE: - return NetworkCapabilities.NET_CAPABILITY_ENTERPRISE; - case ApnSetting.TYPE_RCS: - return NetworkCapabilities.NET_CAPABILITY_RCS; - default: - return -1; - } + @NetCapability + public static int apnTypeToNetworkCapability(@ApnType int apnType) { + return switch (apnType) { + case ApnSetting.TYPE_MMS -> NetworkCapabilities.NET_CAPABILITY_MMS; + case ApnSetting.TYPE_SUPL -> NetworkCapabilities.NET_CAPABILITY_SUPL; + case ApnSetting.TYPE_DUN -> NetworkCapabilities.NET_CAPABILITY_DUN; + case ApnSetting.TYPE_FOTA -> NetworkCapabilities.NET_CAPABILITY_FOTA; + case ApnSetting.TYPE_IMS -> NetworkCapabilities.NET_CAPABILITY_IMS; + case ApnSetting.TYPE_CBS -> NetworkCapabilities.NET_CAPABILITY_CBS; + case ApnSetting.TYPE_XCAP -> NetworkCapabilities.NET_CAPABILITY_XCAP; + case ApnSetting.TYPE_EMERGENCY -> NetworkCapabilities.NET_CAPABILITY_EIMS; + case ApnSetting.TYPE_DEFAULT -> NetworkCapabilities.NET_CAPABILITY_INTERNET; + case ApnSetting.TYPE_MCX -> NetworkCapabilities.NET_CAPABILITY_MCX; + case ApnSetting.TYPE_IA -> NetworkCapabilities.NET_CAPABILITY_IA; + case ApnSetting.TYPE_BIP -> NetworkCapabilities.NET_CAPABILITY_BIP; + case ApnSetting.TYPE_VSIM -> NetworkCapabilities.NET_CAPABILITY_VSIM; + case ApnSetting.TYPE_ENTERPRISE -> NetworkCapabilities.NET_CAPABILITY_ENTERPRISE; + case ApnSetting.TYPE_RCS -> NetworkCapabilities.NET_CAPABILITY_RCS; + default -> -1; + }; } /** @@ -312,37 +323,26 @@ public class DataUtils { * @param networkType The network type. * @return The access network type. */ - public static @RadioAccessNetworkType int networkTypeToAccessNetworkType( - @NetworkType int networkType) { - switch (networkType) { - case TelephonyManager.NETWORK_TYPE_GPRS: - case TelephonyManager.NETWORK_TYPE_EDGE: - case TelephonyManager.NETWORK_TYPE_GSM: - return AccessNetworkType.GERAN; - case TelephonyManager.NETWORK_TYPE_UMTS: - case TelephonyManager.NETWORK_TYPE_HSDPA: - case TelephonyManager.NETWORK_TYPE_HSPAP: - case TelephonyManager.NETWORK_TYPE_HSUPA: - case TelephonyManager.NETWORK_TYPE_HSPA: - case TelephonyManager.NETWORK_TYPE_TD_SCDMA: - return AccessNetworkType.UTRAN; - case TelephonyManager.NETWORK_TYPE_CDMA: - case TelephonyManager.NETWORK_TYPE_EVDO_0: - case TelephonyManager.NETWORK_TYPE_EVDO_A: - case TelephonyManager.NETWORK_TYPE_EVDO_B: - case TelephonyManager.NETWORK_TYPE_1xRTT: - case TelephonyManager.NETWORK_TYPE_EHRPD: - return AccessNetworkType.CDMA2000; - case TelephonyManager.NETWORK_TYPE_LTE: - case TelephonyManager.NETWORK_TYPE_LTE_CA: - return AccessNetworkType.EUTRAN; - case TelephonyManager.NETWORK_TYPE_IWLAN: - return AccessNetworkType.IWLAN; - case TelephonyManager.NETWORK_TYPE_NR: - return AccessNetworkType.NGRAN; - default: - return AccessNetworkType.UNKNOWN; - } + @RadioAccessNetworkType + public static int networkTypeToAccessNetworkType(@NetworkType int networkType) { + return switch (networkType) { + case TelephonyManager.NETWORK_TYPE_GPRS, TelephonyManager.NETWORK_TYPE_EDGE, + TelephonyManager.NETWORK_TYPE_GSM -> + AccessNetworkType.GERAN; + case TelephonyManager.NETWORK_TYPE_UMTS, TelephonyManager.NETWORK_TYPE_HSDPA, + TelephonyManager.NETWORK_TYPE_HSPAP, TelephonyManager.NETWORK_TYPE_HSUPA, + TelephonyManager.NETWORK_TYPE_HSPA, TelephonyManager.NETWORK_TYPE_TD_SCDMA -> + AccessNetworkType.UTRAN; + case TelephonyManager.NETWORK_TYPE_CDMA, TelephonyManager.NETWORK_TYPE_EVDO_0, + TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyManager.NETWORK_TYPE_EVDO_B, + TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyManager.NETWORK_TYPE_EHRPD -> + AccessNetworkType.CDMA2000; + case TelephonyManager.NETWORK_TYPE_LTE, TelephonyManager.NETWORK_TYPE_LTE_CA -> + AccessNetworkType.EUTRAN; + case TelephonyManager.NETWORK_TYPE_IWLAN -> AccessNetworkType.IWLAN; + case TelephonyManager.NETWORK_TYPE_NR -> AccessNetworkType.NGRAN; + default -> AccessNetworkType.UNKNOWN; + }; } /** @@ -351,7 +351,8 @@ public class DataUtils { * @param elapsedTime The elapsed time retrieved from {@link SystemClock#elapsedRealtime()}. * @return The string format time. */ - public static @NonNull String elapsedTimeToString(@ElapsedRealtimeLong long elapsedTime) { + @NonNull + public static String elapsedTimeToString(@ElapsedRealtimeLong long elapsedTime) { return (elapsedTime != 0) ? systemTimeToString(System.currentTimeMillis() - SystemClock.elapsedRealtime() + elapsedTime) : "never"; } @@ -362,7 +363,8 @@ public class DataUtils { * @param systemTime The system time retrieved from {@link System#currentTimeMillis()}. * @return The string format time. */ - public static @NonNull String systemTimeToString(@CurrentTimeMillisLong long systemTime) { + @NonNull + public static String systemTimeToString(@CurrentTimeMillisLong long systemTime) { return (systemTime != 0) ? TIME_FORMAT.format(systemTime) : "never"; } @@ -372,14 +374,16 @@ public class DataUtils { * @param imsFeature IMS feature. * @return IMS feature in string format. */ - public static @NonNull String imsFeatureToString(@ImsFeature.FeatureType int imsFeature) { - switch (imsFeature) { - case ImsFeature.FEATURE_MMTEL: return "MMTEL"; - case ImsFeature.FEATURE_RCS: return "RCS"; - default: + @NonNull + public static String imsFeatureToString(@ImsFeature.FeatureType int imsFeature) { + return switch (imsFeature) { + case ImsFeature.FEATURE_MMTEL -> "MMTEL"; + case ImsFeature.FEATURE_RCS -> "RCS"; + default -> { loge("Unknown IMS feature(" + imsFeature + ")"); - return "Unknown(" + imsFeature + ")"; - } + yield "Unknown(" + imsFeature + ")"; + } + }; } /** @@ -390,7 +394,8 @@ public class DataUtils { * * @return The network requests after grouping. */ - public static @NonNull List<NetworkRequestList> getGroupedNetworkRequestList( + @NonNull + public static List<NetworkRequestList> getGroupedNetworkRequestList( @NonNull NetworkRequestList networkRequestList, @NonNull FeatureFlags featureFlags) { List<NetworkRequestList> requests = new ArrayList<>(); if (featureFlags.satelliteInternet()) { @@ -406,8 +411,7 @@ public class DataUtils { Arrays.stream(networkRequest.getNativeNetworkRequest() .getEnterpriseIds()) .boxed().collect(Collectors.toSet()), - Arrays.stream(networkRequest.getNativeNetworkRequest() - .getTransportTypes()) + Arrays.stream(networkRequest.getTransportTypes()) .boxed().collect(Collectors.toSet()) ), v -> new NetworkRequestList()).add(networkRequest); @@ -454,41 +458,31 @@ public class DataUtils { * @param sourceTransport The source transport. * @return The target transport. */ - public static @TransportType int getTargetTransport(@TransportType int sourceTransport) { + @TransportType + public static int getTargetTransport(@TransportType int sourceTransport) { return sourceTransport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN ? AccessNetworkConstants.TRANSPORT_TYPE_WLAN : AccessNetworkConstants.TRANSPORT_TYPE_WWAN; } /** - * Get the source transport from target transport. This is only used for handover between - * IWLAN and cellular scenario. - * - * @param targetTransport The target transport. - * @return The source transport. - */ - public static @TransportType int getSourceTransport(@TransportType int targetTransport) { - return targetTransport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN - ? AccessNetworkConstants.TRANSPORT_TYPE_WLAN - : AccessNetworkConstants.TRANSPORT_TYPE_WWAN; - } - - /** * Convert link status to string. * * @param linkStatus The link status. * @return The link status in string format. */ - public static @NonNull String linkStatusToString(@LinkStatus int linkStatus) { - switch (linkStatus) { - case DataCallResponse.LINK_STATUS_UNKNOWN: return "UNKNOWN"; - case DataCallResponse.LINK_STATUS_INACTIVE: return "INACTIVE"; - case DataCallResponse.LINK_STATUS_ACTIVE: return "ACTIVE"; - case DataCallResponse.LINK_STATUS_DORMANT: return "DORMANT"; - default: + @NonNull + public static String linkStatusToString(@LinkStatus int linkStatus) { + return switch (linkStatus) { + case DataCallResponse.LINK_STATUS_UNKNOWN -> "UNKNOWN"; + case DataCallResponse.LINK_STATUS_INACTIVE -> "INACTIVE"; + case DataCallResponse.LINK_STATUS_ACTIVE -> "ACTIVE"; + case DataCallResponse.LINK_STATUS_DORMANT -> "DORMANT"; + default -> { loge("Unknown link status(" + linkStatus + ")"); - return "UNKNOWN(" + linkStatus + ")"; - } + yield "UNKNOWN(" + linkStatus + ")"; + } + }; } /** @@ -498,17 +492,12 @@ public class DataUtils { * @return {@code true} if the access network type is valid. */ public static boolean isValidAccessNetwork(@RadioAccessNetworkType int accessNetworkType) { - switch (accessNetworkType) { - case AccessNetworkType.GERAN: - case AccessNetworkType.UTRAN: - case AccessNetworkType.EUTRAN: - case AccessNetworkType.CDMA2000: - case AccessNetworkType.IWLAN: - case AccessNetworkType.NGRAN: - return true; - default: - return false; - } + return switch (accessNetworkType) { + case AccessNetworkType.GERAN, AccessNetworkType.UTRAN, AccessNetworkType.EUTRAN, + AccessNetworkType.CDMA2000, AccessNetworkType.IWLAN, AccessNetworkType.NGRAN -> + true; + default -> false; + }; } /** @@ -517,17 +506,19 @@ public class DataUtils { * @param dataActivity The data activity. * @return The data activity in string format. */ - public static @NonNull String dataActivityToString(@DataActivityType int dataActivity) { - switch (dataActivity) { - case TelephonyManager.DATA_ACTIVITY_NONE: return "NONE"; - case TelephonyManager.DATA_ACTIVITY_IN: return "IN"; - case TelephonyManager.DATA_ACTIVITY_OUT: return "OUT"; - case TelephonyManager.DATA_ACTIVITY_INOUT: return "INOUT"; - case TelephonyManager.DATA_ACTIVITY_DORMANT: return "DORMANT"; - default: + @NonNull + public static String dataActivityToString(@DataActivityType int dataActivity) { + return switch (dataActivity) { + case TelephonyManager.DATA_ACTIVITY_NONE -> "NONE"; + case TelephonyManager.DATA_ACTIVITY_IN -> "IN"; + case TelephonyManager.DATA_ACTIVITY_OUT -> "OUT"; + case TelephonyManager.DATA_ACTIVITY_INOUT -> "INOUT"; + case TelephonyManager.DATA_ACTIVITY_DORMANT -> "DORMANT"; + default -> { loge("Unknown data activity(" + dataActivity + ")"); - return "UNKNOWN(" + dataActivity + ")"; - } + yield "UNKNOWN(" + dataActivity + ")"; + } + }; } private static void loge(String msg) { diff --git a/src/java/com/android/internal/telephony/data/KeepaliveStatus.java b/src/java/com/android/internal/telephony/data/KeepaliveStatus.java index 818de9614b..7b6c38d79b 100644 --- a/src/java/com/android/internal/telephony/data/KeepaliveStatus.java +++ b/src/java/com/android/internal/telephony/data/KeepaliveStatus.java @@ -23,7 +23,7 @@ import android.os.Parcelable; /** * This class serves to pass around the parameters of Keepalive session * status within the telephony framework. - * + * <p> * {@hide} */ public class KeepaliveStatus implements Parcelable { @@ -54,7 +54,8 @@ public class KeepaliveStatus implements Parcelable { * A status code indicating whether this Keepalive session is * active, inactive, or pending activation */ - public final @KeepaliveStatusCode int statusCode; + @KeepaliveStatusCode + public final int statusCode; /** An error code indicating a lower layer failure, if any */ public final int errorCode; @@ -98,7 +99,7 @@ public class KeepaliveStatus implements Parcelable { } public static final Parcelable.Creator<KeepaliveStatus> CREATOR = - new Parcelable.Creator<KeepaliveStatus>() { + new Parcelable.Creator<>() { @Override public KeepaliveStatus createFromParcel(Parcel source) { return new KeepaliveStatus(source); diff --git a/src/java/com/android/internal/telephony/data/KeepaliveTracker.java b/src/java/com/android/internal/telephony/data/KeepaliveTracker.java index 0a0133995d..f221779f04 100644 --- a/src/java/com/android/internal/telephony/data/KeepaliveTracker.java +++ b/src/java/com/android/internal/telephony/data/KeepaliveTracker.java @@ -56,19 +56,24 @@ public class KeepaliveTracker extends Handler { private static final int EVENT_UNREGISTER_FOR_KEEPALIVE_STATUS = 5; /** The phone instance. */ - private final @NonNull Phone mPhone; + @NonNull + private final Phone mPhone; /** The parent data network. */ - private final @NonNull DataNetwork mDataNetwork; + @NonNull + private final DataNetwork mDataNetwork; /** The associated network agent. */ - private final @NonNull TelephonyNetworkAgent mNetworkAgent; + @NonNull + private final TelephonyNetworkAgent mNetworkAgent; /** The log tag. */ - private final @NonNull String mLogTag; + @NonNull + private final String mLogTag; /** The keepalive records. */ - private final @NonNull SparseArray<KeepaliveRecord> mKeepalives = new SparseArray<>(); + @NonNull + private final SparseArray<KeepaliveRecord> mKeepalives = new SparseArray<>(); /** * Keepalive session record @@ -78,7 +83,8 @@ public class KeepaliveTracker extends Handler { public int slotIndex; /** The current status. */ - public @KeepaliveStatusCode int currentStatus; + @KeepaliveStatusCode + public int currentStatus; /** * Constructor diff --git a/src/java/com/android/internal/telephony/data/LinkBandwidthEstimator.java b/src/java/com/android/internal/telephony/data/LinkBandwidthEstimator.java index b92a590e70..534f191e61 100644 --- a/src/java/com/android/internal/telephony/data/LinkBandwidthEstimator.java +++ b/src/java/com/android/internal/telephony/data/LinkBandwidthEstimator.java @@ -178,6 +178,7 @@ public class LinkBandwidthEstimator extends Handler { private long mRxBytesDeltaAcc; private ModemActivityInfo mLastModemActivityInfo = null; + private final TelephonyCallback mTelephonyCallback = new TelephonyCallbackImpl(); private int mSignalStrengthDbm; private int mSignalLevel; private int mDataRat = TelephonyManager.NETWORK_TYPE_UNKNOWN; @@ -315,8 +316,7 @@ public class LinkBandwidthEstimator extends Handler { if (cm != null) { cm.registerDefaultNetworkCallback(mDefaultNetworkCallback, this); } - mTelephonyManager.registerTelephonyCallback(new HandlerExecutor(this), - new TelephonyCallbackImpl()); + mTelephonyManager.registerTelephonyCallback(new HandlerExecutor(this), mTelephonyCallback); mPlaceholderNetwork = new NetworkBandwidth(UNKNOWN_PLMN); initAvgBwPerRatTable(); registerNrStateFrequencyChange(); diff --git a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java index b7aa2510d6..27b4331ed9 100644 --- a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java +++ b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java @@ -53,7 +53,6 @@ import android.os.Registrant; import android.os.RegistrantList; import android.os.RemoteException; import android.telephony.CarrierConfigManager; -import android.telephony.PhoneCapability; import android.telephony.PhoneStateListener; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; @@ -183,10 +182,12 @@ public class PhoneSwitcher extends Handler { } } - private final @NonNull NetworkRequestList mNetworkRequestList = new NetworkRequestList(); + @NonNull + private final NetworkRequestList mNetworkRequestList = new NetworkRequestList(); protected final RegistrantList mActivePhoneRegistrants; private final SubscriptionManagerService mSubscriptionManagerService; - private final @NonNull FeatureFlags mFlags; + @NonNull + private final FeatureFlags mFlags; protected final Context mContext; private final LocalLog mLocalLog; protected PhoneState[] mPhoneStates; @@ -310,7 +311,7 @@ public class PhoneSwitcher extends Handler { private static final int MAX_LOCAL_LOG_LINES = 256; // Default timeout value of network validation in millisecond. - private final static int DEFAULT_VALIDATION_EXPIRATION_TIME = 2000; + private static final int DEFAULT_VALIDATION_EXPIRATION_TIME = 2000; /** Controller that tracks {@link TelephonyManager#MOBILE_DATA_POLICY_AUTO_DATA_SWITCH} */ @NonNull private final AutoDataSwitchController mAutoDataSwitchController; @@ -318,21 +319,23 @@ public class PhoneSwitcher extends Handler { @NonNull private final AutoDataSwitchController.AutoDataSwitchControllerCallback mAutoDataSwitchCallback; - private ConnectivityManager mConnectivityManager; + private final ConnectivityManager mConnectivityManager; private int mImsRegistrationTech = REGISTRATION_TECH_NONE; @VisibleForTesting public final SparseIntArray mImsRegistrationRadioTechMap = new SparseIntArray(); - private List<Set<CommandException.Error>> mCurrentDdsSwitchFailure; + @NonNull + private final List<Set<CommandException.Error>> mCurrentDdsSwitchFailure; /** Data settings manager callback. Key is the phone id. */ - private final @NonNull Map<Integer, DataSettingsManagerCallback> mDataSettingsManagerCallbacks = + @NonNull + private final Map<Integer, DataSettingsManagerCallback> mDataSettingsManagerCallbacks = new ArrayMap<>(); private class DefaultNetworkCallback extends ConnectivityManager.NetworkCallback { public int mExpectedSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; public int mSwitchReason = TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN; @Override - public void onCapabilitiesChanged(Network network, + public void onCapabilitiesChanged(@NonNull Network network, NetworkCapabilities networkCapabilities) { if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { if (SubscriptionManager.isValidSubscriptionId(mExpectedSubId) @@ -350,15 +353,15 @@ public class PhoneSwitcher extends Handler { } @Override - public void onLost(Network network) { + public void onLost(@NonNull Network network) { mAutoDataSwitchController.updateDefaultNetworkCapabilities(null); } } - private RegistrationManager.RegistrationCallback mRegistrationCallback = + private final RegistrationManager.RegistrationCallback mRegistrationCallback = new RegistrationManager.RegistrationCallback() { @Override - public void onRegistered(ImsRegistrationAttributes attributes) { + public void onRegistered(@NonNull ImsRegistrationAttributes attributes) { int imsRegistrationTech = attributes.getRegistrationTechnology(); if (imsRegistrationTech != mImsRegistrationTech) { mImsRegistrationTech = imsRegistrationTech; @@ -367,7 +370,7 @@ public class PhoneSwitcher extends Handler { } @Override - public void onUnregistered(ImsReasonInfo info) { + public void onUnregistered(@NonNull ImsReasonInfo info) { if (mImsRegistrationTech != REGISTRATION_TECH_NONE) { mImsRegistrationTech = REGISTRATION_TECH_NONE; sendMessage(obtainMessage(EVENT_IMS_RADIO_TECH_CHANGED)); @@ -402,14 +405,8 @@ public class PhoneSwitcher extends Handler { @VisibleForTesting public ImsRegisterCallback mImsRegisterCallback = - (context, phoneId, cb, executor)-> { - try { - ImsManager.getInstance(context, phoneId) - .addRegistrationCallback(cb, executor); - } catch (ImsException e) { - throw e; - } - }; + (context, phoneId, cb, executor)-> ImsManager.getInstance(context, phoneId) + .addRegistrationCallback(cb, executor); /** * Method to get singleton instance. @@ -497,7 +494,7 @@ public class PhoneSwitcher extends Handler { mRadioConfig = RadioConfig.getInstance(); mValidator = CellularNetworkValidator.getInstance(); - mCurrentDdsSwitchFailure = new ArrayList<Set<CommandException.Error>>(); + mCurrentDdsSwitchFailure = new ArrayList<>(); IntentFilter filter = new IntentFilter(); filter.addAction(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED); mContext.registerReceiver(mSimStateIntentReceiver, filter); @@ -545,7 +542,7 @@ public class PhoneSwitcher extends Handler { registerForImsRadioTechChange(context, phoneId); } } - Set<CommandException.Error> ddsFailure = new HashSet<CommandException.Error>(); + Set<CommandException.Error> ddsFailure = new HashSet<>(); mCurrentDdsSwitchFailure.add(ddsFailure); } @@ -652,7 +649,7 @@ public class PhoneSwitcher extends Handler { } }; - private BroadcastReceiver mSimStateIntentReceiver = new BroadcastReceiver() { + private final BroadcastReceiver mSimStateIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); @@ -874,10 +871,8 @@ public class PhoneSwitcher extends Handler { mEmergencyOverride.mOverrideCompleteFuture.complete(false); } } - mEmergencyOverride = req; - } else { - mEmergencyOverride = req; } + mEmergencyOverride = req; logl("new emergency override - " + mEmergencyOverride); // a new request has been created, remove any previous override complete scheduled. @@ -960,13 +955,9 @@ public class PhoneSwitcher extends Handler { mImsRegistrationRadioTechMap.put(phoneId, tech); - if (subId == INVALID_SUBSCRIPTION_ID) { - // Need to update the cached IMS registration tech but no need to do any of the - // following. When the SIM removed, REGISTRATION_STATE_NOT_REGISTERED is notified. - return false; - } - - return true; + // Need to update the cached IMS registration tech but no need to do any of the + // following. When the SIM removed, REGISTRATION_STATE_NOT_REGISTERED is notified. + return subId != INVALID_SUBSCRIPTION_ID; } private synchronized void onMultiSimConfigChanged(int activeModemCount) { @@ -1023,7 +1014,7 @@ public class PhoneSwitcher extends Handler { phone.getDataSettingsManager().registerCallback( mDataSettingsManagerCallbacks.get(phone.getPhoneId())); - Set<CommandException.Error> ddsFailure = new HashSet<CommandException.Error>(); + Set<CommandException.Error> ddsFailure = new HashSet<>(); mCurrentDdsSwitchFailure.add(ddsFailure); if (!mFlags.changeMethodOfObtainingImsRegistrationRadioTech()) { @@ -1072,7 +1063,7 @@ public class PhoneSwitcher extends Handler { } @Override - protected void needNetworkFor(NetworkRequest networkRequest) { + protected void needNetworkFor(@NonNull NetworkRequest networkRequest) { if (VDBG) log("needNetworkFor " + networkRequest); Message msg = mPhoneSwitcher.obtainMessage(EVENT_REQUEST_NETWORK); msg.obj = networkRequest; @@ -1080,7 +1071,7 @@ public class PhoneSwitcher extends Handler { } @Override - protected void releaseNetworkFor(NetworkRequest networkRequest) { + protected void releaseNetworkFor(@NonNull NetworkRequest networkRequest) { if (VDBG) log("releaseNetworkFor " + networkRequest); Message msg = mPhoneSwitcher.obtainMessage(EVENT_RELEASE_NETWORK); msg.obj = networkRequest; @@ -1157,7 +1148,7 @@ public class PhoneSwitcher extends Handler { protected static final boolean REQUESTS_UNCHANGED = false; /** * Re-evaluate things. Do nothing if nothing's changed. - * + * <p> * Otherwise, go through the requests in priority order adding their phone until we've added up * to the max allowed. Then go through shutting down phones that aren't in the active phone * list. Finally, activate all phones in the active phone list. @@ -1251,13 +1242,11 @@ public class PhoneSwitcher extends Handler { } sendRilCommands(mPreferredDataPhoneId); } else { - List<Integer> newActivePhones = new ArrayList<Integer>(); + List<Integer> newActivePhones = new ArrayList<>(); - /** - * If all phones can have PS attached, activate all. - * Otherwise, choose to activate phones according to requests. And - * if list is not full, add mPreferredDataPhoneId. - */ + // If all phones can have PS attached, activate all. + // Otherwise, choose to activate phones according to requests. And + // if list is not full, add mPreferredDataPhoneId. if (mMaxDataAttachModemCount == mActiveModemCount) { for (int i = 0; i < mMaxDataAttachModemCount; i++) { newActivePhones.add(i); @@ -1345,7 +1334,7 @@ public class PhoneSwitcher extends Handler { /** * Switch the Default data for the context of an outgoing emergency call. - * + * <p> * In some cases, we need to try to switch the Default Data subscription before placing the * emergency call on DSDS devices. This includes the following situation: * - The modem does not support processing GNSS SUPL requests on the non-default data @@ -1391,16 +1380,6 @@ public class PhoneSwitcher extends Handler { } } - private void onPhoneCapabilityChangedInternal(PhoneCapability capability) { - int newMaxDataAttachModemCount = TelephonyManager.getDefault() - .getNumberOfModemsWithSimultaneousDataConnections(); - if (mMaxDataAttachModemCount != newMaxDataAttachModemCount) { - mMaxDataAttachModemCount = newMaxDataAttachModemCount; - logl("Max active phones changed to " + mMaxDataAttachModemCount); - onEvaluate(REQUESTS_UNCHANGED, "phoneCfgChanged"); - } - } - private int phoneIdForRequest(TelephonyNetworkRequest networkRequest) { NetworkRequest netRequest = networkRequest.getNativeNetworkRequest(); int subId = getSubIdFromNetworkSpecifier(netRequest.getNetworkSpecifier()); @@ -1777,7 +1756,7 @@ public class PhoneSwitcher extends Handler { /** * Notify PhoneSwitcher to try to switch data to an opportunistic subscription. - * + * <p> * Set opportunistic data subscription. It's an indication to switch Internet data to this * subscription. It has to be an active subscription, and PhoneSwitcher will try to validate * it first if needed. If subId is DEFAULT_SUBSCRIPTION_ID, it means we are un-setting @@ -1856,20 +1835,16 @@ public class PhoneSwitcher extends Handler { * @param reason The switch reason. * @return The switch reason in string format. */ - private static @NonNull String switchReasonToString(int reason) { - switch(reason) { - case TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN: - return "UNKNOWN"; - case TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_MANUAL: - return "MANUAL"; - case TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL: - return "IN_CALL"; - case TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_CBRS: - return "CBRS"; - case TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_AUTO: - return "AUTO"; - default: return "UNKNOWN(" + reason + ")"; - } + @NonNull + private static String switchReasonToString(int reason) { + return switch (reason) { + case DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN -> "UNKNOWN"; + case DataSwitch.Reason.DATA_SWITCH_REASON_MANUAL -> "MANUAL"; + case DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL -> "IN_CALL"; + case DataSwitch.Reason.DATA_SWITCH_REASON_CBRS -> "CBRS"; + case DataSwitch.Reason.DATA_SWITCH_REASON_AUTO -> "AUTO"; + default -> "UNKNOWN(" + reason + ")"; + }; } /** @@ -1878,16 +1853,14 @@ public class PhoneSwitcher extends Handler { * @param state The switching state. * @return The switching state in string format. */ - private static @NonNull String switchStateToString(int state) { - switch(state) { - case TelephonyEvent.EventState.EVENT_STATE_UNKNOWN: - return "UNKNOWN"; - case TelephonyEvent.EventState.EVENT_STATE_START: - return "START"; - case TelephonyEvent.EventState.EVENT_STATE_END: - return "END"; - default: return "UNKNOWN(" + state + ")"; - } + @NonNull + private static String switchStateToString(int state) { + return switch (state) { + case TelephonyEvent.EventState.EVENT_STATE_UNKNOWN -> "UNKNOWN"; + case TelephonyEvent.EventState.EVENT_STATE_START -> "START"; + case TelephonyEvent.EventState.EVENT_STATE_END -> "END"; + default -> "UNKNOWN(" + state + ")"; + }; } /** diff --git a/src/java/com/android/internal/telephony/data/QosCallbackTracker.java b/src/java/com/android/internal/telephony/data/QosCallbackTracker.java index ebddbad007..a1ac379037 100644 --- a/src/java/com/android/internal/telephony/data/QosCallbackTracker.java +++ b/src/java/com/android/internal/telephony/data/QosCallbackTracker.java @@ -63,7 +63,8 @@ public class QosCallbackTracker extends Handler { private final RcsStats mRcsStats; // We perform an exact match on the address - private final @NonNull Map<Integer, IFilter> mCallbacksToFilter; + @NonNull + private final Map<Integer, IFilter> mCallbacksToFilter; private final int mPhoneId; @@ -143,11 +144,6 @@ public class QosCallbackTracker extends Handler { } }); } - - @Override - public void onQosCallbackUnregistered(int qosCallbackId) { - - } }); } @@ -259,7 +255,6 @@ public class QosCallbackTracker extends Handler { // The filter matches which means it was previously available, and now is // lost if (doFiltersMatch(existingSession, filter)) { - bearerState = DEDICATED_BEARER_EVENT_STATE_DELETED; sendSessionLost(callbackId, existingSession); notifyMetricDedicatedBearerEvent(existingSession, bearerState, true); sessionsReportedToMetric.add(sessionId); @@ -285,13 +280,13 @@ public class QosCallbackTracker extends Handler { }); } - private boolean doFiltersMatch(final @NonNull QosBearerSession qosBearerSession, - final @NonNull IFilter filter) { + private boolean doFiltersMatch(@NonNull final QosBearerSession qosBearerSession, + @NonNull final IFilter filter) { return getMatchingQosBearerFilter(qosBearerSession, filter) != null; } - private boolean matchesByLocalAddress(final @NonNull QosBearerFilter sessionFilter, - final @NonNull IFilter filter) { + private boolean matchesByLocalAddress(@NonNull final QosBearerFilter sessionFilter, + @NonNull final IFilter filter) { int portStart; int portEnd; if (sessionFilter.getLocalPortRange() == null) { @@ -320,7 +315,7 @@ public class QosCallbackTracker extends Handler { } private boolean matchesByRemoteAddress(@NonNull QosBearerFilter sessionFilter, - final @NonNull IFilter filter) { + @NonNull final IFilter filter) { int portStart; int portEnd; boolean result = false; @@ -350,8 +345,8 @@ public class QosCallbackTracker extends Handler { } private boolean matchesByProtocol(@NonNull QosBearerFilter sessionFilter, - final @NonNull IFilter filter, boolean hasMatchedFilter) { - boolean result = false; + @NonNull final IFilter filter, boolean hasMatchedFilter) { + boolean result; int protocol = sessionFilter.getProtocol(); if (protocol == QosBearerFilter.QOS_PROTOCOL_TCP || protocol == QosBearerFilter.QOS_PROTOCOL_UDP) { @@ -371,8 +366,9 @@ public class QosCallbackTracker extends Handler { ? sessionFilter : qosFilter; } - private @Nullable QosBearerFilter getMatchingQosBearerFilter( - @NonNull QosBearerSession qosBearerSession, final @NonNull IFilter filter) { + @Nullable + private QosBearerFilter getMatchingQosBearerFilter( + @NonNull QosBearerSession qosBearerSession, @NonNull final IFilter filter) { QosBearerFilter qosFilter = null; for (final QosBearerFilter sessionFilter : qosBearerSession.getQosBearerFilterList()) { @@ -410,11 +406,11 @@ public class QosCallbackTracker extends Handler { return qosFilter; } - private void sendSessionAvailable(final int callbackId, final @NonNull QosBearerSession session, - @NonNull IFilter filter) { + private void sendSessionAvailable(final int callbackId, @NonNull final QosBearerSession session, + @NonNull IFilter filter) { QosBearerFilter qosBearerFilter = getMatchingQosBearerFilter(session, filter); List<InetSocketAddress> remoteAddresses = new ArrayList<>(); - if (qosBearerFilter.getRemoteAddresses().size() > 0 + if (qosBearerFilter != null && !qosBearerFilter.getRemoteAddresses().isEmpty() && qosBearerFilter.getRemotePortRange() != null) { remoteAddresses.add( new InetSocketAddress(qosBearerFilter.getRemoteAddresses().get(0).getAddress(), @@ -459,17 +455,16 @@ public class QosCallbackTracker extends Handler { } private void notifyMetricDedicatedBearerListenerAdded(final int callbackId, - final @NonNull QosBearerSession session) { + @NonNull final QosBearerSession session) { - final int slotId = mPhoneId; final int rat = getRatInfoFromSessionInfo(session); final int qci = getQCIFromSessionInfo(session); - mRcsStats.onImsDedicatedBearerListenerAdded(callbackId, slotId, rat, qci); + mRcsStats.onImsDedicatedBearerListenerAdded(callbackId, mPhoneId, rat, qci); } private void notifyMetricDedicatedBearerListenerBearerUpdateSession( - final int callbackId, final @NonNull QosBearerSession session) { + final int callbackId, @NonNull final QosBearerSession session) { mRcsStats.onImsDedicatedBearerListenerUpdateSession(callbackId, mPhoneId, getRatInfoFromSessionInfo(session), getQCIFromSessionInfo(session), true); } @@ -522,13 +517,12 @@ public class QosCallbackTracker extends Handler { private void notifyMetricDedicatedBearerEvent(final QosBearerSession session, final int bearerState, final boolean hasListener) { - final int slotId = mPhoneId; int ratAtEnd = getRatInfoFromSessionInfo(session); int qci = getQCIFromSessionInfo(session); boolean localConnectionInfoReceived = doesLocalConnectionInfoExist(session); boolean remoteConnectionInfoReceived = doesRemoteConnectionInfoExist(session); - mRcsStats.onImsDedicatedBearerEvent(slotId, ratAtEnd, qci, bearerState, + mRcsStats.onImsDedicatedBearerEvent(mPhoneId, ratAtEnd, qci, bearerState, localConnectionInfoReceived, remoteConnectionInfoReceived, hasListener); } diff --git a/src/java/com/android/internal/telephony/data/TelephonyNetworkAgent.java b/src/java/com/android/internal/telephony/data/TelephonyNetworkAgent.java index d90724e191..5a81f19b43 100644 --- a/src/java/com/android/internal/telephony/data/TelephonyNetworkAgent.java +++ b/src/java/com/android/internal/telephony/data/TelephonyNetworkAgent.java @@ -70,7 +70,8 @@ public class TelephonyNetworkAgent extends NetworkAgent { * The callbacks that are used to pass information to {@link DataNetwork} and * {@link QosCallbackTracker}. */ - private final @NonNull Set<TelephonyNetworkAgentCallback> mTelephonyNetworkAgentCallbacks = + @NonNull + private final Set<TelephonyNetworkAgentCallback> mTelephonyNetworkAgentCallbacks = new ArraySet<>(); /** @@ -110,7 +111,7 @@ public class TelephonyNetworkAgent extends NetworkAgent { /** * Called when a qos callback is registered with a filter. - * + * <p> * Any QoS events that are sent with the same callback id after this method is called are a * no-op. * @@ -267,7 +268,7 @@ public class TelephonyNetworkAgent extends NetworkAgent { * @param filter the filter being registered */ @Override - public void onQosCallbackRegistered(final int qosCallbackId, final @NonNull QosFilter filter) { + public void onQosCallbackRegistered(final int qosCallbackId, @NonNull final QosFilter filter) { if (mAbandoned) { log("The agent is already abandoned. Ignored onQosCallbackRegistered."); return; @@ -278,7 +279,7 @@ public class TelephonyNetworkAgent extends NetworkAgent { /** * Called when a qos callback is registered with a filter. - * + * <p> * Any QoS events that are sent with the same callback id after this method is called are a * no-op. * diff --git a/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java b/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java index a16cee6c64..ca34ca78e4 100644 --- a/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java +++ b/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java @@ -265,13 +265,13 @@ public class TelephonyNetworkFactory extends NetworkFactory { } @Override - public void needNetworkFor(NetworkRequest networkRequest) { + public void needNetworkFor(@NonNull NetworkRequest networkRequest) { Message msg = mInternalHandler.obtainMessage(EVENT_NETWORK_REQUEST); msg.obj = networkRequest; msg.sendToTarget(); } - private void onNeedNetworkFor(Message msg) { + private void onNeedNetworkFor(@NonNull Message msg) { TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest((NetworkRequest) msg.obj, mPhone, mFlags); boolean shouldApply = mPhoneSwitcher.shouldApplyNetworkRequest( diff --git a/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java b/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java index b059100823..117eb3690d 100644 --- a/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java +++ b/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java @@ -24,6 +24,7 @@ import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.net.NetworkSpecifier; import android.os.SystemClock; +import android.telephony.Annotation.ConnectivityTransport; import android.telephony.Annotation.NetCapability; import android.telephony.data.ApnSetting; import android.telephony.data.DataProfile; @@ -137,19 +138,22 @@ public class TelephonyNetworkRequest { ); /** The phone instance. */ - private final @NonNull Phone mPhone; + @NonNull + private final Phone mPhone; /** * Native network request from the clients. See {@link NetworkRequest}; */ - private final @NonNull NetworkRequest mNativeNetworkRequest; + @NonNull + private final NetworkRequest mNativeNetworkRequest; /** * The attributes of the network capabilities in this network request. This describes how this * network request can be translated to different fields in {@link DataProfile} or perform * special actions in telephony. */ - private final @NetCapabilityAttribute int mCapabilitiesAttributes; + @NetCapabilityAttribute + private final int mCapabilitiesAttributes; /** * Priority of the network request. The network request has higher priority will be satisfied @@ -160,13 +164,15 @@ public class TelephonyNetworkRequest { /** * Data config manager for retrieving data config. */ - private final @NonNull DataConfigManager mDataConfigManager; + @NonNull + private final DataConfigManager mDataConfigManager; /** * The attached data network. Note that the data network could be in any state. {@code null} * indicates this network request is not satisfied. */ - private @Nullable DataNetwork mAttachedDataNetwork; + @Nullable + private DataNetwork mAttachedDataNetwork; /** * The state of the network request. @@ -175,16 +181,20 @@ public class TelephonyNetworkRequest { * @see #REQUEST_STATE_SATISFIED */ // This is not a boolean because there might be more states in the future. - private @RequestState int mState; + @RequestState + private int mState; /** The timestamp when this network request enters telephony. */ - private final @ElapsedRealtimeLong long mCreatedTimeMillis; + @ElapsedRealtimeLong + private final long mCreatedTimeMillis; /** The data evaluation result. */ - private @Nullable DataEvaluation mEvaluation; + @Nullable + private DataEvaluation mEvaluation; /** Feature flag. */ - private final @NonNull FeatureFlags mFeatureFlags; + @NonNull + private final FeatureFlags mFeatureFlags; /** * Constructor @@ -219,14 +229,17 @@ public class TelephonyNetworkRequest { /** * @see NetworkRequest#getNetworkSpecifier() */ - public @Nullable NetworkSpecifier getNetworkSpecifier() { + @Nullable + public NetworkSpecifier getNetworkSpecifier() { return mNativeNetworkRequest.getNetworkSpecifier(); } /** * @see NetworkRequest#getCapabilities() */ - public @NonNull @NetCapability int[] getCapabilities() { + @NonNull + @NetCapability + public int[] getCapabilities() { return mNativeNetworkRequest.getCapabilities(); } @@ -238,6 +251,23 @@ public class TelephonyNetworkRequest { } /** + * @see NetworkRequest#getTransportTypes() + */ + @NonNull + @ConnectivityTransport + public int[] getTransportTypes() { + return mNativeNetworkRequest.getTransportTypes(); + } + + /** + * @return {@code true} if the request can be served on the specified transport. + * @see NetworkRequest#hasTransport + */ + public boolean hasTransport(@ConnectivityTransport int transport) { + return mNativeNetworkRequest.hasTransport(transport); + } + + /** * @see NetworkRequest#canBeSatisfiedBy(NetworkCapabilities) */ public boolean canBeSatisfiedBy(@Nullable NetworkCapabilities nc) { @@ -354,7 +384,8 @@ public class TelephonyNetworkRequest { * @return The highest priority APN type based network capability from this network request. -1 * if there is no APN type capabilities in this network request. */ - public @NetCapability int getApnTypeNetworkCapability() { + @NetCapability + public int getApnTypeNetworkCapability() { if (!hasAttribute(CAPABILITY_ATTRIBUTE_APN_SETTING)) return -1; return Arrays.stream(getCapabilities()).boxed() .filter(cap -> DataUtils.networkCapabilityToApnType(cap) != ApnSetting.TYPE_NONE) @@ -364,7 +395,8 @@ public class TelephonyNetworkRequest { /** * @return The native network request. */ - public @NonNull NetworkRequest getNativeNetworkRequest() { + @NonNull + public NetworkRequest getNativeNetworkRequest() { return mNativeNetworkRequest; } @@ -373,7 +405,7 @@ public class TelephonyNetworkRequest { * * @param dataNetwork The data network. */ - public void setAttachedNetwork(@NonNull DataNetwork dataNetwork) { + public void setAttachedNetwork(@Nullable DataNetwork dataNetwork) { mAttachedDataNetwork = dataNetwork; } @@ -381,7 +413,8 @@ public class TelephonyNetworkRequest { * @return The attached network. {@code null} indicates the request is not attached to any * network (i.e. the request is unsatisfied). */ - public @Nullable DataNetwork getAttachedNetwork() { + @Nullable + public DataNetwork getAttachedNetwork() { return mAttachedDataNetwork; } @@ -397,7 +430,8 @@ public class TelephonyNetworkRequest { /** * @return The state of the network request. */ - public @RequestState int getState() { + @RequestState + public int getState() { return mState; } @@ -440,7 +474,8 @@ public class TelephonyNetworkRequest { * @return Os/App id. {@code null} if the request does not have traffic descriptor based network * capabilities. */ - public @Nullable OsAppId getOsAppId() { + @Nullable + public OsAppId getOsAppId() { if (!hasAttribute(CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_OS_APP_ID)) return null; // We do not support multiple network capabilities translated to Os/App id at this time. @@ -471,18 +506,19 @@ public class TelephonyNetworkRequest { * @param state The request state. * @return The request state in string format. */ - private static @NonNull String requestStateToString( + @NonNull + private static String requestStateToString( @TelephonyNetworkRequest.RequestState int state) { - switch (state) { - case TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED: return "UNSATISFIED"; - case TelephonyNetworkRequest.REQUEST_STATE_SATISFIED: return "SATISFIED"; - default: return "UNKNOWN(" + state + ")"; - } + return switch (state) { + case TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED -> "UNSATISFIED"; + case TelephonyNetworkRequest.REQUEST_STATE_SATISFIED -> "SATISFIED"; + default -> "UNKNOWN(" + state + ")"; + }; } @Override public String toString() { - return "[" + mNativeNetworkRequest.toString() + ", mPriority=" + mPriority + return "[" + mNativeNetworkRequest + ", mPriority=" + mPriority + ", state=" + requestStateToString(mState) + ", mAttachedDataNetwork=" + (mAttachedDataNetwork != null ? mAttachedDataNetwork.name() : null) + ", isMetered=" + isMeteredRequest() diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java index 02dd613b88..06ebff287d 100644 --- a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java +++ b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java @@ -50,6 +50,7 @@ import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.PhoneFactory; import com.android.internal.telephony.ServiceStateTracker; +import com.android.internal.telephony.TelephonyCapabilities; import com.android.internal.telephony.flags.FeatureFlags; import com.android.internal.telephony.metrics.EmergencyNumberStats; import com.android.internal.telephony.metrics.TelephonyMetrics; @@ -186,7 +187,7 @@ public class EmergencyNumberTracker extends Handler { mFeatureFlags = featureFlags; mResources = ctx.getResources(); - if (mFeatureFlags.minimalTelephonyCdmCheck() + if (TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags) && !ctx.getPackageManager().hasSystemFeature( PackageManager.FEATURE_TELEPHONY_CALLING)) { throw new UnsupportedOperationException("EmergencyNumberTracker requires calling"); diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java index 690f0ecf05..8478cff675 100644 --- a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java +++ b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java @@ -163,6 +163,7 @@ public class EmergencyStateTracker { private Runnable mOnEcmExitCompleteRunnable; private int mOngoingCallProperties; private boolean mSentEmergencyCallState; + private android.telecom.Connection mNormalRoutingEmergencyConnection; /** For emergency SMS */ private final Set<String> mOngoingEmergencySmsIds = new ArraySet<>(); @@ -633,8 +634,14 @@ public class EmergencyStateTracker { mOngoingConnection = c; mIsTestEmergencyNumber = isTestEmergencyNumber; sendEmergencyCallStateChange(mPhone, true); + final android.telecom.Connection expectedConnection = mOngoingConnection; maybeRejectIncomingCall(result -> { Rlog.i(TAG, "maybeRejectIncomingCall : result = " + result); + if (!Objects.equals(mOngoingConnection, expectedConnection)) { + Rlog.i(TAG, "maybeRejectIncomingCall " + + expectedConnection.getTelecomCallId() + " canceled."); + return; + } turnOnRadioAndSwitchDds(mPhone, EMERGENCY_TYPE_CALL, mIsTestEmergencyNumber); }); return mCallEmergencyModeFuture; @@ -1933,6 +1940,27 @@ public class EmergencyStateTracker { } } + private Call getRingingCall(Phone phone) { + if (phone == null) return null; + Call ringingCall = phone.getRingingCall(); + if (ringingCall != null + && ringingCall.getState() != Call.State.IDLE + && ringingCall.getState() != Call.State.DISCONNECTED) { + return ringingCall; + } + // Check the ImsPhoneCall in DISCONNECTING state. + Phone imsPhone = phone.getImsPhone(); + if (imsPhone != null) { + ringingCall = imsPhone.getRingingCall(); + } + if (imsPhone != null && ringingCall != null + && ringingCall.getState() != Call.State.IDLE + && ringingCall.getState() != Call.State.DISCONNECTED) { + return ringingCall; + } + return null; + } + /** * Ensures that there is no incoming call. * @@ -1951,14 +1979,14 @@ public class EmergencyStateTracker { Call ringingCall = null; for (Phone phone : phones) { - ringingCall = phone.getRingingCall(); - if (ringingCall != null && ringingCall.isRinging()) { + ringingCall = getRingingCall(phone); + if (ringingCall != null) { Rlog.i(TAG, "maybeRejectIncomingCall found a ringing call"); break; } } - if (ringingCall == null || !ringingCall.isRinging()) { + if (ringingCall == null) { if (completeConsumer != null) { completeConsumer.accept(true); } @@ -2007,9 +2035,13 @@ public class EmergencyStateTracker { */ private void handleNewRingingConnection(Message msg) { Connection c = (Connection) ((AsyncResult) msg.obj).result; - if (c == null || mOngoingConnection == null + if (c == null) return; + if ((mNormalRoutingEmergencyConnection == null + || mNormalRoutingEmergencyConnection.getState() == STATE_ACTIVE + || mNormalRoutingEmergencyConnection.getState() == STATE_DISCONNECTED) + && (mOngoingConnection == null || mOngoingConnection.getState() == STATE_ACTIVE - || mOngoingConnection.getState() == STATE_DISCONNECTED) { + || mOngoingConnection.getState() == STATE_DISCONNECTED)) { return; } if ((c.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) @@ -2024,4 +2056,53 @@ public class EmergencyStateTracker { } } } + + /** + * Indicates the start of a normal routing emergency call. + * + * <p> + * Handles turning on radio and switching DDS. + * + * @param phone the {@code Phone} on which to process the emergency call. + * @param c the {@code Connection} on which to process the emergency call. + * @param completeConsumer The consumer to call once rejecting incoming call completes, + * provides {@code true} result if operation completes successfully + * or {@code false} if the operation timed out/failed. + */ + public void startNormalRoutingEmergencyCall(@NonNull Phone phone, + @NonNull android.telecom.Connection c, @NonNull Consumer<Boolean> completeConsumer) { + Rlog.i(TAG, "startNormalRoutingEmergencyCall: phoneId=" + phone.getPhoneId() + + ", callId=" + c.getTelecomCallId()); + + mNormalRoutingEmergencyConnection = c; + maybeRejectIncomingCall(completeConsumer); + } + + /** + * Indicates the termination of a normal routing emergency call. + * + * @param c the normal routing emergency call disconnected. + */ + public void endNormalRoutingEmergencyCall(@NonNull android.telecom.Connection c) { + if (c != mNormalRoutingEmergencyConnection) return; + Rlog.i(TAG, "endNormalRoutingEmergencyCall: callId=" + c.getTelecomCallId()); + mNormalRoutingEmergencyConnection = null; + } + + /** + * Handles the normal routing emergency call state change. + * + * @param c the call whose state has changed + * @param state the new call state + */ + public void onNormalRoutingEmergencyCallStateChanged(android.telecom.Connection c, + @android.telecom.Connection.ConnectionState int state) { + if (c != mNormalRoutingEmergencyConnection) return; + + // If the call is connected, we don't need to monitor incoming call any more. + if (state == android.telecom.Connection.STATE_ACTIVE + || state == android.telecom.Connection.STATE_DISCONNECTED) { + endNormalRoutingEmergencyCall(c); + } + } } diff --git a/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java b/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java index 13fb82698e..175f5e4a5d 100644 --- a/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java +++ b/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java @@ -309,6 +309,7 @@ public class DataCallSessionStats { copy.isIwlanCrossSim = call.isIwlanCrossSim; copy.isNtn = call.isNtn; copy.isSatelliteTransport = call.isSatelliteTransport; + copy.isProvisioningProfile = call.isProvisioningProfile; return copy; } @@ -339,6 +340,7 @@ public class DataCallSessionStats { proto.isNtn = mSatelliteController != null ? mSatelliteController.isInSatelliteModeForCarrierRoaming(mPhone) : false; proto.isSatelliteTransport = isSatellite; + proto.isProvisioningProfile = getIsProvisioningProfile(); return proto; } @@ -355,6 +357,17 @@ public class DataCallSessionStats { return subInfo != null && subInfo.isOpportunistic(); } + private boolean getIsProvisioningProfile() { + SubscriptionInfoInternal subInfo = SubscriptionManagerService.getInstance() + .getSubscriptionInfoInternal(mPhone.getSubId()); + try { + return subInfo.getProfileClass() == SubscriptionManager.PROFILE_CLASS_PROVISIONING; + } catch (Exception ex) { + loge("getIsProvisioningProfile: " + ex.getMessage()); + return false; + } + } + private boolean getIsOos() { ServiceStateTracker serviceStateTracker = mPhone.getServiceStateTracker(); ServiceState serviceState = diff --git a/src/java/com/android/internal/telephony/metrics/DataConnectionStateTracker.java b/src/java/com/android/internal/telephony/metrics/DataConnectionStateTracker.java index 0197e36710..079ff03193 100644 --- a/src/java/com/android/internal/telephony/metrics/DataConnectionStateTracker.java +++ b/src/java/com/android/internal/telephony/metrics/DataConnectionStateTracker.java @@ -21,6 +21,7 @@ import static com.android.internal.telephony.flags.Flags.dataRatMetricEnabled; import android.os.Handler; import android.os.HandlerExecutor; import android.os.HandlerThread; +import android.telephony.PhysicalChannelConfig; import android.telephony.PreciseDataConnectionState; import android.telephony.SubscriptionManager; import android.telephony.TelephonyCallback; @@ -50,8 +51,10 @@ public class DataConnectionStateTracker { private int mSubId; private HashMap<Integer, PreciseDataConnectionState> mLastPreciseDataConnectionState = new HashMap<>(); - private PreciseDataConnectionStateListenerImpl mDataConnectionStateListener; + private TelephonyListenerImpl mTelephonyListener; private int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + private int mChannelCountEnum = TelephonyStatsLog + .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_UNSPECIFIED; private final SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionsChangedListener = new SubscriptionManager.OnSubscriptionsChangedListener() { @@ -136,15 +139,15 @@ public class DataConnectionStateTracker { TelephonyManager telephonyManager = mPhone.getContext().getSystemService(TelephonyManager.class); if (telephonyManager != null) { - mDataConnectionStateListener = new PreciseDataConnectionStateListenerImpl(mExecutor); - mDataConnectionStateListener.register(telephonyManager.createForSubscriptionId(subId)); + mTelephonyListener = new TelephonyListenerImpl(mExecutor); + mTelephonyListener.register(telephonyManager.createForSubscriptionId(subId)); } } private void unregisterTelephonyListener() { - if (mDataConnectionStateListener != null) { - mDataConnectionStateListener.unregister(); - mDataConnectionStateListener = null; + if (mTelephonyListener != null) { + mTelephonyListener.unregister(); + mTelephonyListener = null; } } @@ -167,7 +170,11 @@ public class DataConnectionStateTracker { return sDataConnectionStateTracker.valueAt(0).mActiveDataSubId; } - /** Log RAT if the active data subId changes to another subId with a different RAT */ + /** + * Log RAT if the active data subId changes to another subId with a different RAT. + * + * @param subId the current active data subId + */ private void logRATChanges(int subId) { if (mSubId == subId && mActiveDataSubId != subId) { int newDataRat = mPhone.getServiceStateTracker() @@ -188,13 +195,14 @@ public class DataConnectionStateTracker { } } - private class PreciseDataConnectionStateListenerImpl extends TelephonyCallback + private class TelephonyListenerImpl extends TelephonyCallback implements TelephonyCallback.PreciseDataConnectionStateListener, - TelephonyCallback.ActiveDataSubscriptionIdListener { + TelephonyCallback.ActiveDataSubscriptionIdListener, + TelephonyCallback.PhysicalChannelConfigListener { private final Executor mExecutor; private TelephonyManager mTelephonyManager = null; - PreciseDataConnectionStateListenerImpl(Executor executor) { + TelephonyListenerImpl(Executor executor) { mExecutor = executor; } @@ -223,7 +231,52 @@ public class DataConnectionStateTracker { public void onActiveDataSubscriptionIdChanged(int subId) { if (dataRatMetricEnabled()) { logRATChanges(subId); - mActiveDataSubId = subId; + } + mActiveDataSubId = subId; + } + + @Override + public void onPhysicalChannelConfigChanged(List<PhysicalChannelConfig> configs) { + logChannelChange(configs); + } + + /** Log channel number if it changes for active data subscription*/ + private void logChannelChange(List<PhysicalChannelConfig> configs) { + int connectedChannelCount = configs.size(); + int channelCountEnum = TelephonyStatsLog + .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_UNSPECIFIED; + switch(connectedChannelCount) { + case 0: + channelCountEnum = TelephonyStatsLog + .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_ONE; + break; + case 1: + channelCountEnum = TelephonyStatsLog + .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_ONE; + break; + case 2: + channelCountEnum = TelephonyStatsLog + .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_TWO; + break; + case 3: + channelCountEnum = TelephonyStatsLog + .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_THREE; + break; + case 4: + channelCountEnum = TelephonyStatsLog + .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_FOUR; + break; + // Greater than 4 + default: + channelCountEnum = TelephonyStatsLog + .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_FIVE; + } + if (mChannelCountEnum != channelCountEnum) { + if (mSubId != mActiveDataSubId) { + TelephonyStatsLog.write(TelephonyStatsLog.CONNECTED_CHANNEL_CHANGED, + channelCountEnum); + } + mChannelCountEnum = channelCountEnum; } } } diff --git a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java index e1a0385917..4232f20ed8 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, @@ -1134,7 +1208,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { dataCallSession.isNonDds, dataCallSession.isIwlanCrossSim, dataCallSession.isNtn, - dataCallSession.isSatelliteTransport); + dataCallSession.isSatelliteTransport, + dataCallSession.isProvisioningProfile); } private static StatsEvent buildStatsEvent(ImsRegistrationStats stats) { @@ -1394,7 +1469,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { satelliteSession.countOfOutgoingDatagramFailed, satelliteSession.countOfIncomingDatagramSuccess, satelliteSession.countOfIncomingDatagramFailed, - satelliteSession.isDemoMode); + satelliteSession.isDemoMode, + satelliteSession.maxNtnSignalStrengthLevel); } private static StatsEvent buildStatsEvent(SatelliteIncomingDatagram stats) { @@ -1450,6 +1526,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..975750ed4f 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"); @@ -2117,7 +2275,7 @@ public class PersistAtomsStorage { } /** - * Returns SatelliteOutgoingDatagram atom that has same values or {@code null} + * Returns SatelliteSession atom that has same values or {@code null} * if it does not exist. */ private @Nullable SatelliteSession find( @@ -2136,7 +2294,8 @@ public class PersistAtomsStorage { && stats.countOfOutgoingDatagramFailed == key.countOfOutgoingDatagramFailed && stats.countOfIncomingDatagramSuccess == key.countOfIncomingDatagramSuccess && stats.countOfIncomingDatagramFailed == key.countOfIncomingDatagramFailed - && stats.isDemoMode == key.isDemoMode) { + && stats.isDemoMode == key.isDemoMode + && stats.maxNtnSignalStrengthLevel == key.maxNtnSignalStrengthLevel) { return stats; } } @@ -2144,7 +2303,7 @@ public class PersistAtomsStorage { } /** - * Returns SatelliteOutgoingDatagram atom that has same values or {@code null} + * Returns SatelliteSosMessageRecommender atom that has same values or {@code null} * if it does not exist. */ private @Nullable SatelliteSosMessageRecommender find( @@ -2179,6 +2338,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 +2625,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..978e9d3df6 100644 --- a/src/java/com/android/internal/telephony/metrics/SatelliteStats.java +++ b/src/java/com/android/internal/telephony/metrics/SatelliteStats.java @@ -16,15 +16,23 @@ package com.android.internal.telephony.metrics; +import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE; + +import android.telephony.satellite.NtnSignalStrength; 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; /** Tracks Satellite metrics for each phone */ @@ -560,6 +568,7 @@ public class SatelliteStats { private final int mCountOfIncomingDatagramSuccess; private final int mCountOfIncomingDatagramFailed; private final boolean mIsDemoMode; + private final @NtnSignalStrength.NtnSignalStrengthLevel int mMaxNtnSignalStrengthLevel; private SatelliteSessionParams(Builder builder) { this.mSatelliteServiceInitializationResult = @@ -575,6 +584,7 @@ public class SatelliteStats { this.mCountOfIncomingDatagramSuccess = builder.mCountOfIncomingDatagramSuccess; this.mCountOfIncomingDatagramFailed = builder.mCountOfIncomingDatagramFailed; this.mIsDemoMode = builder.mIsDemoMode; + this.mMaxNtnSignalStrengthLevel = builder.mMaxNtnSignalStrengthLevel; } public int getSatelliteServiceInitializationResult() { @@ -621,6 +631,10 @@ public class SatelliteStats { return mIsDemoMode; } + public @NtnSignalStrength.NtnSignalStrengthLevel int getMaxNtnSignalStrengthLevel() { + return mMaxNtnSignalStrengthLevel; + } + /** * A builder class to create {@link SatelliteSessionParams} data structure class */ @@ -636,6 +650,8 @@ public class SatelliteStats { private int mCountOfIncomingDatagramSuccess = -1; private int mCountOfIncomingDatagramFailed = -1; private boolean mIsDemoMode = false; + private @NtnSignalStrength.NtnSignalStrengthLevel int mMaxNtnSignalStrengthLevel = + NTN_SIGNAL_STRENGTH_NONE; /** * Sets satelliteServiceInitializationResult value of {@link SatelliteSession} @@ -711,6 +727,13 @@ public class SatelliteStats { return this; } + /** Sets the max ntn signal strength for the satellite session */ + public Builder setMaxNtnSignalStrengthLevel( + @NtnSignalStrength.NtnSignalStrengthLevel int maxNtnSignalStrengthLevel) { + this.mMaxNtnSignalStrengthLevel = maxNtnSignalStrengthLevel; + return this; + } + /** * Returns SessionParams, which contains whole component of * {@link SatelliteSession} atom @@ -735,6 +758,7 @@ public class SatelliteStats { + ", CountOfIncomingDatagramSuccess=" + mCountOfIncomingDatagramSuccess + ", CountOfIncomingDatagramFailed=" + mCountOfIncomingDatagramFailed + ", IsDemoMode=" + mIsDemoMode + + ", MaxNtnSignalStrengthLevel=" + mMaxNtnSignalStrengthLevel + ")"; } } @@ -1206,6 +1230,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=" + mRssnrMedian + + ", 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(); @@ -1261,6 +1970,7 @@ public class SatelliteStats { proto.countOfIncomingDatagramSuccess = param.getCountOfIncomingDatagramSuccess(); proto.countOfIncomingDatagramFailed = param.getCountOfOutgoingDatagramFailed(); proto.isDemoMode = param.getIsDemoMode(); + proto.maxNtnSignalStrengthLevel = param.getMaxNtnSignalStrengthLevel(); mAtomsStorage.addSatelliteSessionStats(proto); } @@ -1311,4 +2021,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/metrics/ServiceStateStats.java b/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java index f1ad9b2d4b..3f24968aba 100644 --- a/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java +++ b/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java @@ -67,14 +67,12 @@ public class ServiceStateStats extends DataNetworkControllerCallback { private boolean mExistAnyConnectedInternetPdn; private int mCurrentDataRat = TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_UNSPECIFIED; - private final SatelliteController mSatelliteController; public ServiceStateStats(Phone phone) { super(Runnable::run); mPhone = phone; mStorage = PhoneFactory.getMetricsCollector().getAtomsStorage(); mDeviceStateHelper = PhoneFactory.getMetricsCollector().getDeviceStateHelper(); - mSatelliteController = SatelliteController.getInstance(); } /** Finalizes the durations of the current service state segment. */ @@ -126,6 +124,7 @@ public class ServiceStateStats extends DataNetworkControllerCallback { // Finish the duration of last service state and mark modem off addServiceState(mLastState.getAndSet(new TimestampedServiceState(null, now)), now); } else { + SatelliteController satelliteController = SatelliteController.getInstance(); CellularServiceState newState = new CellularServiceState(); newState.voiceRat = getVoiceRat(mPhone, serviceState); newState.dataRat = getRat(serviceState, NetworkRegistrationInfo.DOMAIN_PS); @@ -143,8 +142,8 @@ public class ServiceStateStats extends DataNetworkControllerCallback { newState.overrideVoiceService = mOverrideVoiceService.get(); newState.isDataEnabled = mPhone.getDataSettingsManager().isDataEnabled(); newState.isIwlanCrossSim = isCrossSimCallingRegistered(mPhone); - newState.isNtn = mSatelliteController != null - ? mSatelliteController.isInSatelliteModeForCarrierRoaming(mPhone) : false; + newState.isNtn = satelliteController != null + && satelliteController.isInSatelliteModeForCarrierRoaming(mPhone); TimestampedServiceState prevState = mLastState.getAndSet(new TimestampedServiceState(newState, now)); addServiceStateAndSwitch( diff --git a/src/java/com/android/internal/telephony/satellite/DatagramController.java b/src/java/com/android/internal/telephony/satellite/DatagramController.java index 6300640463..8271187ac3 100644 --- a/src/java/com/android/internal/telephony/satellite/DatagramController.java +++ b/src/java/com/android/internal/telephony/satellite/DatagramController.java @@ -29,6 +29,7 @@ import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCC import android.annotation.NonNull; import android.content.Context; +import android.content.res.Resources; import android.os.Build; import android.os.Looper; import android.os.SystemProperties; @@ -69,6 +70,8 @@ public class DatagramController { public static final int TIMEOUT_TYPE_WAIT_FOR_DATAGRAM_SENDING_RESPONSE = 3; /** This type is used by CTS to override the time to datagram delay in demo mode */ public static final int TIMEOUT_TYPE_DATAGRAM_DELAY_IN_DEMO_MODE = 4; + /** This type is used by CTS to override wait for device alignment in demo datagram boolean */ + public static final int BOOLEAN_TYPE_WAIT_FOR_DEVICE_ALIGNMENT_IN_DEMO_DATAGRAM = 1; private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem"; private static final boolean DEBUG = !"user".equals(Build.TYPE); @@ -101,6 +104,8 @@ public class DatagramController { private long mAlignTimeoutDuration = SATELLITE_ALIGN_TIMEOUT; private long mDatagramWaitTimeForConnectedState; private long mModemImageSwitchingDuration; + private boolean mWaitForDeviceAlignmentInDemoDatagram; + private long mDatagramWaitTimeForConnectedStateForLastMessage; @GuardedBy("mLock") @SatelliteManager.SatelliteModemState private int mSatelltieModemState = SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN; @@ -155,6 +160,10 @@ public class DatagramController { mDatagramWaitTimeForConnectedState = getDatagramWaitForConnectedStateTimeoutMillis(); mModemImageSwitchingDuration = getSatelliteModemImageSwitchingDurationMillis(); + mWaitForDeviceAlignmentInDemoDatagram = + getWaitForDeviceAlignmentInDemoDatagramFromResources(); + mDatagramWaitTimeForConnectedStateForLastMessage = + getDatagramWaitForConnectedStateForLastMessageTimeoutMillis(); mDemoModeDatagramList = new ArrayList<>(); } @@ -420,13 +429,15 @@ public class DatagramController { /** * Set last sent datagram for demo mode - * @param datagramType datagram type, only DATAGRAM_TYPE_SOS_MESSAGE will be saved + * @param datagramType datagram type, DATAGRAM_TYPE_SOS_MESSAGE, + * DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP, + * DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED will be saved * @param datagram datagram The last datagram saved when sendSatelliteDatagramForDemo is called */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public void pushDemoModeDatagram(@SatelliteManager.DatagramType int datagramType, SatelliteDatagram datagram) { - if (mIsDemoMode && datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) { + if (mIsDemoMode && SatelliteServiceUtils.isSosMessage(datagramType)) { synchronized (mLock) { mDemoModeDatagramList.add(datagram); logd("pushDemoModeDatagram size=" + mDemoModeDatagramList.size()); @@ -439,13 +450,17 @@ public class DatagramController { } @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public long getDatagramWaitTimeForConnectedState() { + public long getDatagramWaitTimeForConnectedState(boolean isLastSosMessage) { synchronized (mLock) { + long timeout = isLastSosMessage ? mDatagramWaitTimeForConnectedStateForLastMessage : + mDatagramWaitTimeForConnectedState; + logd("getDatagramWaitTimeForConnectedState: isLastSosMessage=" + isLastSosMessage + + ", timeout=" + timeout + ", modemState=" + mSatelltieModemState); if (mSatelltieModemState == SATELLITE_MODEM_STATE_OFF || mSatelltieModemState == SATELLITE_MODEM_STATE_IDLE) { - return (mDatagramWaitTimeForConnectedState + mModemImageSwitchingDuration); + return (timeout + mModemImageSwitchingDuration); } - return mDatagramWaitTimeForConnectedState; + return timeout; } } @@ -490,6 +505,36 @@ public class DatagramController { return true; } + /** + * This API can be used by only CTS to override the boolean configs used by the + * DatagramController module. + * + * @param enable Whether to enable or disable boolean config. + * @return {@code true} if the boolean config is set successfully, {@code false} otherwise. + */ + boolean setDatagramControllerBooleanConfig( + boolean reset, int booleanType, boolean enable) { + if (!isMockModemAllowed()) { + loge("Updating boolean config is not allowed"); + return false; + } + + logd("setDatagramControllerTimeoutDuration: booleanType=" + booleanType + + ", reset=" + reset + ", enable=" + enable); + if (booleanType == BOOLEAN_TYPE_WAIT_FOR_DEVICE_ALIGNMENT_IN_DEMO_DATAGRAM) { + if (reset) { + mWaitForDeviceAlignmentInDemoDatagram = + getWaitForDeviceAlignmentInDemoDatagramFromResources(); + } else { + mWaitForDeviceAlignmentInDemoDatagram = enable; + } + } else { + loge("Invalid boolean type " + booleanType); + return false; + } + return true; + } + private boolean isMockModemAllowed() { return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false)); } @@ -515,6 +560,11 @@ public class DatagramController { R.integer.config_satellite_modem_image_switching_duration_millis); } + private long getDatagramWaitForConnectedStateForLastMessageTimeoutMillis() { + return mContext.getResources().getInteger( + R.integer.config_datagram_wait_for_connected_state_for_last_message_timeout_millis); + } + /** * This API can be used by only CTS to override the cached value for the device overlay config * value : config_send_satellite_datagram_to_modem_in_demo_mode, which determines whether @@ -544,6 +594,38 @@ public class DatagramController { } } + /** + * Get whether to wait for device alignment with satellite before sending datagrams. + * + * @param isAligned if the device is aligned with satellite or not + * @return {@code true} if device is not aligned to satellite, + * and it is required to wait for alignment else {@code false} + */ + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + public boolean waitForAligningToSatellite(boolean isAligned) { + if (isAligned) { + return false; + } + + return getWaitForDeviceAlignmentInDemoDatagram(); + } + + private boolean getWaitForDeviceAlignmentInDemoDatagram() { + return mWaitForDeviceAlignmentInDemoDatagram; + } + + private boolean getWaitForDeviceAlignmentInDemoDatagramFromResources() { + boolean waitForDeviceAlignmentInDemoDatagram = false; + try { + waitForDeviceAlignmentInDemoDatagram = mContext.getResources().getBoolean( + R.bool.config_wait_for_device_alignment_in_demo_datagram); + } catch (Resources.NotFoundException ex) { + loge("getWaitForDeviceAlignmentInDemoDatagram: ex=" + ex); + } + + return waitForDeviceAlignmentInDemoDatagram; + } + private static void logd(@NonNull String log) { Rlog.d(TAG, log); } diff --git a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java index 6f7b23a407..3984a5f399 100644 --- a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java +++ b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java @@ -104,6 +104,7 @@ public class DatagramDispatcher extends Handler { mPendingNonEmergencyDatagramsMap = new LinkedHashMap<>(); private long mWaitTimeForDatagramSendingResponse; + private long mWaitTimeForDatagramSendingForLastMessageResponse; @SatelliteManager.DatagramType private int mLastSendRequestDatagramType = DATAGRAM_TYPE_UNKNOWN; @@ -142,6 +143,8 @@ public class DatagramDispatcher extends Handler { mSendingDatagramInProgress = false; } mWaitTimeForDatagramSendingResponse = getWaitForDatagramSendingResponseTimeoutMillis(); + mWaitTimeForDatagramSendingForLastMessageResponse = + getWaitForDatagramSendingResponseForLastMessageTimeoutMillis(); } private static final class DatagramDispatcherHandlerRequest { @@ -221,7 +224,7 @@ public class DatagramDispatcher extends Handler { } else { SatelliteModemInterface.getInstance().sendSatelliteDatagram( argument.datagram, - argument.datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE, + SatelliteServiceUtils.isSosMessage(argument.datagramType), argument.needFullScreenPointingUI, onCompleted); startWaitForDatagramSendingResponseTimer(argument); } @@ -239,7 +242,7 @@ public class DatagramDispatcher extends Handler { if (mIsDemoMode && (error == SatelliteManager.SATELLITE_RESULT_SUCCESS)) { if (argument.skipCheckingSatelliteAligned) { logd("Satellite was already aligned. No need to check alignment again"); - } else if (!mIsAligned) { + } else if (mDatagramController.waitForAligningToSatellite(mIsAligned)) { logd("Satellite is not aligned in demo mode, wait for the alignment."); startSatelliteAlignedTimer(request); break; @@ -266,7 +269,7 @@ public class DatagramDispatcher extends Handler { // Log metrics about the outgoing datagram reportSendDatagramCompleted(argument, error); // Remove current datagram from pending map. - if (argument.datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) { + if (SatelliteServiceUtils.isSosMessage(argument.datagramType)) { mPendingEmergencyDatagramsMap.remove(argument.datagramId); } else { mPendingNonEmergencyDatagramsMap.remove(argument.datagramId); @@ -277,9 +280,6 @@ public class DatagramDispatcher extends Handler { mDatagramController.updateSendStatus(argument.subId, argument.datagramType, SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS, getPendingDatagramCount(), error); - mControllerMetricsStats.reportOutgoingDatagramSuccessCount( - argument.datagramType, mIsDemoMode); - mSessionMetricsStats.addCountOfSuccessfulOutgoingDatagram(); startWaitForSimulatedPollDatagramsDelayTimer(request); if (getPendingDatagramCount() > 0) { // Send response for current datagram @@ -306,9 +306,6 @@ public class DatagramDispatcher extends Handler { // after updating datagram transfer state internally. argument.callback.accept(error); // Abort sending all the pending datagrams - mControllerMetricsStats.reportOutgoingDatagramFailCount( - argument.datagramType, mIsDemoMode); - mSessionMetricsStats.addCountOfFailedOutgoingDatagram(); abortSendingPendingDatagrams(argument.subId, SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED); } @@ -373,7 +370,7 @@ public class DatagramDispatcher extends Handler { synchronized (mLock) { // Add datagram to pending datagram map - if (datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) { + if (SatelliteServiceUtils.isSosMessage(datagramType)) { mPendingEmergencyDatagramsMap.put(datagramId, datagramArgs); } else { mPendingNonEmergencyDatagramsMap.put(datagramId, datagramArgs); @@ -550,8 +547,6 @@ public class DatagramDispatcher extends Handler { pendingDatagramsMap.entrySet()) { SendSatelliteDatagramArgument argument = entry.getValue(); reportSendDatagramCompleted(argument, errorCode); - mControllerMetricsStats.reportOutgoingDatagramFailCount(argument.datagramType, - mIsDemoMode); argument.callback.accept(errorCode); } @@ -610,6 +605,15 @@ public class DatagramDispatcher extends Handler { ? (System.currentTimeMillis() - argument.datagramStartTime) : 0) .setIsDemoMode(mIsDemoMode) .build()); + if (resultCode == SatelliteManager.SATELLITE_RESULT_SUCCESS) { + mControllerMetricsStats.reportOutgoingDatagramSuccessCount(argument.datagramType, + mIsDemoMode); + mSessionMetricsStats.addCountOfSuccessfulOutgoingDatagram(); + } else { + mControllerMetricsStats.reportOutgoingDatagramFailCount(argument.datagramType, + mIsDemoMode); + mSessionMetricsStats.addCountOfFailedOutgoingDatagram(); + } } /** @@ -679,7 +683,8 @@ public class DatagramDispatcher extends Handler { } sendMessageDelayed(obtainMessage( EVENT_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMED_OUT, datagramArgs), - mDatagramController.getDatagramWaitTimeForConnectedState()); + mDatagramController.getDatagramWaitTimeForConnectedState( + SatelliteServiceUtils.isLastSosMessage(datagramArgs.datagramType))); } private void stopDatagramWaitForConnectedStateTimer() { @@ -708,9 +713,13 @@ public class DatagramDispatcher extends Handler { logd("WaitForDatagramSendingResponseTimer was already started"); return; } + long waitTime = SatelliteServiceUtils.isLastSosMessage(argument.datagramType) + ? mWaitTimeForDatagramSendingForLastMessageResponse + : mWaitTimeForDatagramSendingResponse; + logd("startWaitForDatagramSendingResponseTimer: datagramType=" + argument.datagramType + + ", waitTime=" + waitTime); sendMessageDelayed(obtainMessage( - EVENT_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_TIMED_OUT, argument), - mWaitTimeForDatagramSendingResponse); + EVENT_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_TIMED_OUT, argument), waitTime); } private void stopWaitForDatagramSendingResponseTimer() { @@ -733,9 +742,6 @@ public class DatagramDispatcher extends Handler { 0, SatelliteManager.SATELLITE_RESULT_SUCCESS); abortSendingPendingDatagrams(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, SATELLITE_RESULT_NOT_REACHABLE); - mControllerMetricsStats.reportOutgoingDatagramFailCount(argument.datagramType, - mIsDemoMode); - mSessionMetricsStats.addCountOfFailedOutgoingDatagram(); } } @@ -762,10 +768,15 @@ public class DatagramDispatcher extends Handler { R.integer.config_wait_for_datagram_sending_response_timeout_millis); } + private long getWaitForDatagramSendingResponseForLastMessageTimeoutMillis() { + return mContext.getResources().getInteger(R.integer + .config_wait_for_datagram_sending_response_for_last_message_timeout_millis); + } + private boolean shouldProcessEventSendSatelliteDatagramDone( @NonNull SendSatelliteDatagramArgument argument) { synchronized (mLock) { - if (argument.datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) { + if (SatelliteServiceUtils.isSosMessage(argument.datagramType)) { return mPendingEmergencyDatagramsMap.containsKey(argument.datagramId); } else { return mPendingNonEmergencyDatagramsMap.containsKey(argument.datagramId); @@ -798,10 +809,8 @@ public class DatagramDispatcher extends Handler { // Log metrics about the outgoing datagram reportSendDatagramCompleted(argument, SATELLITE_RESULT_MODEM_TIMEOUT); - mControllerMetricsStats.reportOutgoingDatagramFailCount(argument.datagramType, - mIsDemoMode); // Remove current datagram from pending map. - if (argument.datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) { + if (SatelliteServiceUtils.isSosMessage(argument.datagramType)) { mPendingEmergencyDatagramsMap.remove(argument.datagramId); } else { mPendingNonEmergencyDatagramsMap.remove(argument.datagramId); diff --git a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java index 145b0174b9..21e4318556 100644 --- a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java +++ b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java @@ -620,7 +620,7 @@ public class DatagramReceiver extends Handler { DatagramReceiverHandlerRequest request = new DatagramReceiverHandlerRequest( callback, phone, subId); synchronized (mLock) { - if (mIsAligned) { + if (!mDatagramController.waitForAligningToSatellite(mIsAligned)) { Message msg = obtainMessage(EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE, request); AsyncResult.forMessage(msg, null, null); @@ -818,7 +818,7 @@ public class DatagramReceiver extends Handler { } sendMessageDelayed(obtainMessage( EVENT_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMED_OUT), - mDatagramController.getDatagramWaitTimeForConnectedState()); + mDatagramController.getDatagramWaitTimeForConnectedState(false)); } private void stopDatagramWaitForConnectedStateTimer() { diff --git a/src/java/com/android/internal/telephony/satellite/DemoSimulator.java b/src/java/com/android/internal/telephony/satellite/DemoSimulator.java new file mode 100644 index 0000000000..3c31ae8f6e --- /dev/null +++ b/src/java/com/android/internal/telephony/satellite/DemoSimulator.java @@ -0,0 +1,329 @@ +/* + * 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.NonNull; +import android.content.Context; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.telephony.IIntegerConsumer; +import android.telephony.satellite.stub.ISatelliteListener; +import android.telephony.satellite.stub.NtnSignalStrength; +import android.telephony.satellite.stub.SatelliteModemState; +import android.telephony.satellite.stub.SatelliteResult; +import android.util.Log; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.State; +import com.android.internal.util.StateMachine; + +public class DemoSimulator extends StateMachine { + private static final String TAG = "DemoSimulator"; + private static final boolean DBG = true; + + private static final int EVENT_SATELLITE_MODE_ON = 1; + private static final int EVENT_SATELLITE_MODE_OFF = 2; + private static final int EVENT_DEVICE_ALIGNED_WITH_SATELLITE = 3; + protected static final int EVENT_DEVICE_ALIGNED = 4; + protected static final int EVENT_DEVICE_NOT_ALIGNED = 5; + + @NonNull private static DemoSimulator sInstance; + + @NonNull private final Context mContext; + @NonNull private final SatelliteController mSatelliteController; + @NonNull private final PowerOffState mPowerOffState = new PowerOffState(); + @NonNull private final NotConnectedState mNotConnectedState = new NotConnectedState(); + @NonNull private final ConnectedState mConnectedState = new ConnectedState(); + @NonNull private final Object mLock = new Object(); + @GuardedBy("mLock") + private boolean mIsAligned = false; + private ISatelliteListener mISatelliteListener; + + /** + * @return The singleton instance of DemoSimulator. + */ + public static DemoSimulator getInstance() { + if (sInstance == null) { + Log.e(TAG, "DemoSimulator was not yet initialized."); + } + return sInstance; + } + + /** + * Create the DemoSimulator singleton instance. + * + * @param context The Context for the DemoSimulator. + * @return The singleton instance of DemoSimulator. + */ + public static DemoSimulator make(@NonNull Context context, + @NonNull SatelliteController satelliteController) { + if (sInstance == null) { + sInstance = new DemoSimulator(context, Looper.getMainLooper(), satelliteController); + } + return sInstance; + } + + /** + * Create a DemoSimulator. + * + * @param context The Context for the DemoSimulator. + * @param looper The looper associated with the handler of this class. + */ + protected DemoSimulator(@NonNull Context context, @NonNull Looper looper, + @NonNull SatelliteController satelliteController) { + super(TAG, looper); + + mContext = context; + mSatelliteController = satelliteController; + addState(mPowerOffState); + addState(mNotConnectedState); + addState(mConnectedState); + setInitialState(mPowerOffState); + start(); + } + + private class PowerOffState extends State { + @Override + public void enter() { + logd("Entering PowerOffState"); + } + + @Override + public void exit() { + logd("Exiting PowerOffState"); + } + + @Override + public boolean processMessage(Message msg) { + if (DBG) log("PowerOffState: processing " + getWhatToString(msg.what)); + switch (msg.what) { + case EVENT_SATELLITE_MODE_ON: + transitionTo(mNotConnectedState); + break; + } + // Ignore all unexpected events. + return HANDLED; + } + } + + private class NotConnectedState extends State { + @Override + public void enter() { + logd("Entering NotConnectedState"); + + try { + NtnSignalStrength ntnSignalStrength = new NtnSignalStrength(); + ntnSignalStrength.signalStrengthLevel = 0; + mISatelliteListener.onSatelliteModemStateChanged( + SatelliteModemState.SATELLITE_MODEM_STATE_NOT_CONNECTED); + mISatelliteListener.onNtnSignalStrengthChanged(ntnSignalStrength); + + synchronized (mLock) { + if (mIsAligned) { + handleEventDeviceAlignedWithSatellite(true); + } + } + } catch (RemoteException e) { + loge("NotConnectedState: RemoteException " + e); + } + } + + @Override + public void exit() { + logd("Exiting NotConnectedState"); + } + + @Override + public boolean processMessage(Message msg) { + if (DBG) log("NotConnectedState: processing " + getWhatToString(msg.what)); + switch (msg.what) { + case EVENT_SATELLITE_MODE_OFF: + transitionTo(mPowerOffState); + break; + case EVENT_DEVICE_ALIGNED_WITH_SATELLITE: + handleEventDeviceAlignedWithSatellite((boolean) msg.obj); + break; + case EVENT_DEVICE_ALIGNED: + transitionTo(mConnectedState); + break; + } + // Ignore all unexpected events. + return HANDLED; + } + + private void handleEventDeviceAlignedWithSatellite(boolean isAligned) { + if (isAligned && !hasMessages(EVENT_DEVICE_ALIGNED)) { + long durationMillis = mSatelliteController.getDemoPointingAlignedDurationMillis(); + logd("NotConnectedState: handleEventAlignedWithSatellite isAligned=true." + + " Send delayed EVENT_DEVICE_ALIGNED message in" + + " durationMillis=" + durationMillis); + sendMessageDelayed(EVENT_DEVICE_ALIGNED, durationMillis); + } else if (!isAligned && hasMessages(EVENT_DEVICE_ALIGNED)) { + logd("NotConnectedState: handleEventAlignedWithSatellite isAligned=false." + + " Remove EVENT_DEVICE_ALIGNED message."); + removeMessages(EVENT_DEVICE_ALIGNED); + } + } + } + + private class ConnectedState extends State { + @Override + public void enter() { + logd("Entering ConnectedState"); + + try { + NtnSignalStrength ntnSignalStrength = new NtnSignalStrength(); + ntnSignalStrength.signalStrengthLevel = 2; + mISatelliteListener.onSatelliteModemStateChanged( + SatelliteModemState.SATELLITE_MODEM_STATE_CONNECTED); + mISatelliteListener.onNtnSignalStrengthChanged(ntnSignalStrength); + + synchronized (mLock) { + if (!mIsAligned) { + handleEventDeviceAlignedWithSatellite(false); + } + } + } catch (RemoteException e) { + loge("ConnectedState: RemoteException " + e); + } + } + + @Override + public void exit() { + logd("Exiting ConnectedState"); + } + + @Override + public boolean processMessage(Message msg) { + if (DBG) log("ConnectedState: processing " + getWhatToString(msg.what)); + switch (msg.what) { + case EVENT_SATELLITE_MODE_OFF: + transitionTo(mPowerOffState); + break; + case EVENT_DEVICE_ALIGNED_WITH_SATELLITE: + handleEventDeviceAlignedWithSatellite((boolean) msg.obj); + break; + case EVENT_DEVICE_NOT_ALIGNED: + transitionTo(mNotConnectedState); + break; + } + // Ignore all unexpected events. + return HANDLED; + } + + private void handleEventDeviceAlignedWithSatellite(boolean isAligned) { + if (!isAligned && !hasMessages(EVENT_DEVICE_NOT_ALIGNED)) { + long durationMillis = + mSatelliteController.getDemoPointingNotAlignedDurationMillis(); + logd("ConnectedState: handleEventAlignedWithSatellite isAligned=false." + + " Send delayed EVENT_DEVICE_NOT_ALIGNED message" + + " in durationMillis=" + durationMillis); + sendMessageDelayed(EVENT_DEVICE_NOT_ALIGNED, durationMillis); + } else if (isAligned && hasMessages(EVENT_DEVICE_NOT_ALIGNED)) { + logd("ConnectedState: handleEventAlignedWithSatellite isAligned=true." + + " Remove EVENT_DEVICE_NOT_ALIGNED message."); + removeMessages(EVENT_DEVICE_NOT_ALIGNED); + } + } + } + + /** + * @return the string for msg.what + */ + @Override + protected String getWhatToString(int what) { + String whatString; + switch (what) { + case EVENT_SATELLITE_MODE_ON: + whatString = "EVENT_SATELLITE_MODE_ON"; + break; + case EVENT_SATELLITE_MODE_OFF: + whatString = "EVENT_SATELLITE_MODE_OFF"; + break; + case EVENT_DEVICE_ALIGNED_WITH_SATELLITE: + whatString = "EVENT_DEVICE_ALIGNED_WITH_SATELLITE"; + break; + case EVENT_DEVICE_ALIGNED: + whatString = "EVENT_DEVICE_ALIGNED"; + break; + case EVENT_DEVICE_NOT_ALIGNED: + whatString = "EVENT_DEVICE_NOT_ALIGNED"; + break; + default: + whatString = "UNKNOWN EVENT " + what; + } + return whatString; + } + + /** + * Register the callback interface with satellite service. + * + * @param listener The callback interface to handle satellite service indications. + */ + public void setSatelliteListener(@NonNull ISatelliteListener listener) { + mISatelliteListener = listener; + } + + /** + * Allow cellular modem scanning while satellite mode is on. + * + * @param enabled {@code true} to enable cellular modem while satellite mode is on + * and {@code false} to disable + * @param errorCallback The callback to receive the error code result of the operation. + */ + public void enableCellularModemWhileSatelliteModeIsOn(boolean enabled, + @NonNull IIntegerConsumer errorCallback) { + try { + errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS); + } catch (RemoteException e) { + loge("enableCellularModemWhileSatelliteModeIsOn: RemoteException " + e); + } + } + + /** + * This function is used by {@link SatelliteSessionController} to notify {@link DemoSimulator} + * that satellite mode is ON. + */ + public void onSatelliteModeOn() { + if (mSatelliteController.isDemoModeEnabled()) { + sendMessage(EVENT_SATELLITE_MODE_ON); + } + } + + /** + * This function is used by {@link SatelliteSessionController} to notify {@link DemoSimulator} + * that satellite mode is OFF. + */ + public void onSatelliteModeOff() { + sendMessage(EVENT_SATELLITE_MODE_OFF); + } + + /** + * Set whether the device is aligned with the satellite. + */ + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + public void setDeviceAlignedWithSatellite(boolean isAligned) { + synchronized (mLock) { + if (mSatelliteController.isDemoModeEnabled()) { + mIsAligned = isAligned; + sendMessage(EVENT_DEVICE_ALIGNED_WITH_SATELLITE, isAligned); + } + } + } +} 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..9cc342af9d 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; @@ -153,6 +155,7 @@ public class SatelliteController extends Handler { private static final boolean DEBUG = !"user".equals(Build.TYPE); /** File used to store shared preferences related to satellite. */ public static final String SATELLITE_SHARED_PREF = "satellite_shared_pref"; + public static final String SATELLITE_SUBSCRIPTION_ID = "satellite_subscription_id"; /** Value to pass for the setting key SATELLITE_MODE_ENABLED, enabled = 1, disabled = 0 */ public static final int SATELLITE_MODE_ENABLED_TRUE = 1; public static final int SATELLITE_MODE_ENABLED_FALSE = 0; @@ -162,6 +165,10 @@ public class SatelliteController extends Handler { * to enable satellite. */ public static final int TIMEOUT_TYPE_WAIT_FOR_SATELLITE_ENABLING_RESPONSE = 1; + /** This is used by CTS to override demo pointing aligned duration. */ + public static final int TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS = 2; + /** This is used by CTS to override demo pointing not aligned duration. */ + public static final int TIMEOUT_TYPE_DEMO_POINTING_NOT_ALIGNED_DURATION_MILLIS = 3; /** Key used to read/write OEM-enabled satellite provision status in shared preferences. */ private static final String OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY = @@ -214,12 +221,14 @@ public class SatelliteController extends Handler { @NonNull private static SatelliteController sInstance; @NonNull private final Context mContext; @NonNull private final SatelliteModemInterface mSatelliteModemInterface; - @NonNull private SatelliteSessionController mSatelliteSessionController; + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) + @NonNull protected SatelliteSessionController mSatelliteSessionController; @NonNull private final PointingAppController mPointingAppController; @NonNull private final DatagramController mDatagramController; @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; @@ -266,6 +275,8 @@ public class SatelliteController extends Handler { new AtomicBoolean(false); private final AtomicBoolean mIsModemEnabledReportingNtnSignalStrength = new AtomicBoolean(false); + private final AtomicBoolean mLatestRequestedStateForNtnSignalStrengthReport = + new AtomicBoolean(false); private final AtomicBoolean mRegisteredForSatelliteSupportedStateChanged = new AtomicBoolean(false); /** @@ -364,6 +375,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} @@ -401,6 +416,8 @@ public class SatelliteController extends Handler { private final SparseArray<List<String>> mMergedPlmnListPerCarrier = new SparseArray<>(); private static AtomicLong sNextSatelliteEnableRequestId = new AtomicLong(0); private long mWaitTimeForSatelliteEnablingResponse; + private long mDemoPointingAlignedDurationMillis; + private long mDemoPointingNotAlignedDurationMillis; /** Key used to read/write satellite system notification done in shared preferences. */ private static final String SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY = @@ -473,6 +490,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, @@ -528,6 +547,9 @@ public class SatelliteController extends Handler { null); loadSatelliteSharedPreferences(); mWaitTimeForSatelliteEnablingResponse = getWaitForSatelliteEnablingResponseTimeoutMillis(); + mDemoPointingAlignedDurationMillis = getDemoPointingAlignedDurationMillisFromResources(); + mDemoPointingNotAlignedDurationMillis = + getDemoPointingNotAlignedDurationMillisFromResources(); } /** @@ -995,6 +1017,7 @@ public class SatelliteController extends Handler { } } // Request Ntn signal strength report when satellite enabled or disabled done. + mLatestRequestedStateForNtnSignalStrengthReport.set(argument.enableSatellite); updateNtnSignalStrengthReporting(argument.enableSatellite); } else { synchronized (mSatelliteEnabledRequestLock) { @@ -1355,6 +1378,13 @@ public class SatelliteController extends Handler { + shouldReport); if (errorCode == SATELLITE_RESULT_SUCCESS) { mIsModemEnabledReportingNtnSignalStrength.set(shouldReport); + if (mLatestRequestedStateForNtnSignalStrengthReport.get() + != mIsModemEnabledReportingNtnSignalStrength.get()) { + logd("mLatestRequestedStateForNtnSignalStrengthReport does not match with " + + "mIsModemEnabledReportingNtnSignalStrength"); + updateNtnSignalStrengthReporting( + mLatestRequestedStateForNtnSignalStrengthReport.get()); + } } else { loge(((boolean) request.argument ? "startSendingNtnSignalStrength" : "stopSendingNtnSignalStrength") + "returns " + errorCode); @@ -1626,6 +1656,7 @@ public class SatelliteController extends Handler { /* We have already successfully queried the satellite modem. */ Bundle bundle = new Bundle(); bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, mIsSatelliteSupported); + bundle.putInt(SATELLITE_SUBSCRIPTION_ID, subId); result.send(SATELLITE_RESULT_SUCCESS, bundle); return; } @@ -2046,6 +2077,8 @@ public class SatelliteController extends Handler { logd("setDeviceAlignedWithSatellite: oemEnabledSatelliteFlag is disabled"); return; } + + DemoSimulator.getInstance().setDeviceAlignedWithSatellite(isAligned); mDatagramController.setDeviceAlignedWithSatellite(isAligned); } @@ -2376,6 +2409,25 @@ public class SatelliteController extends Handler { } /** + * This API can be used by only CTS to override the boolean configs used by the + * DatagramController module. + * + * @param enable Whether to enable or disable boolean config. + * @return {@code true} if the boolean config is set successfully, {@code false} otherwise. + */ + public boolean setDatagramControllerBooleanConfig( + boolean reset, int booleanType, boolean enable) { + if (!mFeatureFlags.oemEnabledSatelliteFlag()) { + logd("setDatagramControllerBooleanConfig: oemEnabledSatelliteFlag is disabled"); + return false; + } + logd("setDatagramControllerBooleanConfig: reset=" + reset + ", booleanType=" + + booleanType + ", enable=" + enable); + return mDatagramController.setDatagramControllerBooleanConfig( + reset, booleanType, enable); + } + + /** * This API can be used by only CTS to override timeout durations used by SatelliteController * module. * @@ -2402,6 +2454,20 @@ public class SatelliteController extends Handler { mWaitTimeForSatelliteEnablingResponse = timeoutMillis; } logd("mWaitTimeForSatelliteEnablingResponse=" + mWaitTimeForSatelliteEnablingResponse); + } else if (timeoutType == TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS) { + if (reset) { + mDemoPointingAlignedDurationMillis = + getDemoPointingAlignedDurationMillisFromResources(); + } else { + mDemoPointingAlignedDurationMillis = timeoutMillis; + } + } else if (timeoutType == TIMEOUT_TYPE_DEMO_POINTING_NOT_ALIGNED_DURATION_MILLIS) { + if (reset) { + mDemoPointingNotAlignedDurationMillis = + getDemoPointingNotAlignedDurationMillisFromResources(); + } else { + mDemoPointingNotAlignedDurationMillis = timeoutMillis; + } } else { logw("Invalid timeoutType=" + timeoutType); return false; @@ -3198,13 +3264,15 @@ public class SatelliteController extends Handler { } mSatelliteSessionController = SatelliteSessionController.make( mContext, getLooper(), supported); + logd("create a new SatelliteSessionController due to isSatelliteSupported state has " + + "changed to " + supported); + if (supported) { registerForSatelliteProvisionStateChanged(); registerForPendingDatagramCount(); registerForSatelliteModemStateChanged(); registerForNtnSignalStrengthChanged(); registerForCapabilitiesChanged(); - registerForSatelliteSupportedStateChanged(); requestIsSatelliteProvisioned(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, new ResultReceiver(this) { @@ -3231,6 +3299,7 @@ public class SatelliteController extends Handler { } }); } + registerForSatelliteSupportedStateChanged(); } private void updateSatelliteEnabledState(boolean enabled, String caller) { @@ -3386,6 +3455,7 @@ public class SatelliteController extends Handler { synchronized (mNtnSignalsStrengthLock) { mNtnSignalStrength = ntnSignalStrength; } + mSessionMetricsStats.updateMaxNtnSignalStrengthLevel(ntnSignalStrength.getLevel()); List<INtnSignalStrengthCallback> deadCallersList = new ArrayList<>(); mNtnSignalStrengthChangedListeners.values().forEach(listener -> { @@ -3437,6 +3507,9 @@ public class SatelliteController extends Handler { } return; } + + updateSatelliteSupportedStateWhenSatelliteServiceConnected(supported); + /* In case satellite has been reported as not support from modem, but satellite is enabled, request disable satellite. */ synchronized (mIsSatelliteEnabledLock) { @@ -3614,6 +3687,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 +3702,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 +3714,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"); @@ -3727,11 +3806,6 @@ public class SatelliteController extends Handler { private void processNewCarrierConfigData(int subId) { configureSatellitePlmnForCarrier(subId); - synchronized (mIsSatelliteEnabledLock) { - mSatelliteAttachRestrictionForCarrierArray.clear(); - mIsSatelliteAttachEnabledForCarrierArrayPerSub.clear(); - } - setSatelliteAttachEnabledForCarrierOnSimLoaded(subId); updateRestrictReasonForEntitlementPerCarrier(subId); } @@ -4113,7 +4187,18 @@ public class SatelliteController extends Handler { } synchronized (mSatelliteConnectedLock) { + CarrierRoamingSatelliteSessionStats sessionStats = + mCarrierRoamingSatelliteSessionStatsMap.get(subId); + if (serviceState.isUsingNonTerrestrialNetwork()) { + if (sessionStats != null) { + sessionStats.onSignalStrength(phone); + if (!mWasSatelliteConnectedViaCarrier.get(subId)) { + // Log satellite connection start + sessionStats.onConnectionStart(); + } + } + resetCarrierRoamingSatelliteModeParams(subId); mWasSatelliteConnectedViaCarrier.put(subId, true); @@ -4139,6 +4224,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 +4253,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 = + CarrierRoamingSatelliteSessionStats.getInstance(subId); + sessionStats.onSessionStart(phone.getCarrierId()); + mCarrierRoamingSatelliteSessionStatsMap.put(subId, sessionStats); + } else if (lastNotifiedNtnMode && !currNtnMode) { + // Log satellite session end + CarrierRoamingSatelliteSessionStats sessionStats = + mCarrierRoamingSatelliteSessionStatsMap.get(subId); + sessionStats.onSessionEnd(); + mCarrierRoamingSatelliteSessionStatsMap.remove(subId); } } } @@ -4374,6 +4485,7 @@ public class SatelliteController extends Handler { return; } + mLatestRequestedStateForNtnSignalStrengthReport.set(shouldReport); if (mIsModemEnabledReportingNtnSignalStrength.get() == shouldReport) { logd("handleCmdUpdateNtnSignalStrengthReporting: ignore request. " + "mIsModemEnabledReportingNtnSignalStrength=" @@ -4523,6 +4635,8 @@ public class SatelliteController extends Handler { notificationManager.notifyAsUser(NOTIFICATION_TAG, NOTIFICATION_ID, notificationBuilder.build(), UserHandle.ALL); + + mCarrierRoamingSatelliteControllerStats.reportCountOfSatelliteNotificationDisplayed(); } private void resetCarrierRoamingSatelliteModeParams() { @@ -4536,7 +4650,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); @@ -4573,6 +4686,40 @@ public class SatelliteController extends Handler { } } + private long getDemoPointingAlignedDurationMillisFromResources() { + long durationMillis = 15000L; + try { + durationMillis = mContext.getResources().getInteger( + R.integer.config_demo_pointing_aligned_duration_millis); + } catch (Resources.NotFoundException ex) { + loge("getPointingAlignedDurationMillis: ex=" + ex); + } + + return durationMillis; + } + + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + public long getDemoPointingAlignedDurationMillis() { + return mDemoPointingAlignedDurationMillis; + } + + private long getDemoPointingNotAlignedDurationMillisFromResources() { + long durationMillis = 30000L; + try { + durationMillis = mContext.getResources().getInteger( + R.integer.config_demo_pointing_not_aligned_duration_millis); + } catch (Resources.NotFoundException ex) { + loge("getPointingNotAlignedDurationMillis: ex=" + ex); + } + + return durationMillis; + } + + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + public long getDemoPointingNotAlignedDurationMillis() { + return mDemoPointingNotAlignedDurationMillis; + } + private static void logd(@NonNull String log) { Rlog.d(TAG, log); } diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java index 2e99ae65e1..8a26fd2642 100644 --- a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java +++ b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java @@ -42,6 +42,7 @@ import android.telephony.satellite.stub.INtnSignalStrengthConsumer; import android.telephony.satellite.stub.ISatellite; import android.telephony.satellite.stub.ISatelliteCapabilitiesConsumer; import android.telephony.satellite.stub.ISatelliteListener; +import android.telephony.satellite.stub.SatelliteModemState; import android.telephony.satellite.stub.SatelliteService; import android.text.TextUtils; import android.util.Pair; @@ -64,6 +65,9 @@ public class SatelliteModemInterface { @NonNull private static SatelliteModemInterface sInstance; @NonNull private final Context mContext; + @NonNull private final DemoSimulator mDemoSimulator; + @NonNull private final SatelliteListener mVendorListener; + @NonNull private final SatelliteListener mDemoListener; @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) @NonNull protected final ExponentialBackoff mExponentialBackoff; @NonNull private final Object mLock = new Object(); @@ -96,7 +100,14 @@ public class SatelliteModemInterface { @NonNull private final RegistrantList mSatelliteSupportedStateChangedRegistrants = new RegistrantList(); - @NonNull private final ISatelliteListener mListener = new ISatelliteListener.Stub() { + private class SatelliteListener extends ISatelliteListener.Stub { + + private final boolean mIsDemoListener; + + SatelliteListener(boolean isDemoListener) { + mIsDemoListener = isDemoListener; + } + @Override public void onSatelliteProvisionStateChanged(boolean provisioned) { mSatelliteProvisionStateChangedRegistrants.notifyResult(provisioned); @@ -105,15 +116,19 @@ public class SatelliteModemInterface { @Override public void onSatelliteDatagramReceived( android.telephony.satellite.stub.SatelliteDatagram datagram, int pendingCount) { - logd("onSatelliteDatagramReceived: pendingCount=" + pendingCount); - mSatelliteDatagramsReceivedRegistrants.notifyResult(new Pair<>( - SatelliteServiceUtils.fromSatelliteDatagram(datagram), pendingCount)); + if (notifyResultIfExpectedListener()) { + logd("onSatelliteDatagramReceived: pendingCount=" + pendingCount); + mSatelliteDatagramsReceivedRegistrants.notifyResult(new Pair<>( + SatelliteServiceUtils.fromSatelliteDatagram(datagram), pendingCount)); + } } @Override public void onPendingDatagrams() { - logd("onPendingDatagrams"); - mPendingDatagramsRegistrants.notifyResult(null); + if (notifyResultIfExpectedListener()) { + logd("onPendingDatagrams"); + mPendingDatagramsRegistrants.notifyResult(null); + } } @Override @@ -125,33 +140,39 @@ public class SatelliteModemInterface { @Override public void onSatelliteModemStateChanged(int state) { - mSatelliteModemStateChangedRegistrants.notifyResult( - SatelliteServiceUtils.fromSatelliteModemState(state)); - int datagramTransferState = SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN; - switch (state) { - case SatelliteManager.SATELLITE_MODEM_STATE_IDLE: - datagramTransferState = SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE; - break; - case SatelliteManager.SATELLITE_MODEM_STATE_LISTENING: - datagramTransferState = - SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING; - break; - case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING: - datagramTransferState = - SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING; - break; - case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING: - // keep previous state as this could be retrying sending or receiving - break; + if (notifyModemStateChanged(state)) { + mSatelliteModemStateChangedRegistrants.notifyResult( + SatelliteServiceUtils.fromSatelliteModemState(state)); + int datagramTransferState = + SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN; + switch (state) { + case SatelliteManager.SATELLITE_MODEM_STATE_IDLE: + datagramTransferState = + SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE; + break; + case SatelliteManager.SATELLITE_MODEM_STATE_LISTENING: + datagramTransferState = + SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING; + break; + case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING: + datagramTransferState = + SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING; + break; + case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING: + // keep previous state as this could be retrying sending or receiving + break; + } + mDatagramTransferStateChangedRegistrants.notifyResult(datagramTransferState); } - mDatagramTransferStateChangedRegistrants.notifyResult(datagramTransferState); } @Override public void onNtnSignalStrengthChanged( android.telephony.satellite.stub.NtnSignalStrength ntnSignalStrength) { - mNtnSignalStrengthChangedRegistrants.notifyResult( - SatelliteServiceUtils.fromNtnSignalStrength(ntnSignalStrength)); + if (notifyResultIfExpectedListener()) { + mNtnSignalStrengthChangedRegistrants.notifyResult( + SatelliteServiceUtils.fromNtnSignalStrength(ntnSignalStrength)); + } } @Override @@ -165,7 +186,22 @@ public class SatelliteModemInterface { public void onSatelliteSupportedStateChanged(boolean supported) { mSatelliteSupportedStateChangedRegistrants.notifyResult(supported); } - }; + + private boolean notifyResultIfExpectedListener() { + // Demo listener should notify results only during demo mode + // Vendor listener should notify result only during real mode + return mIsDemoListener == mSatelliteController.isDemoModeEnabled(); + } + + private boolean notifyModemStateChanged(int state) { + if (notifyResultIfExpectedListener()) { + return true; + } + + return state == SatelliteModemState.SATELLITE_MODEM_STATE_OFF + || state == SatelliteModemState.SATELLITE_MODEM_STATE_UNAVAILABLE; + } + } /** * @return The singleton instance of SatelliteModemInterface. @@ -202,6 +238,9 @@ public class SatelliteModemInterface { protected SatelliteModemInterface(@NonNull Context context, SatelliteController satelliteController, @NonNull Looper looper) { mContext = context; + mDemoSimulator = DemoSimulator.make(context, satelliteController); + mVendorListener = new SatelliteListener(false); + mDemoListener = new SatelliteListener(true); mIsSatelliteServiceSupported = getSatelliteServiceSupport(); mSatelliteController = satelliteController; mExponentialBackoff = new ExponentialBackoff(REBIND_INITIAL_DELAY, REBIND_MAXIMUM_DELAY, @@ -314,7 +353,8 @@ public class SatelliteModemInterface { mSatelliteService = ISatellite.Stub.asInterface(service); mExponentialBackoff.stop(); try { - mSatelliteService.setSatelliteListener(mListener); + mSatelliteService.setSatelliteListener(mVendorListener); + mDemoSimulator.setSatelliteListener(mDemoListener); } catch (RemoteException e) { // TODO: Retry setSatelliteListener logd("setSatelliteListener: RemoteException " + e); @@ -584,19 +624,26 @@ public class SatelliteModemInterface { @Nullable Message message) { if (mSatelliteService != null) { try { - mSatelliteService.enableCellularModemWhileSatelliteModeIsOn(enabled, - new IIntegerConsumer.Stub() { - @Override - public void accept(int result) { - int error = SatelliteServiceUtils.fromSatelliteError(result); - logd("enableCellularModemWhileSatelliteModeIsOn: " + error); - Binder.withCleanCallingIdentity(() -> { - if (message != null) { - sendMessageWithResult(message, null, error); - } - }); + IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() { + @Override + public void accept(int result) { + int error = SatelliteServiceUtils.fromSatelliteError(result); + logd("enableCellularModemWhileSatelliteModeIsOn: " + error); + Binder.withCleanCallingIdentity(() -> { + if (message != null) { + sendMessageWithResult(message, null, error); } }); + } + }; + + if (mSatelliteController.isDemoModeEnabled()) { + mDemoSimulator.enableCellularModemWhileSatelliteModeIsOn( + enabled, errorCallback); + } else { + mSatelliteService.enableCellularModemWhileSatelliteModeIsOn( + enabled, errorCallback); + } } catch (RemoteException e) { loge("enableCellularModemWhileSatelliteModeIsOn: RemoteException " + e); if (message != null) { diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java index 9e9f9d779e..c497ca12f4 100644 --- a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java +++ b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java @@ -190,6 +190,11 @@ public class SatelliteSOSMessageRecommender extends Handler { return; } + if (hasMessages(EVENT_EMERGENCY_CALL_STARTED)) { + logd("onEmergencyCallStarted: Ignoring due to ongoing event:"); + return; + } + /* * Right now, assume that the device is connected to satellite via carrier within hysteresis * time. However, this might not be correct when the monitoring timer expires. Thus, we @@ -277,7 +282,7 @@ public class SatelliteSOSMessageRecommender extends Handler { updateSatelliteViaCarrierAvailability(); boolean isDialerNotified = false; - if (!isImsRegistered() && !isCellularAvailable() + if (!isCellularAvailable() && isSatelliteAllowed() && (isSatelliteViaOemAvailable() || isSatelliteViaCarrierAvailable()) && shouldTrackCall(mEmergencyConnection.getState())) { @@ -434,12 +439,15 @@ public class SatelliteSOSMessageRecommender extends Handler { ServiceState serviceState = phone.getServiceState(); if (serviceState != null) { int state = serviceState.getState(); - if ((state == STATE_IN_SERVICE || state == STATE_EMERGENCY_ONLY) + if ((state == STATE_IN_SERVICE || state == STATE_EMERGENCY_ONLY + || serviceState.isEmergencyOnly()) && !serviceState.isUsingNonTerrestrialNetwork()) { + logv("isCellularAvailable true"); return true; } } } + logv("isCellularAvailable false"); return false; } @@ -474,9 +482,10 @@ public class SatelliteSOSMessageRecommender extends Handler { } private synchronized void handleStateChangedEventForHysteresisTimer() { - if (!isImsRegistered() && !isCellularAvailable()) { + if (!isCellularAvailable()) { startTimer(); } else { + logv("handleStateChangedEventForHysteresisTimer stopTimer"); stopTimer(); } } @@ -489,6 +498,7 @@ public class SatelliteSOSMessageRecommender extends Handler { sendMessageDelayed(obtainMessage(EVENT_TIME_OUT), mTimeoutMillis); mCountOfTimerStarted++; mIsTimerTimedOut = false; + logd("startTimer mCountOfTimerStarted=" + mCountOfTimerStarted); } } @@ -739,6 +749,10 @@ public class SatelliteSOSMessageRecommender extends Handler { || SystemProperties.getBoolean(BOOT_ALLOW_MOCK_MODEM_PROPERTY, false)); } + private static void logv(@NonNull String log) { + Rlog.v(TAG, log); + } + private static void logd(@NonNull String log) { Rlog.d(TAG, log); } diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java b/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java index 548a27fbb2..d33fd73a0c 100644 --- a/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java +++ b/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java @@ -347,6 +347,27 @@ public class SatelliteServiceUtils { } /** + * Check if the datagramType is the sos message (DATAGRAM_TYPE_SOS_MESSAGE, + * DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP, + * DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED) or not + */ + public static boolean isSosMessage(int datagramType) { + return datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE + || datagramType == SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP + || datagramType == SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED; + } + + /** + * Check if the datagramType is the last sos message + * (DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP or + * DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED) or not + */ + public static boolean isLastSosMessage(int datagramType) { + return datagramType == SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP + || datagramType == SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED; + } + + /** * Return phone associated with phoneId 0. * * @return phone associated with phoneId 0 or {@code null} if it doesn't exist. diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java index cd3c05b338..dcf9bb0105 100644 --- a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java +++ b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java @@ -39,7 +39,6 @@ import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.os.SystemProperties; -import android.telephony.Rlog; import android.telephony.satellite.ISatelliteModemStateCallback; import android.telephony.satellite.SatelliteManager; import android.telephony.satellite.stub.ISatelliteGateway; @@ -163,15 +162,9 @@ public class SatelliteSessionController extends StateMachine { */ public static SatelliteSessionController make( @NonNull Context context, @NonNull Looper looper, boolean isSatelliteSupported) { - if (sInstance == null) { + if (sInstance == null || isSatelliteSupported != sInstance.mIsSatelliteSupported) { sInstance = new SatelliteSessionController(context, looper, isSatelliteSupported, SatelliteModemInterface.getInstance()); - } else { - if (isSatelliteSupported != sInstance.mIsSatelliteSupported) { - Rlog.e(TAG, "New satellite support state " + isSatelliteSupported - + " is different from existing state " + sInstance.mIsSatelliteSupported - + ". Ignore the new state."); - } } return sInstance; } @@ -450,6 +443,7 @@ public class SatelliteSessionController extends StateMachine { } unbindService(); stopNbIotInactivityTimer(); + DemoSimulator.getInstance().onSatelliteModeOff(); notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_OFF); } @@ -520,6 +514,7 @@ public class SatelliteSessionController extends StateMachine { } else { transitionTo(mIdleState); } + DemoSimulator.getInstance().onSatelliteModeOn(); } else { /* * During the state transition from ENABLING to NOT_CONNECTED, modem might be 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..4ed4a984c4 --- /dev/null +++ b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java @@ -0,0 +1,269 @@ +/* + * 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.CellInfo; +import android.telephony.CellSignalStrength; +import android.telephony.CellSignalStrengthLte; +import android.telephony.SignalStrength; +import android.telephony.TelephonyManager; +import android.util.Log; +import android.util.SparseArray; + +import com.android.internal.telephony.Phone; +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 static final SparseArray<CarrierRoamingSatelliteSessionStats> + sCarrierRoamingSatelliteSessionStats = new SparseArray<>(); + private int mCarrierId; + private boolean mIsNtnRoamingInHomeCountry; + private int mCountOfIncomingSms; + private int mCountOfOutgoingSms; + private int mCountOfIncomingMms; + private int mCountOfOutgoingMms; + + private int mSessionStartTimeSec; + private List<Long> mConnectionStartTimeList; + private List<Long> mConnectionEndTimeList; + private List<Integer> mRsrpList; + private List<Integer> mRssnrList; + + public CarrierRoamingSatelliteSessionStats() { + logd("Create new CarrierRoamingSatelliteSessionStats."); + initializeParams(); + } + + /** Gets a CarrierRoamingSatelliteSessionStats instance. */ + public static CarrierRoamingSatelliteSessionStats getInstance(int subId) { + synchronized (sCarrierRoamingSatelliteSessionStats) { + if (sCarrierRoamingSatelliteSessionStats.get(subId) == null) { + sCarrierRoamingSatelliteSessionStats.put(subId, + new CarrierRoamingSatelliteSessionStats()); + } + return sCarrierRoamingSatelliteSessionStats.get(subId); + } + } + + /** Log carrier roaming satellite session start */ + public void onSessionStart(int carrierId) { + mCarrierId = carrierId; + 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()); + } + + /** Log rsrp and rssnr when occurred the service state change with NTN is connected. */ + public void onSignalStrength(Phone phone) { + CellSignalStrengthLte cellSignalStrengthLte = getCellSignalStrengthLte(phone); + int rsrp = cellSignalStrengthLte.getRsrp(); + int rssnr = cellSignalStrengthLte.getRssnr(); + if (rsrp == CellInfo.UNAVAILABLE) { + logd("onSignalStrength: rsrp unavailable"); + return; + } + if (rssnr == CellInfo.UNAVAILABLE) { + logd("onSignalStrength: rssnr unavailable"); + return; + } + mRsrpList.add(rsrp); + mRssnrList.add(rssnr); + logd("onSignalStrength : rsrp=" + rsrp + ", rssnr=" + rssnr); + } + + /** Log incoming sms success case */ + public void onIncomingSms() { + mCountOfIncomingSms += 1; + logd("onIncomingSms: mCountOfIncomingSms=" + mCountOfIncomingSms); + } + + /** Log outgoing sms success case */ + public void onOutgoingSms() { + mCountOfOutgoingSms += 1; + logd("onOutgoingSms: mCountOfOutgoingSms=" + mCountOfOutgoingSms); + } + + 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(getAvg(connectionGapList)) + .setSatelliteConnectionGapMaxSec(satelliteConnectionGapMaxSec) + .setRsrpAvg(getAvg(mRsrpList)) + .setRsrpMedian(getMedian(mRsrpList)) + .setRssnrAvg(getAvg(mRssnrList)) + .setRssnrMedian(getMedian(mRssnrList)) + .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; + mCountOfIncomingSms = 0; + mCountOfOutgoingSms = 0; + mCountOfIncomingMms = 0; + mCountOfOutgoingMms = 0; + + mSessionStartTimeSec = 0; + mConnectionStartTimeList = new ArrayList<>(); + mConnectionEndTimeList = new ArrayList<>(); + mRsrpList = new ArrayList<>(); + mRssnrList = new ArrayList<>(); + } + + private CellSignalStrengthLte getCellSignalStrengthLte(Phone phone) { + SignalStrength signalStrength = phone.getSignalStrength(); + List<CellSignalStrength> cellSignalStrengths = signalStrength.getCellSignalStrengths(); + for (CellSignalStrength cellSignalStrength : cellSignalStrengths) { + if (cellSignalStrength instanceof CellSignalStrengthLte) { + return (CellSignalStrengthLte) cellSignalStrength; + } + } + + return new CellSignalStrengthLte(); + } + + 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 getAvg(@NonNull List<Integer> list) { + if (list.isEmpty()) { + return 0; + } + + int total = 0; + for (int num : list) { + total += num; + } + + return total / list.size(); + } + + private int getMedian(@NonNull List<Integer> list) { + if (list.isEmpty()) { + return 0; + } + int size = list.size(); + if (size == 1) { + return list.get(0); + } + + Collections.sort(list); + return size % 2 == 0 ? (list.get(size / 2 - 1) + list.get(size / 2)) / 2 + : list.get(size / 2); + } + + 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/ControllerMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java index bbdd5426df..fdc7c5ca79 100644 --- a/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java +++ b/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java @@ -27,6 +27,7 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.metrics.SatelliteStats; +import com.android.internal.telephony.satellite.SatelliteServiceUtils; /** * Stats to log to satellite metrics @@ -142,7 +143,7 @@ public class ControllerMetricsStats { builder.setCountOfOutgoingDatagramSuccess(ADD_COUNT); } - if (datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) { + if (SatelliteServiceUtils.isSosMessage(datagramType)) { builder.setCountOfDatagramTypeSosSmsSuccess(ADD_COUNT); } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING) { builder.setCountOfDatagramTypeLocationSharingSuccess(ADD_COUNT); @@ -167,7 +168,7 @@ public class ControllerMetricsStats { builder.setCountOfOutgoingDatagramFail(ADD_COUNT); } - if (datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) { + if (SatelliteServiceUtils.isSosMessage(datagramType)) { builder.setCountOfDatagramTypeSosSmsFail(ADD_COUNT); } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING) { builder.setCountOfDatagramTypeLocationSharingFail(ADD_COUNT); 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/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java index c50db076b1..73ede600e8 100644 --- a/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java +++ b/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java @@ -16,7 +16,10 @@ package com.android.internal.telephony.satellite.metrics; +import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE; + import android.annotation.NonNull; +import android.telephony.satellite.NtnSignalStrength; import android.telephony.satellite.SatelliteManager; import android.util.Log; @@ -41,7 +44,7 @@ public class SessionMetricsStats { private int mCountOfSuccessfulIncomingDatagram; private int mCountOfIncomingDatagramFailed; private boolean mIsDemoMode; - + private @NtnSignalStrength.NtnSignalStrengthLevel int mMaxNtnSignalStrengthLevel; private SessionMetricsStats() { initializeSessionMetricsParam(); @@ -144,6 +147,17 @@ public class SessionMetricsStats { return this; } + /** Updates the max Ntn signal strength level for the session. */ + public SessionMetricsStats updateMaxNtnSignalStrengthLevel( + @NtnSignalStrength.NtnSignalStrengthLevel int latestNtnSignalStrengthLevel) { + if (latestNtnSignalStrengthLevel > mMaxNtnSignalStrengthLevel) { + mMaxNtnSignalStrengthLevel = latestNtnSignalStrengthLevel; + } + logd("updateMaxNtnSignalsStrength: latest signal strength=" + latestNtnSignalStrengthLevel + + ", max signal strength=" + mMaxNtnSignalStrengthLevel); + return this; + } + /** Report the session metrics atoms to PersistAtomsStorage in telephony. */ public void reportSessionMetrics() { SatelliteStats.SatelliteSessionParams sessionParams = @@ -159,6 +173,7 @@ public class SessionMetricsStats { .setCountOfIncomingDatagramSuccess(mCountOfSuccessfulIncomingDatagram) .setCountOfIncomingDatagramFailed(mCountOfIncomingDatagramFailed) .setIsDemoMode(mIsDemoMode) + .setMaxNtnSignalStrengthLevel(mMaxNtnSignalStrengthLevel) .build(); logd("reportSessionMetrics: " + sessionParams.toString()); SatelliteStats.getInstance().onSatelliteSessionMetrics(sessionParams); @@ -187,6 +202,7 @@ public class SessionMetricsStats { mCountOfSuccessfulIncomingDatagram = 0; mCountOfIncomingDatagramFailed = 0; mIsDemoMode = false; + mMaxNtnSignalStrengthLevel = NTN_SIGNAL_STRENGTH_NONE; } private static void logd(@NonNull String log) { diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java index 3d07d47388..75967541d8 100644 --- a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java +++ b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java @@ -1044,7 +1044,7 @@ public class SubscriptionDatabaseManager extends Handler { throw new IllegalArgumentException("updateSubscription: subscription does not " + "exist. subId=" + subId); } - if (oldSubInfo.equals(newSubInfo)) return; + if (oldSubInfo.equalsDbItemsOnly(newSubInfo)) return; if (updateDatabase(subId, createDeltaContentValues(oldSubInfo, newSubInfo)) > 0) { mAllSubscriptionInfoInternalCache.put(subId, newSubInfo); diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java index bb77d5c558..c6dee7c0a1 100644 --- a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java +++ b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java @@ -454,12 +454,13 @@ public class SubscriptionInfoInternal { */ private final int mIsOnlyNonTerrestrialNetwork; - // Below are the fields that do not exist in the SimInfo table. + // This field does not exist in the SimInfo table. /** * The card ID of the SIM card. This maps uniquely to {@link #mCardString}. */ private final int mCardId; + // This field does not exist in the SimInfo table. /** * Whether group of the subscription is disabled. This is only useful if it's a grouped * opportunistic subscription. In this case, if all primary (non-opportunistic) subscriptions @@ -1370,11 +1371,14 @@ public class SubscriptionInfoInternal { + "]"; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - SubscriptionInfoInternal that = (SubscriptionInfoInternal) o; + /** + * Campare only the columns existing in the SimInfo table and the mapped variables to see if + * they are equal. + * + * @param that SubscriptionInfoInternal to be compared + * @return {@code true} if equals. + */ + public boolean equalsDbItemsOnly(@NonNull SubscriptionInfoInternal that) { return mId == that.mId && mSimSlotIndex == that.mSimSlotIndex && mDisplayNameSource == that.mDisplayNameSource && mIconTint == that.mIconTint && mDataRoaming == that.mDataRoaming && mIsEmbedded == that.mIsEmbedded @@ -1407,7 +1411,6 @@ public class SubscriptionInfoInternal { && mPortIndex == that.mPortIndex && mUsageSetting == that.mUsageSetting && mLastUsedTPMessageReference == that.mLastUsedTPMessageReference && mUserId == that.mUserId && mIsSatelliteEnabled == that.mIsSatelliteEnabled - && mCardId == that.mCardId && mIsGroupDisabled == that.mIsGroupDisabled && mIccId.equals(that.mIccId) && mDisplayName.equals(that.mDisplayName) && mCarrierName.equals(that.mCarrierName) && mNumber.equals(that.mNumber) && mMcc.equals(that.mMcc) && mMnc.equals(that.mMnc) && mEhplmns.equals( @@ -1431,6 +1434,15 @@ public class SubscriptionInfoInternal { } @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SubscriptionInfoInternal that = (SubscriptionInfoInternal) o; + return equalsDbItemsOnly(that) + && mCardId == that.mCardId && mIsGroupDisabled == that.mIsGroupDisabled; + } + + @Override public int hashCode() { int result = Objects.hash(mId, mIccId, mSimSlotIndex, mDisplayName, mCarrierName, mDisplayNameSource, mIconTint, mNumber, mDataRoaming, mMcc, mMnc, mEhplmns, mHplmns, diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java index 91811dbc4b..0e98a9e795 100644 --- a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java +++ b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java @@ -1181,7 +1181,7 @@ public class SubscriptionManagerService extends ISub.Stub { SubscriptionManager.INVALID_SIM_SLOT_INDEX, null, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); mSubscriptionDatabaseManager.setDisplayName(subId, mContext.getResources() - .getString(R.string.default_card_name, subId)); + .getString(R.string.default_card_name, getCardNumber(subId))); subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternal(subId); } @@ -1452,6 +1452,11 @@ public class SubscriptionManagerService extends ISub.Stub { if (mSlotIndexToSubId.containsKey(phoneId)) { markSubscriptionsInactive(phoneId); } + + if (Flags.clearCachedImsPhoneNumberWhenDeviceLostImsRegistration()) { + // Clear the cached Ims phone number + setNumberFromIms(getSubId(phoneId), new String("")); + } } else if (simState == TelephonyManager.SIM_STATE_NOT_READY) { // Check if this is the final state. Only update the subscription if NOT_READY is a // final state. @@ -1464,6 +1469,11 @@ public class SubscriptionManagerService extends ISub.Stub { } else { logl("updateSubscription: UICC app disabled on slot " + phoneId); markSubscriptionsInactive(phoneId); + + if (Flags.clearCachedImsPhoneNumberWhenDeviceLostImsRegistration()) { + // Clear the cached Ims phone number + setNumberFromIms(getSubId(phoneId), new String("")); + } } } else { String iccId = getIccId(phoneId); @@ -1495,7 +1505,8 @@ public class SubscriptionManagerService extends ISub.Stub { subId = insertSubscriptionInfo(iccId, phoneId, null, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); mSubscriptionDatabaseManager.setDisplayName(subId, - mContext.getResources().getString(R.string.default_card_name, subId)); + mContext.getResources().getString(R.string.default_card_name, + getCardNumber(subId))); } else { subId = subInfo.getSubscriptionId(); log("updateSubscription: Found existing subscription. subId= " + subId @@ -1571,12 +1582,6 @@ public class SubscriptionManagerService extends ISub.Stub { loge("updateSubscription: ICC card is not available."); } - if (Flags.clearCachedImsPhoneNumberWhenDeviceLostImsRegistration()) { - // Clear the cached Ims phone number - // before proceeding with Ims Registration - setNumberFromIms(subId, new String("")); - } - // Attempt to restore SIM specific settings when SIM is loaded. Bundle result = mContext.getContentResolver().call( SubscriptionManager.SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, @@ -4723,6 +4728,11 @@ public class SubscriptionManagerService extends ISub.Stub { "config_satellite_sim_spn_identifier", ""); } log("isSatelliteSpn: overlaySpn=" + overlaySpn + ", spn=" + spn); + + if (TextUtils.isEmpty(spn) || TextUtils.isEmpty(overlaySpn)) { + return false; + } + return TextUtils.equals(spn, overlaySpn); } @@ -4733,6 +4743,24 @@ public class SubscriptionManagerService extends ISub.Stub { } /** + * Iterates through previously subscribed SIMs to excludes subscriptions that are not visible + * to the users to provide a more appropriate number to describe the current SIM. + * @param subId current subscription id. + * @return cardNumber subId excluding invisible subscriptions. + */ + private int getCardNumber(int subId) { + int cardNumber = subId; // Initialize with the potential card number + for (int i = subId - 1; i > 0; i--) { + SubscriptionInfoInternal subInfo = getSubscriptionInfoInternal(i); + if (subInfo != null && !subInfo.isVisible()) { + cardNumber--; + } + } + + return cardNumber; + } + + /** * Log debug messages. * * @param s debug messages diff --git a/src/java/com/android/internal/telephony/uicc/PinStorage.java b/src/java/com/android/internal/telephony/uicc/PinStorage.java index 23769ad32d..e4a0cfaf96 100644 --- a/src/java/com/android/internal/telephony/uicc/PinStorage.java +++ b/src/java/com/android/internal/telephony/uicc/PinStorage.java @@ -193,9 +193,11 @@ public class PinStorage extends Handler { CarrierConfigManager ccm = mContext.getSystemService(CarrierConfigManager.class); // Callback directly handle config change and should be executed in handler thread - ccm.registerCarrierConfigChangeListener(this::post, - (slotIndex, subId, carrierId, specificCarrierId) -> - onCarrierConfigurationChanged(slotIndex)); + if (ccm != null) { + ccm.registerCarrierConfigChangeListener(this::post, + (slotIndex, subId, carrierId, specificCarrierId) -> + onCarrierConfigurationChanged(slotIndex)); + } // Initialize the long term secret key. This needs to be present in all cases: // - if the device is not secure or is locked: key does not require user authentication diff --git a/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java index a6b2000493..855a5dcbb8 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java @@ -18,10 +18,8 @@ package com.android.internal.telephony; import static android.telephony.TelephonyManager.ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED; import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE; -import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL; import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA; import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DISMISS; -import static android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -251,6 +249,8 @@ public class MultiSimSettingControllerTest extends TelephonyTest { bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true); doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(anyInt()); + doReturn(true).when(mFeatureFlags).resetPrimarySimDefaultValues(); + replaceInstance(PhoneFactory.class, "sPhones", null, mPhones); // Capture listener to emulate the carrier config change notification used later ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor = @@ -496,18 +496,9 @@ public class MultiSimSettingControllerTest extends TelephonyTest { sendCarrierConfigChanged(1, SubscriptionManager.INVALID_SUBSCRIPTION_ID); processAllMessages(); - verify(mSubscriptionManagerService).setDefaultDataSubId( - SubscriptionManager.INVALID_SUBSCRIPTION_ID); - verify(mSubscriptionManagerService).setDefaultSmsSubId( - SubscriptionManager.INVALID_SUBSCRIPTION_ID); - verify(mSubscriptionManagerService, never()).setDefaultVoiceSubId(anyInt()); - - // Verify intent sent to select sub 2 as default for all types. - Intent intent = captureBroadcastIntent(); - assertEquals(ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED, intent.getAction()); - assertEquals(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL, - intent.getIntExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE, -1)); - assertEquals(2, intent.getIntExtra(EXTRA_SUBSCRIPTION_ID, -1)); + verify(mSubscriptionManagerService).setDefaultDataSubId(2); + verify(mSubscriptionManagerService).setDefaultSmsSubId(2); + verify(mSubscriptionManagerService).setDefaultVoiceSubId(2); } @Test @@ -917,8 +908,7 @@ public class MultiSimSettingControllerTest extends TelephonyTest { markSubscriptionInactive(1/*subid*/); sendCarrierConfigChanged(0/*phoneid*/, SubscriptionManager.INVALID_SUBSCRIPTION_ID); - verify(mSubscriptionManagerService).setDefaultDataSubId( - SubscriptionManager.INVALID_SUBSCRIPTION_ID); + verify(mSubscriptionManagerService).setDefaultDataSubId(2); // insert it back, but carrier config not loaded yet clearInvocations(mSubscriptionManagerService); diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java index 1c4e43d6f8..bf9ced3332 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java @@ -21,7 +21,10 @@ import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; +import com.android.internal.telephony.flags.Flags; + import android.net.Uri; +import android.platform.test.flag.junit.SetFlagsRule; import android.telephony.PhoneNumberUtils; import android.text.SpannableStringBuilder; import android.text.style.TtsSpan; @@ -32,6 +35,7 @@ import androidx.test.filters.SmallTest; import org.junit.After; import org.junit.Before; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; public class PhoneNumberUtilsTest { @@ -40,6 +44,8 @@ public class PhoneNumberUtilsTest { private int mOldMinMatch; + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Before public void setUp() throws Exception { mOldMinMatch = PhoneNumberUtils.getMinMatchForTest(); @@ -613,6 +619,60 @@ public class PhoneNumberUtilsTest { assertEquals("+1 650-555-1212", PhoneNumberUtils.formatNumber("+16505551212", "jp")); } + /** + * Test to ensure that when international calls to Singapore are being placed the country + * code is present with and without the feature flag enabled. + */ + @SmallTest + @Test + public void testFormatSingaporeInternational() { + // Disable feature flag. + mSetFlagsRule.disableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS); + + // International call from a US iso + assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "US")); + + // Lowercase country iso + assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "us")); + + // Enable feature flag + mSetFlagsRule.enableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS); + + // Internal call from a US iso + assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "US")); + + // Lowercase country iso + assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "us")); + mSetFlagsRule.disableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS); + } + + /** + * Test to ensure that when local calls from Singaporean numbers are being placed to other + * Singaporean numbers the country code +65 is not being shown. + */ + @SmallTest + @Test + public void testFormatSingaporeNational() { + // Disable feature flag. + mSetFlagsRule.disableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS); + + // Local call from a Singaporean number to a Singaporean number + assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "SG")); + + // Lowercase country iso. + assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "sg")); + + // Enable feature flag. + mSetFlagsRule.enableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS); + + // Local call from a Singaporean number to a Singaporean number. + assertEquals("6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "SG")); + + // Lowercase country iso. + assertEquals("6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "sg")); + mSetFlagsRule.disableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS); + } + @SmallTest @Test public void testFormatNumber_LeadingStarAndHash() { diff --git a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java index bfe9649e78..88c5389024 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java @@ -330,7 +330,7 @@ public class RILTest extends TelephonyTest { proxies.put(HAL_SERVICE_MODEM, mRadioModemProxy); mRILInstance = new RIL(context, RadioAccessFamily.getRafFromNetworkType(RILConstants.PREFERRED_NETWORK_MODE), - Phone.PREFERRED_CDMA_SUBSCRIPTION, 0, proxies); + Phone.PREFERRED_CDMA_SUBSCRIPTION, 0, proxies, mFeatureFlags); mRILUnderTest = spy(mRILInstance); doReturn(mRadioProxy).when(mRILUnderTest).getRadioProxy(); doReturn(mDataProxy).when(mRILUnderTest).getRadioServiceProxy(eq(RadioDataProxy.class)); @@ -354,6 +354,8 @@ public class RILTest extends TelephonyTest { replaceInstance(RIL.class, "mHalVersion", mRILUnderTest, mHalVersionV14); } catch (Exception e) { } + + doReturn(true).when(mFeatureFlags).combineRilDeathHandle(); } @After diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java index 81712c6b83..414fb3be38 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java @@ -816,15 +816,237 @@ public class SmsDispatchersControllerTest extends TelephonyTest { setUpDomainSelectionConnection(); setUpSmsDispatchers(); when(mFeatureFlags.smsDomainSelectionEnabled()).thenReturn(false); + when(mImsSmsDispatcher.isAvailable()).thenReturn(true); + + mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null, + "test-app", false, 0, false, 10, false, 1L, false); + + // Expect that the domain selection is not executed and + // ImsSmsDispatcher handles this text directly. + verify(mImsSmsDispatcher).sendText(eq("1111"), eq("2222"), eq("text"), + eq(mSentIntent), any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10), + eq(false), eq(1L), eq(false)); + } + + @Test + @SmallTest + public void testSendTextWhenDomainSelectionFinishedAndNewTextSent() throws Exception { + setUpDomainSelectionConnection(); + setUpSmsDispatchers(); mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null, "test-app", false, 0, false, 10, false, 1L, false); processAllMessages(); - // Expect that the domain selection logic will not be executed. SmsDispatchersController.DomainSelectionConnectionHolder holder = mSmsDispatchersController.testGetDomainSelectionConnectionHolder(false); - assertNull(holder); + verify(mSmsDsc).requestDomainSelection(any(), any()); + assertNotNull(holder); + assertNotNull(holder.getConnection()); + assertTrue(holder.isDomainSelectionRequested()); + assertEquals(1, holder.getPendingRequests().size()); + + // Expect that finishDomainSelection is called while a new pending request is posted. + mDscFuture.complete(NetworkRegistrationInfo.DOMAIN_PS); + + SmsDomainSelectionConnection newSmsDsc = Mockito.mock(SmsDomainSelectionConnection.class); + mSmsDispatchersController.setDomainSelectionResolverProxy( + new SmsDispatchersController.DomainSelectionResolverProxy() { + @Override + @Nullable + public DomainSelectionConnection getDomainSelectionConnection(Phone phone, + @DomainSelectionService.SelectorType int selectorType, + boolean isEmergency) { + return newSmsDsc; + } + + @Override + public boolean isDomainSelectionSupported() { + return true; + } + }); + CompletableFuture newDscFuture = new CompletableFuture<>(); + when(newSmsDsc.requestDomainSelection( + any(DomainSelectionService.SelectionAttributes.class), + any(DomainSelectionConnection.DomainSelectionConnectionCallback.class))) + .thenReturn(newDscFuture); + + // Expect that new domain selection connection is created and domain selection is performed. + mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null, + "test-app", false, 0, false, 10, false, 1L, false); + processAllMessages(); + + verify(mSmsDsc).finishSelection(); + + verify(newSmsDsc).requestDomainSelection(any(), any()); + assertNotNull(holder.getConnection()); + assertTrue(holder.isDomainSelectionRequested()); + assertEquals(1, holder.getPendingRequests().size()); + + newDscFuture.complete(NetworkRegistrationInfo.DOMAIN_PS); + processAllMessages(); + + verify(newSmsDsc).finishSelection(); + verify(mImsSmsDispatcher, times(2)).sendText(eq("1111"), eq("2222"), eq("text"), + eq(mSentIntent), any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10), + eq(false), eq(1L), eq(false)); + assertNull(holder.getConnection()); + assertFalse(holder.isDomainSelectionRequested()); + assertEquals(0, holder.getPendingRequests().size()); + } + + @Test + @SmallTest + public void testSendTextForEmergencyWhenDomainSelectionFinishedAndNewTextSent() + throws Exception { + setUpDomainSelectionConnection(); + setUpSmsDispatchers(); + setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED); + + mSmsDispatchersController.sendText("911", "2222", "text", mSentIntent, null, null, + "test-app", false, 0, false, 10, false, 1L, false); + processAllMessages(); + + SmsDispatchersController.DomainSelectionConnectionHolder holder = + mSmsDispatchersController.testGetDomainSelectionConnectionHolder(true); + verify(mEmergencySmsDsc).requestDomainSelection(any(), any()); + assertNotNull(holder); + assertNotNull(holder.getConnection()); + assertTrue(holder.isEmergency()); + assertTrue(holder.isDomainSelectionRequested()); + assertEquals(1, holder.getPendingRequests().size()); + + // Expect that finishDomainSelection is called while a new pending request is posted. + mDscFuture.complete(NetworkRegistrationInfo.DOMAIN_PS); + + EmergencySmsDomainSelectionConnection newEmergencySmsDsc = + Mockito.mock(EmergencySmsDomainSelectionConnection.class); + mSmsDispatchersController.setDomainSelectionResolverProxy( + new SmsDispatchersController.DomainSelectionResolverProxy() { + @Override + @Nullable + public DomainSelectionConnection getDomainSelectionConnection(Phone phone, + @DomainSelectionService.SelectorType int selectorType, + boolean isEmergency) { + return newEmergencySmsDsc; + } + + @Override + public boolean isDomainSelectionSupported() { + return true; + } + }); + CompletableFuture newDscFuture = new CompletableFuture<>(); + when(newEmergencySmsDsc.requestDomainSelection( + any(DomainSelectionService.SelectionAttributes.class), + any(DomainSelectionConnection.DomainSelectionConnectionCallback.class))) + .thenReturn(newDscFuture); + + // Expect that new domain selection connection is created and domain selection is performed. + mSmsDispatchersController.sendText("911", "2222", "text", mSentIntent, null, null, + "test-app", false, 0, false, 10, false, 1L, false); + processAllMessages(); + + verify(mEmergencySmsDsc).finishSelection(); + + verify(newEmergencySmsDsc).requestDomainSelection(any(), any()); + assertNotNull(holder.getConnection()); + assertTrue(holder.isDomainSelectionRequested()); + assertEquals(1, holder.getPendingRequests().size()); + + newDscFuture.complete(NetworkRegistrationInfo.DOMAIN_PS); + processAllMessages(); + + verify(newEmergencySmsDsc).finishSelection(); + verify(mImsSmsDispatcher, times(2)).sendText(eq("911"), eq("2222"), eq("text"), + eq(mSentIntent), any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10), + eq(false), eq(1L), eq(false)); + assertNull(holder.getConnection()); + assertFalse(holder.isDomainSelectionRequested()); + assertEquals(0, holder.getPendingRequests().size()); + } + + @Test + @SmallTest + public void testSendTextFallbackWhenDomainSelectionConnectionNotCreated() throws Exception { + mSmsDispatchersController.setDomainSelectionResolverProxy( + new SmsDispatchersController.DomainSelectionResolverProxy() { + @Override + @Nullable + public DomainSelectionConnection getDomainSelectionConnection(Phone phone, + @DomainSelectionService.SelectorType int selectorType, + boolean isEmergency) { + return null; + } + + @Override + public boolean isDomainSelectionSupported() { + return true; + } + }); + when(mFeatureFlags.smsDomainSelectionEnabled()).thenReturn(true); + setUpSmsDispatchers(); + when(mImsSmsDispatcher.isAvailable()).thenReturn(true); + + // Expect that creating a domain selection connection is failed and + // fallback to the legacy implementation. + mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null, + "test-app", false, 0, false, 10, false, 1L, false); + processAllMessages(); + + SmsDispatchersController.DomainSelectionConnectionHolder holder = + mSmsDispatchersController.testGetDomainSelectionConnectionHolder(false); + assertNotNull(holder); + assertNull(holder.getConnection()); + assertFalse(holder.isDomainSelectionRequested()); + assertEquals(0, holder.getPendingRequests().size()); + + verify(mImsSmsDispatcher).sendText(eq("1111"), eq("2222"), eq("text"), eq(mSentIntent), + any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10), eq(false), + eq(1L), eq(false)); + } + + @Test + @SmallTest + public void testSendTextFallbackForEmergencyWhenDomainSelectionConnectionNotCreated() + throws Exception { + mSmsDispatchersController.setDomainSelectionResolverProxy( + new SmsDispatchersController.DomainSelectionResolverProxy() { + @Override + @Nullable + public DomainSelectionConnection getDomainSelectionConnection(Phone phone, + @DomainSelectionService.SelectorType int selectorType, + boolean isEmergency) { + return null; + } + + @Override + public boolean isDomainSelectionSupported() { + return true; + } + }); + when(mFeatureFlags.smsDomainSelectionEnabled()).thenReturn(true); + setUpSmsDispatchers(); + setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED); + when(mImsSmsDispatcher.isAvailable()).thenReturn(true); + + // Expect that creating a domain selection connection is failed and + // fallback to the legacy implementation. + mSmsDispatchersController.sendText("911", "2222", "text", mSentIntent, null, null, + "test-app", false, 0, false, 10, false, 1L, false); + processAllMessages(); + + SmsDispatchersController.DomainSelectionConnectionHolder holder = + mSmsDispatchersController.testGetDomainSelectionConnectionHolder(true); + assertNotNull(holder); + assertNull(holder.getConnection()); + assertTrue(holder.isEmergency()); + assertFalse(holder.isDomainSelectionRequested()); + assertEquals(0, holder.getPendingRequests().size()); + + verify(mImsSmsDispatcher).sendText(eq("911"), eq("2222"), eq("text"), eq(mSentIntent), + any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10), eq(false), + eq(1L), eq(false)); } private void switchImsSmsFormat(int phoneType) { diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java index ddbe9c01e1..0e2676eca8 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java @@ -93,8 +93,10 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { private TelephonyDisplayInfo mGoodTelephonyDisplayInfo; private TelephonyDisplayInfo mBadTelephonyDisplayInfo; private int mDefaultDataSub; + private DataEvaluation mDataEvaluation; private AutoDataSwitchController mAutoDataSwitchControllerUT; private Map<Integer, AlarmManager.OnAlarmListener> mEventsToAlarmListener; + private Map<Integer, Object> mScheduledEventsToExtras; @Before public void setUp() throws Exception { super.setUp(getClass().getSimpleName()); @@ -137,6 +139,8 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { doAnswer(invocation -> phone.getSubId() == mDefaultDataSub) .when(phone).isUserDataEnabled(); } + mDataEvaluation = new DataEvaluation(DataEvaluation.DataEvaluationReason.EXTERNAL_QUERY); + doReturn(mDataEvaluation).when(mDataNetworkController).getInternetEvaluation(anyBoolean()); doReturn(new int[]{SUB_1, SUB_2}).when(mSubscriptionManagerService) .getActiveSubIdList(true); doAnswer(invocation -> { @@ -184,9 +188,12 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { mAutoDataSwitchControllerUT, mMockedAlarmManager); mEventsToAlarmListener = getPrivateField(mAutoDataSwitchControllerUT, "mEventsToAlarmListener", Map.class); + mScheduledEventsToExtras = getPrivateField(mAutoDataSwitchControllerUT, + "mScheduledEventsToExtras", Map.class); doReturn(true).when(mFeatureFlags).autoDataSwitchAllowRoaming(); doReturn(true).when(mFeatureFlags).carrierEnabledSatelliteFlag(); + doReturn(true).when(mFeatureFlags).autoDataSwitchUsesDataEnabled(); } @After @@ -240,7 +247,10 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { prepareIdealUsesNonDdsCondition(); processAllFutureMessages(); clearInvocations(mMockedPhoneSwitcherCallback); - doReturn(false).when(mPhone2).isDataAllowed(); + mDataEvaluation.addDataDisallowedReason(DataEvaluation.DataDisallowedReason + .NO_SUITABLE_DATA_PROFILE); + doReturn(mDataEvaluation) + .when(mDataNetworkController).getInternetEvaluation(anyBoolean()); mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(EVALUATION_REASON_DATA_SETTINGS_CHANGED); processAllFutureMessages(); @@ -350,7 +360,6 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { @Test public void testRoaming_same_roaming_condition_uses_rat_signalStrength() { - doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs(); // On primary phone // 1. Both roaming, user allow roaming on both phone, uses RAT score to decide switch. prepareIdealUsesNonDdsCondition(); @@ -375,7 +384,6 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { @Test public void testCancelSwitch_onPrimary_rat_signalStrength() { - doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs(); // 4.1.1 Display info and signal strength on secondary phone became bad, // but primary is still OOS, so still switch to the secondary. prepareIdealUsesNonDdsCondition(); @@ -467,7 +475,7 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { prepareIdealUsesNonDdsCondition(); // 2.2 Auto switch feature is disabled, no need validation clearInvocations(mCellularNetworkValidator); - doReturn(false).when(mPhone2).isDataAllowed(); + mDataEvaluation.addDataDisallowedReason(DataEvaluation.DataDisallowedReason.DATA_DISABLED); mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(EVALUATION_REASON_DATA_SETTINGS_CHANGED); processAllFutureMessages(); @@ -483,11 +491,13 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { verify(mMockedPhoneSwitcherCallback).onRequireValidation(DEFAULT_PHONE_INDEX, false/*needValidation*/); + + clearInvocations(mMockedPhoneSwitcherCallback); + prepareIdealUsesNonDdsCondition(); } @Test public void testOnNonDdsSwitchBackToPrimary_rat_signalStrength() { - doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs(); prepareIdealUsesNonDdsCondition(); processAllFutureMessages(); doReturn(PHONE_2).when(mPhoneSwitcher).getPreferredDataPhoneId(); @@ -536,10 +546,16 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { @Test public void testStabilityCheckOverride_basic() { + // Disable RAT + signalStrength base switching. + doReturn(-1).when(mDataConfigManager).getAutoDataSwitchScoreTolerance(); + mAutoDataSwitchControllerUT = new AutoDataSwitchController(mContext, Looper.myLooper(), + mPhoneSwitcher, mFeatureFlags, mMockedPhoneSwitcherCallback); + // Starting stability check for switching to non-DDS prepareIdealUsesNonDdsCondition(); - processAllMessages(); + processAllFutureMessages(); + clearInvocations(mMockedPhoneSwitcherCallback); // Switch success, but the previous stability check is still pending doReturn(PHONE_2).when(mPhoneSwitcher).getPreferredDataPhoneId(); @@ -557,7 +573,6 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { @Test public void testStabilityCheckOverride_uses_rat_signalStrength() { - doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs(); // Switching due to availability first. prepareIdealUsesNonDdsCondition(); @@ -578,6 +593,7 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { public void testValidationFailedRetry() { prepareIdealUsesNonDdsCondition(); + clearInvocations(mMockedPhoneSwitcherCallback); for (int i = 0; i < MAX_RETRY; i++) { mAutoDataSwitchControllerUT.evaluateRetryOnValidationFailed(); processAllFutureMessages(); @@ -730,7 +746,7 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { // 4.2 Auto switch feature is enabled doReturn(true).when(mPhone2).getDataRoamingEnabled(); - doReturn(true).when(mPhone2).isDataAllowed(); + mDataEvaluation.addDataAllowedReason(DataEvaluation.DataAllowedReason.NORMAL); // 5. No default network mAutoDataSwitchControllerUT.updateDefaultNetworkCapabilities(null /*networkCapabilities*/); @@ -783,10 +799,12 @@ public class AutoDataSwitchControllerTest extends TelephonyTest { @Override public void processAllFutureMessages() { - if (mFeatureFlags.autoDataSwitchRatSs() - && mEventsToAlarmListener.containsKey(EVENT_STABILITY_CHECK_PASSED)) { + if (mScheduledEventsToExtras.containsKey(EVENT_STABILITY_CHECK_PASSED)) { mEventsToAlarmListener.get(EVENT_STABILITY_CHECK_PASSED).onAlarm(); } + if (mScheduledEventsToExtras.containsKey(EVENT_EVALUATE_AUTO_SWITCH)) { + mEventsToAlarmListener.get(EVENT_EVALUATE_AUTO_SWITCH).onAlarm(); + } super.processAllFutureMessages(); } } diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java index 28e129c6f3..9d1c05eeb5 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java @@ -139,6 +139,8 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.Executor; +import javax.annotation.Nullable; + @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper public class DataNetworkControllerTest extends TelephonyTest { @@ -183,7 +185,6 @@ public class DataNetworkControllerTest extends TelephonyTest { private LinkBandwidthEstimatorCallback mLinkBandwidthEstimatorCallback; private boolean mIsNonTerrestrialNetwork = false; - private FeatureFlags mFeatureFlags; private final DataProfile mGeneralPurposeDataProfile = new DataProfile.Builder() .setApnSetting(new ApnSetting.Builder() @@ -393,17 +394,6 @@ public class DataNetworkControllerTest extends TelephonyTest { "PRIORITIZE_LATENCY", 1).getBytes())) .build(); - private final DataProfile mMmsOnWlanDataProfile = new DataProfile.Builder() - .setApnSetting(new ApnSetting.Builder() - .setEntryName("mms_wlan") - .setApnName("mms_wlan") - .setApnTypeBitmask(ApnSetting.TYPE_MMS) - .setCarrierEnabled(true) - .setNetworkTypeBitmask((int) TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN) - .build()) - .setPreferred(false) - .build(); - private final DataProfile mNtnDataProfile = new DataProfile.Builder() .setApnSetting(new ApnSetting.Builder() .setEntryName("ntn") @@ -873,7 +863,6 @@ public class DataNetworkControllerTest extends TelephonyTest { mMockedDataNetworkControllerCallback = Mockito.mock(DataNetworkControllerCallback.class); mMockedDataRetryManagerCallback = Mockito.mock(DataRetryManagerCallback.class); mMockSubInfo = Mockito.mock(SubscriptionInfo.class); - mFeatureFlags = Mockito.mock(FeatureFlags.class); when(mTelephonyComponentFactory.makeDataSettingsManager(any(Phone.class), any(DataNetworkController.class), any(FeatureFlags.class), any(Looper.class), any(DataSettingsManager.DataSettingsManagerCallback.class))).thenCallRealMethod(); @@ -901,6 +890,8 @@ public class DataNetworkControllerTest extends TelephonyTest { .when(mSubscriptionManagerService).getSubscriptionInfoInternal(anyInt()); doReturn(true).when(mFeatureFlags).carrierEnabledSatelliteFlag(); doReturn(true).when(mFeatureFlags).satelliteInternet(); + doReturn(true).when(mFeatureFlags) + .ignoreExistingNetworksForInternetAllowedChecking(); List<SubscriptionInfo> infoList = new ArrayList<>(); infoList.add(mMockSubInfo); @@ -1002,7 +993,7 @@ public class DataNetworkControllerTest extends TelephonyTest { List<DataProfile> profiles = List.of(mGeneralPurposeDataProfile, mGeneralPurposeDataProfileAlternative, mImsCellularDataProfile, mImsIwlanDataProfile, mEmergencyDataProfile, mFotaDataProfile, - mTetheringDataProfile, mMmsOnWlanDataProfile, mLowLatencyDataProfile, + mTetheringDataProfile, mLowLatencyDataProfile, mNtnDataProfile, mEsimBootstrapDataProfile, mEsimBootstrapImsProfile, mEsimBootstrapRcsInfraStructureProfile); @@ -1141,18 +1132,23 @@ public class DataNetworkControllerTest extends TelephonyTest { } private @NonNull TelephonyNetworkRequest createNetworkRequest(Integer... capabilities) { - return createNetworkRequest(false, capabilities); + return createNetworkRequest(null, capabilities); } - private @NonNull TelephonyNetworkRequest createNetworkRequest(boolean restricted, + private @NonNull TelephonyNetworkRequest createNetworkRequest(@Nullable Boolean restricted, Integer... capabilities) { NetworkCapabilities netCaps = new NetworkCapabilities(); for (int networkCapability : capabilities) { netCaps.addCapability(networkCapability); } - if (restricted) { - netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); + if (restricted != null) { + if (restricted) { + netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); + } + } else { + // Data Network uses the same to define its own capabilities. + netCaps.maybeMarkCapabilitiesRestricted(); } NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps, @@ -1744,6 +1740,14 @@ public class DataNetworkControllerTest extends TelephonyTest { verify(mMockedDataNetworkControllerCallback, never()) .onConnectedInternetDataNetworksChanged(any()); + // However, WLAN network setup shouldn't be affected + doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager) + .getPreferredTransportByNetworkCapability(anyInt()); + mDataNetworkControllerUT.obtainMessage(5 /*EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS*/, + DataEvaluation.DataEvaluationReason.PREFERRED_TRANSPORT_CHANGED).sendToTarget(); + processAllMessages(); + verify(mMockedDataNetworkControllerCallback).onConnectedInternetDataNetworksChanged(any()); + mIsNonTerrestrialNetwork = false; } @@ -3322,12 +3326,20 @@ public class DataNetworkControllerTest extends TelephonyTest { NetworkCapabilities.NET_CAPABILITY_IMS); TelephonyNetworkRequest secondTnr = createNetworkRequest( NetworkCapabilities.NET_CAPABILITY_IMS); + TelephonyNetworkRequest thirdTnr = new TelephonyNetworkRequest( + new NetworkRequest((new NetworkCapabilities.Builder()) + .addCapability(NetworkCapabilities.NET_CAPABILITY_IMS) + .addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE) + .build(), + ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, + NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags); mDataNetworkControllerUT.addNetworkRequest(firstTnr); processAllMessages(); mDataNetworkControllerUT.removeNetworkRequest(firstTnr); mDataNetworkControllerUT.addNetworkRequest(secondTnr); + mDataNetworkControllerUT.addNetworkRequest(thirdTnr); processAllFutureMessages(); verify(mMockedWwanDataServiceManager, times(1)).setupDataCall(anyInt(), @@ -4192,6 +4204,7 @@ public class DataNetworkControllerTest extends TelephonyTest { NetworkCapabilities netCaps = new NetworkCapabilities(); netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS); + netCaps.maybeMarkCapabilitiesRestricted(); netCaps.setRequestorPackageName(FAKE_MMTEL_PACKAGE); NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps, @@ -4244,6 +4257,7 @@ public class DataNetworkControllerTest extends TelephonyTest { // setup emergency data network. NetworkCapabilities netCaps = new NetworkCapabilities(); netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS); + netCaps.maybeMarkCapabilitiesRestricted(); netCaps.setRequestorPackageName(FAKE_MMTEL_PACKAGE); NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps, @@ -5037,34 +5051,6 @@ public class DataNetworkControllerTest extends TelephonyTest { } @Test - public void testAllowBringUpWithDifferentDataProfileForWlan() throws Exception { - // Mock MMS preferred on WLAN - doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager) - .getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_MMS); - - // Setup a default cellular network that's capable of MMS - mDataNetworkControllerUT.addNetworkRequest( - createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET)); - mDataNetworkControllerUT.addNetworkRequest( - createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS)); - processAllMessages(); - verifyConnectedNetworkHasDataProfile(mGeneralPurposeDataProfile); - - // Mock the designated MMS profile when WLAN is preferred - doReturn(mMmsOnWlanDataProfile).when(mDataProfileManager).getDataProfileForNetworkRequest( - any(TelephonyNetworkRequest.class), eq(TelephonyManager.NETWORK_TYPE_IWLAN), - anyBoolean(), anyBoolean(), anyBoolean()); - setSuccessfulSetupDataResponse(mMockedWlanDataServiceManager, - createDataCallResponse(2, DataCallResponse.LINK_STATUS_ACTIVE)); - - // Verify the designated MMS profile is used to satisfy MMS request - mDataNetworkControllerUT.addNetworkRequest( - createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_MMS)); - processAllMessages(); - verifyConnectedNetworkHasDataProfile(mMmsOnWlanDataProfile); - } - - @Test public void testNonTerrestrialNetwork() throws Exception { mIsNonTerrestrialNetwork = true; serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE, @@ -5132,7 +5118,8 @@ public class DataNetworkControllerTest extends TelephonyTest { serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE, NetworkRegistrationInfo.REGISTRATION_STATE_HOME); mDataNetworkControllerUT.addNetworkRequest( - createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET)); + createNetworkRequest(true/*restricted*/, + NetworkCapabilities.NET_CAPABILITY_INTERNET)); processAllMessages(); verifyConnectedNetworkHasDataProfile(mEsimBootstrapDataProfile); @@ -5143,13 +5130,6 @@ public class DataNetworkControllerTest extends TelephonyTest { .get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN), 2); processAllMessages(); verifyConnectedNetworkHasDataProfile(mEsimBootstrapImsProfile); - - serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE, - NetworkRegistrationInfo.REGISTRATION_STATE_HOME); - mDataNetworkControllerUT.addNetworkRequest( - createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_RCS)); - processAllMessages(); - verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_RCS); } @Test @@ -5188,7 +5168,7 @@ public class DataNetworkControllerTest extends TelephonyTest { serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE, NetworkRegistrationInfo.REGISTRATION_STATE_HOME); mDataNetworkControllerUT.addNetworkRequest( - createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET)); + createNetworkRequest(true, NetworkCapabilities.NET_CAPABILITY_INTERNET)); processAllMessages(); // With allowed data limit unlimited, connection is allowed verifyConnectedNetworkHasDataProfile(mEsimBootstrapDataProfile); @@ -5414,4 +5394,14 @@ public class DataNetworkControllerTest extends TelephonyTest { verify(mMockedDataNetworkControllerCallback, never()).onAnyDataNetworkExistingChanged( anyBoolean()); } + + @Test + public void testGetInternetEvaluation() throws Exception { + testSetupDataNetwork(); + doReturn(true).when(mSST).isPendingRadioPowerOffAfterDataOff(); + assertThat(mDataNetworkControllerUT.getInternetEvaluation(false/*ignoreExistingNetworks*/) + .containsDisallowedReasons()).isFalse(); + assertThat(mDataNetworkControllerUT.getInternetEvaluation(true/*ignoreExistingNetworks*/) + .containsDisallowedReasons()).isTrue(); + } } diff --git a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java index a31c64e253..f05099d949 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java @@ -2687,7 +2687,7 @@ public class EmergencyStateTrackerTest extends TelephonyTest { Connection c = mock(Connection.class); Call call = mock(Call.class); doReturn(c).when(call).getLatestConnection(); - doReturn(true).when(call).isRinging(); + doReturn(Call.State.INCOMING).when(call).getState(); doReturn(call).when(phone).getRingingCall(); setEcmSupportedConfig(phone, true); @@ -2790,6 +2790,120 @@ public class EmergencyStateTrackerTest extends TelephonyTest { } /** + * Test that the EmergencyStateTracker rejects incoming call when starting + * a normal routing emergency call. + */ + @Test + @SmallTest + public void testNormalRoutingEmergencyCallRejectRingingCall() { + Phone phone = setupTestPhoneForEmergencyCall(false /* isRoaming */, + false /* isRadioOn */); + when(phone.getSubId()).thenReturn(1); + Connection c = mock(Connection.class); + Call call = mock(Call.class); + doReturn(c).when(call).getLatestConnection(); + doReturn(Call.State.DISCONNECTING).when(call).getState(); + doReturn(call).when(phone).getRingingCall(); + setEcmSupportedConfig(phone, true); + + EmergencyStateTracker testEst = setupEmergencyStateTracker( + false /* isSuplDdsSwitchRequiredForEmergencyCall */); + + // There is an ongoing normal routing emergency call. + testEst.startNormalRoutingEmergencyCall(phone, mTestConnection1, result -> {}); + + // Verify rejecting ringing call. + try { + verify(call).hangup(); + } catch (CallStateException e) { + } + } + + + /** + * Test that the EmergencyStateTracker rejects incoming call if there is + * a normal routing emergency call in dialing state. + */ + @Test + @SmallTest + public void testNormalRoutingRejectNewIncomingCall() { + Phone phone = setupTestPhoneForEmergencyCall(false /* isRoaming */, + false /* isRadioOn */); + when(phone.getSubId()).thenReturn(1); + setEcmSupportedConfig(phone, true); + + EmergencyStateTracker testEst = setupEmergencyStateTracker( + false /* isSuplDdsSwitchRequiredForEmergencyCall */); + + ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class); + ArgumentCaptor<Integer> intCaptor = ArgumentCaptor.forClass(Integer.class); + + verify(phone).registerForNewRingingConnection(handlerCaptor.capture(), + intCaptor.capture(), any()); + assertNotNull(handlerCaptor.getValue()); + assertNotNull(intCaptor.getValue()); + + // There is an ongoing normal routing emergency call. + testEst.startNormalRoutingEmergencyCall(phone, mTestConnection1, result -> {}); + + Connection c = mock(Connection.class); + Call call = mock(Call.class); + doReturn(call).when(c).getCall(); + + Message msg = Message.obtain(handlerCaptor.getValue(), intCaptor.getValue()); + AsyncResult.forMessage(msg, c, null); + msg.sendToTarget(); + processAllMessages(); + + // Verify rejecting incoming call. + try { + verify(call).hangup(); + } catch (CallStateException e) { + } + } + + @Test + @SmallTest + public void testNormalRoutingDiscardedNotRejectNewIncomingCall() { + Phone phone = setupTestPhoneForEmergencyCall(false /* isRoaming */, + false /* isRadioOn */); + when(phone.getSubId()).thenReturn(1); + setEcmSupportedConfig(phone, true); + + EmergencyStateTracker testEst = setupEmergencyStateTracker( + false /* isSuplDdsSwitchRequiredForEmergencyCall */); + + ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class); + ArgumentCaptor<Integer> intCaptor = ArgumentCaptor.forClass(Integer.class); + + verify(phone).registerForNewRingingConnection(handlerCaptor.capture(), + intCaptor.capture(), any()); + assertNotNull(handlerCaptor.getValue()); + assertNotNull(intCaptor.getValue()); + + // Start normal routing emergency call. + testEst.startNormalRoutingEmergencyCall(phone, mTestConnection1, result -> {}); + + // Discard normal routing emergency call. + testEst.endNormalRoutingEmergencyCall(mTestConnection1); + + Connection c = mock(Connection.class); + Call call = mock(Call.class); + doReturn(call).when(c).getCall(); + + Message msg = Message.obtain(handlerCaptor.getValue(), intCaptor.getValue()); + AsyncResult.forMessage(msg, c, null); + msg.sendToTarget(); + processAllMessages(); + + // Verify not rejecting incoming call. + try { + verify(call, never()).hangup(); + } catch (CallStateException e) { + } + } + + /** * Test that emergency call state changes are sent. */ @Test diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/DataCallSessionStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/DataCallSessionStatsTest.java index 5ac21f85a4..7374aef6eb 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/metrics/DataCallSessionStatsTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/DataCallSessionStatsTest.java @@ -40,6 +40,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.telephony.Phone; import com.android.internal.telephony.TelephonyTest; import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession; +import com.android.internal.telephony.subscription.SubscriptionInfoInternal; import org.junit.After; import org.junit.Before; @@ -356,4 +357,55 @@ public class DataCallSessionStatsTest extends TelephonyTest { assertFalse(stats.isNtn); } + + @Test + public void testIsProvisioningProfile() { + SubscriptionInfoInternal mSubInfoInternal = new SubscriptionInfoInternal.Builder() + .setProfileClass(mSubscriptionManager.PROFILE_CLASS_PROVISIONING).build(); + + when(mSubscriptionManagerService.getSubscriptionInfoInternal(mPhone.getSubId())) + .thenReturn(mSubInfoInternal); + + mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS, false); + mDataCallSessionStats.onSetupDataCallResponse( + mDefaultImsResponse, + TelephonyManager.NETWORK_TYPE_IWLAN, + ApnSetting.TYPE_IMS, + ApnSetting.PROTOCOL_IP, + DataFailCause.NONE); + + mDataCallSessionStats.setTimeMillis(60000L); + mDataCallSessionStats.conclude(); + + ArgumentCaptor<DataCallSession> callCaptor = + ArgumentCaptor.forClass(DataCallSession.class); + verify(mPersistAtomsStorage, times(1)).addDataCallSession( + callCaptor.capture()); + DataCallSession stats = callCaptor.getValue(); + + assertTrue(stats.isProvisioningProfile); + + reset(mPersistAtomsStorage); + + mSubInfoInternal = new SubscriptionInfoInternal.Builder() + .setProfileClass(mSubscriptionManager.PROFILE_CLASS_OPERATIONAL).build(); + + when(mSubscriptionManagerService.getSubscriptionInfoInternal(mPhone.getSubId())) + .thenReturn(mSubInfoInternal); + + mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS, false); + mDataCallSessionStats.onSetupDataCallResponse( + mDefaultImsResponse, + TelephonyManager.NETWORK_TYPE_IWLAN, + ApnSetting.TYPE_IMS, + ApnSetting.PROTOCOL_IP, + DataFailCause.NONE); + + mDataCallSessionStats.setTimeMillis(60000L); + mDataCallSessionStats.conclude(); + verify(mPersistAtomsStorage).addDataCallSession(callCaptor.capture()); + stats = callCaptor.getValue(); + + assertFalse(stats.isProvisioningProfile); + } } 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..a9b183f456 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(); @@ -1163,6 +1183,7 @@ public class PersistAtomsStorageTest extends TelephonyTest { mSatelliteSession1.countOfIncomingDatagramSuccess = 1; mSatelliteSession1.countOfIncomingDatagramFailed = 0; mSatelliteSession1.isDemoMode = false; + mSatelliteSession1.maxNtnSignalStrengthLevel = 2; mSatelliteSession2 = new SatelliteSession(); mSatelliteSession2.satelliteServiceInitializationResult = @@ -1170,16 +1191,17 @@ public class PersistAtomsStorageTest extends TelephonyTest { mSatelliteSession2.satelliteTechnology = SatelliteProtoEnums.NT_RADIO_TECHNOLOGY_NB_IOT_NTN; mSatelliteSession2.count = 1; - mSatelliteSession1.satelliteServiceTerminationResult = + mSatelliteSession2.satelliteServiceTerminationResult = SatelliteProtoEnums.SATELLITE_ERROR_NONE; - mSatelliteSession1.initializationProcessingTimeMillis = 300; - mSatelliteSession1.terminationProcessingTimeMillis = 100; - mSatelliteSession1.sessionDurationSeconds = 10; - mSatelliteSession1.countOfOutgoingDatagramSuccess = 0; - mSatelliteSession1.countOfOutgoingDatagramFailed = 2; - mSatelliteSession1.countOfIncomingDatagramSuccess = 0; - mSatelliteSession1.countOfIncomingDatagramFailed = 1; + mSatelliteSession2.initializationProcessingTimeMillis = 300; + mSatelliteSession2.terminationProcessingTimeMillis = 100; + mSatelliteSession2.sessionDurationSeconds = 10; + mSatelliteSession2.countOfOutgoingDatagramSuccess = 0; + mSatelliteSession2.countOfOutgoingDatagramFailed = 2; + mSatelliteSession2.countOfIncomingDatagramSuccess = 0; + mSatelliteSession2.countOfIncomingDatagramFailed = 1; mSatelliteSession2.isDemoMode = true; + mSatelliteSession2.maxNtnSignalStrengthLevel = 4; mSatelliteSessions = new SatelliteSession[] { @@ -1268,6 +1290,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 +1616,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 +4783,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 +5339,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 +5515,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 +6031,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..daa47c1908 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java @@ -16,6 +16,8 @@ package com.android.internal.telephony.metrics; +import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_GOOD; + import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -24,7 +26,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; @@ -167,6 +173,7 @@ public class SatelliteStatsTest extends TelephonyTest { .setCountOfIncomingDatagramSuccess(1) .setCountOfIncomingDatagramFailed(0) .setIsDemoMode(false) + .setMaxNtnSignalStrengthLevel(NTN_SIGNAL_STRENGTH_GOOD) .build(); mSatelliteStats.onSatelliteSessionMetrics(param); @@ -189,6 +196,7 @@ public class SatelliteStatsTest extends TelephonyTest { stats.countOfIncomingDatagramSuccess); assertEquals(param.getCountOfIncomingDatagramFailed(), stats.countOfIncomingDatagramFailed); assertEquals(param.getIsDemoMode(), stats.isDemoMode); + assertEquals(param.getMaxNtnSignalStrengthLevel(), stats.maxNtnSignalStrengthLevel); verifyNoMoreInteractions(mPersistAtomsStorage); } @@ -296,4 +304,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); + } } diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java index 9201806bb6..8173bbccbe 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java @@ -133,38 +133,42 @@ public class ControllerMetricsStatsTest extends TelephonyTest { @Test public void testReportOutgoingDatagramSuccessCount() { mTestStats.initializeParams(); - int datagramType = SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE; - for (int i = 0; i < 10; i++) { - mControllerMetricsStatsUT.reportOutgoingDatagramSuccessCount(datagramType, false); + int[] sosDatagramTypes = {SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE, + SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP, + SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED}; + for (int datagramType : sosDatagramTypes) { + for (int i = 0; i < 10; i++) { + mControllerMetricsStatsUT.reportOutgoingDatagramSuccessCount(datagramType, false); + } + assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsSuccess); + assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsFail); + assertEquals(10, mTestStats.mCountOfOutgoingDatagramSuccess); + assertEquals(0, mTestStats.mCountOfOutgoingDatagramFail); + assertEquals(0, mTestStats.mCountOfIncomingDatagramSuccess); + assertEquals(0, mTestStats.mCountOfIncomingDatagramFail); + assertEquals(10, mTestStats.mCountOfDatagramTypeSosSmsSuccess); + assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsFail); + assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingSuccess); + assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingFail); + assertEquals(0, mTestStats.mCountOfProvisionSuccess); + assertEquals(0, mTestStats.mCountOfProvisionFail); + assertEquals(0, mTestStats.mCountOfDeprovisionSuccess); + assertEquals(0, mTestStats.mCountOfDeprovisionFail); + assertEquals(0, mTestStats.mTotalServiceUptimeSec); + assertEquals(0, mTestStats.mTotalBatteryConsumptionPercent); + assertEquals(0, mTestStats.mTotalBatteryChargedTimeSec); + assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsSuccess); + assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsFail); + assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramSuccess); + assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramFail); + assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramSuccess); + assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramFail); + assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveSuccess); + assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveFail); + mTestStats.initializeParams(); } - assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsSuccess); - assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsFail); - assertEquals(10, mTestStats.mCountOfOutgoingDatagramSuccess); - assertEquals(0, mTestStats.mCountOfOutgoingDatagramFail); - assertEquals(0, mTestStats.mCountOfIncomingDatagramSuccess); - assertEquals(0, mTestStats.mCountOfIncomingDatagramFail); - assertEquals(10, mTestStats.mCountOfDatagramTypeSosSmsSuccess); - assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsFail); - assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingSuccess); - assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingFail); - assertEquals(0, mTestStats.mCountOfProvisionSuccess); - assertEquals(0, mTestStats.mCountOfProvisionFail); - assertEquals(0, mTestStats.mCountOfDeprovisionSuccess); - assertEquals(0, mTestStats.mCountOfDeprovisionFail); - assertEquals(0, mTestStats.mTotalServiceUptimeSec); - assertEquals(0, mTestStats.mTotalBatteryConsumptionPercent); - assertEquals(0, mTestStats.mTotalBatteryChargedTimeSec); - assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsSuccess); - assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsFail); - assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramSuccess); - assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramFail); - assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramSuccess); - assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramFail); - assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveSuccess); - assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveFail); - mTestStats.initializeParams(); - datagramType = SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING; + int datagramType = SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING; for (int i = 0; i < 10; i++) { mControllerMetricsStatsUT.reportOutgoingDatagramSuccessCount(datagramType, true); } @@ -230,38 +234,42 @@ public class ControllerMetricsStatsTest extends TelephonyTest { @Test public void reportOutgoingDatagramFailCount() { mTestStats.initializeParams(); - int datagramType = SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE; - for (int i = 0; i < 10; i++) { - mControllerMetricsStatsUT.reportOutgoingDatagramFailCount(datagramType, false); + int[] sosDatagramTypes = {SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE, + SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP, + SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED}; + for (int datagramType : sosDatagramTypes) { + for (int i = 0; i < 10; i++) { + mControllerMetricsStatsUT.reportOutgoingDatagramFailCount(datagramType, false); + } + assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsSuccess); + assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsFail); + assertEquals(0, mTestStats.mCountOfOutgoingDatagramSuccess); + assertEquals(10, mTestStats.mCountOfOutgoingDatagramFail); + assertEquals(0, mTestStats.mCountOfIncomingDatagramSuccess); + assertEquals(0, mTestStats.mCountOfIncomingDatagramFail); + assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsSuccess); + assertEquals(10, mTestStats.mCountOfDatagramTypeSosSmsFail); + assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingSuccess); + assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingFail); + assertEquals(0, mTestStats.mCountOfProvisionSuccess); + assertEquals(0, mTestStats.mCountOfProvisionFail); + assertEquals(0, mTestStats.mCountOfDeprovisionSuccess); + assertEquals(0, mTestStats.mCountOfDeprovisionFail); + assertEquals(0, mTestStats.mTotalServiceUptimeSec); + assertEquals(0, mTestStats.mTotalBatteryConsumptionPercent); + assertEquals(0, mTestStats.mTotalBatteryChargedTimeSec); + assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsSuccess); + assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsFail); + assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramSuccess); + assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramFail); + assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramSuccess); + assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramFail); + assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveSuccess); + assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveFail); + mTestStats.initializeParams(); } - assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsSuccess); - assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsFail); - assertEquals(0, mTestStats.mCountOfOutgoingDatagramSuccess); - assertEquals(10, mTestStats.mCountOfOutgoingDatagramFail); - assertEquals(0, mTestStats.mCountOfIncomingDatagramSuccess); - assertEquals(0, mTestStats.mCountOfIncomingDatagramFail); - assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsSuccess); - assertEquals(10, mTestStats.mCountOfDatagramTypeSosSmsFail); - assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingSuccess); - assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingFail); - assertEquals(0, mTestStats.mCountOfProvisionSuccess); - assertEquals(0, mTestStats.mCountOfProvisionFail); - assertEquals(0, mTestStats.mCountOfDeprovisionSuccess); - assertEquals(0, mTestStats.mCountOfDeprovisionFail); - assertEquals(0, mTestStats.mTotalServiceUptimeSec); - assertEquals(0, mTestStats.mTotalBatteryConsumptionPercent); - assertEquals(0, mTestStats.mTotalBatteryChargedTimeSec); - assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsSuccess); - assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsFail); - assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramSuccess); - assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramFail); - assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramSuccess); - assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramFail); - assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveSuccess); - assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveFail); - mTestStats.initializeParams(); - datagramType = SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING; + int datagramType = SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING; for (int i = 0; i < 10; i++) { mControllerMetricsStatsUT.reportOutgoingDatagramFailCount(datagramType, true); } diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java index 9c9a677525..f1508eec04 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java @@ -17,6 +17,8 @@ package com.android.internal.telephony.satellite; import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE; +import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED; +import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP; import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING; import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE; import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN; @@ -92,7 +94,7 @@ public class DatagramControllerTest extends TelephonyTest { SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, 0, SATELLITE_RESULT_SUCCESS); mDatagramControllerUT.updateReceiveStatus(SUB_ID, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, 0, SATELLITE_RESULT_SUCCESS); - pushDemoModeSosDatagram(); + pushDemoModeSosDatagram(DATAGRAM_TYPE_SOS_MESSAGE); } @After @@ -109,6 +111,12 @@ public class DatagramControllerTest extends TelephonyTest { SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE); testUpdateSendStatus(false, DATAGRAM_TYPE_KEEP_ALIVE, SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING); + pushDemoModeSosDatagram(DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP); + testUpdateSendStatus(true, DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP, + SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING); + pushDemoModeSosDatagram(DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED); + testUpdateSendStatus(true, DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED, + SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING); } @Test @@ -150,27 +158,33 @@ public class DatagramControllerTest extends TelephonyTest { .needsWaitingForSatelliteConnected(DATAGRAM_TYPE_KEEP_ALIVE)); when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true); - mDatagramControllerUT.onSatelliteModemStateChanged( - SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED); - assertFalse(mDatagramControllerUT - .needsWaitingForSatelliteConnected(DATAGRAM_TYPE_KEEP_ALIVE)); - assertTrue(mDatagramControllerUT - .needsWaitingForSatelliteConnected(DATAGRAM_TYPE_SOS_MESSAGE)); - - mDatagramControllerUT.onSatelliteModemStateChanged( - SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED); - assertFalse(mDatagramControllerUT - .needsWaitingForSatelliteConnected(DATAGRAM_TYPE_SOS_MESSAGE)); - mDatagramControllerUT.onSatelliteModemStateChanged( - SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING); - assertFalse(mDatagramControllerUT - .needsWaitingForSatelliteConnected(DATAGRAM_TYPE_SOS_MESSAGE)); - - mDatagramControllerUT.onSatelliteModemStateChanged( - SatelliteManager.SATELLITE_MODEM_STATE_IDLE); - assertTrue(mDatagramControllerUT - .needsWaitingForSatelliteConnected(DATAGRAM_TYPE_SOS_MESSAGE)); + int[] sosDatagramTypes = {DATAGRAM_TYPE_SOS_MESSAGE, + DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP, + DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED}; + for (int datagramType : sosDatagramTypes) { + mDatagramControllerUT.onSatelliteModemStateChanged( + SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED); + assertFalse(mDatagramControllerUT + .needsWaitingForSatelliteConnected(DATAGRAM_TYPE_KEEP_ALIVE)); + assertTrue(mDatagramControllerUT + .needsWaitingForSatelliteConnected(datagramType)); + + mDatagramControllerUT.onSatelliteModemStateChanged( + SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED); + assertFalse(mDatagramControllerUT + .needsWaitingForSatelliteConnected(datagramType)); + + mDatagramControllerUT.onSatelliteModemStateChanged( + SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING); + assertFalse(mDatagramControllerUT + .needsWaitingForSatelliteConnected(datagramType)); + + mDatagramControllerUT.onSatelliteModemStateChanged( + SatelliteManager.SATELLITE_MODEM_STATE_IDLE); + assertTrue(mDatagramControllerUT + .needsWaitingForSatelliteConnected(datagramType)); + } } private void testUpdateSendStatus(boolean isDemoMode, int datagramType, int sendState) { @@ -244,10 +258,10 @@ public class DatagramControllerTest extends TelephonyTest { clearInvocations(mMockDatagramDispatcher); } - private void pushDemoModeSosDatagram() { + private void pushDemoModeSosDatagram(int datagramType) { String testMessage = "This is a test datagram message"; SatelliteDatagram datagram = new SatelliteDatagram(testMessage.getBytes()); mDatagramControllerUT.setDemoMode(true); - mDatagramControllerUT.pushDemoModeDatagram(DATAGRAM_TYPE_SOS_MESSAGE, datagram); + mDatagramControllerUT.pushDemoModeDatagram(datagramType, datagram); } } diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java index 6f8d08065a..dba288e73d 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java @@ -86,6 +86,11 @@ public class DatagramDispatcherTest extends TelephonyTest { private static final int DATAGRAM_TYPE1 = SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE; private static final int DATAGRAM_TYPE2 = SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING; private static final int DATAGRAM_TYPE3 = SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE; + private static final int DATAGRAM_TYPE4 = + SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP; + private static final int DATAGRAM_TYPE5 = + SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED; + private static final String TEST_MESSAGE = "This is a test datagram message"; private static final long TEST_EXPIRE_TIMER_SATELLITE_ALIGN = TimeUnit.SECONDS.toMillis(1); private static final int TEST_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_TIMEOUT_MILLIS = @@ -93,6 +98,12 @@ public class DatagramDispatcherTest extends TelephonyTest { private static final long TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(60); private static final Long TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE = TimeUnit.SECONDS.toMillis(10); + private static final long + TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_FOR_LAST_MESSAGE_TIMEOUT_MILLIS = + TimeUnit.SECONDS.toMillis(60); + private static final int + TEST_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_FOR_LAST_MESSAGE_TIMEOUT_MILLIS = + (int) TimeUnit.SECONDS.toMillis(60); private TestDatagramDispatcher mDatagramDispatcherUT; @@ -175,202 +186,233 @@ public class DatagramDispatcherTest extends TelephonyTest { return null; }).when(mMockSatelliteModemInterface).sendSatelliteDatagram(any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class)); - doReturn(true).when(mMockDatagramController) - .needsWaitingForSatelliteConnected(eq(DATAGRAM_TYPE1)); - when(mMockDatagramController.getDatagramWaitTimeForConnectedState()) - .thenReturn(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS); - mResultListener.clear(); - - mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram, - true, mResultListener::offer); - processAllMessages(); - mInOrder.verify(mMockDatagramController) - .needsWaitingForSatelliteConnected(eq(DATAGRAM_TYPE1)); - mInOrder.verify(mMockDatagramController).updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT), eq(1), - eq(SATELLITE_RESULT_SUCCESS)); - mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(); - verifyZeroInteractions(mMockSatelliteModemInterface); - assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted()); - - doReturn(false).when(mMockDatagramController) - .needsWaitingForSatelliteConnected(eq(DATAGRAM_TYPE1)); - mDatagramDispatcherUT.onSatelliteModemStateChanged( - SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED); - processAllMessages(); - - mInOrder.verify(mMockDatagramController).isPollingInIdleState(); - mInOrder.verify(mMockDatagramController) - .needsWaitingForSatelliteConnected(eq(DATAGRAM_TYPE1)); - mInOrder.verify(mMockDatagramController) - .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1), - eq(SATELLITE_RESULT_SUCCESS)); - mInOrder.verify(mMockDatagramController) - .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS), eq(0), - eq(SATELLITE_RESULT_SUCCESS)); - mInOrder.verify(mMockDatagramController) - .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0), - eq(SATELLITE_RESULT_SUCCESS)); - verifyNoMoreInteractions(mMockDatagramController); - verify(mMockSessionMetricsStats, times(1)).addCountOfSuccessfulOutgoingDatagram(); - verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram( - any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class)); - assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted()); - assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_SUCCESS); - - clearInvocations(mMockSatelliteModemInterface); - clearInvocations(mMockDatagramController); - mResultListener.clear(); - - clearInvocations(mMockSatelliteModemInterface); - clearInvocations(mMockDatagramController); - mResultListener.clear(); - doReturn(true).when(mMockDatagramController) - .needsWaitingForSatelliteConnected(eq(DATAGRAM_TYPE1)); - mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram, - true, mResultListener::offer); - processAllMessages(); - verifyZeroInteractions(mMockSatelliteModemInterface); - mInOrder.verify(mMockDatagramController) - .needsWaitingForSatelliteConnected(eq(DATAGRAM_TYPE1)); - mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(); - assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted()); - - moveTimeForward(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS); - processAllMessages(); - verifyZeroInteractions(mMockSatelliteModemInterface); - mInOrder.verify(mMockDatagramController) - .updateSendStatus(eq(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID), - eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED), eq(1), - eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE)); - mInOrder.verify(mMockDatagramController) - .updateSendStatus(eq(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID), - eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0), - eq(SATELLITE_RESULT_SUCCESS)); - assertEquals(1, mResultListener.size()); - assertThat(mResultListener.peek()).isEqualTo( - SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE); - assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted()); - verify(mMockSessionMetricsStats, times(1)).addCountOfFailedOutgoingDatagram(); - - mResultListener.clear(); - mDatagramDispatcherUT.onSatelliteModemStateChanged( - SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED); - processAllMessages(); - verifyZeroInteractions(mMockSatelliteModemInterface); - assertEquals(0, mResultListener.size()); - - clearInvocations(mMockSatelliteModemInterface); - clearInvocations(mMockDatagramController); - mResultListener.clear(); - mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram, - true, mResultListener::offer); - processAllMessages(); - verifyZeroInteractions(mMockSatelliteModemInterface); - mInOrder.verify(mMockDatagramController) - .needsWaitingForSatelliteConnected(eq(DATAGRAM_TYPE1)); - mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(); - assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted()); - assertEquals(0, mResultListener.size()); - - mDatagramDispatcherUT.onSatelliteModemStateChanged( - SatelliteManager.SATELLITE_MODEM_STATE_OFF); - processAllMessages(); - verifyZeroInteractions(mMockSatelliteModemInterface); - assertEquals(1, mResultListener.size()); - assertThat(mResultListener.peek()).isEqualTo( - SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED); - assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted()); - verify(mMockSessionMetricsStats, times(1)).addCountOfFailedOutgoingDatagram(); + int[] sosDatagramTypes = {DATAGRAM_TYPE1, DATAGRAM_TYPE4, DATAGRAM_TYPE5}; + for (int datagramType : sosDatagramTypes) { + clearInvocations(mMockDatagramController); + clearInvocations(mMockSessionMetricsStats); + clearInvocations(mMockSatelliteModemInterface); + doReturn(true).when(mMockDatagramController) + .needsWaitingForSatelliteConnected(eq(datagramType)); + when(mMockDatagramController.getDatagramWaitTimeForConnectedState(eq(false))) + .thenReturn(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS); + when(mMockDatagramController.getDatagramWaitTimeForConnectedState(eq(true))) + .thenReturn( + TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_FOR_LAST_MESSAGE_TIMEOUT_MILLIS); + mResultListener.clear(); + + mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram, + true, mResultListener::offer); + processAllMessages(); + mInOrder.verify(mMockDatagramController) + .needsWaitingForSatelliteConnected(eq(datagramType)); + mInOrder.verify(mMockDatagramController).updateSendStatus(eq(SUB_ID), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT), + eq(1), + eq(SATELLITE_RESULT_SUCCESS)); + mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState( + eq(SatelliteServiceUtils.isLastSosMessage(datagramType))); + verifyZeroInteractions(mMockSatelliteModemInterface); + assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted()); + + doReturn(false).when(mMockDatagramController) + .needsWaitingForSatelliteConnected(eq(datagramType)); + mDatagramDispatcherUT.onSatelliteModemStateChanged( + SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED); + processAllMessages(); + + mInOrder.verify(mMockDatagramController).isPollingInIdleState(); + mInOrder.verify(mMockDatagramController) + .needsWaitingForSatelliteConnected(eq(datagramType)); + mInOrder.verify(mMockDatagramController) + .updateSendStatus(eq(SUB_ID), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1), + eq(SATELLITE_RESULT_SUCCESS)); + mInOrder.verify(mMockDatagramController) + .updateSendStatus(eq(SUB_ID), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS), + eq(0), + eq(SATELLITE_RESULT_SUCCESS)); + mInOrder.verify(mMockDatagramController) + .updateSendStatus(eq(SUB_ID), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0), + eq(SATELLITE_RESULT_SUCCESS)); + verifyNoMoreInteractions(mMockDatagramController); + verify(mMockSessionMetricsStats, times(1)).addCountOfSuccessfulOutgoingDatagram(); + verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram( + any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class)); + assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted()); + + assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_SUCCESS); + + clearInvocations(mMockSatelliteModemInterface); + clearInvocations(mMockDatagramController); + clearInvocations(mMockSessionMetricsStats); + mResultListener.clear(); + doReturn(true).when(mMockDatagramController) + .needsWaitingForSatelliteConnected(eq(datagramType)); + mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram, + true, mResultListener::offer); + processAllMessages(); + verifyZeroInteractions(mMockSatelliteModemInterface); + mInOrder.verify(mMockDatagramController) + .needsWaitingForSatelliteConnected(eq(datagramType)); + mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState( + eq(SatelliteServiceUtils.isLastSosMessage(datagramType))); + assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted()); + + moveTimeForward(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS); + processAllMessages(); + verifyZeroInteractions(mMockSatelliteModemInterface); + mInOrder.verify(mMockDatagramController) + .updateSendStatus(eq(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID), + eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED), + eq(1), + eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE)); + mInOrder.verify(mMockDatagramController) + .updateSendStatus(eq(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID), + eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0), + eq(SATELLITE_RESULT_SUCCESS)); + assertEquals(1, mResultListener.size()); + assertThat(mResultListener.peek()).isEqualTo( + SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE); + assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted()); + verify(mMockSessionMetricsStats, times(1)).addCountOfFailedOutgoingDatagram(); + + mResultListener.clear(); + mDatagramDispatcherUT.onSatelliteModemStateChanged( + SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED); + processAllMessages(); + verifyZeroInteractions(mMockSatelliteModemInterface); + assertEquals(0, mResultListener.size()); + + clearInvocations(mMockSatelliteModemInterface); + clearInvocations(mMockDatagramController); + clearInvocations(mMockSessionMetricsStats); + mResultListener.clear(); + mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram, + true, mResultListener::offer); + processAllMessages(); + verifyZeroInteractions(mMockSatelliteModemInterface); + mInOrder.verify(mMockDatagramController) + .needsWaitingForSatelliteConnected(eq(datagramType)); + mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState( + eq(SatelliteServiceUtils.isLastSosMessage(datagramType))); + assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted()); + assertEquals(0, mResultListener.size()); + + mDatagramDispatcherUT.onSatelliteModemStateChanged( + SatelliteManager.SATELLITE_MODEM_STATE_OFF); + processAllMessages(); + verifyZeroInteractions(mMockSatelliteModemInterface); + assertEquals(1, mResultListener.size()); + assertThat(mResultListener.peek()).isEqualTo( + SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED); + assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted()); + verify(mMockSessionMetricsStats, times(1)).addCountOfFailedOutgoingDatagram(); + } } @Test public void testSendSatelliteDatagram_timeout() throws Exception { - doAnswer(invocation -> { - Message message = (Message) invocation.getArguments()[3]; - - mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/, - new AsyncResult(message.obj, null, null)) - .sendToTarget(); - - // DatagramDispatcher should ignore the second EVENT_SEND_SATELLITE_DATAGRAM_DONE - mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/, - new AsyncResult(message.obj, null, null)) - .sendToTarget(); - - return null; - }).when(mMockSatelliteModemInterface).sendSatelliteDatagram(any(SatelliteDatagram.class), - anyBoolean(), anyBoolean(), any(Message.class)); - doReturn(false).when(mMockDatagramController) - .needsWaitingForSatelliteConnected(eq(DATAGRAM_TYPE1)); - when(mMockDatagramController.getDatagramWaitTimeForConnectedState()) + when(mMockDatagramController.getDatagramWaitTimeForConnectedState(eq(false))) .thenReturn(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS); + when(mMockDatagramController.getDatagramWaitTimeForConnectedState(eq(true))) + .thenReturn(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_FOR_LAST_MESSAGE_TIMEOUT_MILLIS); mContextFixture.putIntResource( R.integer.config_wait_for_datagram_sending_response_timeout_millis, TEST_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_TIMEOUT_MILLIS); + mContextFixture.putIntResource( + R.integer.config_wait_for_datagram_sending_response_for_last_message_timeout_millis, + TEST_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_FOR_LAST_MESSAGE_TIMEOUT_MILLIS); mResultListener.clear(); - - mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram, - true, mResultListener::offer); - processAllMessages(); - mInOrder.verify(mMockDatagramController) - .needsWaitingForSatelliteConnected(eq(DATAGRAM_TYPE1)); - mInOrder.verify(mMockDatagramController).isPollingInIdleState(); - mInOrder.verify(mMockDatagramController) - .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1), - eq(SATELLITE_RESULT_SUCCESS)); - mInOrder.verify(mMockDatagramController) - .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS), eq(0), - eq(SATELLITE_RESULT_SUCCESS)); - mInOrder.verify(mMockDatagramController) - .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0), - eq(SATELLITE_RESULT_SUCCESS)); - verifyNoMoreInteractions(mMockDatagramController); - verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram( - any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class)); - assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_SUCCESS); - verify(mMockSessionMetricsStats, times(1)).addCountOfSuccessfulOutgoingDatagram(); - clearInvocations(mMockSatelliteModemInterface); - clearInvocations(mMockDatagramController); - mResultListener.clear(); - - // No response for the send request from modem - doNothing().when(mMockSatelliteModemInterface).sendSatelliteDatagram( - any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class)); - - mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram, - true, mResultListener::offer); - processAllMessages(); - mInOrder.verify(mMockDatagramController) - .needsWaitingForSatelliteConnected(eq(DATAGRAM_TYPE1)); - mInOrder.verify(mMockDatagramController).isPollingInIdleState(); - mInOrder.verify(mMockDatagramController) - .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1), - eq(SATELLITE_RESULT_SUCCESS)); - mInOrder.verify(mMockDatagramController) - .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED), eq(1), - eq(SATELLITE_RESULT_MODEM_TIMEOUT)); - mInOrder.verify(mMockDatagramController) - .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0), - eq(SATELLITE_RESULT_SUCCESS)); - verifyNoMoreInteractions(mMockDatagramController); - verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram( - any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class)); - verify(mMockSatelliteModemInterface).abortSendingSatelliteDatagrams(any(Message.class)); - assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_MODEM_TIMEOUT); - verify(mMockSessionMetricsStats, never()).addCountOfFailedOutgoingDatagram(); + int[] sosDatagramTypes = {DATAGRAM_TYPE1, DATAGRAM_TYPE4, DATAGRAM_TYPE5}; + for (int datagramType : sosDatagramTypes) { + doAnswer(invocation -> { + Message message = (Message) invocation.getArguments()[3]; + + mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/, + new AsyncResult(message.obj, null, null)) + .sendToTarget(); + + // DatagramDispatcher should ignore the second EVENT_SEND_SATELLITE_DATAGRAM_DONE + mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/, + new AsyncResult(message.obj, null, null)) + .sendToTarget(); + + return null; + }).when(mMockSatelliteModemInterface).sendSatelliteDatagram( + any(SatelliteDatagram.class), + anyBoolean(), anyBoolean(), any(Message.class)); + doReturn(false).when(mMockDatagramController) + .needsWaitingForSatelliteConnected(eq(datagramType)); + + mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram, + true, mResultListener::offer); + processAllMessages(); + mInOrder.verify(mMockDatagramController) + .needsWaitingForSatelliteConnected(eq(datagramType)); + mInOrder.verify(mMockDatagramController).isPollingInIdleState(); + mInOrder.verify(mMockDatagramController) + .updateSendStatus(eq(SUB_ID), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1), + eq(SATELLITE_RESULT_SUCCESS)); + mInOrder.verify(mMockDatagramController) + .updateSendStatus(eq(SUB_ID), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS), + eq(0), + eq(SATELLITE_RESULT_SUCCESS)); + mInOrder.verify(mMockDatagramController) + .updateSendStatus(eq(SUB_ID), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0), + eq(SATELLITE_RESULT_SUCCESS)); + verifyNoMoreInteractions(mMockDatagramController); + verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram( + any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class)); + assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_SUCCESS); + verify(mMockSessionMetricsStats, times(1)).addCountOfSuccessfulOutgoingDatagram(); + clearInvocations(mMockSatelliteModemInterface); + clearInvocations(mMockDatagramController); + clearInvocations(mMockSessionMetricsStats); + mResultListener.clear(); + + // No response for the send request from modem + doNothing().when(mMockSatelliteModemInterface).sendSatelliteDatagram( + any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class)); + + mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram, + true, mResultListener::offer); + processAllMessages(); + mInOrder.verify(mMockDatagramController) + .needsWaitingForSatelliteConnected(eq(datagramType)); + mInOrder.verify(mMockDatagramController).isPollingInIdleState(); + mInOrder.verify(mMockDatagramController) + .updateSendStatus(eq(SUB_ID), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1), + eq(SATELLITE_RESULT_SUCCESS)); + mInOrder.verify(mMockDatagramController) + .updateSendStatus(eq(SUB_ID), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED), + eq(1), + eq(SATELLITE_RESULT_MODEM_TIMEOUT)); + mInOrder.verify(mMockDatagramController) + .updateSendStatus(eq(SUB_ID), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0), + eq(SATELLITE_RESULT_SUCCESS)); + verifyNoMoreInteractions(mMockDatagramController); + verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram( + any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class)); + verify(mMockSatelliteModemInterface).abortSendingSatelliteDatagrams(any(Message.class)); + assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_MODEM_TIMEOUT); + verify(mMockSessionMetricsStats, times(1)).addCountOfFailedOutgoingDatagram(); + + clearInvocations(mMockSatelliteModemInterface); + clearInvocations(mMockDatagramController); + clearInvocations(mMockSessionMetricsStats); + mResultListener.clear(); + } } @Test @@ -427,29 +469,35 @@ public class DatagramDispatcherTest extends TelephonyTest { mDatagramDispatcherUT.setDemoMode(true); mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true); - mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram, - true, mResultListener::offer); - - processAllMessages(); - moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE); - processAllMessages(); - - mInOrder.verify(mMockDatagramController) - .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1), - eq(SATELLITE_RESULT_SUCCESS)); - mInOrder.verify(mMockDatagramController) - .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS), eq(0), - eq(SATELLITE_RESULT_SUCCESS)); - mInOrder.verify(mMockDatagramController) - .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0), - eq(SATELLITE_RESULT_SUCCESS)); - assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_SUCCESS); - verify(mMockSessionMetricsStats, times(1)).addCountOfSuccessfulOutgoingDatagram(); - mDatagramDispatcherUT.setDemoMode(false); - mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false); + int[] sosDatagramTypes = {DATAGRAM_TYPE1, DATAGRAM_TYPE4, DATAGRAM_TYPE5}; + for (int datagramType : sosDatagramTypes) { + clearInvocations(mMockDatagramController); + clearInvocations(mMockSessionMetricsStats); + mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram, + true, mResultListener::offer); + + processAllMessages(); + moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE); + processAllMessages(); + + mInOrder.verify(mMockDatagramController) + .updateSendStatus(eq(SUB_ID), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1), + eq(SATELLITE_RESULT_SUCCESS)); + mInOrder.verify(mMockDatagramController) + .updateSendStatus(eq(SUB_ID), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS), + eq(0), + eq(SATELLITE_RESULT_SUCCESS)); + mInOrder.verify(mMockDatagramController) + .updateSendStatus(eq(SUB_ID), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0), + eq(SATELLITE_RESULT_SUCCESS)); + assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_SUCCESS); + verify(mMockSessionMetricsStats, times(1)).addCountOfSuccessfulOutgoingDatagram(); + mDatagramDispatcherUT.setDemoMode(false); + mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false); + } } @Test @@ -467,29 +515,36 @@ public class DatagramDispatcherTest extends TelephonyTest { mDatagramDispatcherUT.setDemoMode(true); mDatagramDispatcherUT.setDuration(TEST_EXPIRE_TIMER_SATELLITE_ALIGN); mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false); + when(mMockDatagramController.waitForAligningToSatellite(false)).thenReturn(true); + + int[] sosDatagramTypes = {DATAGRAM_TYPE1, DATAGRAM_TYPE4, DATAGRAM_TYPE5}; + for (int datagramType : sosDatagramTypes) { + clearInvocations(mMockDatagramController); + clearInvocations(mMockSessionMetricsStats); + mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram, + true, mResultListener::offer); + + mInOrder.verify(mMockDatagramController) + .updateSendStatus(eq(SUB_ID), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1), + eq(SATELLITE_RESULT_SUCCESS)); + processAllFutureMessages(); + mInOrder.verify(mMockDatagramController) + .updateSendStatus(eq(SUB_ID), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED), + anyInt(), eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE)); + mInOrder.verify(mMockDatagramController) + .updateSendStatus(eq(SUB_ID), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0), + eq(SATELLITE_RESULT_SUCCESS)); + assertThat(mResultListener.peek()).isEqualTo( + SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE); + verify(mMockDatagramController, never()).pollPendingSatelliteDatagrams(anyInt(), any()); + verify(mMockDatagramController, never()).pushDemoModeDatagram( + anyInt(), any(SatelliteDatagram.class)); + verify(mMockSessionMetricsStats, times(1)).addCountOfFailedOutgoingDatagram(); + } - mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram, - true, mResultListener::offer); - - mInOrder.verify(mMockDatagramController) - .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1), - eq(SATELLITE_RESULT_SUCCESS)); - processAllFutureMessages(); - mInOrder.verify(mMockDatagramController) - .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED), - anyInt(), eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE)); - mInOrder.verify(mMockDatagramController) - .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0), - eq(SATELLITE_RESULT_SUCCESS)); - assertThat(mResultListener.peek()).isEqualTo( - SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE); - verify(mMockDatagramController, never()).pollPendingSatelliteDatagrams(anyInt(), any()); - verify(mMockDatagramController, never()).pushDemoModeDatagram( - anyInt(), any(SatelliteDatagram.class)); - verify(mMockSessionMetricsStats, times(1)).addCountOfFailedOutgoingDatagram(); mDatagramDispatcherUT.setDemoMode(false); mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false); mDatagramDispatcherUT.setDuration(previousTimer); @@ -542,14 +597,18 @@ public class DatagramDispatcherTest extends TelephonyTest { public void testSatelliteModemBusy_modemPollingDatagram_sendingDelayed() { when(mMockDatagramController.isPollingInIdleState()).thenReturn(false); - mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram, - true, mResultListener::offer); - processAllMessages(); - // As modem is busy receiving datagrams, sending datagram did not proceed further. - mInOrder.verify(mMockDatagramController) - .needsWaitingForSatelliteConnected(eq(DATAGRAM_TYPE1)); - mInOrder.verify(mMockDatagramController, times(2)).isPollingInIdleState(); - verifyNoMoreInteractions(mMockDatagramController); + int[] sosDatagramTypes = {DATAGRAM_TYPE1, DATAGRAM_TYPE4, DATAGRAM_TYPE5}; + for (int datagramType : sosDatagramTypes) { + clearInvocations(mMockDatagramController); + mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram, + true, mResultListener::offer); + processAllMessages(); + // As modem is busy receiving datagrams, sending datagram did not proceed further. + mInOrder.verify(mMockDatagramController) + .needsWaitingForSatelliteConnected(eq(datagramType)); + mInOrder.verify(mMockDatagramController, times(2)).isPollingInIdleState(); + verifyNoMoreInteractions(mMockDatagramController); + } } @Test @@ -562,22 +621,26 @@ public class DatagramDispatcherTest extends TelephonyTest { @Test public void testOnSatelliteModemStateChanged_modemStateOff_modemSendingDatagrams() { - mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram, - true, mResultListener::offer); - - mDatagramDispatcherUT.onSatelliteModemStateChanged( - SatelliteManager.SATELLITE_MODEM_STATE_OFF); - - processAllMessages(); - - mInOrder.verify(mMockDatagramController) - .updateSendStatus(anyInt(), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED), - eq(1), eq(SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED)); - mInOrder.verify(mMockDatagramController) - .updateSendStatus(anyInt(), eq(DATAGRAM_TYPE1), - eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), - eq(0), eq(SATELLITE_RESULT_SUCCESS)); + int[] sosDatagramTypes = {DATAGRAM_TYPE1, DATAGRAM_TYPE4, DATAGRAM_TYPE5}; + for (int datagramType : sosDatagramTypes) { + clearInvocations(mMockDatagramController); + mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram, + true, mResultListener::offer); + + mDatagramDispatcherUT.onSatelliteModemStateChanged( + SatelliteManager.SATELLITE_MODEM_STATE_OFF); + + processAllMessages(); + + mInOrder.verify(mMockDatagramController) + .updateSendStatus(anyInt(), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED), + eq(1), eq(SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED)); + mInOrder.verify(mMockDatagramController) + .updateSendStatus(anyInt(), eq(datagramType), + eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), + eq(0), eq(SATELLITE_RESULT_SUCCESS)); + } } @Test @@ -594,87 +657,96 @@ public class DatagramDispatcherTest extends TelephonyTest { } @Test - public void testSendSatelliteDatagramToModemInDemoMode() - throws Exception { + public void testSendSatelliteDatagramToModemInDemoMode() throws Exception { when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true); - doAnswer(invocation -> { - Message message = (Message) invocation.getArguments()[3]; - mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/, - new AsyncResult(message.obj, null, null)) - .sendToTarget(); - return null; - }).when(mMockSatelliteModemInterface).sendSatelliteDatagram(any(SatelliteDatagram.class), - anyBoolean(), anyBoolean(), any(Message.class)); mDatagramDispatcherUT.setDemoMode(true); mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true); - mIntegerConsumerSemaphore.drainPermits(); - - // Test when overlay config config_send_satellite_datagram_to_modem_in_demo_mode is true - mDatagramDispatcherUT.setShouldSendDatagramToModemInDemoMode(null); - mContextFixture.putBooleanResource(mConfigSendSatelliteDatagramToModemInDemoMode, true); - mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram, - true, mIntegerConsumer); - processAllMessages(); - moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE); - processAllMessages(); - waitForIntegerConsumerResult(1); - assertEquals(SATELLITE_RESULT_SUCCESS, - (int) mIntegerConsumerResult.get(0)); - mIntegerConsumerResult.clear(); - verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram( - any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class)); - - moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE); - processAllMessages(); - verify(mMockDatagramController).pushDemoModeDatagram( - anyInt(), any(SatelliteDatagram.class)); - verify(mMockDatagramController).pollPendingSatelliteDatagrams(anyInt(), any()); - verify(mMockSessionMetricsStats, times(1)).addCountOfSuccessfulOutgoingDatagram(); - - // Test when overlay config config_send_satellite_datagram_to_modem_in_demo_mode is false - reset(mMockSatelliteModemInterface); - mDatagramDispatcherUT.setShouldSendDatagramToModemInDemoMode(null); - mContextFixture.putBooleanResource(mConfigSendSatelliteDatagramToModemInDemoMode, false); - mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram, - true, mIntegerConsumer); - processAllMessages(); - moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE); - processAllMessages(); - waitForIntegerConsumerResult(1); - assertEquals(SATELLITE_RESULT_SUCCESS, - (int) mIntegerConsumerResult.get(0)); - mIntegerConsumerResult.clear(); - verify(mMockSatelliteModemInterface, never()).sendSatelliteDatagram( - any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class)); - - moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE); - processAllMessages(); - verify(mMockDatagramController, times(2)).pushDemoModeDatagram( - anyInt(), any(SatelliteDatagram.class)); - verify(mMockDatagramController, times(2)).pollPendingSatelliteDatagrams(anyInt(), any()); - - // Send datagram one more time - reset(mMockSatelliteModemInterface); - mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram, - true, mIntegerConsumer); - processAllMessages(); - moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE); - processAllMessages(); - - waitForIntegerConsumerResult(1); - assertEquals(SATELLITE_RESULT_SUCCESS, - (int) mIntegerConsumerResult.get(0)); - mIntegerConsumerResult.clear(); - verify(mMockSatelliteModemInterface, never()).sendSatelliteDatagram( - any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class)); - - moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE); - processAllMessages(); - verify(mMockDatagramController, times(3)).pushDemoModeDatagram( - anyInt(), any(SatelliteDatagram.class)); - verify(mMockDatagramController, times(3)).pollPendingSatelliteDatagrams(anyInt(), any()); + int[] sosDatagramTypes = {DATAGRAM_TYPE1, DATAGRAM_TYPE4, DATAGRAM_TYPE5}; + for (int datagramType : sosDatagramTypes) { + mIntegerConsumerSemaphore.drainPermits(); + mIntegerConsumerResult.clear(); + clearInvocations(mMockDatagramController); + clearInvocations(mMockSatelliteModemInterface); + clearInvocations(mMockSessionMetricsStats); + doAnswer(invocation -> { + Message message = (Message) invocation.getArguments()[3]; + mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/, + new AsyncResult(message.obj, null, null)) + .sendToTarget(); + return null; + }).when(mMockSatelliteModemInterface).sendSatelliteDatagram( + any(SatelliteDatagram.class), + anyBoolean(), anyBoolean(), any(Message.class)); + + // Test when overlay config config_send_satellite_datagram_to_modem_in_demo_mode is true + mDatagramDispatcherUT.setShouldSendDatagramToModemInDemoMode(null); + mContextFixture.putBooleanResource(mConfigSendSatelliteDatagramToModemInDemoMode, true); + mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram, + true, mIntegerConsumer); + processAllMessages(); + moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE); + processAllMessages(); + waitForIntegerConsumerResult(1); + assertEquals(SATELLITE_RESULT_SUCCESS, (int) mIntegerConsumerResult.get(0)); + mIntegerConsumerResult.clear(); + verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram( + any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class)); + + moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE); + processAllMessages(); + verify(mMockDatagramController).pushDemoModeDatagram( + anyInt(), any(SatelliteDatagram.class)); + verify(mMockDatagramController).pollPendingSatelliteDatagrams(anyInt(), any()); + verify(mMockSessionMetricsStats, times(1)).addCountOfSuccessfulOutgoingDatagram(); + + // Test when overlay config config_send_satellite_datagram_to_modem_in_demo_mode is + // false + reset(mMockSatelliteModemInterface); + mDatagramDispatcherUT.setShouldSendDatagramToModemInDemoMode(null); + mContextFixture.putBooleanResource(mConfigSendSatelliteDatagramToModemInDemoMode, + false); + mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram, + true, mIntegerConsumer); + processAllMessages(); + moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE); + processAllMessages(); + + waitForIntegerConsumerResult(1); + assertEquals(SATELLITE_RESULT_SUCCESS, (int) mIntegerConsumerResult.get(0)); + mIntegerConsumerResult.clear(); + verify(mMockSatelliteModemInterface, never()).sendSatelliteDatagram( + any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class)); + + moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE); + processAllMessages(); + verify(mMockDatagramController, times(2)).pushDemoModeDatagram( + anyInt(), any(SatelliteDatagram.class)); + verify(mMockDatagramController, times(2)).pollPendingSatelliteDatagrams(anyInt(), + any()); + + // Send datagram one more time + reset(mMockSatelliteModemInterface); + mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram, + true, mIntegerConsumer); + processAllMessages(); + moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE); + processAllMessages(); + + waitForIntegerConsumerResult(1); + assertEquals(SATELLITE_RESULT_SUCCESS, (int) mIntegerConsumerResult.get(0)); + mIntegerConsumerResult.clear(); + verify(mMockSatelliteModemInterface, never()).sendSatelliteDatagram( + any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class)); + + moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE); + processAllMessages(); + verify(mMockDatagramController, times(3)).pushDemoModeDatagram( + anyInt(), any(SatelliteDatagram.class)); + verify(mMockDatagramController, times(3)).pollPendingSatelliteDatagrams(anyInt(), + any()); + } mDatagramDispatcherUT.setDemoMode(false); mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false); diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java index 361c638d96..4d3acb424d 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java @@ -25,6 +25,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.clearInvocations; @@ -170,7 +171,7 @@ public class DatagramReceiverTest extends TelephonyTest { }).when(mMockSatelliteModemInterface).pollPendingSatelliteDatagrams(any(Message.class)); doReturn(true).when(mMockDatagramController) .needsWaitingForSatelliteConnected(eq(SatelliteManager.DATAGRAM_TYPE_UNKNOWN)); - when(mMockDatagramController.getDatagramWaitTimeForConnectedState()) + when(mMockDatagramController.getDatagramWaitTimeForConnectedState(anyBoolean())) .thenReturn(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS); mResultListener.clear(); @@ -181,7 +182,7 @@ public class DatagramReceiverTest extends TelephonyTest { mInOrder.verify(mMockDatagramController).updateReceiveStatus(eq(SUB_ID), eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT), eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS)); - mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(); + mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(eq(false)); verifyZeroInteractions(mMockSatelliteModemInterface); assertTrue(mDatagramReceiverUT.isDatagramWaitForConnectedStateTimerStarted()); @@ -210,7 +211,7 @@ public class DatagramReceiverTest extends TelephonyTest { processAllMessages(); mInOrder.verify(mMockDatagramController) .needsWaitingForSatelliteConnected(eq(SatelliteManager.DATAGRAM_TYPE_UNKNOWN)); - mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(); + mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(eq(false)); verifyZeroInteractions(mMockSatelliteModemInterface); assertTrue(mDatagramReceiverUT.isDatagramWaitForConnectedStateTimerStarted()); @@ -372,6 +373,7 @@ public class DatagramReceiverTest extends TelephonyTest { mTestDemoModeDatagramReceiver.setDemoMode(true); mTestDemoModeDatagramReceiver.setDuration(TEST_EXPIRE_TIMER_SATELLITE_ALIGN); mTestDemoModeDatagramReceiver.setDeviceAlignedWithSatellite(false); + when(mMockDatagramController.waitForAligningToSatellite(false)).thenReturn(true); when(mMockDatagramController.popDemoModeDatagram()).thenReturn(mDatagram); mTestDemoModeDatagramReceiver.pollPendingSatelliteDatagrams(SUB_ID, mResultListener::offer); processAllMessages(); diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DemoSimulatorTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DemoSimulatorTest.java new file mode 100644 index 0000000000..319e39f59d --- /dev/null +++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DemoSimulatorTest.java @@ -0,0 +1,246 @@ +/* + * 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.annotation.NonNull; +import android.content.Context; +import android.os.Looper; +import android.telephony.satellite.stub.ISatelliteListener; +import android.telephony.satellite.stub.NtnSignalStrength; +import android.telephony.satellite.stub.SatelliteModemState; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import com.android.internal.telephony.TelephonyTest; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Unit tests for DemoSimulator + */ +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class DemoSimulatorTest extends TelephonyTest { + private static final String TAG = "DemoSimulatorTest"; + private static final long TEST_DEVICE_POINTING_ALIGNED_DURATION_MILLIS = 200L; + private static final long TEST_DEVICE_POINTING_NOT_ALIGNED_DURATION_MILLIS = 300L; + private static final String STATE_POWER_OFF = "PowerOffState"; + private static final String STATE_NOT_CONNECTED = "NotConnectedState"; + private static final String STATE_CONNECTED = "ConnectedState"; + + private TestDemoSimulator mTestDemoSimulator; + @Mock private ISatelliteListener mISatelliteListener; + + @Mock private SatelliteController mMockSatelliteController; + + @Before + public void setUp() throws Exception { + super.setUp(getClass().getSimpleName()); + MockitoAnnotations.initMocks(this); + + when(mMockSatelliteController.isDemoModeEnabled()).thenReturn(true); + when(mMockSatelliteController.getDemoPointingAlignedDurationMillis()).thenReturn( + TEST_DEVICE_POINTING_ALIGNED_DURATION_MILLIS); + when(mMockSatelliteController.getDemoPointingNotAlignedDurationMillis()).thenReturn( + TEST_DEVICE_POINTING_NOT_ALIGNED_DURATION_MILLIS); + + mTestDemoSimulator = new TestDemoSimulator(mContext, Looper.myLooper(), + mMockSatelliteController); + mTestDemoSimulator.setSatelliteListener(mISatelliteListener); + } + + @After + public void tearDown() throws Exception { + super.tearDown(); + } + + @Test + public void testInitialState() { + assertNotNull(mTestDemoSimulator); + processAllMessages(); + assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName()); + } + + @Test + public void testStateTransition() { + // State transitions: POWER_OFF -> NOT_CONNECTED -> CONNECTED + moveToConnectedState(); + + // Device is not aligned with satellite. EVENT_DEVICE_NOT_ALIGNED timer should start + mTestDemoSimulator.setDeviceAlignedWithSatellite(false); + processAllMessages(); + assertTrue(mTestDemoSimulator.isDeviceNotAlignedTimerStarted()); + + // After timeout, DemoSimulator should move to NOT_CONNECTED state. + moveTimeForward(TEST_DEVICE_POINTING_NOT_ALIGNED_DURATION_MILLIS); + processAllMessages(); + assertEquals(STATE_NOT_CONNECTED, mTestDemoSimulator.getCurrentStateName()); + + // Satellite mode is OFF. DemoSimulator should move to POWER_OFF state. + mTestDemoSimulator.onSatelliteModeOff(); + processAllMessages(); + assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName()); + } + + @Test + public void testNotConnectedState_enter() throws Exception { + clearInvocations(mISatelliteListener); + + // State transitions: POWER_OFF -> NOT_CONNECTED + moveToNotConnectedState(); + + verify(mISatelliteListener).onSatelliteModemStateChanged( + SatelliteModemState.SATELLITE_MODEM_STATE_NOT_CONNECTED); + ArgumentCaptor<NtnSignalStrength> ntnSignalStrength = ArgumentCaptor.forClass( + NtnSignalStrength.class); + verify(mISatelliteListener).onNtnSignalStrengthChanged(ntnSignalStrength.capture()); + assertEquals(0, ntnSignalStrength.getValue().signalStrengthLevel); + } + + @Test + public void testNotConnectedState() { + // State transitions: POWER_OFF -> NOT_CONNECTED + moveToNotConnectedState(); + + // Device is aligned with satellite. EVENT_DEVICE_ALIGNED timer should start. + mTestDemoSimulator.setDeviceAlignedWithSatellite(true); + processAllMessages(); + assertTrue(mTestDemoSimulator.isDeviceAlignedTimerStarted()); + + // Device is not aligned with satellite. EVENT_DEVICE_ALIGNED messages should be removed. + mTestDemoSimulator.setDeviceAlignedWithSatellite(false); + processAllMessages(); + assertFalse(mTestDemoSimulator.isDeviceAlignedTimerStarted()); + assertEquals(STATE_NOT_CONNECTED, mTestDemoSimulator.getCurrentStateName()); + + // Satellite mode is OFF. DemoSimulator should move to POWER_OFF state. + mTestDemoSimulator.onSatelliteModeOff(); + processAllMessages(); + assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName()); + } + + @Test + public void testConnectedState_enter() throws Exception { + clearInvocations(mISatelliteListener); + + // State transitions: POWER_OFF -> NOT_CONNECTED -> CONNECTED + moveToConnectedState(); + + verify(mISatelliteListener).onSatelliteModemStateChanged( + SatelliteModemState.SATELLITE_MODEM_STATE_NOT_CONNECTED); + verify(mISatelliteListener).onSatelliteModemStateChanged( + SatelliteModemState.SATELLITE_MODEM_STATE_CONNECTED); + ArgumentCaptor<NtnSignalStrength> ntnSignalStrength = ArgumentCaptor.forClass( + NtnSignalStrength.class); + verify(mISatelliteListener, times(2)) + .onNtnSignalStrengthChanged(ntnSignalStrength.capture()); + NtnSignalStrength ntnSignalStrengthOnConnected = ntnSignalStrength.getAllValues().get(1); + assertEquals(2, ntnSignalStrengthOnConnected.signalStrengthLevel); + } + + @Test + public void testConnectedState() { + // State transitions: POWER_OFF -> NOT_CONNECTED -> CONNECTED + moveToConnectedState(); + + // Device is not aligned with satellite. EVENT_DEVICE_NOT_ALIGNED timer should start + mTestDemoSimulator.setDeviceAlignedWithSatellite(false); + processAllMessages(); + assertTrue(mTestDemoSimulator.isDeviceNotAlignedTimerStarted()); + + // Device is aligned with satellite before timeout. + // EVENT_DEVICE_NOT_ALIGNED messages should be removed. + mTestDemoSimulator.setDeviceAlignedWithSatellite(true); + processAllMessages(); + assertFalse(mTestDemoSimulator.isDeviceNotAlignedTimerStarted()); + assertEquals(STATE_CONNECTED, mTestDemoSimulator.getCurrentStateName()); + + // Satellite mode is off. DemoSimulator should move to POWER_OFF state + mTestDemoSimulator.onSatelliteModeOff(); + processAllMessages(); + assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName()); + } + + private void moveToNotConnectedState() { + // DemoSimulator will initially be in POWER_OFF state. + assertNotNull(mTestDemoSimulator); + processAllMessages(); + assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName()); + + // Satellite mode is ON. DemoSimulator should move to NOT_CONNECTED state. + mTestDemoSimulator.onSatelliteModeOn(); + processAllMessages(); + assertEquals(STATE_NOT_CONNECTED, mTestDemoSimulator.getCurrentStateName()); + } + + private void moveToConnectedState() { + // DemoSimulator will initially be in POWER_OFF state. + assertNotNull(mTestDemoSimulator); + processAllMessages(); + assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName()); + + // Satellite mode is ON. DemoSimulator should move to NOT_CONNECTED state. + mTestDemoSimulator.onSatelliteModeOn(); + processAllMessages(); + assertEquals(STATE_NOT_CONNECTED, mTestDemoSimulator.getCurrentStateName()); + + // Device is aligned with satellite. EVENT_DEVICE_ALIGNED timer should start. + mTestDemoSimulator.setDeviceAlignedWithSatellite(true); + processAllMessages(); + assertTrue(mTestDemoSimulator.isDeviceAlignedTimerStarted()); + + // After timeout, DemoSimulator should move to CONNECTED state. + moveTimeForward(TEST_DEVICE_POINTING_ALIGNED_DURATION_MILLIS); + processAllMessages(); + assertEquals(STATE_CONNECTED, mTestDemoSimulator.getCurrentStateName()); + } + + private static class TestDemoSimulator extends DemoSimulator { + + TestDemoSimulator(@NonNull Context context, @NonNull Looper looper, + @NonNull SatelliteController satelliteController) { + super(context, looper, satelliteController); + } + + String getCurrentStateName() { + return getCurrentState().getName(); + } + + boolean isDeviceAlignedTimerStarted() { + return hasMessages(EVENT_DEVICE_ALIGNED); + } + + boolean isDeviceNotAlignedTimerStarted() { + return hasMessages(EVENT_DEVICE_NOT_ALIGNED); + } + } +} diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java index 3d3afa3cbd..c37d7e9e91 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java @@ -103,6 +103,7 @@ import android.os.PersistableBundle; import android.os.RemoteException; import android.os.ResultReceiver; import android.telephony.CarrierConfigManager; +import android.telephony.CellSignalStrength; import android.telephony.NetworkRegistrationInfo; import android.telephony.Rlog; import android.telephony.ServiceState; @@ -201,7 +202,9 @@ public class SatelliteControllerTest extends TelephonyTest { @Mock private FeatureFlags mFeatureFlags; @Mock private TelephonyConfigUpdateInstallReceiver mMockTelephonyConfigUpdateInstallReceiver; @Mock private SatelliteConfigParser mMockConfigParser; + @Mock private CellSignalStrength mCellSignalStrength; @Mock private SatelliteConfig mMockConfig; + @Mock private DemoSimulator mMockDemoSimulator; private Semaphore mIIntegerConsumerSemaphore = new Semaphore(0); private IIntegerConsumer mIIntegerConsumer = new IIntegerConsumer.Stub() { @@ -475,6 +478,7 @@ public class SatelliteControllerTest extends TelephonyTest { replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[]{mPhone, mPhone2}); replaceInstance(TelephonyConfigUpdateInstallReceiver.class, "sReceiverAdaptorInstance", null, mMockTelephonyConfigUpdateInstallReceiver); + replaceInstance(DemoSimulator.class, "sInstance", null, mMockDemoSimulator); mServiceState2 = Mockito.mock(ServiceState.class); when(mPhone.getServiceState()).thenReturn(mServiceState); @@ -785,6 +789,7 @@ public class SatelliteControllerTest extends TelephonyTest { setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS); mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false, mIIntegerConsumer); + mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController); processAllMessages(); assertTrue(waitForIIntegerConsumerResult(1)); assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0)); @@ -1304,6 +1309,7 @@ public class SatelliteControllerTest extends TelephonyTest { .registerForSatelliteModemStateChanged(callback); resetSatelliteControllerUTToSupportedAndProvisionedState(); + mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController); errorCode = mSatelliteControllerUT.registerForSatelliteModemStateChanged( SUB_ID, callback); @@ -1324,7 +1330,7 @@ public class SatelliteControllerTest extends TelephonyTest { .unregisterForSatelliteModemStateChanged(callback); resetSatelliteControllerUTToSupportedAndProvisionedState(); - + mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController); mSatelliteControllerUT.unregisterForModemStateChanged(SUB_ID, callback); verify(mMockSatelliteSessionController).unregisterForSatelliteModemStateChanged(callback); } @@ -1414,46 +1420,54 @@ public class SatelliteControllerTest extends TelephonyTest { String mText = "This is a test datagram message from user"; SatelliteDatagram datagram = new SatelliteDatagram(mText.getBytes()); - mIIntegerConsumerResults.clear(); - mSatelliteControllerUT.sendDatagram(SUB_ID, - SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE, datagram, true, mIIntegerConsumer); - processAllMessages(); - assertTrue(waitForIIntegerConsumerResult(1)); - assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, - (long) mIIntegerConsumerResults.get(0)); - verify(mMockDatagramController, never()).sendSatelliteDatagram(anyInt(), - eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE), eq(datagram), eq(true), - any()); - - mIIntegerConsumerResults.clear(); - setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS); - verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS); - sendProvisionedStateChangedEvent(false, null); - processAllMessages(); - verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS); - mSatelliteControllerUT.sendDatagram(SUB_ID, - SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE, datagram, true, mIIntegerConsumer); - processAllMessages(); - assertTrue(waitForIIntegerConsumerResult(1)); - assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED, - (long) mIIntegerConsumerResults.get(0)); - verify(mMockDatagramController, never()).sendSatelliteDatagram(anyInt(), - eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE), eq(datagram), eq(true), - any()); - - mIIntegerConsumerResults.clear(); - sendProvisionedStateChangedEvent(true, null); - processAllMessages(); - verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS); - mSatelliteControllerUT.sendDatagram(SUB_ID, - SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE, datagram, true, mIIntegerConsumer); - processAllMessages(); - assertFalse(waitForIIntegerConsumerResult(1)); - verify(mMockDatagramController, times(1)).sendSatelliteDatagram(anyInt(), - eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE), eq(datagram), eq(true), - any()); - verify(mMockPointingAppController, times(1)).startPointingUI(eq(true), anyBoolean(), - anyBoolean()); + int[] sosDatagramTypes = {SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE, + SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP, + SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED}; + for (int datagramType : sosDatagramTypes) { + mSatelliteControllerUT = + new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags); + mIIntegerConsumerSemaphore.drainPermits(); + mIIntegerConsumerResults.clear(); + clearInvocations(mMockDatagramController); + clearInvocations(mMockPointingAppController); + + mSatelliteControllerUT.sendDatagram(SUB_ID, datagramType, datagram, true, + mIIntegerConsumer); + processAllMessages(); + assertTrue(waitForIIntegerConsumerResult(1)); + assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, + (long) mIIntegerConsumerResults.get(0)); + verify(mMockDatagramController, never()).sendSatelliteDatagram(anyInt(), + eq(datagramType), eq(datagram), eq(true), any()); + + mIIntegerConsumerResults.clear(); + setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS); + verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS); + sendProvisionedStateChangedEvent(false, null); + processAllMessages(); + verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS); + mSatelliteControllerUT.sendDatagram(SUB_ID, datagramType, datagram, true, + mIIntegerConsumer); + processAllMessages(); + assertTrue(waitForIIntegerConsumerResult(1)); + assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED, + (long) mIIntegerConsumerResults.get(0)); + verify(mMockDatagramController, never()).sendSatelliteDatagram(anyInt(), + eq(datagramType), eq(datagram), eq(true), any()); + + mIIntegerConsumerResults.clear(); + sendProvisionedStateChangedEvent(true, null); + processAllMessages(); + verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS); + mSatelliteControllerUT.sendDatagram(SUB_ID, datagramType, datagram, true, + mIIntegerConsumer); + processAllMessages(); + assertFalse(waitForIIntegerConsumerResult(1)); + verify(mMockDatagramController, times(1)).sendSatelliteDatagram(anyInt(), + eq(datagramType), eq(datagram), eq(true), any()); + verify(mMockPointingAppController, times(1)).startPointingUI(eq(true), anyBoolean(), + anyBoolean()); + } } @Test @@ -2242,6 +2256,7 @@ public class SatelliteControllerTest extends TelephonyTest { SATELLITE_MODEM_STATE_CONNECTED); resetSatelliteControllerUTToSupportedAndProvisionedState(); + mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController); clearInvocations(mMockSatelliteSessionController); clearInvocations(mMockDatagramController); sendSatelliteModemStateChangedEvent(SATELLITE_MODEM_STATE_UNAVAILABLE, null); @@ -2614,6 +2629,11 @@ public class SatelliteControllerTest extends TelephonyTest { /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0) ); } + doReturn(mSignalStrength).when(mPhone).getSignalStrength(); + doReturn(mSignalStrength).when(mPhone2).getSignalStrength(); + List<CellSignalStrength> cellSignalStrengthList = new ArrayList<>(); + cellSignalStrengthList.add(mCellSignalStrength); + doReturn(cellSignalStrengthList).when(mSignalStrength).getCellSignalStrengths(); processAllMessages(); mSatelliteControllerUT.elapsedRealtime = 0; assertFalse(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime()); @@ -4494,5 +4514,9 @@ public class SatelliteControllerTest extends TelephonyTest { protected long getElapsedRealtime() { return elapsedRealtime; } + + void setSatelliteSessionController(SatelliteSessionController satelliteSessionController) { + mSatelliteSessionController = satelliteSessionController; + } } } diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java index fc04688d33..876fc51e6e 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java @@ -16,6 +16,8 @@ package com.android.internal.telephony.satellite; +import static android.telephony.ServiceState.STATE_IN_SERVICE; +import static android.telephony.ServiceState.STATE_OUT_OF_SERVICE; import static android.telephony.TelephonyManager.EXTRA_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE; import static android.telephony.TelephonyManager.EXTRA_EMERGENCY_CALL_TO_SATELLITE_LAUNCH_INTENT; import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS; @@ -141,8 +143,8 @@ public class SatelliteSOSMessageRecommenderTest extends TelephonyTest { when(mPhone2.getPhoneId()).thenReturn(PHONE_ID2); mTestSOSMessageRecommender = new TestSOSMessageRecommender(mContext, Looper.myLooper(), mTestSatelliteController, mTestImsManager); - when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE); - when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE); + when(mServiceState.getState()).thenReturn(STATE_OUT_OF_SERVICE); + when(mServiceState2.getState()).thenReturn(STATE_OUT_OF_SERVICE); when(mPhone.isImsRegistered()).thenReturn(false); when(mPhone2.isImsRegistered()).thenReturn(false); } @@ -291,7 +293,7 @@ public class SatelliteSOSMessageRecommenderTest extends TelephonyTest { } @Test - public void testImsRegistrationStateChangedBeforeTimeout() { + public void testNetworkStateChangedBeforeTimeout() { mTestSOSMessageRecommender.isSatelliteAllowedCallback = null; mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection); processAllMessages(); @@ -302,6 +304,7 @@ public class SatelliteSOSMessageRecommenderTest extends TelephonyTest { assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback); when(mPhone.isImsRegistered()).thenReturn(true); + when(mServiceState.getState()).thenReturn(STATE_IN_SERVICE); mTestImsManager.sendImsRegistrationStateChangedEvent(0, true); processAllMessages(); @@ -311,18 +314,30 @@ public class SatelliteSOSMessageRecommenderTest extends TelephonyTest { assertUnregisterForStateChangedEventsTriggered(mPhone, 0, 0, 0); when(mPhone.isImsRegistered()).thenReturn(false); + when(mServiceState.getState()).thenReturn(STATE_OUT_OF_SERVICE); + mTestImsManager.sendImsRegistrationStateChangedEvent(0, true); + processAllMessages(); + + assertFalse(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE)); + assertTrue(mTestSOSMessageRecommender.isTimerStarted()); + assertEquals(2, mTestSOSMessageRecommender.getCountOfTimerStarted()); + assertUnregisterForStateChangedEventsTriggered(mPhone, 0, 0, 0); + + when(mPhone.isImsRegistered()).thenReturn(false); when(mPhone2.isImsRegistered()).thenReturn(true); + when(mServiceState.getState()).thenReturn(STATE_IN_SERVICE); mTestImsManager.sendImsRegistrationStateChangedEvent(1, true); processAllMessages(); assertFalse(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE)); assertFalse(mTestSOSMessageRecommender.isTimerStarted()); - assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted()); + assertEquals(2, mTestSOSMessageRecommender.getCountOfTimerStarted()); assertUnregisterForStateChangedEventsTriggered(mPhone, 0, 0, 0); when(mPhone2.isImsRegistered()).thenReturn(false); + when(mServiceState.getState()).thenReturn(STATE_OUT_OF_SERVICE); mTestImsManager.sendImsRegistrationStateChangedEvent(1, false); processAllMessages(); - assertEquals(2, mTestSOSMessageRecommender.getCountOfTimerStarted()); + assertEquals(3, mTestSOSMessageRecommender.getCountOfTimerStarted()); assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback); // Move Location service to emergency mode @@ -436,7 +451,7 @@ public class SatelliteSOSMessageRecommenderTest extends TelephonyTest { @Test public void testCellularServiceStateChangedBeforeTimeout_InServiceToOutOfService() { testCellularServiceStateChangedBeforeTimeout( - ServiceState.STATE_IN_SERVICE, ServiceState.STATE_OUT_OF_SERVICE); + ServiceState.STATE_IN_SERVICE, STATE_OUT_OF_SERVICE); } @Test @@ -448,7 +463,7 @@ public class SatelliteSOSMessageRecommenderTest extends TelephonyTest { @Test public void testCellularServiceStateChangedBeforeTimeout_EmergencyOnlyToOutOfService() { testCellularServiceStateChangedBeforeTimeout( - ServiceState.STATE_EMERGENCY_ONLY, ServiceState.STATE_OUT_OF_SERVICE); + ServiceState.STATE_EMERGENCY_ONLY, STATE_OUT_OF_SERVICE); } @Test diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java index 0d49a3c340..eb06ff1eea 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java @@ -44,6 +44,7 @@ import static com.android.internal.telephony.subscription.SubscriptionDatabaseMa import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_RCS_CONFIG1; import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_RCS_CONFIG2; import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SATELLITE_ENTITLEMENT_PLMNS1; +import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SATELLITE_IS_NTN_DISABLED; import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SUBSCRIPTION_INFO1; import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SUBSCRIPTION_INFO2; import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_UUID1; @@ -3225,6 +3226,69 @@ public class SubscriptionManagerServiceTest extends TelephonyTest { } @Test + public void testIsSatelliteSpnWithEmptySpn() { + mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier, ""); // Empty + System.setProperty("persist.radio.allow_mock_modem", "true"); + doReturn(true).when(mFlags).oemEnabledSatelliteFlag(); + + EuiccProfileInfo profileInfo1 = new EuiccProfileInfo.Builder(FAKE_ICCID1) + .setIccid(FAKE_ICCID1) + .setNickname(FAKE_CARRIER_NAME1) + .setServiceProviderName(FAKE_CARRIER_NAME1) + .setProfileClass(SubscriptionManager.PROFILE_CLASS_OPERATIONAL) + .setCarrierIdentifier(new CarrierIdentifier(FAKE_MCC1, FAKE_MNC1, + FAKE_CARRIER_NAME1, null, null, null, FAKE_CARRIER_ID1, FAKE_CARRIER_ID1)) + .setUiccAccessRule(Arrays.asList(UiccAccessRule.decodeRules( + FAKE_NATIVE_ACCESS_RULES1))) + .build(); + + GetEuiccProfileInfoListResult result = new GetEuiccProfileInfoListResult( + EuiccService.RESULT_OK, new EuiccProfileInfo[]{profileInfo1}, false); + doReturn(result).when(mEuiccController).blockingGetEuiccProfileInfoList(eq(1)); + doReturn(TelephonyManager.INVALID_PORT_INDEX).when(mUiccSlot) + .getPortIndexFromIccId(anyString()); + doReturn(FAKE_ICCID1).when(mUiccController).convertToCardString(eq(1)); + + mSubscriptionManagerServiceUT.updateEmbeddedSubscriptions(List.of(1), null); + processAllMessages(); + + SubscriptionInfoInternal subInfo = mSubscriptionManagerServiceUT + .getSubscriptionInfoInternal(1); + assertThat(subInfo.getOnlyNonTerrestrialNetwork()) + .isEqualTo(FAKE_SATELLITE_IS_NTN_DISABLED); + + mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier, + FAKE_CARRIER_NAME1); + EuiccProfileInfo profileInfo2 = new EuiccProfileInfo.Builder(FAKE_ICCID2) + .setIccid(FAKE_ICCID2) + .setNickname(FAKE_CARRIER_NAME2) + .setServiceProviderName("") + .setProfileClass(SubscriptionManager.PROFILE_CLASS_OPERATIONAL) + .setCarrierIdentifier(new CarrierIdentifier(FAKE_MCC2, FAKE_MNC2, + FAKE_CARRIER_NAME2, null, null, null, FAKE_CARRIER_ID2, FAKE_CARRIER_ID2)) + .setUiccAccessRule(Arrays.asList(UiccAccessRule.decodeRules( + FAKE_NATIVE_ACCESS_RULES2))) + .build(); + result = new GetEuiccProfileInfoListResult( + EuiccService.RESULT_OK, new EuiccProfileInfo[]{profileInfo2}, false); + doReturn(result).when(mEuiccController).blockingGetEuiccProfileInfoList(eq(2)); + doReturn(TelephonyManager.INVALID_PORT_INDEX).when(mUiccSlot) + .getPortIndexFromIccId(anyString()); + doReturn(FAKE_ICCID2).when(mUiccController).convertToCardString(eq(2)); + + mSubscriptionManagerServiceUT.updateEmbeddedSubscriptions(List.of(2), null); + processAllMessages(); + + subInfo = mSubscriptionManagerServiceUT + .getSubscriptionInfoInternal(2); + assertThat(subInfo.getOnlyNonTerrestrialNetwork()) + .isEqualTo(FAKE_SATELLITE_IS_NTN_DISABLED); + + System.setProperty("persist.radio.allow_mock_modem", "false"); + doReturn(false).when(mFlags).oemEnabledSatelliteFlag(); + } + + @Test public void testIsSatelliteSpnWithNullCarrierIdentifier() { mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier, FAKE_CARRIER_NAME1); |