Add SatelliteProxy

Bug: 260644201
Test: atest VtsHalRadioTargetTest
atest TelephonyManagerTestOnMockModem
MO/MT SMS, MMS, voice calls with live network

Change-Id: I6c8d6c5bb829cf378a17eb013cadf6f0289e747c
diff --git a/Android.bp b/Android.bp
index 4097571..5027635 100644
--- a/Android.bp
+++ b/Android.bp
@@ -90,6 +90,7 @@
         "android.hardware.radio.modem-V2-java",
         "android.hardware.radio.network-V2-java",
         "android.hardware.radio.sim-V2-java",
+        "android.hardware.radio.satellite-V1-java",
         "android.hardware.radio.voice-V2-java",
         "voip-common",
         "ims-common",
diff --git a/src/java/com/android/internal/telephony/BaseCommands.java b/src/java/com/android/internal/telephony/BaseCommands.java
index f36161a..e32101f 100644
--- a/src/java/com/android/internal/telephony/BaseCommands.java
+++ b/src/java/com/android/internal/telephony/BaseCommands.java
@@ -17,6 +17,8 @@
 
 package com.android.internal.telephony;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.AsyncResult;
@@ -118,6 +120,13 @@
     protected RegistrantList mConnectionSetupFailureRegistrants = new RegistrantList();
     protected RegistrantList mNotifyAnbrRegistrants = new RegistrantList();
     protected RegistrantList mTriggerImsDeregistrationRegistrants = new RegistrantList();
+    protected RegistrantList mPendingSatelliteMessageCountRegistrants = new RegistrantList();
+    protected RegistrantList mNewSatelliteMessagesRegistrants = new RegistrantList();
+    protected RegistrantList mSatelliteMessagesTransferCompleteRegistrants = new RegistrantList();
+    protected RegistrantList mSatellitePointingInfoChangedRegistrants = new RegistrantList();
+    protected RegistrantList mSatelliteModeChangedRegistrants = new RegistrantList();
+    protected RegistrantList mSatelliteRadioTechnologyChangedRegistrants = new RegistrantList();
+    protected RegistrantList mSatelliteProvisionStateChangedRegistrants = new RegistrantList();
 
     @UnsupportedAppUsage
     protected Registrant mGsmSmsRegistrant;
@@ -1188,4 +1197,81 @@
     public void unregisterForTriggerImsDeregistration(Handler h) {
         mTriggerImsDeregistrationRegistrants.remove(h);
     }
+
+    @Override
+    public void registerForPendingSatelliteMessageCount(
+            @NonNull Handler h, int what, @Nullable Object obj) {
+        mPendingSatelliteMessageCountRegistrants.add(h, what, obj);
+    }
+
+    @Override
+    public void unregisterForPendingSatelliteMessageCount(@NonNull Handler h) {
+        mPendingSatelliteMessageCountRegistrants.remove(h);
+    }
+
+    @Override
+    public void registerForNewSatelliteMessages(
+            @NonNull Handler h, int what, @Nullable Object obj) {
+        mNewSatelliteMessagesRegistrants.add(h, what, obj);
+    }
+
+    @Override
+    public void unregisterForNewSatelliteMessages(@NonNull Handler h) {
+        mNewSatelliteMessagesRegistrants.remove(h);
+    }
+
+    @Override
+    public void registerForSatelliteMessagesTransferComplete(@NonNull Handler h,
+            int what, @Nullable Object obj) {
+        mSatelliteMessagesTransferCompleteRegistrants.add(h, what, obj);
+    }
+
+    @Override
+    public void unregisterForSatelliteMessagesTransferComplete(@NonNull Handler h) {
+        mSatelliteMessagesTransferCompleteRegistrants.remove(h);
+    }
+
+    @Override
+    public void registerForSatellitePointingInfoChanged(@NonNull Handler h,
+            int what, @Nullable Object obj) {
+        mSatellitePointingInfoChangedRegistrants.add(h, what, obj);
+    }
+
+    @Override
+    public void unregisterForSatellitePointingInfoChanged(@NonNull Handler h) {
+        mSatellitePointingInfoChangedRegistrants.remove(h);
+    }
+
+    @Override
+    public void registerForSatelliteModeChanged(@NonNull Handler h,
+            int what, @Nullable Object obj) {
+        mSatelliteModeChangedRegistrants.add(h, what, obj);
+    }
+
+    @Override
+    public void unregisterForSatelliteModeChanged(@NonNull Handler h) {
+        mSatelliteModeChangedRegistrants.remove(h);
+    }
+
+    @Override
+    public void registerForSatelliteRadioTechnologyChanged(@NonNull Handler h,
+            int what, @Nullable Object obj) {
+        mSatelliteRadioTechnologyChangedRegistrants.add(h, what, obj);
+    }
+
+    @Override
+    public void unregisterForSatelliteRadioTechnologyChanged(@NonNull Handler h) {
+        mSatelliteRadioTechnologyChangedRegistrants.remove(h);
+    }
+
+    @Override
+    public void registerForSatelliteProvisionStateChanged(@NonNull Handler h,
+            int what, @Nullable Object obj) {
+        mSatelliteProvisionStateChangedRegistrants.add(h, what, obj);
+    }
+
+    @Override
+    public void unregisterForSatelliteProvisionStateChanged(@NonNull Handler h) {
+        mSatelliteProvisionStateChangedRegistrants.remove(h);
+    }
 }
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index 92f1696..915465f 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -3025,4 +3025,242 @@
      * @param result Callback message to receive the result.
      */
     default void isN1ModeEnabled(Message result) {}
+
+    /**
+     * Get feature capabilities supported by satellite.
+     *
+     * @param result Message that will be sent back to the requester
+     */
+    default void getSatelliteCapabilities(Message result) {}
+
+    /**
+     * Turn satellite modem on/off.
+     *
+     * @param result Message that will be sent back to the requester
+     * @param on {@code true} for turning on.
+     *           {@code false} for turning off.
+     */
+    default void setSatellitePower(Message result, boolean on) {}
+
+    /**
+     * Get satellite modem state.
+     *
+     * @param result Message that will be sent back to the requester
+     */
+    default void getSatellitePowerState(Message result) {}
+
+    /**
+     * Provision the subscription with a satellite provider. This is needed to register the
+     * subscription if the provider allows dynamic registration.
+     *
+     * @param result Message that will be sent back to the requester.
+     * @param imei IMEI of the SIM associated with the satellite modem.
+     * @param msisdn MSISDN of the SIM associated with the satellite modem.
+     * @param imsi IMSI of the SIM associated with the satellite modem.
+     * @param features List of features to be provisioned.
+     */
+    default void provisionSatelliteService(
+            Message result, String imei, String msisdn, String imsi, int[] features) {}
+
+    /**
+     * Add contacts that are allowed to be used for satellite communication. This is applicable for
+     * incoming messages as well.
+     *
+     * @param result Message that will be sent back to the requester.
+     * @param contacts List of allowed contacts to be added.
+     */
+    default void addAllowedSatelliteContacts(Message result, String[] contacts) {}
+
+    /**
+     * Remove contacts that are allowed to be used for satellite communication. This is applicable
+     * for incoming messages as well.
+     *
+     * @param result Message that will be sent back to the requester.
+     * @param contacts List of allowed contacts to be removed.
+     */
+    default void removeAllowedSatelliteContacts(Message result, String[] contacts) {}
+
+    /**
+     * Send text messages.
+     *
+     * @param result Message that will be sent back to the requester.
+     * @param messages List of messages in text format to be sent.
+     * @param destination The recipient of the message.
+     * @param latitude The current latitude of the device.
+     * @param longitude The current longitude of the device. The location (i.e., latitude and
+     *        longitude) of the device will be filled for emergency messages.
+     */
+    default void sendSatelliteMessages(Message result, String[] messages, String destination,
+            double latitude, double longitude) {}
+
+    /**
+     * Get pending messages.
+     *
+     * @param result Message that will be sent back to the requester.
+     */
+    default void getPendingSatelliteMessages(Message result) {}
+
+    /**
+     * Get current satellite registration mode.
+     *
+     * @param result Message that will be sent back to the requester.
+     */
+    default void getSatelliteMode(Message result) {}
+
+    /**
+     * Set the filter for what type of indication framework want to receive from modem.
+     *
+     * @param result Message that will be sent back to the requester.
+     * @param filterBitmask The filter bitmask identifying what type of indication Telephony
+     *                      framework wants to receive from modem.
+     */
+    default void setSatelliteIndicationFilter(Message result, int filterBitmask) {}
+
+    /**
+     * User started pointing to the satellite. Modem should continue to update the ponting input
+     * as user moves device.
+     *
+     * @param result Message that will be sent back to the requester.
+     */
+    default void startSendingSatellitePointingInfo(Message result) {}
+
+    /**
+     * Stop sending satellite pointing info to the framework.
+     *
+     * @param result Message that will be sent back to the requester.
+     */
+    default void stopSendingSatellitePointingInfo(Message result) {}
+
+    /**
+     * Get max number of characters per text message.
+     *
+     * @param result Message that will be sent back to the requester.
+     */
+    default void getMaxCharactersPerSatelliteTextMessage(Message result) {}
+
+    /**
+     * Get time for next visibility of satellite.
+     *
+     * @param result Message that will be sent back to the requester.
+     */
+    default void getTimeForNextSatelliteVisibility(Message result) {}
+
+    /**
+     * Registers for pending message count from satellite modem.
+     *
+     * @param h Handler for notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    default void registerForPendingSatelliteMessageCount(@NonNull Handler h,
+            int what, @Nullable Object obj) {}
+
+    /**
+     * Unregisters for pending message count from satellite modem.
+     *
+     * @param h Handler to be removed from the registrant list.
+     */
+    default void unregisterForPendingSatelliteMessageCount(@NonNull Handler h) {}
+
+    /**
+     * Registers for new messages from satellite modem.
+     *
+     * @param h Handler for notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    default void registerForNewSatelliteMessages(@NonNull Handler h,
+            int what, @Nullable Object obj) {}
+
+    /**
+     * Unregisters for new messages from satellite modem.
+     *
+     * @param h Handler to be removed from the registrant list.
+     */
+    default void unregisterForNewSatelliteMessages(@NonNull Handler h) {}
+
+    /**
+     * Registers for messages transfer complete from satellite modem.
+     *
+     * @param h Handler for notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    default void registerForSatelliteMessagesTransferComplete(@NonNull Handler h,
+            int what, @Nullable Object obj) {}
+
+    /**
+     * Unregisters for messages transfer complete from satellite modem.
+     *
+     * @param h Handler to be removed from the registrant list.
+     */
+    default void unregisterForSatelliteMessagesTransferComplete(@NonNull Handler h) {}
+
+    /**
+     * Registers for pointing info changed from satellite modem.
+     *
+     * @param h Handler for notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    default void registerForSatellitePointingInfoChanged(@NonNull Handler h,
+            int what, @Nullable Object obj) {}
+
+    /**
+     * Unregisters for pointing info changed from satellite modem.
+     *
+     * @param h Handler to be removed from the registrant list.
+     */
+    default void unregisterForSatellitePointingInfoChanged(@NonNull Handler h) {}
+
+    /**
+     * Registers for mode changed from satellite modem.
+     *
+     * @param h Handler for notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    default void registerForSatelliteModeChanged(@NonNull Handler h,
+            int what, @Nullable Object obj) {}
+
+    /**
+     * Unregisters for mode changed from satellite modem.
+     *
+     * @param h Handler to be removed from the registrant list.
+     */
+    default void unregisterForSatelliteModeChanged(@NonNull Handler h) {}
+
+    /**
+     * Registers for radio technology changed from satellite modem.
+     *
+     * @param h Handler for notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    default void registerForSatelliteRadioTechnologyChanged(@NonNull Handler h,
+            int what, @Nullable Object obj) {}
+
+    /**
+     * Unregisters for radio technology changed from satellite modem.
+     *
+     * @param h Handler to be removed from the registrant list.
+     */
+    default void unregisterForSatelliteRadioTechnologyChanged(@NonNull Handler h) {}
+
+    /**
+     * Registers for provision state changed from satellite modem.
+     *
+     * @param h Handler for notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    default void registerForSatelliteProvisionStateChanged(@NonNull Handler h,
+            int what, @Nullable Object obj) {}
+
+    /**
+     * Unregisters for provision state changed from satellite modem.
+     *
+     * @param h Handler to be removed from the registrant list.
+     */
+    default void unregisterForSatelliteProvisionStateChanged(@NonNull Handler h) {}
 }
diff --git a/src/java/com/android/internal/telephony/MockModem.java b/src/java/com/android/internal/telephony/MockModem.java
index a20e748..83417c5 100644
--- a/src/java/com/android/internal/telephony/MockModem.java
+++ b/src/java/com/android/internal/telephony/MockModem.java
@@ -21,6 +21,7 @@
 import static android.telephony.TelephonyManager.HAL_SERVICE_MESSAGING;
 import static android.telephony.TelephonyManager.HAL_SERVICE_MODEM;
 import static android.telephony.TelephonyManager.HAL_SERVICE_NETWORK;
+import static android.telephony.TelephonyManager.HAL_SERVICE_SATELLITE;
 import static android.telephony.TelephonyManager.HAL_SERVICE_SIM;
 import static android.telephony.TelephonyManager.HAL_SERVICE_VOICE;
 
@@ -44,6 +45,8 @@
     private static final String BIND_IRADIOVOICE = "android.telephony.mockmodem.iradiovoice";
     private static final String BIND_IRADIOIMS = "android.telephony.mockmodem.iradioims";
     private static final String BIND_IRADIOCONFIG = "android.telephony.mockmodem.iradioconfig";
+    private static final String BIND_IRADIOSATELLITE =
+            "android.telephony.mockmodem.iradiosatellite";
     private static final String PHONE_ID = "phone_id";
 
     private static final byte DEFAULT_PHONE_ID = 0x00;
@@ -65,6 +68,7 @@
     private IBinder mVoiceBinder;
     private IBinder mImsBinder;
     private IBinder mConfigBinder;
+    private IBinder mSatelliteBinder;
     private ServiceConnection mModemServiceConnection;
     private ServiceConnection mSimServiceConnection;
     private ServiceConnection mMessagingServiceConnection;
@@ -73,6 +77,7 @@
     private ServiceConnection mVoiceServiceConnection;
     private ServiceConnection mImsServiceConnection;
     private ServiceConnection mConfigServiceConnection;
+    private ServiceConnection mSatelliteServiceConnection;
 
     private byte mPhoneId;
     private String mTag;
@@ -115,6 +120,8 @@
                 mVoiceBinder = binder;
             } else if (mService == HAL_SERVICE_IMS) {
                 mImsBinder = binder;
+            } else if (mService == HAL_SERVICE_SATELLITE) {
+                mSatelliteBinder = binder;
             } else if (mService == RADIOCONFIG_SERVICE) {
                 mConfigBinder = binder;
             }
@@ -138,6 +145,8 @@
                 mVoiceBinder = null;
             } else if (mService == HAL_SERVICE_IMS) {
                 mImsBinder = null;
+            } else if (mService == HAL_SERVICE_SATELLITE) {
+                mSatelliteBinder = null;
             } else if (mService == RADIOCONFIG_SERVICE) {
                 mConfigBinder = null;
             }
@@ -179,6 +188,8 @@
                 return mVoiceBinder;
             case HAL_SERVICE_IMS:
                 return mImsBinder;
+            case HAL_SERVICE_SATELLITE:
+                return mSatelliteBinder;
             case RADIOCONFIG_SERVICE:
                 return mConfigBinder;
             default:
@@ -306,6 +317,20 @@
             } else {
                 Rlog.d(TAG, "IRadio Ims is bound");
             }
+        } else if (service == HAL_SERVICE_SATELLITE) {
+            if (mSatelliteBinder == null) {
+                mSatelliteServiceConnection = new MockModemConnection(HAL_SERVICE_SATELLITE);
+
+                boolean status =
+                        bindModuleToMockModemService(
+                                mPhoneId, BIND_IRADIOSATELLITE, mSatelliteServiceConnection);
+                if (!status) {
+                    Rlog.d(TAG, "IRadio Satellite bind fail");
+                    mSatelliteServiceConnection = null;
+                }
+            } else {
+                Rlog.d(TAG, "IRadio Satellite is bound");
+            }
         }
     }
 
@@ -368,6 +393,13 @@
                 mImsBinder = null;
                 Rlog.d(TAG, "unbind IRadio Ims");
             }
+        } else if (service == HAL_SERVICE_SATELLITE) {
+            if (mSatelliteServiceConnection != null) {
+                mContext.unbindService(mSatelliteServiceConnection);
+                mSatelliteServiceConnection = null;
+                mSatelliteBinder = null;
+                Rlog.d(TAG, "unbind IRadio Satellite");
+            }
         }
     }
 
@@ -391,6 +423,8 @@
                 return "voice";
             case HAL_SERVICE_IMS:
                 return "ims";
+            case HAL_SERVICE_SATELLITE:
+                return "satellite";
             case RADIOCONFIG_SERVICE:
                 return "config";
             default:
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 51fa529..fb23e83 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -22,6 +22,7 @@
 import static android.telephony.TelephonyManager.HAL_SERVICE_MODEM;
 import static android.telephony.TelephonyManager.HAL_SERVICE_NETWORK;
 import static android.telephony.TelephonyManager.HAL_SERVICE_RADIO;
+import static android.telephony.TelephonyManager.HAL_SERVICE_SATELLITE;
 import static android.telephony.TelephonyManager.HAL_SERVICE_SIM;
 import static android.telephony.TelephonyManager.HAL_SERVICE_VOICE;
 
@@ -226,7 +227,7 @@
 
     public static final int MIN_SERVICE_IDX = HAL_SERVICE_RADIO;
 
-    public static final int MAX_SERVICE_IDX = HAL_SERVICE_IMS;
+    public static final int MAX_SERVICE_IDX = HAL_SERVICE_SATELLITE;
 
     /**
      * An array of sets that records if services are disabled in the HAL for a specific phone ID
@@ -261,6 +262,8 @@
     private ModemIndication mModemIndication;
     private NetworkResponse mNetworkResponse;
     private NetworkIndication mNetworkIndication;
+    private SatelliteResponse mSatelliteResponse;
+    private SatelliteIndication mSatelliteIndication;
     private SimResponse mSimResponse;
     private SimIndication mSimIndication;
     private VoiceResponse mVoiceResponse;
@@ -746,7 +749,7 @@
     /**
      * Returns a {@link RadioDataProxy}, {@link RadioMessagingProxy}, {@link RadioModemProxy},
      * {@link RadioNetworkProxy}, {@link RadioSimProxy}, {@link RadioVoiceProxy},
-     * {@link RadioImsProxy}, or null if the service is not available.
+     * {@link RadioImsProxy}, {@link RadioSatelliteProxy}, or null if the service is not available.
      */
     @NonNull
     public <T extends RadioServiceProxy> T getRadioServiceProxy(Class<T> serviceClass,
@@ -772,6 +775,9 @@
         if (serviceClass == RadioImsProxy.class) {
             return (T) getRadioServiceProxy(HAL_SERVICE_IMS, result);
         }
+        if (serviceClass == RadioSatelliteProxy.class) {
+            return (T) getRadioServiceProxy(HAL_SERVICE_SATELLITE, result);
+        }
         riljLoge("getRadioServiceProxy: unrecognized " + serviceClass);
         return null;
     }
@@ -784,7 +790,8 @@
     @NonNull
     public synchronized RadioServiceProxy getRadioServiceProxy(int service, Message result) {
         if (!SubscriptionManager.isValidPhoneId(mPhoneId)) return mServiceProxies.get(service);
-        if (service == HAL_SERVICE_IMS && !isRadioServiceSupported(service)) {
+        if ((service >= HAL_SERVICE_IMS)
+                && !isRadioServiceSupported(service)) {
             return mServiceProxies.get(service);
         }
         if (!mIsCellularSupported) {
@@ -914,6 +921,21 @@
                                             .asInterface(binder)));
                         }
                         break;
+                    case HAL_SERVICE_SATELLITE:
+                        if (mMockModem == null) {
+                            binder = ServiceManager.waitForDeclaredService(
+                                    android.hardware.radio.satellite.IRadioSatellite.DESCRIPTOR
+                                            + "/" + HIDL_SERVICE_NAME[mPhoneId]);
+                        } else {
+                            binder = mMockModem.getServiceBinder(HAL_SERVICE_SATELLITE);
+                        }
+                        if (binder != null) {
+                            mHalVersion.put(service, ((RadioSatelliteProxy) serviceProxy).setAidl(
+                                    mHalVersion.get(service),
+                                    android.hardware.radio.satellite.IRadioSatellite.Stub
+                                            .asInterface(binder)));
+                        }
+                        break;
                 }
 
                 if (serviceProxy.isEmpty()
@@ -1038,6 +1060,12 @@
                                 ((RadioImsProxy) serviceProxy).getAidl().setResponseFunctions(
                                         mImsResponse, mImsIndication);
                                 break;
+                            case HAL_SERVICE_SATELLITE:
+                                mDeathRecipients.get(service).linkToDeath(
+                                        ((RadioSatelliteProxy) serviceProxy).getAidl().asBinder());
+                                ((RadioSatelliteProxy) serviceProxy).getAidl().setResponseFunctions(
+                                        mSatelliteResponse, mSatelliteIndication);
+                                break;
                         }
                     } else {
                         if (mHalVersion.get(service)
@@ -1152,6 +1180,8 @@
         mModemIndication = new ModemIndication(this);
         mNetworkResponse = new NetworkResponse(this);
         mNetworkIndication = new NetworkIndication(this);
+        mSatelliteResponse = new SatelliteResponse(this);
+        mSatelliteIndication = new SatelliteIndication(this);
         mSimResponse = new SimResponse(this);
         mSimIndication = new SimIndication(this);
         mVoiceResponse = new VoiceResponse(this);
@@ -1186,6 +1216,7 @@
             mServiceProxies.put(HAL_SERVICE_SIM, new RadioSimProxy());
             mServiceProxies.put(HAL_SERVICE_VOICE, new RadioVoiceProxy());
             mServiceProxies.put(HAL_SERVICE_IMS, new RadioImsProxy());
+            mServiceProxies.put(HAL_SERVICE_SATELLITE, new RadioSatelliteProxy());
         } else {
             mServiceProxies = proxies;
         }
@@ -1268,6 +1299,9 @@
             case HAL_SERVICE_IMS:
                 serviceName = android.hardware.radio.ims.IRadioIms.DESCRIPTOR;
                 break;
+            case HAL_SERVICE_SATELLITE:
+                serviceName = android.hardware.radio.satellite.IRadioSatellite.DESCRIPTOR;
+                break;
         }
 
         if (!serviceName.equals("")
@@ -5734,6 +5768,545 @@
         }
     }
 
+    /**
+     * Get feature capabilities supported by satellite.
+     *
+     * @param result Message that will be sent back to the requester
+     */
+    @Override
+    public void getSatelliteCapabilities(Message result) {
+        RadioSatelliteProxy radioSatelliteProxy =
+                getRadioServiceProxy(RadioSatelliteProxy.class, result);
+        if (radioSatelliteProxy.isEmpty()) return;
+        if (mHalVersion.get(HAL_SERVICE_SATELLITE).greaterOrEqual(RADIO_HAL_VERSION_2_0)) {
+            RILRequest rr = obtainRequest(RIL_REQUEST_GET_SATELLITE_CAPABILITIES, result,
+                    mRILDefaultWorkSource);
+
+            if (RILJ_LOGD) {
+                // Do not log function arg for privacy
+                riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+            }
+
+            try {
+                radioSatelliteProxy.getCapabilities(rr.mSerial);
+            } catch (RemoteException | RuntimeException e) {
+                handleRadioProxyExceptionForRR(
+                        HAL_SERVICE_SATELLITE, "getSatelliteCapabilities", e);
+            }
+        } else {
+            if (RILJ_LOGD) {
+                Rlog.d(RILJ_LOG_TAG, "getSatelliteCapabilities: REQUEST_NOT_SUPPORTED");
+            }
+            if (result != null) {
+                AsyncResult.forMessage(result, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                result.sendToTarget();
+            }
+        }
+    }
+
+    /**
+     * Turn satellite modem on/off.
+     *
+     * @param result Message that will be sent back to the requester
+     * @param on True for turning on.
+     *           False for turning off.
+     */
+    @Override
+    public void setSatellitePower(Message result, boolean on) {
+        RadioSatelliteProxy radioSatelliteProxy =
+                getRadioServiceProxy(RadioSatelliteProxy.class, result);
+        if (radioSatelliteProxy.isEmpty()) return;
+        if (mHalVersion.get(HAL_SERVICE_SATELLITE).greaterOrEqual(RADIO_HAL_VERSION_2_0)) {
+            RILRequest rr = obtainRequest(RIL_REQUEST_SET_SATELLITE_POWER, result,
+                    mRILDefaultWorkSource);
+
+            if (RILJ_LOGD) {
+                // Do not log function arg for privacy
+                riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+            }
+
+            try {
+                radioSatelliteProxy.setPower(rr.mSerial, on);
+            } catch (RemoteException | RuntimeException e) {
+                handleRadioProxyExceptionForRR(HAL_SERVICE_SATELLITE, "setSatellitePower", e);
+            }
+        } else {
+            if (RILJ_LOGD) {
+                Rlog.d(RILJ_LOG_TAG, "setSatellitePower: REQUEST_NOT_SUPPORTED");
+            }
+            if (result != null) {
+                AsyncResult.forMessage(result, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                result.sendToTarget();
+            }
+        }
+    }
+
+    /**
+     * Get satellite modem state.
+     *
+     * @param result Message that will be sent back to the requester
+     */
+    @Override
+    public void getSatellitePowerState(Message result) {
+        RadioSatelliteProxy radioSatelliteProxy =
+                getRadioServiceProxy(RadioSatelliteProxy.class, result);
+        if (radioSatelliteProxy.isEmpty()) return;
+        if (mHalVersion.get(HAL_SERVICE_SATELLITE).greaterOrEqual(RADIO_HAL_VERSION_2_0)) {
+            RILRequest rr = obtainRequest(RIL_REQUEST_GET_SATELLITE_POWER, result,
+                    mRILDefaultWorkSource);
+
+            if (RILJ_LOGD) {
+                // Do not log function arg for privacy
+                riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+            }
+
+            try {
+                radioSatelliteProxy.getPowerState(rr.mSerial);
+            } catch (RemoteException | RuntimeException e) {
+                handleRadioProxyExceptionForRR(HAL_SERVICE_SATELLITE, "getSatellitePowerState", e);
+            }
+        } else {
+            if (RILJ_LOGD) {
+                Rlog.d(RILJ_LOG_TAG, "getSatellitePowerState: REQUEST_NOT_SUPPORTED");
+            }
+            if (result != null) {
+                AsyncResult.forMessage(result, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                result.sendToTarget();
+            }
+        }
+    }
+
+    /**
+     * Provision the subscription with a satellite provider. This is needed to register the
+     * subscription if the provider allows dynamic registration.
+     *
+     * @param result Message that will be sent back to the requester.
+     * @param imei IMEI of the SIM associated with the satellite modem.
+     * @param msisdn MSISDN of the SIM associated with the satellite modem.
+     * @param imsi IMSI of the SIM associated with the satellite modem.
+     * @param features List of features to be provisioned.
+     */
+    @Override
+    public void provisionSatelliteService(
+            Message result, String imei, String msisdn, String imsi, int[] features) {
+        RadioSatelliteProxy radioSatelliteProxy =
+                getRadioServiceProxy(RadioSatelliteProxy.class, result);
+        if (radioSatelliteProxy.isEmpty()) return;
+        if (mHalVersion.get(HAL_SERVICE_SATELLITE).greaterOrEqual(RADIO_HAL_VERSION_2_0)) {
+            RILRequest rr = obtainRequest(RIL_REQUEST_PROVISION_SATELLITE_SERVICE, result,
+                    mRILDefaultWorkSource);
+
+            if (RILJ_LOGD) {
+                // Do not log function arg for privacy
+                riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+            }
+
+            try {
+                radioSatelliteProxy.provisionService(rr.mSerial, imei, msisdn, imsi, features);
+            } catch (RemoteException | RuntimeException e) {
+                handleRadioProxyExceptionForRR(
+                        HAL_SERVICE_SATELLITE, "provisionSatelliteService", e);
+            }
+        } else {
+            if (RILJ_LOGD) {
+                Rlog.d(RILJ_LOG_TAG, "provisionSatelliteService: REQUEST_NOT_SUPPORTED");
+            }
+            if (result != null) {
+                AsyncResult.forMessage(result, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                result.sendToTarget();
+            }
+        }
+    }
+
+    /**
+     * Add contacts that are allowed to be used for satellite communication. This is applicable for
+     * incoming messages as well.
+     *
+     * @param result Message that will be sent back to the requester.
+     * @param contacts List of allowed contacts to be added.
+     */
+    @Override
+    public void addAllowedSatelliteContacts(Message result, String[] contacts) {
+        RadioSatelliteProxy radioSatelliteProxy =
+                getRadioServiceProxy(RadioSatelliteProxy.class, result);
+        if (radioSatelliteProxy.isEmpty()) return;
+        if (mHalVersion.get(HAL_SERVICE_SATELLITE).greaterOrEqual(RADIO_HAL_VERSION_2_0)) {
+            RILRequest rr = obtainRequest(RIL_REQUEST_ADD_ALLOWED_SATELLITE_CONTACTS, result,
+                    mRILDefaultWorkSource);
+
+            if (RILJ_LOGD) {
+                // Do not log function arg for privacy
+                riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+            }
+
+            try {
+                radioSatelliteProxy.addAllowedSatelliteContacts(rr.mSerial, contacts);
+            } catch (RemoteException | RuntimeException e) {
+                handleRadioProxyExceptionForRR(HAL_SERVICE_SATELLITE,
+                        "addAllowedSatelliteContacts", e);
+            }
+        } else {
+            if (RILJ_LOGD) {
+                Rlog.d(RILJ_LOG_TAG, "addAllowedSatelliteContacts: REQUEST_NOT_SUPPORTED");
+            }
+            if (result != null) {
+                AsyncResult.forMessage(result, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                result.sendToTarget();
+            }
+        }
+    }
+
+    /**
+     * Remove contacts that are allowed to be used for satellite communication. This is applicable
+     * for incoming messages as well.
+     *
+     * @param result Message that will be sent back to the requester.
+     * @param contacts List of allowed contacts to be removed.
+     */
+    @Override
+    public void removeAllowedSatelliteContacts(Message result, String[] contacts) {
+        RadioSatelliteProxy radioSatelliteProxy =
+                getRadioServiceProxy(RadioSatelliteProxy.class, result);
+        if (radioSatelliteProxy.isEmpty()) return;
+        if (mHalVersion.get(HAL_SERVICE_SATELLITE).greaterOrEqual(RADIO_HAL_VERSION_2_0)) {
+            RILRequest rr = obtainRequest(RIL_REQUEST_REMOVE_ALLOWED_SATELLITE_CONTACTS, result,
+                    mRILDefaultWorkSource);
+
+            if (RILJ_LOGD) {
+                // Do not log function arg for privacy
+                riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+            }
+
+            try {
+                radioSatelliteProxy.removeAllowedSatelliteContacts(rr.mSerial, contacts);
+            } catch (RemoteException | RuntimeException e) {
+                handleRadioProxyExceptionForRR(HAL_SERVICE_SATELLITE,
+                        "removeAllowedSatelliteContacts", e);
+            }
+        } else {
+            if (RILJ_LOGD) {
+                Rlog.d(RILJ_LOG_TAG, "removeAllowedSatelliteContacts: REQUEST_NOT_SUPPORTED");
+            }
+            if (result != null) {
+                AsyncResult.forMessage(result, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                result.sendToTarget();
+            }
+        }
+    }
+
+    /**
+     * Send text messages.
+     *
+     * @param result Message that will be sent back to the requester.
+     * @param messages List of messages in text format to be sent.
+     * @param destination The recipient of the message.
+     * @param latitude The current latitude of the device.
+     * @param longitude The current longitude of the device.
+     */
+    @Override
+    public void sendSatelliteMessages(Message result, String[] messages, String destination,
+            double latitude, double longitude) {
+        RadioSatelliteProxy radioSatelliteProxy =
+                getRadioServiceProxy(RadioSatelliteProxy.class, result);
+        if (radioSatelliteProxy.isEmpty()) return;
+        if (mHalVersion.get(HAL_SERVICE_SATELLITE).greaterOrEqual(RADIO_HAL_VERSION_2_0)) {
+            RILRequest rr = obtainRequest(
+                    RIL_REQUEST_SEND_SATELLITE_MESSAGES, result, mRILDefaultWorkSource);
+
+            if (RILJ_LOGD) {
+                // Do not log function arg for privacy
+                riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+            }
+
+            try {
+                radioSatelliteProxy.sendMessages(rr.mSerial, messages, destination, latitude,
+                        longitude);
+            } catch (RemoteException | RuntimeException e) {
+                handleRadioProxyExceptionForRR(HAL_SERVICE_SATELLITE, "sendSatelliteMessages", e);
+            }
+        } else {
+            if (RILJ_LOGD) {
+                Rlog.d(RILJ_LOG_TAG, "sendSatelliteMessages: REQUEST_NOT_SUPPORTED");
+            }
+            if (result != null) {
+                AsyncResult.forMessage(result, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                result.sendToTarget();
+            }
+        }
+    }
+
+    /**
+     * Get pending messages.
+     *
+     * @param result Message that will be sent back to the requester.
+     */
+    @Override
+    public void getPendingSatelliteMessages(Message result) {
+        RadioSatelliteProxy radioSatelliteProxy =
+                getRadioServiceProxy(RadioSatelliteProxy.class, result);
+        if (radioSatelliteProxy.isEmpty()) return;
+        if (mHalVersion.get(HAL_SERVICE_SATELLITE).greaterOrEqual(RADIO_HAL_VERSION_2_0)) {
+            RILRequest rr = obtainRequest(RIL_REQUEST_GET_PENDING_SATELLITE_MESSAGES, result,
+                    mRILDefaultWorkSource);
+
+            if (RILJ_LOGD) {
+                // Do not log function arg for privacy
+                riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+            }
+
+            try {
+                radioSatelliteProxy.getPendingMessages(rr.mSerial);
+            } catch (RemoteException | RuntimeException e) {
+                handleRadioProxyExceptionForRR(
+                        HAL_SERVICE_SATELLITE, "getPendingSatelliteMessages", e);
+            }
+        } else {
+            if (RILJ_LOGD) {
+                Rlog.d(RILJ_LOG_TAG, "getPendingSatelliteMessages: REQUEST_NOT_SUPPORTED");
+            }
+            if (result != null) {
+                AsyncResult.forMessage(result, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                result.sendToTarget();
+            }
+        }
+    }
+
+    /**
+     * Get current satellite registration mode.
+     *
+     * @param result Message that will be sent back to the requester.
+     */
+    @Override
+    public void getSatelliteMode(Message result) {
+        RadioSatelliteProxy radioSatelliteProxy =
+                getRadioServiceProxy(RadioSatelliteProxy.class, result);
+        if (radioSatelliteProxy.isEmpty()) return;
+        if (mHalVersion.get(HAL_SERVICE_SATELLITE).greaterOrEqual(RADIO_HAL_VERSION_2_0)) {
+            RILRequest rr = obtainRequest(RIL_REQUEST_GET_SATELLITE_MODE, result,
+                    mRILDefaultWorkSource);
+
+            if (RILJ_LOGD) {
+                // Do not log function arg for privacy
+                riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+            }
+
+            try {
+                radioSatelliteProxy.getSatelliteMode(rr.mSerial);
+            } catch (RemoteException | RuntimeException e) {
+                handleRadioProxyExceptionForRR(HAL_SERVICE_SATELLITE, "getSatelliteMode", e);
+            }
+        } else {
+            if (RILJ_LOGD) {
+                Rlog.d(RILJ_LOG_TAG, "getSatelliteMode: REQUEST_NOT_SUPPORTED");
+            }
+            if (result != null) {
+                AsyncResult.forMessage(result, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                result.sendToTarget();
+            }
+        }
+    }
+
+    /**
+     * Set the filter for what type of indication framework want to receive from modem.
+     *
+     * @param result Message that will be sent back to the requester.
+     * @param filterBitmask The filter bitmask identifying what type of indication framework want to
+     *                         receive from modem.
+     */
+    @Override
+    public void setSatelliteIndicationFilter(Message result, int filterBitmask) {
+        RadioSatelliteProxy radioSatelliteProxy =
+                getRadioServiceProxy(RadioSatelliteProxy.class, result);
+        if (radioSatelliteProxy.isEmpty()) return;
+        if (mHalVersion.get(HAL_SERVICE_SATELLITE).greaterOrEqual(RADIO_HAL_VERSION_2_0)) {
+            RILRequest rr = obtainRequest(RIL_REQUEST_SET_SATELLITE_INDICATION_FILTER, result,
+                    mRILDefaultWorkSource);
+
+            if (RILJ_LOGD) {
+                // Do not log function arg for privacy
+                riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+            }
+
+            try {
+                radioSatelliteProxy.setIndicationFilter(rr.mSerial, filterBitmask);
+            } catch (RemoteException | RuntimeException e) {
+                handleRadioProxyExceptionForRR(HAL_SERVICE_SATELLITE,
+                        "setSatelliteIndicationFilter", e);
+            }
+        } else {
+            if (RILJ_LOGD) {
+                Rlog.d(RILJ_LOG_TAG, "setSatelliteIndicationFilter: REQUEST_NOT_SUPPORTED");
+            }
+            if (result != null) {
+                AsyncResult.forMessage(result, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                result.sendToTarget();
+            }
+        }
+    }
+
+    /**
+     * User started pointing to the satellite. Modem should continue to update the ponting input
+     * as user moves device.
+     *
+     * @param result Message that will be sent back to the requester.
+     */
+    @Override
+    public void startSendingSatellitePointingInfo(Message result) {
+        RadioSatelliteProxy radioSatelliteProxy =
+                getRadioServiceProxy(RadioSatelliteProxy.class, result);
+        if (radioSatelliteProxy.isEmpty()) return;
+        if (mHalVersion.get(HAL_SERVICE_SATELLITE).greaterOrEqual(RADIO_HAL_VERSION_2_0)) {
+            RILRequest rr = obtainRequest(RIL_REQUEST_START_SENDING_SATELLITE_POINTING_INFO, result,
+                    mRILDefaultWorkSource);
+
+            if (RILJ_LOGD) {
+                // Do not log function arg for privacy
+                riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+            }
+
+            try {
+                radioSatelliteProxy.startSendingSatellitePointingInfo(rr.mSerial);
+            } catch (RemoteException | RuntimeException e) {
+                handleRadioProxyExceptionForRR(HAL_SERVICE_SATELLITE,
+                        "startSendingSatellitePointingInfo", e);
+            }
+        } else {
+            if (RILJ_LOGD) {
+                Rlog.d(RILJ_LOG_TAG,
+                        "startSendingSatellitePointingInfo: REQUEST_NOT_SUPPORTED");
+            }
+            if (result != null) {
+                AsyncResult.forMessage(result, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                result.sendToTarget();
+            }
+        }
+    }
+
+    /**
+     * Stop pointing to satellite indications.
+     *
+     * @param result Message that will be sent back to the requester.
+     */
+    @Override
+    public void stopSendingSatellitePointingInfo(Message result) {
+        RadioSatelliteProxy radioSatelliteProxy =
+                getRadioServiceProxy(RadioSatelliteProxy.class, result);
+        if (radioSatelliteProxy.isEmpty()) return;
+        if (mHalVersion.get(HAL_SERVICE_SATELLITE).greaterOrEqual(RADIO_HAL_VERSION_2_0)) {
+            RILRequest rr = obtainRequest(RIL_REQUEST_STOP_SENDING_SATELLITE_POINTING_INFO, result,
+                    mRILDefaultWorkSource);
+
+            if (RILJ_LOGD) {
+                // Do not log function arg for privacy
+                riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+            }
+
+            try {
+                radioSatelliteProxy.stopSendingSatellitePointingInfo(rr.mSerial);
+            } catch (RemoteException | RuntimeException e) {
+                handleRadioProxyExceptionForRR(HAL_SERVICE_SATELLITE,
+                        "stopSendingSatellitePointingInfo", e);
+            }
+        } else {
+            if (RILJ_LOGD) {
+                Rlog.d(RILJ_LOG_TAG,
+                        "stopSendingSatellitePointingInfo: REQUEST_NOT_SUPPORTED");
+            }
+            if (result != null) {
+                AsyncResult.forMessage(result, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                result.sendToTarget();
+            }
+        }
+    }
+
+    /**
+     * Get max text limit for messaging per message.
+     *
+     * @param result Message that will be sent back to the requester.
+     */
+    @Override
+    public void getMaxCharactersPerSatelliteTextMessage(Message result) {
+        RadioSatelliteProxy radioSatelliteProxy =
+                getRadioServiceProxy(RadioSatelliteProxy.class, result);
+        if (radioSatelliteProxy.isEmpty()) return;
+        if (mHalVersion.get(HAL_SERVICE_SATELLITE).greaterOrEqual(RADIO_HAL_VERSION_2_0)) {
+            RILRequest rr = obtainRequest(RIL_REQUEST_GET_MAX_CHARACTERS_PER_SATELLITE_TEXT_MESSAGE,
+                    result, mRILDefaultWorkSource);
+
+            if (RILJ_LOGD) {
+                // Do not log function arg for privacy
+                riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+            }
+
+            try {
+                radioSatelliteProxy.getMaxCharactersPerTextMessage(rr.mSerial);
+            } catch (RemoteException | RuntimeException e) {
+                handleRadioProxyExceptionForRR(HAL_SERVICE_SATELLITE,
+                        "getMaxCharactersPerSatelliteTextMessage", e);
+            }
+        } else {
+            if (RILJ_LOGD) {
+                Rlog.d(RILJ_LOG_TAG,
+                        "getMaxCharactersPerSatelliteTextMessage: REQUEST_NOT_SUPPORTED");
+            }
+            if (result != null) {
+                AsyncResult.forMessage(result, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                result.sendToTarget();
+            }
+        }
+    }
+
+    /**
+     * Get time for next visibility of satellite.
+     *
+     * @param result Message that will be sent back to the requester.
+     */
+    @Override
+    public void getTimeForNextSatelliteVisibility(Message result) {
+        RadioSatelliteProxy radioSatelliteProxy =
+                getRadioServiceProxy(RadioSatelliteProxy.class, result);
+        if (radioSatelliteProxy.isEmpty()) return;
+        if (mHalVersion.get(HAL_SERVICE_SATELLITE).greaterOrEqual(RADIO_HAL_VERSION_2_0)) {
+            RILRequest rr = obtainRequest(RIL_REQUEST_GET_TIME_FOR_NEXT_SATELLITE_VISIBILITY,
+                    result, mRILDefaultWorkSource);
+
+            if (RILJ_LOGD) {
+                // Do not log function arg for privacy
+                riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+            }
+
+            try {
+                radioSatelliteProxy.getTimeForNextSatelliteVisibility(rr.mSerial);
+            } catch (RemoteException | RuntimeException e) {
+                handleRadioProxyExceptionForRR(HAL_SERVICE_SATELLITE,
+                        "getTimeForNextSatelliteVisibility", e);
+            }
+        } else {
+            if (RILJ_LOGD) {
+                Rlog.d(RILJ_LOG_TAG,
+                        "getTimeForNextSatelliteVisibility: REQUEST_NOT_SUPPORTED");
+            }
+            if (result != null) {
+                AsyncResult.forMessage(result, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                result.sendToTarget();
+            }
+        }
+    }
+
     //***** Private Methods
     /**
      * This is a helper function to be called when an indication callback is called for any radio
@@ -6524,6 +7097,7 @@
         pw.println(" " + mServiceProxies.get(HAL_SERVICE_SIM));
         pw.println(" " + mServiceProxies.get(HAL_SERVICE_VOICE));
         pw.println(" " + mServiceProxies.get(HAL_SERVICE_IMS));
+        pw.println(" " + mServiceProxies.get(HAL_SERVICE_SATELLITE));
         pw.println(" mWakeLock=" + mWakeLock);
         pw.println(" mWakeLockTimeout=" + mWakeLockTimeout);
         synchronized (mRequestList) {
@@ -6646,6 +7220,8 @@
                 return "VOICE";
             case HAL_SERVICE_IMS:
                 return "IMS";
+            case HAL_SERVICE_SATELLITE:
+                return "SATELLITE";
             default:
                 return "UNKNOWN:" + service;
         }
diff --git a/src/java/com/android/internal/telephony/RILUtils.java b/src/java/com/android/internal/telephony/RILUtils.java
index 95b0011..4064a5c 100644
--- a/src/java/com/android/internal/telephony/RILUtils.java
+++ b/src/java/com/android/internal/telephony/RILUtils.java
@@ -25,6 +25,7 @@
 import static android.telephony.TelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK;
 
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_ADD_ALLOWED_SATELLITE_CONTACTS;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_ALLOCATE_PDU_SESSION_ID;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_ALLOW_DATA;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_ANSWER;
@@ -90,12 +91,17 @@
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_IMEI;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_IMEISV;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_IMSI;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_MAX_CHARACTERS_PER_SATELLITE_TEXT_MESSAGE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_MODEM_STATUS;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_MUTE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_NEIGHBORING_CELL_IDS;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_PENDING_SATELLITE_MESSAGES;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_PHONE_CAPABILITY;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_RADIO_CAPABILITY;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SATELLITE_CAPABILITIES;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SATELLITE_MODE;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SATELLITE_POWER;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SIM_PHONEBOOK_CAPACITY;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SIM_PHONEBOOK_RECORDS;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SIM_STATUS;
@@ -103,6 +109,7 @@
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SLOT_STATUS;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SMSC_ADDRESS;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_TIME_FOR_NEXT_SATELLITE_VISIBILITY;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_UICC_APPLICATIONS_ENABLEMENT;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_USAGE_SETTING;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GSM_BROADCAST_ACTIVATION;
@@ -126,6 +133,7 @@
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_OEM_HOOK_RAW;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_OEM_HOOK_STRINGS;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_OPERATOR;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_PROVISION_SATELLITE_SERVICE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_PULL_LCEDATA;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_QUERY_AVAILABLE_NETWORKS;
@@ -137,12 +145,14 @@
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_QUERY_TTY_MODE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_RADIO_POWER;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_RELEASE_PDU_SESSION_ID;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_REMOVE_ALLOWED_SATELLITE_CONTACTS;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_REPORT_SMS_MEMORY_STATUS;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_RESET_RADIO;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SCREEN_STATE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SEND_ANBR_QUERY;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SEND_DEVICE_STATE;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SEND_SATELLITE_MESSAGES;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SEND_SMS;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SEND_SMS_EXPECT_MORE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SEND_USSD;
@@ -172,6 +182,8 @@
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_PREFERRED_DATA_MODEM;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_RADIO_CAPABILITY;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SATELLITE_INDICATION_FILTER;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SATELLITE_POWER;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SIM_CARD_POWER;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SMSC_ADDRESS;
@@ -197,6 +209,7 @@
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_START_KEEPALIVE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_START_LCE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_START_NETWORK_SCAN;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_START_SENDING_SATELLITE_POINTING_INFO;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_STK_GET_PROFILE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND;
@@ -207,6 +220,7 @@
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_STOP_KEEPALIVE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_STOP_LCE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_STOP_NETWORK_SCAN;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_STOP_SENDING_SATELLITE_POINTING_INFO;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_TRIGGER_EMERGENCY_NETWORK_SCAN;
@@ -241,6 +255,7 @@
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_LCEDATA_RECV;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_MODEM_RESTART;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_NETWORK_SCAN_RESULT;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_NEW_SATELLITE_MESSAGES;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_NITZ_TIME_RECEIVED;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_NOTIFY_ANBR;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_OEM_HOOK_RAW;
@@ -248,6 +263,7 @@
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_ON_USSD;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_ON_USSD_REQUEST;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_PCO_DATA;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_PENDING_SATELLITE_MESSAGE_COUNT;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_PHYSICAL_CHANNEL_CONFIG;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RADIO_CAPABILITY;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_REGISTRATION_FAILED;
@@ -267,6 +283,11 @@
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RESTRICTED_STATE_CHANGED;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RIL_CONNECTED;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RINGBACK_TONE;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SATELLITE_MESSAGES_TRANSFER_COMPLETE;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SATELLITE_MODE_CHANGED;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SATELLITE_POINTING_INFO_CHANGED;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SATELLITE_PROVISION_STATE_CHANGED;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SATELLITE_RADIO_TECHNOLOGY_CHANGED;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SIGNAL_STRENGTH;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SIM_REFRESH;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SIM_SMS_STORAGE_FULL;
@@ -353,6 +374,9 @@
 import android.telephony.ims.feature.MmTelFeature;
 import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.telephony.ims.stub.ImsRegistrationImplBase.ImsDeregistrationReason;
+import android.telephony.satellite.PointingInfo;
+import android.telephony.satellite.SatelliteCapabilities;
+import android.telephony.satellite.stub.SatelliteImplBase;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.SparseArray;
@@ -5297,6 +5321,34 @@
                 return "SET_N1_MODE_ENABLED";
             case RIL_REQUEST_IS_N1_MODE_ENABLED:
                 return "IS_N1_MODE_ENABLED";
+            case RIL_REQUEST_GET_SATELLITE_CAPABILITIES:
+                return "GET_SATELLITE_CAPABILITIES";
+            case RIL_REQUEST_SET_SATELLITE_POWER:
+                return "SET_SATELLITE_POWER";
+            case RIL_REQUEST_GET_SATELLITE_POWER:
+                return "GET_SATELLITE_POWER";
+            case RIL_REQUEST_PROVISION_SATELLITE_SERVICE:
+                return "PROVISION_SATELLITE_SERVICE";
+            case RIL_REQUEST_ADD_ALLOWED_SATELLITE_CONTACTS:
+                return "ADD_ALLOWED_SATELLITE_CONTACTS";
+            case RIL_REQUEST_REMOVE_ALLOWED_SATELLITE_CONTACTS:
+                return "REMOVE_ALLOWED_SATELLITE_CONTACTS";
+            case RIL_REQUEST_SEND_SATELLITE_MESSAGES:
+                return "SEND_SATELLITE_MESSAGES";
+            case RIL_REQUEST_GET_PENDING_SATELLITE_MESSAGES:
+                return "GET_PENDING_SATELLITE_MESSAGES";
+            case RIL_REQUEST_GET_SATELLITE_MODE:
+                return "GET_SATELLITE_MODE";
+            case RIL_REQUEST_SET_SATELLITE_INDICATION_FILTER:
+                return "SET_SATELLITE_INDICATION_FILTER";
+            case RIL_REQUEST_START_SENDING_SATELLITE_POINTING_INFO:
+                return "START_SENDING_SATELLITE_POINTING_INFO";
+            case RIL_REQUEST_STOP_SENDING_SATELLITE_POINTING_INFO:
+                return "STOP_SENDING_SATELLITE_POINTING_INFO";
+            case RIL_REQUEST_GET_MAX_CHARACTERS_PER_SATELLITE_TEXT_MESSAGE:
+                return "GET_MAX_CHARACTERS_PER_SATELLITE_TEXT_MESSAGE";
+            case RIL_REQUEST_GET_TIME_FOR_NEXT_SATELLITE_VISIBILITY:
+                return "GET_TIME_FOR_NEXT_SATELLITE_VISIBILITY";
             default:
                 return "<unknown request " + request + ">";
         }
@@ -5437,6 +5489,20 @@
                 return "UNSOL_NOTIFY_ANBR";
             case RIL_UNSOL_TRIGGER_IMS_DEREGISTRATION:
                 return "UNSOL_TRIGGER_IMS_DEREGISTRATION";
+            case RIL_UNSOL_PENDING_SATELLITE_MESSAGE_COUNT:
+                return "UNSOL_PENDING_SATELLITE_MESSAGE_COUNT";
+            case RIL_UNSOL_NEW_SATELLITE_MESSAGES:
+                return "UNSOL_NEW_SATELLITE_MESSAGES";
+            case RIL_UNSOL_SATELLITE_MESSAGES_TRANSFER_COMPLETE:
+                return "UNSOL_SATELLITE_MESSAGES_TRANSFER_COMPLETE";
+            case RIL_UNSOL_SATELLITE_POINTING_INFO_CHANGED:
+                return "UNSOL_SATELLITE_POINTING_INFO_CHANGED";
+            case RIL_UNSOL_SATELLITE_MODE_CHANGED:
+                return "UNSOL_SATELLITE_MODE_CHANGED";
+            case RIL_UNSOL_SATELLITE_RADIO_TECHNOLOGY_CHANGED:
+                return "UNSOL_SATELLITE_RADIO_TECHNOLOGY_CHANGED";
+            case RIL_UNSOL_SATELLITE_PROVISION_STATE_CHANGED:
+                return "UNSOL_SATELLITE_PROVISION_STATE_CHANGED";
             default:
                 return "<unknown response>";
         }
@@ -5822,6 +5888,88 @@
     }
 
     /**
+     * Convert android.hardware.radio.satellite.SatelliteCapabilities to
+     * android.telephony.satellite.SatelliteCapabilities
+     */
+    public static SatelliteCapabilities convertHalSatelliteCapabilities(
+            android.hardware.radio.satellite.SatelliteCapabilities capabilities) {
+        Set<Integer> supportedRadioTechnologies = new HashSet<>();
+        if (capabilities.supportedRadioTechnologies != null
+                && capabilities.supportedRadioTechnologies.length > 0) {
+            for (int technology : capabilities.supportedRadioTechnologies) {
+                supportedRadioTechnologies.add(technology);
+            }
+        }
+
+        Set<Integer> supportedFeatures = new HashSet<>();
+        if (capabilities.supportedFeatures != null
+                && capabilities.supportedFeatures.length > 0) {
+            for (int feature : capabilities.supportedFeatures) {
+                supportedFeatures.add(feature);
+            }
+        }
+        return new SatelliteCapabilities(supportedRadioTechnologies, capabilities.isAlwaysOn,
+                capabilities.needsPointingToSatellite, supportedFeatures,
+                capabilities.needsSeparateSimProfile);
+    }
+
+    /**
+     * Convert from android.hardware.radio.satellite.Feature to
+     * android.telephony.satellite.stub.SatelliteImplBase.Feature
+     */
+    public static int convertHalSatelliteFeature(int feature) {
+        switch (feature) {
+            case android.hardware.radio.satellite.SatelliteFeature.SOS_SMS:
+                return SatelliteImplBase.FEATURE_SOS_SMS;
+            case android.hardware.radio.satellite.SatelliteFeature.EMERGENCY_SMS:
+                return SatelliteImplBase.FEATURE_EMERGENCY_SMS;
+            case android.hardware.radio.satellite.SatelliteFeature.SMS:
+                return SatelliteImplBase.FEATURE_SMS;
+            case android.hardware.radio.satellite.SatelliteFeature.LOCATION_SHARING:
+                return SatelliteImplBase.FEATURE_LOCATION_SHARING;
+            default: return SatelliteImplBase.FEATURE_UNKNOWN;
+        }
+    }
+    /**
+     * Convert from android.hardware.radio.satellite.PointingInfo to
+     * android.telephony.satellite.stub.PointingInfo
+     */
+    public static PointingInfo convertHalSatellitePointingInfo(
+            android.hardware.radio.satellite.PointingInfo pointingInfo) {
+        return new PointingInfo(pointingInfo.satelliteAzimuthDegrees,
+                pointingInfo.satelliteElevationDegrees, pointingInfo.antennaAzimuthDegrees,
+                pointingInfo.antennaPitchDegrees, pointingInfo.antennaRollDegrees);
+    }
+
+    /**
+     * Convert array of android.hardware.radio.satellite.Feature to
+     * array of android.telephony.satellite.stub.SatelliteImplBase.Feature
+     */
+    public static int[] convertHalSatelliteFeatures(int[] features) {
+        int[] convertedFeatrures = new int[features.length];
+        for (int i = 0; i < features.length; i++) {
+            convertedFeatrures[i] = convertHalSatelliteFeature(features[i]);
+        }
+        return convertedFeatrures;
+    }
+
+    /**
+     * Convert from android.telephony.satellite.stub.PointingInfo to
+     * android.hardware.radio.satellite.PointingInfo
+     */
+    public static android.hardware.radio.satellite.PointingInfo convertToHalSatellitePointingInfo(
+            PointingInfo pointingInfo) {
+        android.hardware.radio.satellite.PointingInfo halPointingInfo =
+                new android.hardware.radio.satellite.PointingInfo();
+        halPointingInfo.satelliteAzimuthDegrees = pointingInfo.getSatelliteAzimuthDegrees();
+        halPointingInfo.satelliteElevationDegrees = pointingInfo.getSatelliteElevationDegrees();
+        halPointingInfo.antennaAzimuthDegrees = pointingInfo.getAntennaAzimuthDegrees();
+        halPointingInfo.antennaPitchDegrees = pointingInfo.getAntennaPitchDegrees();
+        halPointingInfo.antennaRollDegrees = pointingInfo.getAntennaRollDegrees();
+        return halPointingInfo;
+    }
+
+    /**
      * Converts the call state to HAL IMS call state.
      *
      * @param state The {@link Call.State}.
diff --git a/src/java/com/android/internal/telephony/RadioSatelliteProxy.java b/src/java/com/android/internal/telephony/RadioSatelliteProxy.java
new file mode 100644
index 0000000..1530c1a
--- /dev/null
+++ b/src/java/com/android/internal/telephony/RadioSatelliteProxy.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.os.RemoteException;
+import android.telephony.Rlog;
+
+/**
+ * A holder for IRadioSatellite.
+ * Use getAidl to get IRadioSatellite and call the AIDL implementations of the HAL APIs.
+ */
+public class RadioSatelliteProxy extends RadioServiceProxy {
+    private static final String TAG = "RadioSatelliteProxy";
+    private volatile android.hardware.radio.satellite.IRadioSatellite mRadioSatelliteProxy = null;
+
+    /**
+     * Sets IRadioSatellite as the AIDL implementation for RadioSatelliteProxy.
+     * @param halVersion Radio HAL version.
+     * @param radioSatellite IRadioSatellite implementation.
+     *
+     * @return updated HAL version.
+     */
+    public HalVersion setAidl(HalVersion halVersion,
+            android.hardware.radio.satellite.IRadioSatellite radioSatellite) {
+        mHalVersion = halVersion;
+        mRadioSatelliteProxy = radioSatellite;
+        mIsAidl = true;
+
+        try {
+            HalVersion newHalVersion;
+            int version = radioSatellite.getInterfaceVersion();
+            switch(version) {
+                default:
+                    newHalVersion = RIL.RADIO_HAL_VERSION_2_0;
+                    break;
+            }
+            Rlog.d(TAG, "AIDL version=" + version + ", halVersion=" + newHalVersion);
+
+            if (mHalVersion.less(newHalVersion)) {
+                mHalVersion = newHalVersion;
+            }
+        } catch (RemoteException e) {
+            Rlog.e(TAG, "setAidl: " + e);
+        }
+
+        Rlog.d(TAG, "AIDL initialized mHalVersion=" + mHalVersion);
+        return mHalVersion;
+    }
+
+    /**
+     * Gets the AIDL implementation of RadioSatelliteProxy.
+     * @return IRadioSatellite implementation.
+     */
+    public android.hardware.radio.satellite.IRadioSatellite getAidl() {
+        return mRadioSatelliteProxy;
+    }
+
+    /**
+     * Resets RadioSatelliteProxy.
+     */
+    @Override
+    public void clear() {
+        super.clear();
+        mRadioSatelliteProxy = null;
+    }
+
+    /**
+     * Checks whether a IRadioSatellite implementation exists.
+     * @return true if there is neither a HIDL nor AIDL implementation.
+     */
+    @Override
+    public boolean isEmpty() {
+        return mRadioProxy == null && mRadioSatelliteProxy == null;
+    }
+
+    /**
+     * Call IRadioSatellite#responseAcknowledgement
+     * @throws RemoteException Throws RemoteException when RadioSatellite service is not available.
+     */
+    @Override
+    public void responseAcknowledgement() throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mRadioSatelliteProxy.responseAcknowledgement();
+        }
+    }
+
+    /**
+     * Call IRadioSatellite#getCapabilities
+     * @param serial Serial number of request.
+     * @throws RemoteException Throws RemoteException when RadioSatellite service is not available.
+     */
+    public void getCapabilities(int serial) throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mRadioSatelliteProxy.getCapabilities(serial);
+        }
+    }
+
+    /**
+     * Call IRadioSatellite#setPower
+     * @param serial Serial number of request.
+     * @param on True for turning on.
+     *           False for turning off.
+     * @throws RemoteException Throws RemoteException when RadioSatellite service is not available.
+     */
+    public void setPower(int serial, boolean on) throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mRadioSatelliteProxy.setPower(serial, on);
+        }
+    }
+
+    /**
+     * Call IRadioSatellite#getPowerState
+     * @param serial Serial number of request.
+     * @throws RemoteException Throws RemoteException when RadioSatellite service is not available.
+     */
+    public void getPowerState(int serial) throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mRadioSatelliteProxy.getPowerState(serial);
+        }
+    }
+
+    /**
+     * Call IRadioSatellite#provisionService
+     * @param serial Serial number of request.
+     * @param imei IMEI of the SIM associated with the satellite modem.
+     * @param msisdn MSISDN of the SIM associated with the satellite modem.
+     * @param imsi IMSI of the SIM associated with the satellite modem.
+     * @param features List of features to be provisioned.
+     * @throws RemoteException Throws RemoteException when RadioSatellite service is not available.
+     */
+    public void provisionService(
+            int serial,
+            String imei,
+            String msisdn,
+            String imsi,
+            int[] features) throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mRadioSatelliteProxy.provisionService(serial, imei, msisdn, imsi, features);
+        }
+    }
+
+    /**
+     * Call IRadioSatellite#addAllowedSatelliteContacts
+     * @param serial Serial number of request.
+     * @param contacts List of allowed contacts to be added.
+     * @throws RemoteException Throws RemoteException when RadioSatellite service is not available.
+     */
+    public void addAllowedSatelliteContacts(int serial, String[] contacts) throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mRadioSatelliteProxy.addAllowedSatelliteContacts(serial, contacts);
+        }
+    }
+
+    /**
+     * Call IRadioSatellite#removeAllowedSatelliteContacts
+     * @param serial Serial number of request.
+     * @param contacts List of allowed contacts to be removed.
+     * @throws RemoteException Throws RemoteException when RadioSatellite service is not available.
+     */
+    public void removeAllowedSatelliteContacts(int serial, String[] contacts)
+            throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mRadioSatelliteProxy.removeAllowedSatelliteContacts(serial, contacts);
+        }
+    }
+
+    /**
+     * Call IRadioSatellite#sendMessages
+     * @param serial Serial number of request.
+     * @param messages List of messages in text format to be sent.
+     * @param destination The recipient of the message.
+     * @param latitude The current latitude of the device.
+     * @param longitude The current longitude of the device
+     * @throws RemoteException Throws RemoteException when RadioSatellite service is not available.
+     */
+    public void sendMessages(int serial, String[] messages, String destination, double latitude,
+            double longitude) throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mRadioSatelliteProxy.sendMessages(serial, messages, destination, latitude, longitude);
+        }
+    }
+
+    /**
+     * Call IRadioSatellite#getPendingMessages
+     * @param serial Serial number of request.
+     * @throws RemoteException Throws RemoteException when RadioSatellite service is not available.
+     */
+    public void getPendingMessages(int serial) throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mRadioSatelliteProxy.getPendingMessages(serial);
+        }
+    }
+
+    /**
+     * Call IRadioSatellite#getSatelliteMode
+     * @param serial Serial number of request.
+     * @throws RemoteException Throws RemoteException when RadioSatellite service is not available.
+     */
+    public void getSatelliteMode(int serial) throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mRadioSatelliteProxy.getSatelliteMode(serial);
+        }
+    }
+
+    /**
+     * Call IRadioSatellite#setIndicationFilter
+     * @param serial Serial number of request.
+     * @param filterBitmask The filter identifying what type of indication framework want to
+     *                         receive from modem.
+     * @throws RemoteException Throws RemoteException when RadioSatellite service is not available.
+     */
+    public void setIndicationFilter(int serial, int filterBitmask) throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mRadioSatelliteProxy.setIndicationFilter(serial, filterBitmask);
+        }
+    }
+
+    /**
+     * Call IRadioSatellite#startSendingSatellitePointingInfo
+     * @param serial Serial number of request.
+     * @throws RemoteException Throws RemoteException when RadioSatellite service is not available.
+     */
+    public void startSendingSatellitePointingInfo(int serial) throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mRadioSatelliteProxy.startSendingSatellitePointingInfo(serial);
+        }
+    }
+
+    /**
+     * Call IRadioSatellite#stopSendingSatellitePointingInfo
+     * @param serial Serial number of request.
+     * @throws RemoteException Throws RemoteException when RadioSatellite service is not available.
+     */
+    public void stopSendingSatellitePointingInfo(int serial) throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mRadioSatelliteProxy.stopSendingSatellitePointingInfo(serial);
+        }
+    }
+
+    /**
+     * Call IRadioSatellite#getMaxCharactersPerTextMessage
+     * @param serial Serial number of request.
+     * @throws RemoteException Throws RemoteException when RadioSatellite service is not available.
+     */
+    public void getMaxCharactersPerTextMessage(int serial) throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mRadioSatelliteProxy.getMaxCharactersPerTextMessage(serial);
+        }
+    }
+
+    /**
+     * Call IRadioSatellite#getTimeForNextSatelliteVisibility
+     * @param serial Serial number of request.
+     * @throws RemoteException Throws RemoteException when RadioSatellite service is not available.
+     */
+    public void getTimeForNextSatelliteVisibility(int serial) throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mRadioSatelliteProxy.getTimeForNextSatelliteVisibility(serial);
+        }
+    }
+}
diff --git a/src/java/com/android/internal/telephony/SatelliteIndication.java b/src/java/com/android/internal/telephony/SatelliteIndication.java
new file mode 100644
index 0000000..9b1b0e5
--- /dev/null
+++ b/src/java/com/android/internal/telephony/SatelliteIndication.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import static android.telephony.TelephonyManager.HAL_SERVICE_SATELLITE;
+
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_NEW_SATELLITE_MESSAGES;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_PENDING_SATELLITE_MESSAGE_COUNT;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SATELLITE_MESSAGES_TRANSFER_COMPLETE;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SATELLITE_MODE_CHANGED;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SATELLITE_POINTING_INFO_CHANGED;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SATELLITE_PROVISION_STATE_CHANGED;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SATELLITE_RADIO_TECHNOLOGY_CHANGED;
+
+import android.hardware.radio.satellite.IRadioSatelliteIndication;
+import android.os.AsyncResult;
+import android.telephony.satellite.stub.SatelliteImplBase;
+
+/**
+ * Interface declaring unsolicited radio indications for Satellite APIs.
+ */
+public class SatelliteIndication extends IRadioSatelliteIndication.Stub {
+    private final RIL mRil;
+
+    public SatelliteIndication(RIL ril) {
+        mRil = ril;
+    }
+
+    @Override
+    public String getInterfaceHash() {
+        return IRadioSatelliteIndication.HASH;
+    }
+
+    @Override
+    public int getInterfaceVersion() {
+        return IRadioSatelliteIndication.VERSION;
+    }
+
+    /**
+     * Indicates that satellite has pending messages for the device to be pulled.
+     *
+     * @param indicationType Type of radio indication
+     * @param count Number of pending messages.
+     */
+    public void onPendingMessageCount(int indicationType, int count) {
+        mRil.processIndication(HAL_SERVICE_SATELLITE, indicationType);
+
+        if (mRil.isLogOrTrace()) mRil.unsljLog(RIL_UNSOL_PENDING_SATELLITE_MESSAGE_COUNT);
+
+        if (mRil.mPendingSatelliteMessageCountRegistrants != null) {
+            mRil.mPendingSatelliteMessageCountRegistrants.notifyRegistrants(
+                    new AsyncResult(null, count, null));
+        }
+    }
+
+    /**
+     * Indicates new message received on device.
+     *
+     * @param indicationType Type of radio indication
+     * @param messages List of new messages received.
+     */
+    public void onNewMessages(int indicationType, String[] messages) {
+        mRil.processIndication(HAL_SERVICE_SATELLITE, indicationType);
+
+        if (mRil.isLogOrTrace()) mRil.unsljLog(RIL_UNSOL_NEW_SATELLITE_MESSAGES);
+
+        if (mRil.mNewSatelliteMessagesRegistrants != null) {
+            mRil.mNewSatelliteMessagesRegistrants.notifyRegistrants(
+                    new AsyncResult(null, messages, null));
+        }
+    }
+
+    /**
+     * Confirms that ongoing message transfer is complete.
+     *
+     * @param indicationType Type of radio indication
+     * @param complete True mean the transfer is complete.
+     *                 False means the transfer is not complete.
+     */
+    public void onMessagesTransferComplete(int indicationType, boolean complete) {
+        mRil.processIndication(HAL_SERVICE_SATELLITE, indicationType);
+
+        if (mRil.isLogOrTrace()) mRil.unsljLog(RIL_UNSOL_SATELLITE_MESSAGES_TRANSFER_COMPLETE);
+
+        if (mRil.mSatelliteMessagesTransferCompleteRegistrants != null) {
+            mRil.mSatelliteMessagesTransferCompleteRegistrants.notifyRegistrants(
+                    new AsyncResult(null, complete, null));
+        }
+    }
+
+    /**
+     * Indicate that satellite Pointing input has changed.
+     *
+     * @param indicationType Type of radio indication
+     * @param pointingInfo The current pointing info.
+     */
+    public void onSatellitePointingInfoChanged(int indicationType,
+            android.hardware.radio.satellite.PointingInfo pointingInfo) {
+        mRil.processIndication(HAL_SERVICE_SATELLITE, indicationType);
+
+        if (mRil.isLogOrTrace()) mRil.unsljLog(RIL_UNSOL_SATELLITE_POINTING_INFO_CHANGED);
+
+        if (mRil.mSatellitePointingInfoChangedRegistrants != null) {
+            mRil.mSatellitePointingInfoChangedRegistrants.notifyRegistrants(
+                    new AsyncResult(
+                            null,
+                            RILUtils.convertHalSatellitePointingInfo(pointingInfo),
+                            null));
+        }
+    }
+
+    /**
+     * Indicate that satellite mode has changed.
+     *
+     * @param indicationType Type of radio indication
+     * @param mode The current mode of the satellite modem.
+     */
+    public void onSatelliteModeChanged(int indicationType, @SatelliteImplBase.Mode int mode) {
+        mRil.processIndication(HAL_SERVICE_SATELLITE, indicationType);
+
+        if (mRil.isLogOrTrace()) mRil.unsljLog(RIL_UNSOL_SATELLITE_MODE_CHANGED);
+
+        if (mRil.mSatelliteModeChangedRegistrants != null) {
+            mRil.mSatelliteModeChangedRegistrants.notifyRegistrants(
+                    new AsyncResult(null, mode, null));
+        }
+    }
+
+    /**
+     * Indicate that satellite radio technology has changed.
+     *
+     * @param indicationType Type of radio indication
+     * @param technology The current technology of the satellite modem.
+     */
+    public void onSatelliteRadioTechnologyChanged(int indicationType,
+            @SatelliteImplBase.NTRadioTechnology int technology) {
+        mRil.processIndication(HAL_SERVICE_SATELLITE, indicationType);
+
+        if (mRil.isLogOrTrace()) mRil.unsljLog(RIL_UNSOL_SATELLITE_RADIO_TECHNOLOGY_CHANGED);
+
+        if (mRil.mSatelliteRadioTechnologyChangedRegistrants != null) {
+            mRil.mSatelliteRadioTechnologyChangedRegistrants.notifyRegistrants(
+                    new AsyncResult(null, technology, null));
+        }
+    }
+
+    /**
+     * Indicate that satellite provision state has changed.
+     *
+     * @param indicationType Type of radio indication
+     * @param provisioned True means the service is provisioned.
+     *                    False means the service is not provisioned.
+     * @param features List of Feature whose provision state has changed.
+     */
+    public void onProvisionStateChanged(int indicationType, boolean provisioned, int[] features) {
+        mRil.processIndication(HAL_SERVICE_SATELLITE, indicationType);
+
+        if (mRil.isLogOrTrace()) mRil.unsljLog(RIL_UNSOL_SATELLITE_PROVISION_STATE_CHANGED);
+
+        if (mRil.mSatelliteProvisionStateChangedRegistrants != null) {
+            mRil.mSatelliteProvisionStateChangedRegistrants.notifyRegistrants(
+                    new AsyncResult(null, RILUtils.convertHalSatelliteFeatures(features), null));
+        }
+    }
+}
diff --git a/src/java/com/android/internal/telephony/SatelliteResponse.java b/src/java/com/android/internal/telephony/SatelliteResponse.java
new file mode 100644
index 0000000..e33f38b
--- /dev/null
+++ b/src/java/com/android/internal/telephony/SatelliteResponse.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import static android.telephony.TelephonyManager.HAL_SERVICE_SATELLITE;
+
+import android.hardware.radio.RadioError;
+import android.hardware.radio.RadioResponseInfo;
+import android.hardware.radio.satellite.IRadioSatelliteResponse;
+import android.telephony.satellite.SatelliteCapabilities;
+import android.telephony.satellite.stub.SatelliteImplBase;
+
+/**
+ * Interface declaring response functions to solicited radio requests for Satellite APIs.
+ */
+public class SatelliteResponse extends IRadioSatelliteResponse.Stub {
+    private final RIL mRil;
+
+    public SatelliteResponse(RIL ril) {
+        mRil = ril;
+    }
+
+    /**
+     * Acknowledge the receipt of radio request sent to the vendor. This must be sent only for
+     * radio request which take long time to respond.
+     * For more details, refer https://source.android.com/devices/tech/connect/ril.html
+     * @param serial Serial no. of the request whose acknowledgement is sent.
+     */
+    public void acknowledgeRequest(int serial) {
+        mRil.processRequestAck(serial);
+    }
+    /**
+     * Response of the request getCapabilities.
+     *
+     * @param responseInfo Response info struct containing serial no. and error
+     * @param capabilities List of capabilities that the satellite modem supports.
+     */
+    public void getCapabilitiesResponse(RadioResponseInfo responseInfo,
+            android.hardware.radio.satellite.SatelliteCapabilities capabilities) {
+        RILRequest rr = mRil.processResponse(HAL_SERVICE_SATELLITE, responseInfo);
+
+        if (rr != null) {
+            SatelliteCapabilities convertedSatelliteCapabilities =
+                    RILUtils.convertHalSatelliteCapabilities(capabilities);
+            if (responseInfo.error == RadioError.NONE) {
+                RadioResponse.sendMessageResponse(rr.mResult, convertedSatelliteCapabilities);
+            }
+            mRil.processResponseDone(rr, responseInfo, convertedSatelliteCapabilities);
+        }
+    }
+
+    /**
+     * Response of the request setPower.
+     *
+     * @param responseInfo Response info struct containing serial no. and error
+     */
+    public void setPowerResponse(RadioResponseInfo responseInfo) {
+        RadioResponse.responseVoid(HAL_SERVICE_SATELLITE, mRil, responseInfo);
+    }
+
+    /**
+     * Response of the request getPowerState.
+     *
+     * @param responseInfo Response info struct containing serial no. and error
+     * @param on True means the modem is ON.
+     *           False means the modem is OFF.
+     */
+    public void getPowerStateResponse(RadioResponseInfo responseInfo, boolean on) {
+        RadioResponse.responseInts(HAL_SERVICE_SATELLITE, mRil, responseInfo, on ? 1 : 0);
+    }
+
+    /**
+     * Response of the request provisionService.
+     *
+     * @param responseInfo Response info struct containing serial no. and error
+     * @param provisioned True means the service is provisioned.
+     *                    False means the service is not provisioned.
+     */
+    public void provisionServiceResponse(RadioResponseInfo responseInfo, boolean provisioned) {
+        RadioResponse.responseInts(HAL_SERVICE_SATELLITE, mRil, responseInfo, provisioned ? 1 : 0);
+    }
+
+    /**
+     * Response of the request addAllowedSatelliteContacts.
+     *
+     * @param responseInfo Response info struct containing serial no. and error
+     */
+    public void addAllowedSatelliteContactsResponse(RadioResponseInfo responseInfo) {
+        RadioResponse.responseVoid(HAL_SERVICE_SATELLITE, mRil, responseInfo);
+    }
+
+    /**
+     * Response of the request removeAllowedSatelliteContacts.
+     *
+     * @param responseInfo Response info struct containing serial no. and error
+     */
+    public void removeAllowedSatelliteContactsResponse(RadioResponseInfo responseInfo) {
+        RadioResponse.responseVoid(HAL_SERVICE_SATELLITE, mRil, responseInfo);
+    }
+
+    /**
+     * Response of the request sendMessages.
+     *
+     * @param responseInfo Response info struct containing serial no. and error
+     */
+    public void sendMessagesResponse(RadioResponseInfo responseInfo) {
+        RadioResponse.responseVoid(HAL_SERVICE_SATELLITE, mRil, responseInfo);
+    }
+
+    /**
+     * Response of the request getPendingMessages.
+     *
+     * @param responseInfo Response info struct containing serial no. and error
+     * @param messages List of pending messages received.
+     */
+    public void getPendingMessagesResponse(RadioResponseInfo responseInfo, String[] messages) {
+        RILRequest rr = mRil.processResponse(HAL_SERVICE_SATELLITE, responseInfo);
+
+        if (rr != null) {
+            if (responseInfo.error == RadioError.NONE) {
+                RadioResponse.sendMessageResponse(rr.mResult, messages);
+            }
+            mRil.processResponseDone(rr, responseInfo, messages);
+        }
+    }
+
+    /**
+     * Response of the request getSatelliteMode.
+     *
+     * @param responseInfo Response info struct containing serial no. and error
+     * @param mode Current Mode of the satellite modem.
+     * @param technology The current technology of the satellite modem.
+     */
+    public void getSatelliteModeResponse(
+            RadioResponseInfo responseInfo, @SatelliteImplBase.Mode int mode,
+            @SatelliteImplBase.NTRadioTechnology int technology) {
+        RILRequest rr = mRil.processResponse(HAL_SERVICE_SATELLITE, responseInfo);
+
+        if (rr != null) {
+            int[] ret = new int[]{mode, technology};
+            if (responseInfo.error == RadioError.NONE) {
+                RadioResponse.sendMessageResponse(rr.mResult, ret);
+            }
+            mRil.processResponseDone(rr, responseInfo, ret);
+        }
+    }
+
+    /**
+     * Response of the request setIndicationFilter.
+     *
+     * @param responseInfo Response info struct containing serial no. and error
+     */
+    public void setIndicationFilterResponse(RadioResponseInfo responseInfo) {
+        RadioResponse.responseVoid(HAL_SERVICE_SATELLITE, mRil, responseInfo);
+    }
+
+    /**
+     * Response of the request startSendingSatellitePointingInfo.
+     *
+     * @param responseInfo Response info struct containing serial no. and error
+     */
+    public void startSendingSatellitePointingInfoResponse(RadioResponseInfo responseInfo) {
+        RadioResponse.responseVoid(HAL_SERVICE_SATELLITE, mRil, responseInfo);
+    }
+
+    /**
+     * Response of the request stopSendingSatellitePointingInfo.
+     *
+     * @param responseInfo Response info struct containing serial no. and error
+     */
+    public void stopSendingSatellitePointingInfoResponse(RadioResponseInfo responseInfo) {
+        RadioResponse.responseVoid(HAL_SERVICE_SATELLITE, mRil, responseInfo);
+    }
+
+    /**
+     * Response of the request getMaxCharactersPerTextMessage.
+     *
+     * @param responseInfo Response info struct containing serial no. and error
+     * @param charLimit Maximum number of characters in a text message that can be sent.
+     */
+    public void getMaxCharactersPerTextMessageResponse(
+            RadioResponseInfo responseInfo, int charLimit) {
+        RadioResponse.responseInts(HAL_SERVICE_SATELLITE, mRil, responseInfo, charLimit);
+    }
+
+    /**
+     * Response of the request getTimeForNextSatelliteVisibility.
+     *
+     * @param responseInfo Response info struct containing serial no. and error
+     * @param timeInSeconds The duration in seconds after which the satellite will be visible.
+     */
+    public void getTimeForNextSatelliteVisibilityResponse(
+            RadioResponseInfo responseInfo, int timeInSeconds) {
+        RadioResponse.responseInts(HAL_SERVICE_SATELLITE, mRil, responseInfo, timeInSeconds);
+    }
+
+    @Override
+    public String getInterfaceHash() {
+        return IRadioSatelliteResponse.HASH;
+    }
+
+    @Override
+    public int getInterfaceVersion() {
+        return IRadioSatelliteResponse.VERSION;
+    }
+}