diff options
7 files changed, 201 insertions, 1 deletions
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index 4281da12720b..5ac0c50a312e 100644 --- a/core/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -1689,6 +1689,10 @@ public class PhoneStateListener { public final void onCarrierRoamingNtnModeChanged(boolean active) { // not supported on the deprecated interface - Use TelephonyCallback instead } + + public final void onCarrierRoamingNtnEligibleStateChanged(boolean eligible) { + // not supported on the deprecated interface - Use TelephonyCallback instead + } } private void log(String s) { diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java index b8b84d93c97c..c360e64c8c1a 100644 --- a/core/java/android/telephony/TelephonyCallback.java +++ b/core/java/android/telephony/TelephonyCallback.java @@ -653,6 +653,27 @@ public class TelephonyCallback { public static final int EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED = 42; /** + * Event for listening to changes in carrier roaming non-terrestrial network eligibility. + * + * @see CarrierRoamingNtnModeListener + * + * 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> + * + * @hide + */ + public static final int EVENT_CARRIER_ROAMING_NTN_ELIGIBLE_STATE_CHANGED = 43; + + /** * @hide */ @IntDef(prefix = {"EVENT_"}, value = { @@ -697,7 +718,8 @@ public class TelephonyCallback { EVENT_MEDIA_QUALITY_STATUS_CHANGED, EVENT_EMERGENCY_CALLBACK_MODE_CHANGED, EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED, - EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED + EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED, + EVENT_CARRIER_ROAMING_NTN_ELIGIBLE_STATE_CHANGED }) @Retention(RetentionPolicy.SOURCE) public @interface TelephonyEvent { @@ -1711,6 +1733,23 @@ public class TelephonyCallback { * {code false} otherwise. */ void onCarrierRoamingNtnModeChanged(boolean active); + + /** + * Callback invoked when carrier roaming non-terrestrial network eligibility changes. + * + * @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> + */ + default void onCarrierRoamingNtnEligibleStateChanged(boolean eligible) {} } /** @@ -2125,5 +2164,16 @@ public class TelephonyCallback { Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> listener.onCarrierRoamingNtnModeChanged(active))); } + + public void onCarrierRoamingNtnEligibleStateChanged(boolean eligible) { + if (!Flags.carrierRoamingNbIotNtn()) return; + + CarrierRoamingNtnModeListener listener = + (CarrierRoamingNtnModeListener) mTelephonyCallbackWeakRef.get(); + if (listener == null) return; + + Binder.withCleanCallingIdentity(() -> mExecutor.execute( + () -> listener.onCarrierRoamingNtnEligibleStateChanged(eligible))); + } } } diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index 6160fdb223f2..10f03c15310c 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -1091,6 +1091,34 @@ public class TelephonyRegistryManager { } /** + * Notify external listeners that device eligibility to connect to carrier roaming + * non-terrestrial network changed. + * + * @param subId subscription ID. + * @param eligible {@code true} when the device is eligible for satellite + * communication if all the following conditions are met: + * <ul> + * <li>Any 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, + * and the hysteresis timer defined by {@link CarrierConfigManager + * #KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT} is expired. </li> + * </ul> + * + * @hide + */ + public void notifyCarrierRoamingNtnEligibleStateChanged(int subId, boolean eligible) { + try { + sRegistry.notifyCarrierRoamingNtnEligibleStateChanged(subId, eligible); + } catch (RemoteException ex) { + // system server crash + throw ex.rethrowFromSystemServer(); + } + } + + /** * Processes potential event changes from the provided {@link TelephonyCallback}. * * @param telephonyCallback callback for monitoring callback changes to the telephony state. @@ -1246,6 +1274,11 @@ public class TelephonyRegistryManager { if (telephonyCallback instanceof TelephonyCallback.CarrierRoamingNtnModeListener) { eventList.add(TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED); } + + if (telephonyCallback instanceof TelephonyCallback.CarrierRoamingNtnModeListener) { + eventList.add(TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_ELIGIBLE_STATE_CHANGED); + } + return eventList; } diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl index 792c22348d77..f177e1473b6a 100644 --- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl +++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl @@ -82,4 +82,5 @@ oneway interface IPhoneStateListener { void onCallBackModeStopped(int type, int reason); void onSimultaneousCallingStateChanged(in int[] subIds); void onCarrierRoamingNtnModeChanged(in boolean active); + void onCarrierRoamingNtnEligibleStateChanged(in boolean eligible); } diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 04332cd758a6..e500a37abb53 100644 --- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -121,4 +121,5 @@ interface ITelephonyRegistry { void notifyCallbackModeStarted(int phoneId, int subId, int type); void notifyCallbackModeStopped(int phoneId, int subId, int type, int reason); void notifyCarrierRoamingNtnModeChanged(int subId, in boolean active); + void notifyCarrierRoamingNtnEligibleStateChanged(int subId, in boolean eligible); } diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 3633d0f9dd6f..33cf84220009 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -55,6 +55,7 @@ import android.telephony.Annotation.SrvccState; import android.telephony.BarringInfo; import android.telephony.CallQuality; import android.telephony.CallState; +import android.telephony.CarrierConfigManager; import android.telephony.CellIdentity; import android.telephony.CellInfo; import android.telephony.CellSignalStrength; @@ -426,6 +427,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { private boolean[] mSCBMStarted; private boolean[] mCarrierRoamingNtnMode = null; + private boolean[] mCarrierRoamingNtnEligible = null; /** * Per-phone map of precise data connection state. The key of the map is the pair of transport @@ -726,6 +728,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mSCBMReason = copyOf(mSCBMReason, mNumPhones); mSCBMStarted = copyOf(mSCBMStarted, mNumPhones); mCarrierRoamingNtnMode = copyOf(mCarrierRoamingNtnMode, mNumPhones); + mCarrierRoamingNtnEligible = copyOf(mCarrierRoamingNtnEligible, mNumPhones); // ds -> ss switch. if (mNumPhones < oldNumPhones) { cutListToSize(mCellInfo, mNumPhones); @@ -785,6 +788,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mSCBMReason[i] = TelephonyManager.STOP_REASON_UNKNOWN; mSCBMStarted[i] = false; mCarrierRoamingNtnMode[i] = false; + mCarrierRoamingNtnEligible[i] = false; } } } @@ -859,6 +863,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mSCBMReason = new int[numPhones]; mSCBMStarted = new boolean[numPhones]; mCarrierRoamingNtnMode = new boolean[numPhones]; + mCarrierRoamingNtnEligible = new boolean[numPhones]; for (int i = 0; i < numPhones; i++) { mCallState[i] = TelephonyManager.CALL_STATE_IDLE; @@ -903,6 +908,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mSCBMReason[i] = TelephonyManager.STOP_REASON_UNKNOWN; mSCBMStarted[i] = false; mCarrierRoamingNtnMode[i] = false; + mCarrierRoamingNtnEligible[i] = false; } mAppOps = mContext.getSystemService(AppOpsManager.class); @@ -1518,6 +1524,15 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { remove(r.binder); } } + if (events.contains( + TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_ELIGIBLE_STATE_CHANGED)) { + try { + r.callback.onCarrierRoamingNtnEligibleStateChanged( + mCarrierRoamingNtnEligible[r.phoneId]); + } catch (RemoteException ex) { + remove(r.binder); + } + } } } } @@ -3536,6 +3551,53 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } + /** + * Notify external listeners that device eligibility to connect to carrier roaming + * non-terrestrial network changed. + * + * @param subId subscription ID. + * @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(int subId, boolean eligible) { + if (!checkNotifyPermission("notifyCarrierRoamingNtnEligibleStateChanged")) { + log("notifyCarrierRoamingNtnEligibleStateChanged: caller does not have required " + + "permissions."); + return; + } + + if (VDBG) { + log("notifyCarrierRoamingNtnEligibleStateChanged: " + + "subId=" + subId + " eligible" + eligible); + } + + synchronized (mRecords) { + int phoneId = getPhoneIdFromSubId(subId); + mCarrierRoamingNtnEligible[phoneId] = eligible; + for (Record r : mRecords) { + if (r.matchTelephonyCallbackEvent( + TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_ELIGIBLE_STATE_CHANGED) + && idMatch(r, subId, phoneId)) { + try { + r.callback.onCarrierRoamingNtnEligibleStateChanged(eligible); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + } + @NeverCompile // Avoid size overhead of debugging code. @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { @@ -3589,6 +3651,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println("mECBMStarted=" + mECBMStarted[i]); pw.println("mSCBMReason=" + mSCBMReason[i]); pw.println("mSCBMStarted=" + mSCBMStarted[i]); + pw.println("mCarrierRoamingNtnMode=" + mCarrierRoamingNtnMode[i]); + pw.println("mCarrierRoamingNtnEligible=" + mCarrierRoamingNtnEligible[i]); // We need to obfuscate package names, and primitive arrays' native toString is ugly Pair<List<String>, int[]> carrierPrivilegeState = mCarrierPrivilegeStates.get(i); diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 61698dbebe7c..0468f48379cb 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -9992,6 +9992,51 @@ public class CarrierConfigManager { @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) public static final String KEY_SATELLITE_ESOS_SUPPORTED_BOOL = "satellite_esos_supported_bool"; + /** @hide */ + @IntDef({ + CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC, + CARRIER_ROAMING_NTN_CONNECT_MANUAL, + }) + public @interface CARRIER_ROAMING_NTN_CONNECT_TYPE {} + + /** + * Device can connect to carrier roaming non-terrestrial network automatically. + * @hide + */ + public static final int CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC = 0; + /** + * Device can connect to carrier roaming non-terrestrial network only if user manually triggers + * satellite connection. + * @hide + */ + public static final int CARRIER_ROAMING_NTN_CONNECT_MANUAL = 1; + /** + * Indicates carrier roaming non-terrestrial network connect type that the device can use to + * perform satellite communication. + * If this key is set to CARRIER_ROAMING_NTN_CONNECT_MANUAL then connect button will be + * displayed to user when the device is eligible to use carrier roaming + * non-terrestrial network. + * @hide + */ + public static final String KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT = + "carrier_roaming_ntn_connect_type_int"; + + /** + * The carrier roaming non-terrestrial network hysteresis time in seconds. + * + * If the device supports P2P satellite messaging which is defined by + * {@link CarrierConfigManager#KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE} + * and the device is in {@link ServiceState#STATE_OUT_OF_SERVICE}, not connected to Wi-Fi, + * then hysteresis timer defined by this key will start. + * After the timer is expired, device is marked as eligible for satellite communication. + * + * The default value is 180 seconds. + * + * @hide + */ + public static final String KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT = + "carrier_supported_satellite_notification_hysteresis_sec_int"; + /** * Indicating whether DUN APN should be disabled when the device is roaming. In that case, * the default APN (i.e. internet) will be used for tethering. @@ -11150,6 +11195,8 @@ public class CarrierConfigManager { sDefaults.putInt(KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT, (int) TimeUnit.SECONDS.toMillis(30)); sDefaults.putBoolean(KEY_SATELLITE_ESOS_SUPPORTED_BOOL, false); + sDefaults.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 0); + sDefaults.putInt(KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT, 180); sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, ""); sDefaults.putBoolean(KEY_SUPPORTS_CALL_COMPOSER_BOOL, false); sDefaults.putBoolean(KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL, false); |