From d8c23e3f4181e29e544066ee1f185d1549ad6a6f Mon Sep 17 00:00:00 2001 From: Aishwarya Mallampati Date: Wed, 8 Feb 2023 23:04:30 +0000 Subject: [PATCH] Added Satellite Messaging APIs. The following apis are added in this CL: - registerForSatelliteStateChange() - unregisterForSatelliteStateChange() - registerForSatelliteDatagram() - unregisterForSatelliteDatagram() - getPendingSatelliteDatagrams() Bug: 260896985 Test: atest SatelliteManagerTest Change-Id: Ice9e97f61a6adffbab8ee53dea3b54a8d12ce174 --- .../satellite/ISatelliteStateListener.aidl | 4 + .../satellite/SatelliteCallback.java | 60 ++++++ .../satellite/SatelliteDatagram.aidl | 19 ++ .../satellite/SatelliteDatagram.java | 75 +++++++ .../telephony/satellite/SatelliteManager.java | 203 ++++++++++++++++++ .../internal/telephony/ITelephony.aidl | 50 +++++ 6 files changed, 411 insertions(+) create mode 100644 telephony/java/android/telephony/satellite/SatelliteDatagram.aidl create mode 100644 telephony/java/android/telephony/satellite/SatelliteDatagram.java diff --git a/telephony/java/android/telephony/satellite/ISatelliteStateListener.aidl b/telephony/java/android/telephony/satellite/ISatelliteStateListener.aidl index 6fb09799dacf9..e735285436982 100644 --- a/telephony/java/android/telephony/satellite/ISatelliteStateListener.aidl +++ b/telephony/java/android/telephony/satellite/ISatelliteStateListener.aidl @@ -17,6 +17,7 @@ package android.telephony.satellite; import android.telephony.satellite.PointingInfo; +import android.telephony.satellite.SatelliteDatagram; /** * Interface for satellite state listener. @@ -26,4 +27,7 @@ oneway interface ISatelliteStateListener { void onSatelliteProvisionStateChanged(in int[] features, in boolean provisioned); void onSatellitePositionUpdate(in PointingInfo pointingInfo); void onMessageTransferStateUpdate(in int state); + void onSatelliteModemStateChange(in int state); + void onPendingMessageCount(in int count); + void onSatelliteDatagrams(in SatelliteDatagram[] datagrams); } diff --git a/telephony/java/android/telephony/satellite/SatelliteCallback.java b/telephony/java/android/telephony/satellite/SatelliteCallback.java index 1b82d062047a0..c8a8a61300be8 100644 --- a/telephony/java/android/telephony/satellite/SatelliteCallback.java +++ b/telephony/java/android/telephony/satellite/SatelliteCallback.java @@ -21,6 +21,7 @@ import android.os.Binder; import android.telephony.satellite.stub.SatelliteImplBase; import java.lang.ref.WeakReference; +import java.util.List; import java.util.concurrent.Executor; /** @@ -91,6 +92,34 @@ public class SatelliteCallback { @SatelliteManager.SatelliteMessageTransferState int state); } + /** + * Interface for satellite state change listener. + */ + public interface SatelliteStateListener { + /** + * Called when satellite state changes. + * @param state - The new satellite state. + */ + void onSatelliteModemStateChange(@SatelliteManager.SatelliteModemState int state); + + /** + * Called when there are pending messages to be received from satellite. + * @param count - pending message count. + */ + void onPendingMessageCount(int count); + } + + /** + * Interface for satellite datagram listener. + */ + public interface SatelliteDatagramListener { + /** + * Called when there are incoming datagrams to be received. + * @param datagrams - datagrams to be received over satellite. + */ + void onSatelliteDatagrams(SatelliteDatagram[] datagrams); + } + private static class ISatelliteStateListenerStub extends ISatelliteStateListener.Stub { private WeakReference mSatelliteCallbackWeakRef; private Executor mExecutor; @@ -128,5 +157,36 @@ public class SatelliteCallback { Binder.withCleanCallingIdentity(() -> mExecutor.execute( () -> listener.onMessageTransferStateUpdate(state))); } + + + @Override + public void onSatelliteModemStateChange(@SatelliteManager.SatelliteModemState int state) { + SatelliteStateListener listener = + (SatelliteStateListener) mSatelliteCallbackWeakRef.get(); + if (listener == null) return; + + Binder.withCleanCallingIdentity(() -> mExecutor.execute( + () -> listener.onSatelliteModemStateChange(state))); + } + + @Override + public void onPendingMessageCount(int count) { + SatelliteStateListener listener = + (SatelliteStateListener) mSatelliteCallbackWeakRef.get(); + if (listener == null) return; + + Binder.withCleanCallingIdentity(() -> mExecutor.execute( + () -> listener.onPendingMessageCount(count))); + } + + @Override + public void onSatelliteDatagrams(SatelliteDatagram[] datagrams) { + SatelliteDatagramListener listener = + (SatelliteDatagramListener) mSatelliteCallbackWeakRef.get(); + if (listener == null) return; + + Binder.withCleanCallingIdentity(() -> mExecutor.execute( + () -> listener.onSatelliteDatagrams(datagrams))); + } } } diff --git a/telephony/java/android/telephony/satellite/SatelliteDatagram.aidl b/telephony/java/android/telephony/satellite/SatelliteDatagram.aidl new file mode 100644 index 0000000000000..993aacf80bd12 --- /dev/null +++ b/telephony/java/android/telephony/satellite/SatelliteDatagram.aidl @@ -0,0 +1,19 @@ +/* + * Copyright 2023, 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 android.telephony.satellite; + +parcelable SatelliteDatagram; diff --git a/telephony/java/android/telephony/satellite/SatelliteDatagram.java b/telephony/java/android/telephony/satellite/SatelliteDatagram.java new file mode 100644 index 0000000000000..cc5a9f45de838 --- /dev/null +++ b/telephony/java/android/telephony/satellite/SatelliteDatagram.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2023 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 android.telephony.satellite; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * @hide + */ +public final class SatelliteDatagram implements Parcelable { + /** + * Datagram to be sent or received over satellite. + */ + private byte[] mData; + + /** + * @hide + */ + public SatelliteDatagram(@NonNull byte[] data) { + mData = data; + } + + private SatelliteDatagram(Parcel in) { + readFromParcel(in); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeByteArray(mData); + } + + public static final @android.annotation.NonNull Creator CREATOR = + new Creator() { + @Override + public SatelliteDatagram createFromParcel(Parcel in) { + return new SatelliteDatagram(in); + } + + @Override + public SatelliteDatagram[] newArray(int size) { + return new SatelliteDatagram[size]; + } + }; + + @Nullable + public byte[] getSatelliteDatagram() { + return mData; + } + + private void readFromParcel(Parcel in) { + mData = in.createByteArray(); + } +} diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java index 129d4cafa5b5f..693f9d2d4b7eb 100644 --- a/telephony/java/android/telephony/satellite/SatelliteManager.java +++ b/telephony/java/android/telephony/satellite/SatelliteManager.java @@ -490,6 +490,44 @@ public class SatelliteManager { }) public @interface SatelliteMessageTransferState {} + /* Satellite modem is in idle state. */ + public static final int SATELLITE_MODEM_STATE_IDLE = 0; + + /* Satellite modem is listening for incoming messages. */ + public static final int SATELLITE_MODEM_STATE_LISTENING = 1; + + /* Satellite modem is sending and/or receiving messages. */ + public static final int SATELLITE_MODEM_STATE_MESSAGE_TRANSFERRING = 2; + + /* Satellite modem is powered off */ + public static final int SATELLITE_MODEM_STATE_OFF = 3; + + /** @hide */ + @IntDef(prefix = {"SATELLITE_STATE_"}, + value = { + SATELLITE_MODEM_STATE_IDLE, + SATELLITE_MODEM_STATE_LISTENING, + SATELLITE_MODEM_STATE_MESSAGE_TRANSFERRING, + SATELLITE_MODEM_STATE_OFF + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SatelliteModemState {} + + /** SOS SMS */ + public static final int DATAGRAM_TYPE_SOS_SMS = 0; + + /** Location sharing message */ + public static final int DATAGRAM_TYPE_LOCATION_SHARING = 3; + + @IntDef( + prefix = "DATAGRAM_TYPE_", + value = { + DATAGRAM_TYPE_SOS_SMS, + DATAGRAM_TYPE_LOCATION_SHARING, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface DatagramType {} + /** * Start receiving satellite position updates. * This can be called by the pointing UI when the user starts pointing to the satellite. @@ -824,6 +862,171 @@ public class SatelliteManager { } } + /** + * Register for listening to satellite modem state changes. + * + * @param executor - The executor on which the callback will be called. + * @param callback - The callback to handle the satellite state change event. This + * SatelliteCallback should implement the interface + * {@link SatelliteCallback.SatelliteStateListener}. + * + * @return The error code of the request. + * @throws SecurityException if the caller doesn't have required permission. + * @throws IllegalStateException if the Telephony process is not currently available. + */ + @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) + @SatelliteError + public int registerForSatelliteModemStateChange(@NonNull @CallbackExecutor Executor executor, + @NonNull SatelliteCallback callback) { + Objects.requireNonNull(executor); + Objects.requireNonNull(callback); + + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + callback.init(executor); + return telephony.registerForSatelliteModemStateChange(mSubId, + callback.getCallbackStub()); + } else { + throw new IllegalStateException("telephony service is null."); + } + } catch (RemoteException ex) { + loge("registerForSatelliteModemStateChange() RemoteException:" + ex); + ex.rethrowFromSystemServer(); + } + return SATELLITE_REQUEST_FAILED; + } + + /** + * Unregister to stop listening to satellite modem state changes. + * + * @param callback - The callback that was passed to + * {@link #registerForSatelliteModemStateChange(Executor, SatelliteCallback)} + * + * @return The error code of the request. + * @throws SecurityException if the caller doesn't have required permission. + * @throws IllegalStateException if the Telephony process is not currently available. + */ + @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) + @SatelliteError + public int unregisterForSatelliteModemStateChange(@NonNull SatelliteCallback callback) { + Objects.requireNonNull(callback); + + if (callback.getCallbackStub() == null) { + loge("unregisterForSatelliteModemStateChange: callbackStub is null"); + return SATELLITE_INVALID_ARGUMENTS; + } + + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.unregisterForSatelliteModemStateChange(mSubId, + callback.getCallbackStub()); + } else { + throw new IllegalStateException("telephony service is null."); + } + } catch (RemoteException ex) { + loge("unregisterForSatelliteModemStateChange() RemoteException:" + ex); + ex.rethrowFromSystemServer(); + } + return SATELLITE_REQUEST_FAILED; + } + + /** + * Register to receive incoming datagrams over satellite. + * + * @param datagramType - type of datagram + * @param executor - The executor on which the callback will be called. + * @param callback - The callback to handle incoming datagrams over satellite. This + * SatelliteCallback should implement the interface + * {@link SatelliteCallback.SatelliteDatagramListener}. + * + * @return The error code of the request. + * @throws SecurityException if the caller doesn't have required permission. + * @throws IllegalStateException if the Telephony process is not currently available. + */ + @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) + @SatelliteError + public int registerForSatelliteDatagram(@DatagramType int datagramType, + @NonNull @CallbackExecutor Executor executor, @NonNull SatelliteCallback callback) { + Objects.requireNonNull(executor); + Objects.requireNonNull(callback); + + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + callback.init(executor); + return telephony.registerForSatelliteDatagram(mSubId, datagramType, + callback.getCallbackStub()); + } else { + throw new IllegalStateException("telephony service is null."); + } + } catch (RemoteException ex) { + loge("registerForSatelliteDatagram() RemoteException:" + ex); + ex.rethrowFromSystemServer(); + } + return SATELLITE_REQUEST_FAILED; + } + + /** + * Unregister to stop receiving incoming datagrams over satellite. + * + * @param callback - The callback that was passed to + * {@link #registerForSatelliteDatagram(int, Executor, SatelliteCallback)} + * + * @return The error code of the request. + * @throws SecurityException if the caller doesn't have required permission. + * @throws IllegalStateException if the Telephony process is not currently available. + */ + @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) + @SatelliteError + public int unregisterForSatelliteDatagram(@NonNull SatelliteCallback callback) { + Objects.requireNonNull(callback); + + if (callback.getCallbackStub() == null) { + loge("unregisterForSatelliteDatagram: callbackStub is null"); + return SATELLITE_INVALID_ARGUMENTS; + } + + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.unregisterForSatelliteDatagram(mSubId, + callback.getCallbackStub()); + } else { + throw new IllegalStateException("telephony service is null."); + } + } catch (RemoteException ex) { + loge("unregisterForSatelliteDatagram() RemoteException:" + ex); + ex.rethrowFromSystemServer(); + } + return SATELLITE_REQUEST_FAILED; + } + + /** + * Poll pending satellite datagrams over satellite. + * + * @return The result of the operation. + * @throws SecurityException if the caller doesn't have required permission. + * @throws IllegalStateException if the Telephony process is not currently available. + */ + @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) + @SatelliteError + public int pollPendingSatelliteDatagrams() { + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.pollPendingSatelliteDatagrams(mSubId); + } else { + throw new IllegalStateException("telephony service is null."); + } + } catch (RemoteException ex) { + loge("pollPendingSatelliteDatagrams() RemoteException:" + ex); + ex.rethrowFromSystemServer(); + } + return SATELLITE_REQUEST_FAILED; + } + private static ITelephony getITelephony() { ITelephony binder = ITelephony.Stub.asInterface(TelephonyFrameworkInitializer .getTelephonyServiceManager() diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 07deead956580..3b20e729d5869 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -2827,4 +2827,54 @@ interface ITelephony { @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" + "android.Manifest.permission.SATELLITE_COMMUNICATION)") void requestIsSatelliteProvisioned(int subId, in ResultReceiver receiver); + + /** + * Register for listening to satellite modem state changes. + * + * @param subId - The subId of the subscription used for listening to satellite state changes. + * @param callback - The callback to handle the satellite state changed event. + */ + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" + + "android.Manifest.permission.SATELLITE_COMMUNICATION)") + int registerForSatelliteModemStateChange(int subId, ISatelliteStateListener callback); + + /** + * Unregister to stop listening to satellite modem state changes. + * + * @param subId - The subId of the subscription associated with the satellite service. + * @param callback - The callback that was passed to registerForSatelliteStateChange. + */ + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" + + "android.Manifest.permission.SATELLITE_COMMUNICATION)") + int unregisterForSatelliteModemStateChange(int subId, ISatelliteStateListener callback); + + /** + * Register to receive incoming datagrams over satellite. + * + * @param subId - The subId of the subscription used for receiving datagrams. + * @param datagramType - type of datagram + * @param callback - The callback to receive incoming datagrams. + */ + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" + + "android.Manifest.permission.SATELLITE_COMMUNICATION)") + int registerForSatelliteDatagram(int subId, int datagramType, ISatelliteStateListener callback); + + /** + * Unregister to stop receiving incoming datagrams over satellite. + * + * @param subId - The subId of the subscription associated with the satellite service. + * @param callback - The callback that was passed to registerForSatelliteDatagram. + */ + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" + + "android.Manifest.permission.SATELLITE_COMMUNICATION)") + int unregisterForSatelliteDatagram(int subId, ISatelliteStateListener callback); + + /** + * Poll pending satellite datagrams over satellite. + * + * @param subId - The subId of the subscription used for receiving datagrams. + */ + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" + + "android.Manifest.permission.SATELLITE_COMMUNICATION)") + int pollPendingSatelliteDatagrams(int subId); }