Merge "Add callback/listener for satellite communication allowed state changed" into 24D1-dev
diff --git a/telephony/java/android/telephony/satellite/ISatelliteCommunicationAllowedStateCallback.aidl b/telephony/java/android/telephony/satellite/ISatelliteCommunicationAllowedStateCallback.aidl
new file mode 100644
index 0000000..a7eda48
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/ISatelliteCommunicationAllowedStateCallback.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.satellite;
+
+/**
+ * Interface for satellite communication allowed state callback.
+ * @hide
+ */
+oneway interface ISatelliteCommunicationAllowedStateCallback {
+    /**
+     * Telephony does not guarantee that whenever there is a change in communication allowed
+     * state, this API will be called. Telephony does its best to detect the changes and notify
+     * its listners accordingly.
+     *
+     * @param allowed whether satellite communication state or not
+     */
+    void onSatelliteCommunicationAllowedStateChanged(in boolean isAllowed);
+}
diff --git a/telephony/java/android/telephony/satellite/SatelliteCommunicationAllowedStateCallback.java b/telephony/java/android/telephony/satellite/SatelliteCommunicationAllowedStateCallback.java
new file mode 100644
index 0000000..1a87020
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/SatelliteCommunicationAllowedStateCallback.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.satellite;
+
+import android.annotation.FlaggedApi;
+
+import com.android.internal.telephony.flags.Flags;
+
+
+/**
+ * A callback class for monitoring satellite communication allowed state changed events.
+ *
+ * @hide
+ */
+@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+public interface SatelliteCommunicationAllowedStateCallback {
+
+    /**
+     * Telephony does not guarantee that whenever there is a change in communication allowed state,
+     * this API will be called. Telephony does its best to detect the changes and notify its
+     * listeners accordingly.
+     *
+     * @param isAllowed {@code true} means satellite allow state is changed,
+     *                  {@code false} satellite allow state is not changed
+     * @hide
+     */
+    @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+    void onSatelliteCommunicationAllowedStateChanged(boolean isAllowed);
+}
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 40ad312..0bb5fd5 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -91,6 +91,11 @@
             ISatelliteSupportedStateCallback> sSatelliteSupportedStateCallbackMap =
             new ConcurrentHashMap<>();
 
+    private static final ConcurrentHashMap<SatelliteCommunicationAllowedStateCallback,
+            ISatelliteCommunicationAllowedStateCallback>
+            sSatelliteCommunicationAllowedStateCallbackMap =
+            new ConcurrentHashMap<>();
+
     private final int mSubId;
 
     /**
@@ -2393,7 +2398,89 @@
         }
     }
 
-    @Nullable private static ITelephony getITelephony() {
+    /**
+     * Registers for the satellite communication allowed state changed.
+     *
+     * @param executor The executor on which the callback will be called.
+     * @param callback The callback to handle satellite communication allowed state changed event.
+     * @return The {@link SatelliteResult} result of the operation.
+     * @throws SecurityException     if the caller doesn't have required permission.
+     * @throws IllegalStateException if the Telephony process is not currently available.
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+    @SatelliteResult
+    public int registerForCommunicationAllowedStateChanged(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull SatelliteCommunicationAllowedStateCallback callback) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                ISatelliteCommunicationAllowedStateCallback internalCallback =
+                        new ISatelliteCommunicationAllowedStateCallback.Stub() {
+                            @Override
+                            public void onSatelliteCommunicationAllowedStateChanged(
+                                    boolean isAllowed) {
+                                executor.execute(() -> Binder.withCleanCallingIdentity(
+                                        () -> callback.onSatelliteCommunicationAllowedStateChanged(
+                                                isAllowed)));
+                            }
+                        };
+                sSatelliteCommunicationAllowedStateCallbackMap.put(callback, internalCallback);
+                return telephony.registerForCommunicationAllowedStateChanged(
+                        mSubId, internalCallback);
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            loge("registerForCommunicationAllowedStateChanged() RemoteException: " + ex);
+            ex.rethrowAsRuntimeException();
+        }
+        return SATELLITE_RESULT_REQUEST_FAILED;
+    }
+
+    /**
+     * Unregisters for the satellite communication allowed state changed.
+     * If callback was not registered before, the request will be ignored.
+     *
+     * @param callback The callback that was passed to
+     *                 {@link #registerForCommunicationAllowedStateChanged(Executor,
+     *                 SatelliteCommunicationAllowedStateCallback)}
+     * @throws SecurityException     if the caller doesn't have required permission.
+     * @throws IllegalStateException if the Telephony process is not currently available.
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+    @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+    public void unregisterForCommunicationAllowedStateChanged(
+            @NonNull SatelliteCommunicationAllowedStateCallback callback) {
+        Objects.requireNonNull(callback);
+        ISatelliteCommunicationAllowedStateCallback internalCallback =
+                sSatelliteCommunicationAllowedStateCallbackMap.remove(callback);
+
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                if (internalCallback != null) {
+                    telephony.unregisterForCommunicationAllowedStateChanged(mSubId,
+                            internalCallback);
+                } else {
+                    loge("unregisterForCommunicationAllowedStateChanged: No internal callback.");
+                }
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            loge("unregisterForCommunicationAllowedStateChanged() RemoteException: " + ex);
+            ex.rethrowAsRuntimeException();
+        }
+    }
+
+    @Nullable
+    private static ITelephony getITelephony() {
         ITelephony binder = ITelephony.Stub.asInterface(TelephonyFrameworkInitializer
                 .getTelephonyServiceManager()
                 .getTelephonyServiceRegisterer()
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index f25fc36..f591f40 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -69,6 +69,7 @@
 import android.telephony.ims.aidl.IRcsConfigCallback;
 import android.telephony.satellite.INtnSignalStrengthCallback;
 import android.telephony.satellite.ISatelliteCapabilitiesCallback;
+import android.telephony.satellite.ISatelliteCommunicationAllowedStateCallback;
 import android.telephony.satellite.ISatelliteDatagramCallback;
 import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
 import android.telephony.satellite.ISatelliteProvisionStateCallback;
@@ -3341,4 +3342,29 @@
             + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
     void unregisterForSatelliteSupportedStateChanged(int subId,
             in ISatelliteSupportedStateCallback callback);
+
+    /**
+     * Registers for satellite communication allowed state changed.
+     *
+     * @param subId The subId of the subscription to register for communication allowed state.
+     * @param callback The callback to handle the communication allowed state changed event.
+     *
+     * @return The {@link SatelliteError} result of the operation.
+     */
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+            + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+    int registerForCommunicationAllowedStateChanged(int subId,
+            in ISatelliteCommunicationAllowedStateCallback callback);
+
+    /**
+     * Unregisters for satellite communication allowed state.
+     * If callback was not registered before, the request will be ignored.
+     *
+     * @param subId The subId of the subscription to unregister for supported state changed.
+     * @param callback The callback that was passed to registerForCommunicationAllowedStateChanged.
+     */
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+            + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+    void unregisterForCommunicationAllowedStateChanged(int subId,
+            in ISatelliteCommunicationAllowedStateCallback callback);
 }