Merge Android 24Q2 Release (ab/11526283) to aosp-main-future Bug: 337098550 Merged-In: If747db67f30bd8fc419b1042a3df90c633e36db4 Change-Id: Iba24ee2291cc4f6c6796e86383235e6ed45bb6c2
diff --git a/satellite_client/Android.bp b/satellite_client/Android.bp index 1661dcf..89c5c4b 100644 --- a/satellite_client/Android.bp +++ b/satellite_client/Android.bp
@@ -17,6 +17,10 @@ "app-compat-annotations", "unsupportedappusage", ], + required: [ + "android.telephony.satellite.xml", + ], + provides_uses_lib: "android.telephony.satellite", optimize: { ignore_warnings: false, proguard_flags_files: ["proguard.flags"], @@ -28,5 +32,4 @@ sub_dir: "sysconfig", system_ext_specific: true, src: "android.telephony.satellite.xml", -} - +} \ No newline at end of file
diff --git a/satellite_client/src/android/telephony/satellite/wrapper/SatelliteManagerWrapper.java b/satellite_client/src/android/telephony/satellite/wrapper/SatelliteManagerWrapper.java index ff36bf5..d230e8f 100644 --- a/satellite_client/src/android/telephony/satellite/wrapper/SatelliteManagerWrapper.java +++ b/satellite_client/src/android/telephony/satellite/wrapper/SatelliteManagerWrapper.java
@@ -16,6 +16,8 @@ package android.telephony.satellite.wrapper; +import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN; +import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS; import static android.telephony.satellite.SatelliteManager.SatelliteException; import android.annotation.CallbackExecutor; @@ -26,9 +28,13 @@ import android.content.Context; import android.os.CancellationSignal; import android.os.OutcomeReceiver; +import android.telephony.NetworkRegistrationInfo; +import android.telephony.ServiceState; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; import android.telephony.satellite.AntennaPosition; +import android.telephony.satellite.EnableRequestAttributes; import android.telephony.satellite.NtnSignalStrength; import android.telephony.satellite.NtnSignalStrengthCallback; import android.telephony.satellite.PointingInfo; @@ -37,8 +43,8 @@ import android.telephony.satellite.SatelliteDatagram; import android.telephony.satellite.SatelliteDatagramCallback; import android.telephony.satellite.SatelliteManager; +import android.telephony.satellite.SatelliteModemStateCallback; import android.telephony.satellite.SatelliteProvisionStateCallback; -import android.telephony.satellite.SatelliteStateCallback; import android.telephony.satellite.SatelliteTransmissionUpdateCallback; import com.android.internal.telephony.flags.Flags; @@ -47,12 +53,15 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.time.Duration; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.function.Consumer; +import java.util.stream.Collectors; /** * Wrapper for satellite operations such as provisioning, pointing, messaging, location sharing, @@ -69,8 +78,9 @@ SatelliteProvisionStateCallbackWrapper, SatelliteProvisionStateCallback> sSatelliteProvisionStateCallbackWrapperMap = new ConcurrentHashMap<>(); - private static final ConcurrentHashMap<SatelliteStateCallbackWrapper, SatelliteStateCallback> - sSatelliteStateCallbackWrapperMap = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap<SatelliteModemStateCallbackWrapper, + SatelliteModemStateCallback> sSatelliteModemStateCallbackWrapperMap = + new ConcurrentHashMap<>(); private static final ConcurrentHashMap< SatelliteTransmissionUpdateCallbackWrapper, SatelliteTransmissionUpdateCallback> @@ -86,10 +96,12 @@ private final SatelliteManager mSatelliteManager; private final SubscriptionManager mSubscriptionManager; + private final TelephonyManager mTelephonyManager; SatelliteManagerWrapper(Context context) { mSatelliteManager = context.getSystemService(SatelliteManager.class); mSubscriptionManager = context.getSystemService(SubscriptionManager.class); + mTelephonyManager = context.getSystemService(TelephonyManager.class); } /** @@ -312,6 +324,8 @@ public static final int SATELLITE_RESULT_REQUEST_IN_PROGRESS = 21; /** Satellite modem is currently busy due to which current request cannot be processed. */ public static final int SATELLITE_RESULT_MODEM_BUSY = 22; + /** Telephony process is not currently available or satellite is not supported. */ + public static final int SATELLITE_RESULT_ILLEGAL_STATE = 23; /** @hide */ @IntDef( @@ -339,7 +353,8 @@ SATELLITE_RESULT_NOT_AUTHORIZED, SATELLITE_RESULT_NOT_SUPPORTED, SATELLITE_RESULT_REQUEST_IN_PROGRESS, - SATELLITE_RESULT_MODEM_BUSY + SATELLITE_RESULT_MODEM_BUSY, + SATELLITE_RESULT_ILLEGAL_STATE }) @Retention(RetentionPolicy.SOURCE) public @interface SatelliteResult {} @@ -365,6 +380,34 @@ @Retention(RetentionPolicy.SOURCE) public @interface DeviceHoldPosition {} + /** + * Satellite communication restricted by user. + * @hide + */ + public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER = 0; + + /** + * Satellite communication restricted by geolocation. This can be + * triggered based upon geofence input provided by carrier to enable or disable satellite. + */ + public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION = 1; + + /** + * Satellite communication restricted by entitlement server. This can be triggered based on + * the EntitlementStatus value received from the entitlement server to enable or disable + * satellite. + */ + public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT = 2; + + /** @hide */ + @IntDef(prefix = "SATELLITE_COMMUNICATION_RESTRICTION_REASON_", value = { + SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, + SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION, + SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SatelliteCommunicationRestrictionReason {} + /** Exception from the satellite service containing the {@link SatelliteResult} error code. */ public static class SatelliteExceptionWrapper extends Exception { private final int mErrorCode; @@ -385,17 +428,20 @@ * enabled, this may also disable the cellular modem, and if the satellite modem is disabled, this * may also re-enable the cellular modem. */ - public void requestSatelliteEnabled( + public void requestEnabled( boolean enableSatellite, boolean enableDemoMode, + boolean isEmergency, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener) { - mSatelliteManager.requestSatelliteEnabled( - enableSatellite, enableDemoMode, executor, resultListener); + mSatelliteManager.requestEnabled(new EnableRequestAttributes.Builder(enableSatellite) + .setDemoMode(enableDemoMode) + .setEmergencyMode(isEmergency) + .build(), executor, resultListener); } /** Request to get whether the satellite modem is enabled. */ - public void requestIsSatelliteEnabled( + public void requestIsEnabled( @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteExceptionWrapper> callback) { OutcomeReceiver internalCallback = @@ -410,7 +456,7 @@ callback.onError(new SatelliteExceptionWrapper(exception.getErrorCode())); } }; - mSatelliteManager.requestIsSatelliteEnabled(executor, internalCallback); + mSatelliteManager.requestIsEnabled(executor, internalCallback); } /** Request to get whether the satellite service demo mode is enabled. */ @@ -432,8 +478,27 @@ mSatelliteManager.requestIsDemoModeEnabled(executor, internalCallback); } + /** Request to get whether the satellite service is enabled for emergency mode */ + public void requestIsEmergencyModeEnabled( + @NonNull @CallbackExecutor Executor executor, + @NonNull OutcomeReceiver<Boolean, SatelliteExceptionWrapper> callback) { + OutcomeReceiver internalCallback = + new OutcomeReceiver<Boolean, SatelliteException>() { + @Override + public void onResult(Boolean result) { + callback.onResult(result); + } + + @Override + public void onError(SatelliteException exception) { + callback.onError(new SatelliteExceptionWrapper(exception.getErrorCode())); + } + }; + mSatelliteManager.requestIsEmergencyModeEnabled(executor, internalCallback); + } + /** Request to get whether the satellite service is supported on the device. */ - public void requestIsSatelliteSupported( + public void requestIsSupported( @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteExceptionWrapper> callback) { OutcomeReceiver internalCallback = @@ -448,11 +513,11 @@ callback.onError(new SatelliteExceptionWrapper(exception.getErrorCode())); } }; - mSatelliteManager.requestIsSatelliteSupported(executor, internalCallback); + mSatelliteManager.requestIsSupported(executor, internalCallback); } /** Request to get the {@link SatelliteCapabilities} of the satellite service. */ - public void requestSatelliteCapabilities( + public void requestCapabilities( @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<SatelliteCapabilitiesWrapper, SatelliteExceptionWrapper> callback) { OutcomeReceiver internalCallback = @@ -472,7 +537,7 @@ callback.onError(new SatelliteExceptionWrapper(exception.getErrorCode())); } }; - mSatelliteManager.requestSatelliteCapabilities(executor, internalCallback); + mSatelliteManager.requestCapabilities(executor, internalCallback); } /** @@ -483,7 +548,7 @@ * Once satellite transmission updates begin, position and datagram transfer state updates * will be sent through {@link SatelliteTransmissionUpdateCallback}. */ - public void startSatelliteTransmissionUpdates( + public void startTransmissionUpdates( @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener, @NonNull SatelliteTransmissionUpdateCallbackWrapper callback) { @@ -517,7 +582,7 @@ }; sSatelliteTransmissionUpdateCallbackWrapperMap.put(callback, internalCallback); - mSatelliteManager.startSatelliteTransmissionUpdates(executor, resultListener, internalCallback); + mSatelliteManager.startTransmissionUpdates(executor, resultListener, internalCallback); } /** @@ -526,14 +591,14 @@ * callback is unregistered only on {@link #SATELLITE_RESULT_SUCCESS}. All other results that this * operation failed. */ - public void stopSatelliteTransmissionUpdates( + public void stopTransmissionUpdates( @NonNull SatelliteTransmissionUpdateCallbackWrapper callback, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener) { SatelliteTransmissionUpdateCallback internalCallback = sSatelliteTransmissionUpdateCallbackWrapperMap.get(callback); if (internalCallback != null) { - mSatelliteManager.stopSatelliteTransmissionUpdates( + mSatelliteManager.stopTransmissionUpdates( internalCallback, executor, resultListener); } } @@ -542,13 +607,13 @@ * Provision the device with a satellite provider. This is needed if the provider allows dynamic * registration. */ - public void provisionSatelliteService( + public void provisionService( @NonNull String token, @NonNull byte[] provisionData, @Nullable CancellationSignal cancellationSignal, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener) { - mSatelliteManager.provisionSatelliteService( + mSatelliteManager.provisionService( token, provisionData, cancellationSignal, executor, resultListener); } @@ -558,16 +623,16 @@ * SatelliteProvisionStateCallback#onSatelliteProvisionStateChanged(boolean)} should report as * deprovisioned. */ - public void deprovisionSatelliteService( + public void deprovisionService( @NonNull String token, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener) { - mSatelliteManager.deprovisionSatelliteService(token, executor, resultListener); + mSatelliteManager.deprovisionService(token, executor, resultListener); } /** Registers for the satellite provision state changed. */ @SatelliteResult - public int registerForSatelliteProvisionStateChanged( + public int registerForProvisionStateChanged( @NonNull @CallbackExecutor Executor executor, @NonNull SatelliteProvisionStateCallbackWrapper callback) { SatelliteProvisionStateCallback internalCallback = @@ -579,7 +644,7 @@ }; sSatelliteProvisionStateCallbackWrapperMap.put(callback, internalCallback); int result = - mSatelliteManager.registerForSatelliteProvisionStateChanged(executor, internalCallback); + mSatelliteManager.registerForProvisionStateChanged(executor, internalCallback); return result; } @@ -587,17 +652,17 @@ * Unregisters for the satellite provision state changed. If callback was not registered before, * the request will be ignored. */ - public void unregisterForSatelliteProvisionStateChanged( + public void unregisterForProvisionStateChanged( @NonNull SatelliteProvisionStateCallbackWrapper callback) { SatelliteProvisionStateCallback internalCallback = sSatelliteProvisionStateCallbackWrapperMap.get(callback); if (internalCallback != null) { - mSatelliteManager.unregisterForSatelliteProvisionStateChanged(internalCallback); + mSatelliteManager.unregisterForProvisionStateChanged(internalCallback); } } /** Request to get whether this device is provisioned with a satellite provider. */ - public void requestIsSatelliteProvisioned( + public void requestIsProvisioned( @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteExceptionWrapper> callback) { OutcomeReceiver internalCallback = @@ -612,24 +677,24 @@ callback.onError(new SatelliteExceptionWrapper(exception.getErrorCode())); } }; - mSatelliteManager.requestIsSatelliteProvisioned(executor, internalCallback); + mSatelliteManager.requestIsProvisioned(executor, internalCallback); } /** Registers for modem state changed from satellite modem. */ @SatelliteResult - public int registerForSatelliteModemStateChanged( + public int registerForModemStateChanged( @NonNull @CallbackExecutor Executor executor, - @NonNull SatelliteStateCallbackWrapper callback) { - SatelliteStateCallback internalCallback = - new SatelliteStateCallback() { + @NonNull SatelliteModemStateCallbackWrapper callback) { + SatelliteModemStateCallback internalCallback = + new SatelliteModemStateCallback() { public void onSatelliteModemStateChanged(@SatelliteModemState int state) { callback.onSatelliteModemStateChanged(state); } }; - sSatelliteStateCallbackWrapperMap.put(callback, internalCallback); + sSatelliteModemStateCallbackWrapperMap.put(callback, internalCallback); int result = - mSatelliteManager.registerForSatelliteModemStateChanged(executor, internalCallback); + mSatelliteManager.registerForModemStateChanged(executor, internalCallback); return result; } @@ -637,17 +702,18 @@ * Unregisters for modem state changed from satellite modem. If callback was not registered * before, the request will be ignored. */ - public void unregisterForSatelliteModemStateChanged( - @NonNull SatelliteStateCallbackWrapper callback) { - SatelliteStateCallback internalCallback = sSatelliteStateCallbackWrapperMap.get(callback); + public void unregisterForModemStateChanged( + @NonNull SatelliteModemStateCallbackWrapper callback) { + SatelliteModemStateCallback internalCallback = sSatelliteModemStateCallbackWrapperMap.get( + callback); if (internalCallback != null) { - mSatelliteManager.unregisterForSatelliteModemStateChanged(internalCallback); + mSatelliteManager.unregisterForModemStateChanged(internalCallback); } } /** Register to receive incoming datagrams over satellite. */ @SatelliteResult - public int registerForSatelliteDatagram( + public int registerForIncomingDatagram( @NonNull @CallbackExecutor Executor executor, @NonNull SatelliteDatagramCallbackWrapper callback) { SatelliteDatagramCallback internalCallback = @@ -666,7 +732,7 @@ } }; sSatelliteDatagramCallbackWrapperMap.put(callback, internalCallback); - int result = mSatelliteManager.registerForSatelliteDatagram(executor, internalCallback); + int result = mSatelliteManager.registerForIncomingDatagram(executor, internalCallback); return result; } @@ -674,18 +740,18 @@ * Unregister to stop receiving incoming datagrams over satellite. If callback was not registered * before, the request will be ignored. */ - public void unregisterForSatelliteDatagram(@NonNull SatelliteDatagramCallbackWrapper callback) { + public void unregisterForIncomingDatagram(@NonNull SatelliteDatagramCallbackWrapper callback) { SatelliteDatagramCallback internalCallback = sSatelliteDatagramCallbackWrapperMap.get(callback); if (internalCallback != null) { - mSatelliteManager.unregisterForSatelliteDatagram(internalCallback); + mSatelliteManager.unregisterForIncomingDatagram(internalCallback); } } /** Poll pending satellite datagrams over satellite. */ - public void pollPendingSatelliteDatagrams( + public void pollPendingDatagrams( @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener) { - mSatelliteManager.pollPendingSatelliteDatagrams(executor, resultListener); + mSatelliteManager.pollPendingDatagrams(executor, resultListener); } /** @@ -695,19 +761,19 @@ * input to this method. Datagram received here will be passed down to modem without any encoding * or encryption. */ - public void sendSatelliteDatagram( + public void sendDatagram( @DatagramType int datagramType, @NonNull SatelliteDatagramWrapper datagram, boolean needFullScreenPointingUI, @NonNull @CallbackExecutor Executor executor, @SatelliteResult @NonNull Consumer<Integer> resultListener) { SatelliteDatagram datagramInternal = new SatelliteDatagram(datagram.getSatelliteDatagram()); - mSatelliteManager.sendSatelliteDatagram( + mSatelliteManager.sendDatagram( datagramType, datagramInternal, needFullScreenPointingUI, executor, resultListener); } /** Request to get whether satellite communication is allowed for the current location. */ - public void requestIsSatelliteCommunicationAllowedForCurrentLocation( + public void requestIsCommunicationAllowedForCurrentLocation( @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Boolean, SatelliteExceptionWrapper> callback) { OutcomeReceiver internalCallback = @@ -722,7 +788,7 @@ callback.onError(new SatelliteExceptionWrapper(exception.getErrorCode())); } }; - mSatelliteManager.requestIsSatelliteCommunicationAllowedForCurrentLocation( + mSatelliteManager.requestIsCommunicationAllowedForCurrentLocation( executor, internalCallback); } @@ -781,15 +847,15 @@ @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<NtnSignalStrengthWrapper, SatelliteExceptionWrapper> callback) { OutcomeReceiver internalCallback = - new OutcomeReceiver<NtnSignalStrength, SatelliteException>() { - @Override - public void onResult(NtnSignalStrength result) { - callback.onResult(new NtnSignalStrengthWrapper(result.getLevel())); - } + new OutcomeReceiver<NtnSignalStrength, SatelliteException>() { + @Override + public void onResult(NtnSignalStrength result) { + callback.onResult(new NtnSignalStrengthWrapper(result.getLevel())); + } - @Override - public void onError(SatelliteException exception) { - callback.onError(new SatelliteExceptionWrapper(exception.getErrorCode())); + @Override + public void onError(SatelliteException exception) { + callback.onError(new SatelliteExceptionWrapper(exception.getErrorCode())); } }; mSatelliteManager.requestNtnSignalStrength(executor, internalCallback); @@ -799,7 +865,7 @@ @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) public void registerForNtnSignalStrengthChanged( @NonNull @CallbackExecutor Executor executor, - @NonNull NtnSignalStrengthCallbackWrapper callback) throws SatelliteException { + @NonNull NtnSignalStrengthCallbackWrapper callback) { NtnSignalStrengthCallback internalCallback = new NtnSignalStrengthCallback() { @Override @@ -809,11 +875,7 @@ } }; sNtnSignalStrengthCallbackWrapperMap.put(callback, internalCallback); - try { - mSatelliteManager.registerForNtnSignalStrengthChanged(executor, internalCallback); - } catch (SatelliteException ex) { - throw ex; - } + mSatelliteManager.registerForNtnSignalStrengthChanged(executor, internalCallback); } /** @@ -863,7 +925,7 @@ * @param callback The callback to handle the satellite capabilities changed event. */ @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) - public int registerForSatelliteCapabilitiesChanged( + public int registerForCapabilitiesChanged( @NonNull @CallbackExecutor Executor executor, @NonNull SatelliteCapabilitiesCallbackWrapper callback) { SatelliteCapabilitiesCallback internalCallback = @@ -875,7 +937,7 @@ transformToAntennaPositionWrapperMap( capabilities.getAntennaPositionMap()))); sSatelliteCapabilitiesCallbackWrapperMap.put(callback, internalCallback); - return mSatelliteManager.registerForSatelliteCapabilitiesChanged(executor, internalCallback); + return mSatelliteManager.registerForCapabilitiesChanged(executor, internalCallback); } /** @@ -885,15 +947,239 @@ * @param callback The callback that was passed to. */ @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) - public void unregisterForSatelliteCapabilitiesChanged( + public void unregisterForCapabilitiesChanged( @NonNull SatelliteCapabilitiesCallbackWrapper callback) { SatelliteCapabilitiesCallback internalCallback = sSatelliteCapabilitiesCallbackWrapperMap.get(callback); if (internalCallback != null) { - mSatelliteManager.unregisterForSatelliteCapabilitiesChanged(internalCallback); + mSatelliteManager.unregisterForCapabilitiesChanged(internalCallback); } } + /** + * Wrapper API to provide whether current network is non-terrestrial network or not. + * + * @param subId Subscription ID. + * + * @return {@code true} if current network is a non-terrestrial network, {@code false} otherwise. + * Note: The method returns {@code false} if the no available network info or any other error + * occurs. + */ + public boolean isNonTerrestrialNetwork(int subId) { + ServiceState ss = getServiceStateForSubscriptionId(subId); + + if (ss == null) { + logd("isNonTerrestrialNetwork(): ServiceState is null, return"); + return false; + } + + NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo(DOMAIN_PS, TRANSPORT_TYPE_WWAN); + if (nri == null) { + logd("isNonTerrestrialNetwork(): NetworkRegistrationInfo is null, return"); + return false; + } + + boolean isNonTerrestrialNetwork = nri.isNonTerrestrialNetwork(); + logd("isNonTerrestrialNetwork = " + isNonTerrestrialNetwork); + return isNonTerrestrialNetwork; + } + + /** + * Wrapper API to provide the list of available services. + * + * @param subId Subscription ID. + * + * @return the list of available service types for given subscription ID. + * Note: The method returns empty list if no service is available or any other error occurs. + */ + @NonNull + public List<Integer> getAvailableServices(int subId) { + ServiceState ss = getServiceStateForSubscriptionId(subId); + if (ss == null) { + logd("getAvailableServices(): ServiceState is null, return"); + return new ArrayList<>(); + } + + NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo(DOMAIN_PS, TRANSPORT_TYPE_WWAN); + if (nri == null) { + logd("getAvailableServices(): NetworkRegistrationInfo is null, return empty list"); + return new ArrayList<>(); + } + + List<Integer> serviceType = nri.getAvailableServices(); + logd("getAvailableServices() : serviceType=" + serviceType.stream().map( + Object::toString).collect(Collectors.joining(", "))); + return serviceType; + } + + /** + * Wrapper API to get whether device is connected to a non-terrestrial network. + * + * @param subId Subscription ID. + * + * @return {@code true} if device is connected to a non-terrestrial network, {@code false} + * otherwise. + * Note: The method returns {@code false} if the no available network info or any other error + * occurs. + */ + public boolean isUsingNonTerrestrialNetwork(int subId) { + ServiceState ss = getServiceStateForSubscriptionId(subId); + + if (ss == null) { + logd("isUsingNonTerrestrialNetwork(): ServiceState is null, return"); + return false; + } + + boolean isUsingNonTerrestrialNetwork = ss.isUsingNonTerrestrialNetwork(); + logd("isUsingNonTerrestrialNetwork() returns " + isUsingNonTerrestrialNetwork); + return isUsingNonTerrestrialNetwork; + } + + /** + * User request to enable or disable carrier supported satellite plmn scan and attach by modem. + * <p> + * This API should be called by only settings app to pass down the user input for + * enabling/disabling satellite. This user input will be persisted across device reboots. + * <p> + * Satellite will be enabled only when the following conditions are met: + * <ul> + * <li>Users want to enable it.</li> + * <li>There is no satellite communication restriction, which is added by + * {@link #addAttachRestrictionForCarrier(int, int, Executor, Consumer)}</li> + * <li>The carrier config {@link + * android.telephony.CarrierConfigManager#KEY_SATELLITE_ATTACH_SUPPORTED_BOOL} is set to + * {@code true}.</li> + * </ul> + * + * @param subId The subscription ID of the carrier. + * @param enableSatellite {@code true} to enable the satellite and {@code false} to disable. + * @param executor The executor on which the error code listener will be called. + * @param resultListener Listener for the {@link SatelliteResult} result of the operation. + * + * @throws SecurityException if the caller doesn't have required permission. + * @throws IllegalArgumentException if the subscription is invalid. + */ + public void requestAttachEnabledForCarrier(int subId, boolean enableSatellite, + @NonNull @CallbackExecutor Executor executor, + @SatelliteResult @NonNull Consumer<Integer> resultListener) { + mSatelliteManager.requestAttachEnabledForCarrier(subId, enableSatellite, executor, + resultListener); + } + + /** + * Request to get whether the carrier supported satellite plmn scan and attach by modem is + * enabled by user. + * + * @param subId The subscription ID of the carrier. + * @param executor The executor on which the callback will be called. + * @param callback The callback object to which the result will be delivered. + * If the request is successful, {@link OutcomeReceiver#onResult(Object)} + * will return a {@code boolean} with value {@code true} if the satellite + * is enabled and {@code false} otherwise. + * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)} + * will return a {@link SatelliteExceptionWrapper} with the + * {@link SatelliteResult}. + * + * @throws SecurityException if the caller doesn't have required permission. + * @throws IllegalStateException if the Telephony process is not currently available. + * @throws IllegalArgumentException if the subscription is invalid. + */ + public void requestIsAttachEnabledForCarrier(int subId, + @NonNull @CallbackExecutor Executor executor, + @NonNull OutcomeReceiver<Boolean, SatelliteExceptionWrapper> callback) { + OutcomeReceiver internalCallback = + new OutcomeReceiver<Boolean, SatelliteException>() { + @Override + public void onResult(Boolean result) { + callback.onResult(result); + } + + @Override + public void onError(SatelliteException exception) { + callback.onError(new SatelliteExceptionWrapper(exception.getErrorCode())); + } + }; + mSatelliteManager.requestIsAttachEnabledForCarrier(subId, executor, internalCallback); + } + + /** + * Add a restriction reason for disallowing carrier supported satellite plmn scan and attach + * by modem. + * + * @param subId The subscription ID of the carrier. + * @param reason Reason for disallowing satellite communication. + * @param executor The executor on which the error code listener will be called. + * @param resultListener Listener for the {@link SatelliteResult} result of the + * operation. + * + * @throws SecurityException if the caller doesn't have required permission. + * @throws IllegalArgumentException if the subscription is invalid. + */ + public void addAttachRestrictionForCarrier(int subId, + @SatelliteCommunicationRestrictionReason int reason, + @NonNull @CallbackExecutor Executor executor, + @SatelliteResult @NonNull Consumer<Integer> resultListener) { + mSatelliteManager.addAttachRestrictionForCarrier(subId, reason, executor, resultListener); + } + + /** + * Remove a restriction reason for disallowing carrier supported satellite plmn scan and attach + * by modem. + * + * @param subId The subscription ID of the carrier. + * @param reason Reason for disallowing satellite communication. + * @param executor The executor on which the error code listener will be called. + * @param resultListener Listener for the {@link SatelliteResult} result of the + * operation. + * + * @throws SecurityException if the caller doesn't have required permission. + * @throws IllegalArgumentException if the subscription is invalid. + */ + public void removeAttachRestrictionForCarrier(int subId, + @SatelliteCommunicationRestrictionReason int reason, + @NonNull @CallbackExecutor Executor executor, + @SatelliteResult @NonNull Consumer<Integer> resultListener) { + mSatelliteManager.removeAttachRestrictionForCarrier(subId, reason, executor, resultListener); + } + + /** + * Get reasons for disallowing satellite attach, as requested by + * {@link #addAttachRestrictionForCarrier(int, int, Executor, Consumer)} + * + * @param subId The subscription ID of the carrier. + * @return Set of reasons for disallowing satellite communication. + * + * @throws SecurityException if the caller doesn't have required permission. + * @throws IllegalStateException if the Telephony process is not currently available. + * @throws IllegalArgumentException if the subscription is invalid. + */ + @SatelliteCommunicationRestrictionReason + @NonNull public Set<Integer> getAttachRestrictionReasonsForCarrier(int subId) { + return mSatelliteManager.getAttachRestrictionReasonsForCarrier(subId); + } + + /** + * Get all satellite PLMNs for which attach is enable for carrier. + * + * @param subId subId The subscription ID of the carrier. + * + * @return List of plmn for carrier satellite service. If no plmn is available, empty list will + * be returned. + */ + @NonNull public List<String> getSatellitePlmnsForCarrier(int subId) { + return mSatelliteManager.getSatellitePlmnsForCarrier(subId); + } + + @Nullable + private ServiceState getServiceStateForSubscriptionId(int subId) { + if (!mSubscriptionManager.isValidSubscriptionId(subId)) { + return null; + } + + TelephonyManager tm = mTelephonyManager.createForSubscriptionId(subId); + return tm.getServiceState(); + } + private void logd(String message) { Rlog.d(TAG, message); }
diff --git a/satellite_client/src/android/telephony/satellite/wrapper/SatelliteStateCallbackWrapper.java b/satellite_client/src/android/telephony/satellite/wrapper/SatelliteModemStateCallbackWrapper.java similarity index 94% rename from satellite_client/src/android/telephony/satellite/wrapper/SatelliteStateCallbackWrapper.java rename to satellite_client/src/android/telephony/satellite/wrapper/SatelliteModemStateCallbackWrapper.java index 3d57fa0..450e48a 100644 --- a/satellite_client/src/android/telephony/satellite/wrapper/SatelliteStateCallbackWrapper.java +++ b/satellite_client/src/android/telephony/satellite/wrapper/SatelliteModemStateCallbackWrapper.java
@@ -17,7 +17,7 @@ package android.telephony.satellite.wrapper; /** A callback class for monitoring satellite modem state change events. */ -public interface SatelliteStateCallbackWrapper { +public interface SatelliteModemStateCallbackWrapper { /** * Called when satellite modem state changes.
diff --git a/ts43authentication/src/com/android/libraries/ts43authentication/AuthenticationOutcomeReceiver.java b/ts43authentication/src/com/android/libraries/ts43authentication/AuthenticationOutcomeReceiver.java new file mode 100644 index 0000000..37ad354 --- /dev/null +++ b/ts43authentication/src/com/android/libraries/ts43authentication/AuthenticationOutcomeReceiver.java
@@ -0,0 +1,44 @@ +/* + * 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.libraries.ts43authentication; + +/** + * Callback interface intended for use when an TS.43 authentication request may result in a failure. + * This interface may be used in cases where an asynchronous API may complete either with a value + * or with a {@link Throwable} that indicates an error. + * Functionally the same as an OutcomeReceiver, but creating a new class for backwards compatibility + * on devices with SDK < 31. + * + * @param <R> The type of the result that's being sent. + * @param <E> The type of the {@link Throwable} that contains more information about the error. + */ +public interface AuthenticationOutcomeReceiver <R, E extends Throwable> { + /** + * Called when the asynchronous operation succeeds and delivers a result value. + * + * @param result The value delivered by the asynchronous operation. + */ + void onResult(R result); + + /** + * Called when the asynchronous operation fails. The mode of failure is indicated by the + * {@link Throwable} passed as an argument to this method. + * + * @param error A subclass of {@link Throwable} with more details about the error that occurred. + */ + default void onError(E error) {} +}
diff --git a/ts43authentication/src/com/android/libraries/ts43authentication/Ts43AuthenticationLibrary.java b/ts43authentication/src/com/android/libraries/ts43authentication/Ts43AuthenticationLibrary.java index be3931d..da45671 100644 --- a/ts43authentication/src/com/android/libraries/ts43authentication/Ts43AuthenticationLibrary.java +++ b/ts43authentication/src/com/android/libraries/ts43authentication/Ts43AuthenticationLibrary.java
@@ -22,10 +22,10 @@ import android.content.pm.Signature; import android.content.pm.SigningInfo; import android.os.Binder; +import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; -import android.os.OutcomeReceiver; import android.os.PersistableBundle; import android.telephony.SubscriptionInfo; import android.util.Log; @@ -43,7 +43,6 @@ import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.ArrayList; -import java.util.HexFormat; import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.locks.ReentrantLock; @@ -131,12 +130,12 @@ @Nullable private final String mEntitlementVersion; private final String mAppId; private final Executor mExecutor; - private final OutcomeReceiver< + private final AuthenticationOutcomeReceiver< Ts43Authentication.Ts43AuthToken, AuthenticationException> mCallback; private EapAkaAuthenticationRequest(String appName, @Nullable String appVersion, int slotIndex, URL entitlementServerAddress, @Nullable String entitlementVersion, - String appId, Executor executor, OutcomeReceiver< + String appId, Executor executor, AuthenticationOutcomeReceiver< Ts43Authentication.Ts43AuthToken, AuthenticationException> callback) { mAppName = appName; mAppVersion = appVersion; @@ -157,12 +156,12 @@ @Nullable private final String mEntitlementVersion; private final String mAppId; private final Executor mExecutor; - private final OutcomeReceiver<URL, AuthenticationException> mCallback; + private final AuthenticationOutcomeReceiver<URL, AuthenticationException> mCallback; private OidcAuthenticationServerRequest(String appName, @Nullable String appVersion, int slotIndex, URL entitlementServerAddress, @Nullable String entitlementVersion, String appId, Executor executor, - OutcomeReceiver<URL, AuthenticationException> callback) { + AuthenticationOutcomeReceiver<URL, AuthenticationException> callback) { mAppName = appName; mAppVersion = appVersion; mSlotIndex = slotIndex; @@ -179,11 +178,12 @@ @Nullable private final String mEntitlementVersion; private final URL mAesUrl; private final Executor mExecutor; - private final OutcomeReceiver< + private final AuthenticationOutcomeReceiver< Ts43Authentication.Ts43AuthToken, AuthenticationException> mCallback; private OidcAuthenticationRequest(URL entitlementServerAddress, - @Nullable String entitlementVersion, URL aesUrl, Executor executor, OutcomeReceiver< + @Nullable String entitlementVersion, URL aesUrl, Executor executor, + AuthenticationOutcomeReceiver< Ts43Authentication.Ts43AuthToken, AuthenticationException> callback) { mEntitlementServerAddress = entitlementServerAddress; mEntitlementVersion = entitlementVersion; @@ -216,14 +216,17 @@ * Refer to GSMA Service Entitlement Configuration section 2.3. * @param executor The executor on which the callback will be called. * @param callback The callback to receive the results of the authentication request. - * If authentication is successful, {@link OutcomeReceiver#onResult(Object)} will return - * a {@link Ts43Authentication.Ts43AuthToken} with the token and validity. - * If the authentication fails, {@link OutcomeReceiver#onError(Throwable)} will return an + * If authentication is successful, + * {@link AuthenticationOutcomeReceiver#onResult(Object)} will return a + * {@link Ts43Authentication.Ts43AuthToken} with the token and validity. + * If the authentication fails, + * {@link AuthenticationOutcomeReceiver#onError(Throwable)} will return an * {@link AuthenticationException} with the failure details. */ public void requestEapAkaAuthentication(PersistableBundle configs, String packageName, @Nullable String appVersion, int slotIndex, URL entitlementServerAddress, - @Nullable String entitlementVersion, String appId, Executor executor, OutcomeReceiver< + @Nullable String entitlementVersion, String appId, Executor executor, + AuthenticationOutcomeReceiver< Ts43Authentication.Ts43AuthToken, AuthenticationException> callback) { String[] allowedPackageInfo = configs.getStringArray(KEY_ALLOWED_CERTIFICATES_STRING_ARRAY); String certificate = getMatchingCertificate(allowedPackageInfo, packageName); @@ -245,8 +248,8 @@ * The client should present the content of the URL to the user to continue the authentication * process. After receiving a response from the authentication server, the client can call * {@link #requestOidcAuthentication( - * PersistableBundle, String, URL, String, URL, Executor, OutcomeReceiver)} to get the - * authentication token. + * PersistableBundle, String, URL, String, URL, Executor, AuthenticationOutcomeReceiver)} to get + * the authentication token. * * @param configs The configurations that should be applied to this authentication request. * The keys of the bundle must be in {@link ConfigurationKey}. @@ -267,18 +270,18 @@ * Refer to GSMA Service Entitlement Configuration section 2.3. * @param executor The executor on which the callback will be called. * @param callback The callback to receive the results of the authentication server request. - * If the request is successful, {@link OutcomeReceiver#onResult(Object)} will return a - * {@link URL} with all the required parameters for the client to launch a user interface - * for users to complete the authentication process. The parameters in URL include - * {@code client_id}, {@code redirect_uri}, {@code state}, and {@code nonce}. - * If the authentication fails, {@link OutcomeReceiver#onError(Throwable)} will return an - * {@link AuthenticationException} with the failure details. + * If the request is successful, {@link AuthenticationOutcomeReceiver#onResult(Object)} + * will return a {@link URL} with all the required parameters for the client to launch a + * user interface for users to complete the authentication process. The parameters in URL + * include {@code client_id}, {@code redirect_uri}, {@code state}, and {@code nonce}. + * If the authentication fails, {@link AuthenticationOutcomeReceiver#onError(Throwable)} + * will return an {@link AuthenticationException} with the failure details. */ public void requestOidcAuthenticationServer(PersistableBundle configs, String packageName, @Nullable String appVersion, int slotIndex, URL entitlementServerAddress, @Nullable String entitlementVersion, String appId, Executor executor, - OutcomeReceiver<URL, AuthenticationException> callback) { + AuthenticationOutcomeReceiver<URL, AuthenticationException> callback) { String[] allowedPackageInfo = configs.getStringArray(KEY_ALLOWED_CERTIFICATES_STRING_ARRAY); String certificate = getMatchingCertificate(allowedPackageInfo, packageName); if (isCallingPackageAllowed(allowedPackageInfo, packageName, certificate)) { @@ -309,15 +312,16 @@ * URL include the OIDC authentication code {@code code} and {@code state}. * @param executor The executor on which the callback will be called. * @param callback The callback to receive the results of the authentication request. - * If authentication is successful, {@link OutcomeReceiver#onResult(Object)} will return - * a {@link Ts43Authentication.Ts43AuthToken} with the token and validity. - * If the authentication fails, {@link OutcomeReceiver#onError(Throwable)} will return an - * {@link AuthenticationException} with the failure details. + * If authentication is successful, + * {@link AuthenticationOutcomeReceiver#onResult(Object)} will return a + * {@link Ts43Authentication.Ts43AuthToken} with the token and validity. + * If the authentication fails, {@link AuthenticationOutcomeReceiver#onError(Throwable)} + * will return an {@link AuthenticationException} with the failure details. */ public void requestOidcAuthentication(PersistableBundle configs, String packageName, URL entitlementServerAddress, @Nullable String entitlementVersion, URL aesUrl, Executor executor, - OutcomeReceiver< + AuthenticationOutcomeReceiver< Ts43Authentication.Ts43AuthToken, AuthenticationException> callback) { String[] allowedPackageInfo = configs.getStringArray(KEY_ALLOWED_CERTIFICATES_STRING_ARRAY); String certificate = getMatchingCertificate(allowedPackageInfo, packageName); @@ -372,7 +376,7 @@ for (Signature signature : signatures) { byte[] signatureHash = md.digest(signature.toByteArray()); for (String certificate : allowedCertificates) { - byte[] certificateHash = HexFormat.of().parseHex(certificate); + byte[] certificateHash = hexStringToBytes(certificate); if (Arrays.equals(signatureHash, certificateHash)) { Log.d(TAG, "Found matching certificate for package " + packageName + ": " + certificate); @@ -412,8 +416,14 @@ @Nullable private Signature[] getMainPackageSignatures(String packageName) { PackageInfo packageInfo; try { - packageInfo = mPackageManager.getPackageInfo(packageName, - PackageManager.PackageInfoFlags.of(PackageManager.GET_SIGNING_CERTIFICATES)); + if (Build.VERSION.SDK_INT < 33) { + packageInfo = mPackageManager.getPackageInfo(packageName, + PackageManager.GET_SIGNING_CERTIFICATES); + } else { + packageInfo = mPackageManager.getPackageInfo(packageName, + PackageManager.PackageInfoFlags.of( + PackageManager.GET_SIGNING_CERTIFICATES)); + } } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, "Unable to find package name: " + packageName); return null; @@ -439,6 +449,25 @@ return signatures; } + @Nullable private byte[] hexStringToBytes(@Nullable String hex) { + if (hex == null) { + return null; + } + + int length = hex.length(); + byte[] ret = new byte[length / 2]; + + for (int i = 0; i < length; i += 2) { + ret[i / 2] = + (byte) ((hexCharToInt(hex.charAt(i)) << 4) | hexCharToInt(hex.charAt(i + 1))); + } + return ret; + } + + private int hexCharToInt(char hex) { + return Integer.parseInt(String.valueOf(hex), 16); + } + private boolean isCallingPackageAllowed(@Nullable String[] allowedPackageInfo, String packageName, @Nullable String certificate) { // Check that the package name matches that of the calling package.