Loading src/java/com/android/internal/telephony/DefaultPhoneNotifier.java +6 −0 Original line number Diff line number Diff line Loading @@ -324,6 +324,12 @@ public class DefaultPhoneNotifier implements PhoneNotifier { mTelephonyRegistryMgr.notifyCarrierRoamingNtnModeChanged(sender.getSubId(), active); } @Override public void notifyCarrierRoamingNtnEligibleStateChanged(Phone sender, boolean eligible) { mTelephonyRegistryMgr.notifyCarrierRoamingNtnEligibleStateChanged( sender.getSubId(), eligible); } /** * Convert the {@link Call.State} enum into the PreciseCallState.PRECISE_CALL_STATE_* constants * for the public API. Loading src/java/com/android/internal/telephony/Phone.java +21 −0 Original line number Diff line number Diff line Loading @@ -5326,6 +5326,27 @@ public abstract class Phone extends Handler implements PhoneInternalInterface { mNotifier.notifyCarrierRoamingNtnModeChanged(this, active); } /** * Notify external listeners that the device eligibility to connect to carrier roaming * non-terrestrial network changed. * * @param eligible {@code true} when the device is eligible for satellite * communication if all the following conditions are met: * <ul> * <li>Any subscription on the device supports P2P satellite messaging which is defined by * {@link CarrierConfigManager#KEY_SATELLITE_ATTACH_SUPPORTED_BOOL} </li> * <li>{@link CarrierConfigManager#KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT} set to * {@link CarrierConfigManager#CARRIER_ROAMING_NTN_CONNECT_MANUAL} </li> * <li>The device is in {@link ServiceState#STATE_OUT_OF_SERVICE}, not connected to Wi-Fi, * and the hysteresis timer defined by {@link CarrierConfigManager * #KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT} is expired. </li> * </ul> */ public void notifyCarrierRoamingNtnEligibleStateChanged(boolean eligible) { logd("notifyCarrierRoamingNtnEligibleStateChanged eligible:" + eligible); mNotifier.notifyCarrierRoamingNtnEligibleStateChanged(this, eligible); } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("Phone: subId=" + getSubId()); pw.println(" mPhoneId=" + mPhoneId); Loading src/java/com/android/internal/telephony/PhoneNotifier.java +3 −0 Original line number Diff line number Diff line Loading @@ -156,4 +156,7 @@ public interface PhoneNotifier { /** Notify carrier roaming non-terrestrial network mode changed. **/ void notifyCarrierRoamingNtnModeChanged(Phone sender, boolean active); /** Notify eligibility to connect to carrier roaming non-terrestrial network changed. */ void notifyCarrierRoamingNtnEligibleStateChanged(Phone sender, boolean eligible); } src/java/com/android/internal/telephony/TelephonyCountryDetector.java +29 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.os.RegistrantList; import android.os.SystemClock; import android.os.SystemProperties; import android.telephony.Rlog; Loading Loading @@ -83,6 +84,8 @@ public class TelephonyCountryDetector extends Handler { @NonNull private final Geocoder mGeocoder; @NonNull private final LocationManager mLocationManager; @NonNull private final ConnectivityManager mConnectivityManager; @NonNull private final RegistrantList mWifiConnectivityStateChangedRegistrantList = new RegistrantList(); @NonNull private final Object mLock = new Object(); @NonNull @GuardedBy("mLock") Loading Loading @@ -286,6 +289,8 @@ public class TelephonyCountryDetector extends Handler { handleNetworkCountryCodeChangedEvent((NetworkCountryCodeInfo) msg.obj); break; case EVENT_WIFI_CONNECTIVITY_STATE_CHANGED: handleEventWifiConnectivityStateChanged(); break; case EVENT_LOCATION_UPDATE_REQUEST_QUOTA_RESET: evaluateRequestingLocationUpdates(); break; Loading Loading @@ -470,6 +475,11 @@ public class TelephonyCountryDetector extends Handler { evaluateRequestingLocationUpdates(); } private void handleEventWifiConnectivityStateChanged() { mWifiConnectivityStateChangedRegistrantList.notifyResult(isWifiNetworkConnected()); evaluateRequestingLocationUpdates(); } private void setLocationCountryCode(@NonNull Pair<String, Long> countryCodeInfo) { logd("Set location country code to: " + countryCodeInfo.first); if (!isValid(countryCodeInfo.first)) { Loading Loading @@ -542,6 +552,25 @@ public class TelephonyCountryDetector extends Handler { && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); } /** * Register a callback to receive Wi-Fi connectivity state changes. * @param h Handler for notification message * @param what User-defined message code. * @param obj User object. */ public void registerForWifiConnectivityStateChanged(@NonNull Handler h, int what, @Nullable Object obj) { mWifiConnectivityStateChangedRegistrantList.add(h, what, obj); } /** * Unregisters for Wi-Fi connectivity state changes. * @param h Handler to be removed from the registrant list. */ public void unregisterForWifiConnectivityStateChanged(@NonNull Handler h) { mWifiConnectivityStateChangedRegistrantList.remove(h); } /** * Check whether this is a valid country code. * Loading src/java/com/android/internal/telephony/satellite/SatelliteController.java +243 −1 Original line number Diff line number Diff line Loading @@ -17,7 +17,10 @@ package com.android.internal.telephony.satellite; import static android.provider.Settings.ACTION_SATELLITE_SETTING; import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL; import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT; import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY; import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT; import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE; import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT; import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL; Loading Loading @@ -121,6 +124,7 @@ import com.android.internal.telephony.DeviceStateMonitor; import com.android.internal.telephony.IIntegerConsumer; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneFactory; import com.android.internal.telephony.TelephonyCountryDetector; import com.android.internal.telephony.configupdate.ConfigParser; import com.android.internal.telephony.configupdate.ConfigProviderAdaptor; import com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver; Loading Loading @@ -229,6 +233,8 @@ public class SatelliteController extends Handler { private static final int EVENT_EVALUATE_ESOS_PROFILES_PRIORITIZATION = 43; private static final int CMD_PROVISION_SATELLITE_TOKEN_UPDATED = 44; private static final int EVENT_PROVISION_SATELLITE_TOKEN_UPDATED = 45; private static final int EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT = 46; private static final int EVENT_WIFI_CONNECTIVITY_STATE_CHANGED = 47; @NonNull private static SatelliteController sInstance; @NonNull private final Context mContext; Loading @@ -242,9 +248,15 @@ public class SatelliteController extends Handler { @NonNull private SessionMetricsStats mSessionMetricsStats; @NonNull private CarrierRoamingSatelliteControllerStats mCarrierRoamingSatelliteControllerStats; @NonNull private final SubscriptionManagerService mSubscriptionManagerService; @NonNull private final TelephonyCountryDetector mCountryDetector; private final CommandsInterface mCi; private ContentResolver mContentResolver; private final DeviceStateMonitor mDSM; @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) protected final Object mSatellitePhoneLock = new Object(); @GuardedBy("mSatellitePhoneLock") @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) protected Phone mSatellitePhone = null; private final Object mRadioStateLock = new Object(); Loading Loading @@ -391,6 +403,13 @@ public class SatelliteController extends Handler { @GuardedBy("mSatelliteConnectedLock") @NonNull private final SparseBooleanArray mInitialized = new SparseBooleanArray(); /** * Boolean set to {@code true} when device is eligible to connect to carrier roaming * non-terrestrial network else set to {@code false}. */ @GuardedBy("mSatellitePhoneLock") private Boolean mLastNotifiedNtnEligibility = null; @GuardedBy("mSatelliteConnectedLock") @NonNull private final Map<Integer, CarrierRoamingSatelliteSessionStats> mCarrierRoamingSatelliteSessionStatsMap = new HashMap<>(); Loading Loading @@ -472,6 +491,10 @@ public class SatelliteController extends Handler { // Variable for backup and restore device's screen rotation settings. private String mDeviceRotationLockToBackupAndRestore = null; private final Object mIsWifiConnectedLock = new Object(); @GuardedBy("mIsWifiConnectedLock") private boolean mIsWifiConnected = false; /** * @return The singleton instance of SatelliteController. */ Loading Loading @@ -522,6 +545,9 @@ public class SatelliteController extends Handler { // to the satellite service and HAL interface. mSatelliteModemInterface = SatelliteModemInterface.make( mContext, this, mFeatureFlags); mCountryDetector = TelephonyCountryDetector.getInstance(context); mCountryDetector.registerForWifiConnectivityStateChanged(this, EVENT_WIFI_CONNECTIVITY_STATE_CHANGED, null); // Create the PointingUIController singleton, // which is used to manage interactions with PointingUI app. Loading Loading @@ -1508,6 +1534,18 @@ public class SatelliteController extends Handler { break; } case EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT: { synchronized (mSatellitePhoneLock) { boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone); plogd("EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT:" + " isCarrierRoamingNtnEligible=" + eligible); if (eligible) { updateLastNotifiedNtnEligibilityAndNotify(true); } } break; } case EVENT_EVALUATE_ESOS_PROFILES_PRIORITIZATION: { evaluateESOSProfilesPrioritization(); break; Loading @@ -1519,11 +1557,13 @@ public class SatelliteController extends Handler { (RequestProvisionSatelliteArgument) request.argument; onCompleted = obtainMessage(EVENT_PROVISION_SATELLITE_TOKEN_UPDATED, request); // only pass to index 0. // TODO: Select the subscription with highest priority and set it to mSatelliteSubId int subId = -1; synchronized (mSatelliteTokenProvisionedLock) { subId = mSubscriberIdPerSub.getOrDefault( argument.mProvisionSubscriberIdList.get(0).getSubscriberId(), -1); } setSatellitePhone(subId); String iccId = mSubscriptionManagerService.getSubscriptionInfo(subId).getIccId(); logd("CMD_PROVISION_SATELLITE_TOKEN_UPDATED: subId=" + subId + ", iccId=" + iccId); mSatelliteModemInterface.updateSatelliteSubscription(iccId, onCompleted); Loading Loading @@ -1553,6 +1593,17 @@ public class SatelliteController extends Handler { break; } case EVENT_WIFI_CONNECTIVITY_STATE_CHANGED: { synchronized (mIsWifiConnectedLock) { ar = (AsyncResult) msg.obj; mIsWifiConnected = (boolean) ar.result; plogd("EVENT_WIFI_CONNECTIVITY_STATE_CHANGED: mIsWifiConnected=" + mIsWifiConnected); handleStateChangedForCarrierRoamingNtnEligibility(); } break; } default: Log.w(TAG, "SatelliteControllerHandler: unexpected message code: " + msg.what); Loading Loading @@ -4106,7 +4157,10 @@ public class SatelliteController extends Handler { KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY, KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL, KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT, KEY_SATELLITE_ESOS_SUPPORTED_BOOL); KEY_SATELLITE_ESOS_SUPPORTED_BOOL, KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT ); } if (config == null || config.isEmpty()) { config = CarrierConfigManager.getDefaultConfig(); Loading @@ -4129,6 +4183,7 @@ public class SatelliteController extends Handler { updateSupportedSatelliteServicesForActiveSubscriptions(); processNewCarrierConfigData(subId); resetCarrierRoamingSatelliteModeParams(subId); handleStateChangedForCarrierRoamingNtnEligibility(); sendMessageDelayed(obtainMessage(EVENT_EVALUATE_ESOS_PROFILES_PRIORITIZATION), TimeUnit.MINUTES.toMillis(1)); } Loading Loading @@ -4235,6 +4290,14 @@ public class SatelliteController extends Handler { .getBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL); } private boolean isSatelliteEsosSupported(int subId) { return getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ESOS_SUPPORTED_BOOL); } private int getCarrierRoamingNtnConnectType(int subId) { return getConfigForSubId(subId).getInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT); } /** * Check if satellite attach is enabled by user for the carrier associated with the * {@code subId}. Loading Loading @@ -4529,6 +4592,7 @@ public class SatelliteController extends Handler { } private void handleEventServiceStateChanged() { handleStateChangedForCarrierRoamingNtnEligibility(); handleServiceStateForSatelliteConnectionViaCarrier(); determineSystemNotification(); } Loading Loading @@ -4634,12 +4698,104 @@ public class SatelliteController extends Handler { } } private void handleStateChangedForCarrierRoamingNtnEligibility() { if (!mFeatureFlags.carrierRoamingNbIotNtn()) { plogd("handleStateChangedForCarrierRoamingNtnEligibility: " + "carrierRoamingNbIotNtn flag is disabled"); return; } synchronized (mSatellitePhoneLock) { boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone); plogd("handleStateChangedForCarrierRoamingNtnEligibility: " + "isCarrierRoamingNtnEligible=" + eligible); if (eligible) { if (shouldStartNtnEligibilityHysteresisTimer(eligible)) { startNtnEligibilityHysteresisTimer(); } } else { stopNtnEligibilityHysteresisTimer(); updateLastNotifiedNtnEligibilityAndNotify(false); } } } private boolean shouldStartNtnEligibilityHysteresisTimer(boolean eligible) { if (!eligible) { return false; } if (hasMessages(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT)) { plogd("shouldStartNtnEligibilityHysteresisTimer: Timer is already running."); return false; } synchronized (mSatellitePhoneLock) { if (mLastNotifiedNtnEligibility != null && mLastNotifiedNtnEligibility) { return false; } } return true; } private void startNtnEligibilityHysteresisTimer() { synchronized (mSatellitePhoneLock) { if (mSatellitePhone == null) { ploge("startNtnEligibilityHysteresisTimer: mSatellitePhone is null."); return; } int subId = mSatellitePhone.getSubId(); long timeout = getCarrierSupportedSatelliteNotificationHysteresisTimeMillis(subId); plogd("startNtnEligibilityHysteresisTimer: sendMessageDelayed subId=" + subId + ", phoneId=" + mSatellitePhone.getPhoneId() + ", timeout=" + timeout); sendMessageDelayed(obtainMessage(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT), timeout); } } private void stopNtnEligibilityHysteresisTimer() { if (hasMessages(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT)) { removeMessages(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT); } } private void updateLastNotifiedNtnEligibilityAndNotify(boolean currentNtnEligibility) { if (!mFeatureFlags.carrierRoamingNbIotNtn()) { plogd("notifyNtnEligibility: carrierRoamingNbIotNtn flag is disabled"); return; } synchronized (mSatellitePhoneLock) { if (mSatellitePhone == null) { ploge("notifyNtnEligibility: mSatellitePhone is null"); return; } plogd("notifyNtnEligibility: phoneId=" + mSatellitePhone.getPhoneId() + " currentNtnEligibility=" + currentNtnEligibility); if (mLastNotifiedNtnEligibility == null || mLastNotifiedNtnEligibility != currentNtnEligibility) { mLastNotifiedNtnEligibility = currentNtnEligibility; mSatellitePhone.notifyCarrierRoamingNtnEligibleStateChanged(currentNtnEligibility); } } } private long getSatelliteConnectionHysteresisTimeMillis(int subId) { PersistableBundle config = getPersistableBundle(subId); return (config.getInt( KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT) * 1000L); } private long getCarrierSupportedSatelliteNotificationHysteresisTimeMillis(int subId) { PersistableBundle config = getPersistableBundle(subId); return (config.getInt( KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT) * 1000L); } private void persistOemEnabledSatelliteProvisionStatus(boolean isProvisioned) { synchronized (mSatelliteViaOemProvisionLock) { plogd("persistOemEnabledSatelliteProvisionStatus: isProvisioned=" + isProvisioned); Loading Loading @@ -5422,4 +5578,90 @@ public class SatelliteController extends Handler { result); sendRequestAsync(CMD_PROVISION_SATELLITE_TOKEN_UPDATED, request, null); } @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) protected void setSatellitePhone(int subId) { synchronized (mSatellitePhoneLock) { mSatellitePhone = SatelliteServiceUtils.getPhone(subId); if (mSatellitePhone == null) { mSatellitePhone = SatelliteServiceUtils.getPhone(); } plogd("mSatellitePhone:" + (mSatellitePhone != null) + ", subId=" + subId); } } /** * Get whether phone is eligible to connect to carrier roaming non-terrestrial network. * * @param phone phone object * return {@code true} when the subscription is eligible for satellite * communication if all the following conditions are met: * <ul> * <li>Subscription supports P2P satellite messaging which is defined by * {@link CarrierConfigManager#KEY_SATELLITE_ATTACH_SUPPORTED_BOOL} </li> * <li>{@link CarrierConfigManager#KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT} set to * {@link CarrierConfigManager#CARRIER_ROAMING_NTN_CONNECT_MANUAL} </li> * <li>The device is in {@link ServiceState#STATE_OUT_OF_SERVICE}, not connected to Wi-Fi. </li> * </ul> */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) public boolean isCarrierRoamingNtnEligible(@Nullable Phone phone) { if (!mFeatureFlags.carrierRoamingNbIotNtn()) { plogd("isCarrierRoamingNtnEligible: carrierRoamingNbIotNtn flag is disabled"); return false; } if (phone == null) { plogd("isCarrierRoamingNtnEligible: phone is null"); return false; } int subId = phone.getSubId(); if (!isSatelliteSupportedViaCarrier(subId)) { plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId() + "]: satellite is not supported via carrier"); return false; } if (!isSatelliteServiceSupportedByCarrier(subId, NetworkRegistrationInfo.SERVICE_TYPE_SMS)) { plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId() + "]: SMS is not supported by carrier"); return false; } int carrierRoamingNtnConnectType = getCarrierRoamingNtnConnectType(subId); if (carrierRoamingNtnConnectType != CARRIER_ROAMING_NTN_CONNECT_MANUAL) { plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId() + "]: not manual " + "connect. carrierRoamingNtnConnectType = " + carrierRoamingNtnConnectType); return false; } if (SatelliteServiceUtils.isCellularAvailable()) { plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId() + "]: cellular is available"); return false; } synchronized (mIsWifiConnectedLock) { if (mIsWifiConnected) { plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId() + "]: Wi-Fi is connected"); return false; } } return true; } private boolean isSatelliteServiceSupportedByCarrier(int subId, @NetworkRegistrationInfo.ServiceType int serviceType) { List<String> satellitePlmnList = getSatellitePlmnsForCarrier(subId); for (String satellitePlmn : satellitePlmnList) { if (getSupportedSatelliteServices(subId, satellitePlmn).contains(serviceType)) { return true; } } return false; } } Loading
src/java/com/android/internal/telephony/DefaultPhoneNotifier.java +6 −0 Original line number Diff line number Diff line Loading @@ -324,6 +324,12 @@ public class DefaultPhoneNotifier implements PhoneNotifier { mTelephonyRegistryMgr.notifyCarrierRoamingNtnModeChanged(sender.getSubId(), active); } @Override public void notifyCarrierRoamingNtnEligibleStateChanged(Phone sender, boolean eligible) { mTelephonyRegistryMgr.notifyCarrierRoamingNtnEligibleStateChanged( sender.getSubId(), eligible); } /** * Convert the {@link Call.State} enum into the PreciseCallState.PRECISE_CALL_STATE_* constants * for the public API. Loading
src/java/com/android/internal/telephony/Phone.java +21 −0 Original line number Diff line number Diff line Loading @@ -5326,6 +5326,27 @@ public abstract class Phone extends Handler implements PhoneInternalInterface { mNotifier.notifyCarrierRoamingNtnModeChanged(this, active); } /** * Notify external listeners that the device eligibility to connect to carrier roaming * non-terrestrial network changed. * * @param eligible {@code true} when the device is eligible for satellite * communication if all the following conditions are met: * <ul> * <li>Any subscription on the device supports P2P satellite messaging which is defined by * {@link CarrierConfigManager#KEY_SATELLITE_ATTACH_SUPPORTED_BOOL} </li> * <li>{@link CarrierConfigManager#KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT} set to * {@link CarrierConfigManager#CARRIER_ROAMING_NTN_CONNECT_MANUAL} </li> * <li>The device is in {@link ServiceState#STATE_OUT_OF_SERVICE}, not connected to Wi-Fi, * and the hysteresis timer defined by {@link CarrierConfigManager * #KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT} is expired. </li> * </ul> */ public void notifyCarrierRoamingNtnEligibleStateChanged(boolean eligible) { logd("notifyCarrierRoamingNtnEligibleStateChanged eligible:" + eligible); mNotifier.notifyCarrierRoamingNtnEligibleStateChanged(this, eligible); } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("Phone: subId=" + getSubId()); pw.println(" mPhoneId=" + mPhoneId); Loading
src/java/com/android/internal/telephony/PhoneNotifier.java +3 −0 Original line number Diff line number Diff line Loading @@ -156,4 +156,7 @@ public interface PhoneNotifier { /** Notify carrier roaming non-terrestrial network mode changed. **/ void notifyCarrierRoamingNtnModeChanged(Phone sender, boolean active); /** Notify eligibility to connect to carrier roaming non-terrestrial network changed. */ void notifyCarrierRoamingNtnEligibleStateChanged(Phone sender, boolean eligible); }
src/java/com/android/internal/telephony/TelephonyCountryDetector.java +29 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.os.RegistrantList; import android.os.SystemClock; import android.os.SystemProperties; import android.telephony.Rlog; Loading Loading @@ -83,6 +84,8 @@ public class TelephonyCountryDetector extends Handler { @NonNull private final Geocoder mGeocoder; @NonNull private final LocationManager mLocationManager; @NonNull private final ConnectivityManager mConnectivityManager; @NonNull private final RegistrantList mWifiConnectivityStateChangedRegistrantList = new RegistrantList(); @NonNull private final Object mLock = new Object(); @NonNull @GuardedBy("mLock") Loading Loading @@ -286,6 +289,8 @@ public class TelephonyCountryDetector extends Handler { handleNetworkCountryCodeChangedEvent((NetworkCountryCodeInfo) msg.obj); break; case EVENT_WIFI_CONNECTIVITY_STATE_CHANGED: handleEventWifiConnectivityStateChanged(); break; case EVENT_LOCATION_UPDATE_REQUEST_QUOTA_RESET: evaluateRequestingLocationUpdates(); break; Loading Loading @@ -470,6 +475,11 @@ public class TelephonyCountryDetector extends Handler { evaluateRequestingLocationUpdates(); } private void handleEventWifiConnectivityStateChanged() { mWifiConnectivityStateChangedRegistrantList.notifyResult(isWifiNetworkConnected()); evaluateRequestingLocationUpdates(); } private void setLocationCountryCode(@NonNull Pair<String, Long> countryCodeInfo) { logd("Set location country code to: " + countryCodeInfo.first); if (!isValid(countryCodeInfo.first)) { Loading Loading @@ -542,6 +552,25 @@ public class TelephonyCountryDetector extends Handler { && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); } /** * Register a callback to receive Wi-Fi connectivity state changes. * @param h Handler for notification message * @param what User-defined message code. * @param obj User object. */ public void registerForWifiConnectivityStateChanged(@NonNull Handler h, int what, @Nullable Object obj) { mWifiConnectivityStateChangedRegistrantList.add(h, what, obj); } /** * Unregisters for Wi-Fi connectivity state changes. * @param h Handler to be removed from the registrant list. */ public void unregisterForWifiConnectivityStateChanged(@NonNull Handler h) { mWifiConnectivityStateChangedRegistrantList.remove(h); } /** * Check whether this is a valid country code. * Loading
src/java/com/android/internal/telephony/satellite/SatelliteController.java +243 −1 Original line number Diff line number Diff line Loading @@ -17,7 +17,10 @@ package com.android.internal.telephony.satellite; import static android.provider.Settings.ACTION_SATELLITE_SETTING; import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL; import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT; import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY; import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT; import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE; import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT; import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL; Loading Loading @@ -121,6 +124,7 @@ import com.android.internal.telephony.DeviceStateMonitor; import com.android.internal.telephony.IIntegerConsumer; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneFactory; import com.android.internal.telephony.TelephonyCountryDetector; import com.android.internal.telephony.configupdate.ConfigParser; import com.android.internal.telephony.configupdate.ConfigProviderAdaptor; import com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver; Loading Loading @@ -229,6 +233,8 @@ public class SatelliteController extends Handler { private static final int EVENT_EVALUATE_ESOS_PROFILES_PRIORITIZATION = 43; private static final int CMD_PROVISION_SATELLITE_TOKEN_UPDATED = 44; private static final int EVENT_PROVISION_SATELLITE_TOKEN_UPDATED = 45; private static final int EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT = 46; private static final int EVENT_WIFI_CONNECTIVITY_STATE_CHANGED = 47; @NonNull private static SatelliteController sInstance; @NonNull private final Context mContext; Loading @@ -242,9 +248,15 @@ public class SatelliteController extends Handler { @NonNull private SessionMetricsStats mSessionMetricsStats; @NonNull private CarrierRoamingSatelliteControllerStats mCarrierRoamingSatelliteControllerStats; @NonNull private final SubscriptionManagerService mSubscriptionManagerService; @NonNull private final TelephonyCountryDetector mCountryDetector; private final CommandsInterface mCi; private ContentResolver mContentResolver; private final DeviceStateMonitor mDSM; @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) protected final Object mSatellitePhoneLock = new Object(); @GuardedBy("mSatellitePhoneLock") @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) protected Phone mSatellitePhone = null; private final Object mRadioStateLock = new Object(); Loading Loading @@ -391,6 +403,13 @@ public class SatelliteController extends Handler { @GuardedBy("mSatelliteConnectedLock") @NonNull private final SparseBooleanArray mInitialized = new SparseBooleanArray(); /** * Boolean set to {@code true} when device is eligible to connect to carrier roaming * non-terrestrial network else set to {@code false}. */ @GuardedBy("mSatellitePhoneLock") private Boolean mLastNotifiedNtnEligibility = null; @GuardedBy("mSatelliteConnectedLock") @NonNull private final Map<Integer, CarrierRoamingSatelliteSessionStats> mCarrierRoamingSatelliteSessionStatsMap = new HashMap<>(); Loading Loading @@ -472,6 +491,10 @@ public class SatelliteController extends Handler { // Variable for backup and restore device's screen rotation settings. private String mDeviceRotationLockToBackupAndRestore = null; private final Object mIsWifiConnectedLock = new Object(); @GuardedBy("mIsWifiConnectedLock") private boolean mIsWifiConnected = false; /** * @return The singleton instance of SatelliteController. */ Loading Loading @@ -522,6 +545,9 @@ public class SatelliteController extends Handler { // to the satellite service and HAL interface. mSatelliteModemInterface = SatelliteModemInterface.make( mContext, this, mFeatureFlags); mCountryDetector = TelephonyCountryDetector.getInstance(context); mCountryDetector.registerForWifiConnectivityStateChanged(this, EVENT_WIFI_CONNECTIVITY_STATE_CHANGED, null); // Create the PointingUIController singleton, // which is used to manage interactions with PointingUI app. Loading Loading @@ -1508,6 +1534,18 @@ public class SatelliteController extends Handler { break; } case EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT: { synchronized (mSatellitePhoneLock) { boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone); plogd("EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT:" + " isCarrierRoamingNtnEligible=" + eligible); if (eligible) { updateLastNotifiedNtnEligibilityAndNotify(true); } } break; } case EVENT_EVALUATE_ESOS_PROFILES_PRIORITIZATION: { evaluateESOSProfilesPrioritization(); break; Loading @@ -1519,11 +1557,13 @@ public class SatelliteController extends Handler { (RequestProvisionSatelliteArgument) request.argument; onCompleted = obtainMessage(EVENT_PROVISION_SATELLITE_TOKEN_UPDATED, request); // only pass to index 0. // TODO: Select the subscription with highest priority and set it to mSatelliteSubId int subId = -1; synchronized (mSatelliteTokenProvisionedLock) { subId = mSubscriberIdPerSub.getOrDefault( argument.mProvisionSubscriberIdList.get(0).getSubscriberId(), -1); } setSatellitePhone(subId); String iccId = mSubscriptionManagerService.getSubscriptionInfo(subId).getIccId(); logd("CMD_PROVISION_SATELLITE_TOKEN_UPDATED: subId=" + subId + ", iccId=" + iccId); mSatelliteModemInterface.updateSatelliteSubscription(iccId, onCompleted); Loading Loading @@ -1553,6 +1593,17 @@ public class SatelliteController extends Handler { break; } case EVENT_WIFI_CONNECTIVITY_STATE_CHANGED: { synchronized (mIsWifiConnectedLock) { ar = (AsyncResult) msg.obj; mIsWifiConnected = (boolean) ar.result; plogd("EVENT_WIFI_CONNECTIVITY_STATE_CHANGED: mIsWifiConnected=" + mIsWifiConnected); handleStateChangedForCarrierRoamingNtnEligibility(); } break; } default: Log.w(TAG, "SatelliteControllerHandler: unexpected message code: " + msg.what); Loading Loading @@ -4106,7 +4157,10 @@ public class SatelliteController extends Handler { KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY, KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL, KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT, KEY_SATELLITE_ESOS_SUPPORTED_BOOL); KEY_SATELLITE_ESOS_SUPPORTED_BOOL, KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT ); } if (config == null || config.isEmpty()) { config = CarrierConfigManager.getDefaultConfig(); Loading @@ -4129,6 +4183,7 @@ public class SatelliteController extends Handler { updateSupportedSatelliteServicesForActiveSubscriptions(); processNewCarrierConfigData(subId); resetCarrierRoamingSatelliteModeParams(subId); handleStateChangedForCarrierRoamingNtnEligibility(); sendMessageDelayed(obtainMessage(EVENT_EVALUATE_ESOS_PROFILES_PRIORITIZATION), TimeUnit.MINUTES.toMillis(1)); } Loading Loading @@ -4235,6 +4290,14 @@ public class SatelliteController extends Handler { .getBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL); } private boolean isSatelliteEsosSupported(int subId) { return getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ESOS_SUPPORTED_BOOL); } private int getCarrierRoamingNtnConnectType(int subId) { return getConfigForSubId(subId).getInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT); } /** * Check if satellite attach is enabled by user for the carrier associated with the * {@code subId}. Loading Loading @@ -4529,6 +4592,7 @@ public class SatelliteController extends Handler { } private void handleEventServiceStateChanged() { handleStateChangedForCarrierRoamingNtnEligibility(); handleServiceStateForSatelliteConnectionViaCarrier(); determineSystemNotification(); } Loading Loading @@ -4634,12 +4698,104 @@ public class SatelliteController extends Handler { } } private void handleStateChangedForCarrierRoamingNtnEligibility() { if (!mFeatureFlags.carrierRoamingNbIotNtn()) { plogd("handleStateChangedForCarrierRoamingNtnEligibility: " + "carrierRoamingNbIotNtn flag is disabled"); return; } synchronized (mSatellitePhoneLock) { boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone); plogd("handleStateChangedForCarrierRoamingNtnEligibility: " + "isCarrierRoamingNtnEligible=" + eligible); if (eligible) { if (shouldStartNtnEligibilityHysteresisTimer(eligible)) { startNtnEligibilityHysteresisTimer(); } } else { stopNtnEligibilityHysteresisTimer(); updateLastNotifiedNtnEligibilityAndNotify(false); } } } private boolean shouldStartNtnEligibilityHysteresisTimer(boolean eligible) { if (!eligible) { return false; } if (hasMessages(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT)) { plogd("shouldStartNtnEligibilityHysteresisTimer: Timer is already running."); return false; } synchronized (mSatellitePhoneLock) { if (mLastNotifiedNtnEligibility != null && mLastNotifiedNtnEligibility) { return false; } } return true; } private void startNtnEligibilityHysteresisTimer() { synchronized (mSatellitePhoneLock) { if (mSatellitePhone == null) { ploge("startNtnEligibilityHysteresisTimer: mSatellitePhone is null."); return; } int subId = mSatellitePhone.getSubId(); long timeout = getCarrierSupportedSatelliteNotificationHysteresisTimeMillis(subId); plogd("startNtnEligibilityHysteresisTimer: sendMessageDelayed subId=" + subId + ", phoneId=" + mSatellitePhone.getPhoneId() + ", timeout=" + timeout); sendMessageDelayed(obtainMessage(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT), timeout); } } private void stopNtnEligibilityHysteresisTimer() { if (hasMessages(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT)) { removeMessages(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT); } } private void updateLastNotifiedNtnEligibilityAndNotify(boolean currentNtnEligibility) { if (!mFeatureFlags.carrierRoamingNbIotNtn()) { plogd("notifyNtnEligibility: carrierRoamingNbIotNtn flag is disabled"); return; } synchronized (mSatellitePhoneLock) { if (mSatellitePhone == null) { ploge("notifyNtnEligibility: mSatellitePhone is null"); return; } plogd("notifyNtnEligibility: phoneId=" + mSatellitePhone.getPhoneId() + " currentNtnEligibility=" + currentNtnEligibility); if (mLastNotifiedNtnEligibility == null || mLastNotifiedNtnEligibility != currentNtnEligibility) { mLastNotifiedNtnEligibility = currentNtnEligibility; mSatellitePhone.notifyCarrierRoamingNtnEligibleStateChanged(currentNtnEligibility); } } } private long getSatelliteConnectionHysteresisTimeMillis(int subId) { PersistableBundle config = getPersistableBundle(subId); return (config.getInt( KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT) * 1000L); } private long getCarrierSupportedSatelliteNotificationHysteresisTimeMillis(int subId) { PersistableBundle config = getPersistableBundle(subId); return (config.getInt( KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT) * 1000L); } private void persistOemEnabledSatelliteProvisionStatus(boolean isProvisioned) { synchronized (mSatelliteViaOemProvisionLock) { plogd("persistOemEnabledSatelliteProvisionStatus: isProvisioned=" + isProvisioned); Loading Loading @@ -5422,4 +5578,90 @@ public class SatelliteController extends Handler { result); sendRequestAsync(CMD_PROVISION_SATELLITE_TOKEN_UPDATED, request, null); } @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) protected void setSatellitePhone(int subId) { synchronized (mSatellitePhoneLock) { mSatellitePhone = SatelliteServiceUtils.getPhone(subId); if (mSatellitePhone == null) { mSatellitePhone = SatelliteServiceUtils.getPhone(); } plogd("mSatellitePhone:" + (mSatellitePhone != null) + ", subId=" + subId); } } /** * Get whether phone is eligible to connect to carrier roaming non-terrestrial network. * * @param phone phone object * return {@code true} when the subscription is eligible for satellite * communication if all the following conditions are met: * <ul> * <li>Subscription supports P2P satellite messaging which is defined by * {@link CarrierConfigManager#KEY_SATELLITE_ATTACH_SUPPORTED_BOOL} </li> * <li>{@link CarrierConfigManager#KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT} set to * {@link CarrierConfigManager#CARRIER_ROAMING_NTN_CONNECT_MANUAL} </li> * <li>The device is in {@link ServiceState#STATE_OUT_OF_SERVICE}, not connected to Wi-Fi. </li> * </ul> */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) public boolean isCarrierRoamingNtnEligible(@Nullable Phone phone) { if (!mFeatureFlags.carrierRoamingNbIotNtn()) { plogd("isCarrierRoamingNtnEligible: carrierRoamingNbIotNtn flag is disabled"); return false; } if (phone == null) { plogd("isCarrierRoamingNtnEligible: phone is null"); return false; } int subId = phone.getSubId(); if (!isSatelliteSupportedViaCarrier(subId)) { plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId() + "]: satellite is not supported via carrier"); return false; } if (!isSatelliteServiceSupportedByCarrier(subId, NetworkRegistrationInfo.SERVICE_TYPE_SMS)) { plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId() + "]: SMS is not supported by carrier"); return false; } int carrierRoamingNtnConnectType = getCarrierRoamingNtnConnectType(subId); if (carrierRoamingNtnConnectType != CARRIER_ROAMING_NTN_CONNECT_MANUAL) { plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId() + "]: not manual " + "connect. carrierRoamingNtnConnectType = " + carrierRoamingNtnConnectType); return false; } if (SatelliteServiceUtils.isCellularAvailable()) { plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId() + "]: cellular is available"); return false; } synchronized (mIsWifiConnectedLock) { if (mIsWifiConnected) { plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId() + "]: Wi-Fi is connected"); return false; } } return true; } private boolean isSatelliteServiceSupportedByCarrier(int subId, @NetworkRegistrationInfo.ServiceType int serviceType) { List<String> satellitePlmnList = getSatellitePlmnsForCarrier(subId); for (String satellitePlmn : satellitePlmnList) { if (getSupportedSatelliteServices(subId, satellitePlmn).contains(serviceType)) { return true; } } return false; } }