Merge cherrypicks of ['googleplex-android-review.googlesource.com/27664376', 'googleplex-android-review.googlesource.com/27703542'] into 24D1-release.

Change-Id: Ia7cdd00a0a970710dc2f3b58f7079a9bdbf9cbb1
diff --git a/satellite_client/src/android/telephony/satellite/wrapper/SatelliteCommunicationAllowedStateCallbackWrapper.java b/satellite_client/src/android/telephony/satellite/wrapper/SatelliteCommunicationAllowedStateCallbackWrapper.java
new file mode 100644
index 0000000..85fb42f
--- /dev/null
+++ b/satellite_client/src/android/telephony/satellite/wrapper/SatelliteCommunicationAllowedStateCallbackWrapper.java
@@ -0,0 +1,30 @@
+/*
+ * 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.wrapper;
+
+/** A callback class for monitoring satellite communication allowed state change events. */
+public interface SatelliteCommunicationAllowedStateCallbackWrapper {
+  /**
+   * 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
+   */
+  void onSatelliteCommunicationAllowedStateChanged(boolean isAllowed);
+}
diff --git a/satellite_client/src/android/telephony/satellite/wrapper/SatelliteManagerWrapper.java b/satellite_client/src/android/telephony/satellite/wrapper/SatelliteManagerWrapper.java
index 994c5a2..59045f6 100644
--- a/satellite_client/src/android/telephony/satellite/wrapper/SatelliteManagerWrapper.java
+++ b/satellite_client/src/android/telephony/satellite/wrapper/SatelliteManagerWrapper.java
@@ -41,11 +41,13 @@
 import android.telephony.satellite.PointingInfo;
 import android.telephony.satellite.SatelliteCapabilities;
 import android.telephony.satellite.SatelliteCapabilitiesCallback;
+import android.telephony.satellite.SatelliteCommunicationAllowedStateCallback;
 import android.telephony.satellite.SatelliteDatagram;
 import android.telephony.satellite.SatelliteDatagramCallback;
 import android.telephony.satellite.SatelliteManager;
 import android.telephony.satellite.SatelliteModemStateCallback;
 import android.telephony.satellite.SatelliteProvisionStateCallback;
+import android.telephony.satellite.SatelliteSessionStats;
 import android.telephony.satellite.SatelliteSupportedStateCallback;
 import android.telephony.satellite.SatelliteTransmissionUpdateCallback;
 
@@ -104,6 +106,10 @@
           CarrierRoamingNtnModeListenerWrapper, TelephonyCallback.CarrierRoamingNtnModeListener>
           sCarrierRoamingNtnModeListenerWrapperMap = new ConcurrentHashMap<>();
 
+  private static final ConcurrentHashMap<SatelliteCommunicationAllowedStateCallbackWrapper,
+          SatelliteCommunicationAllowedStateCallback>
+          sSatelliteCommunicationAllowedStateCallbackWrapperMap = new ConcurrentHashMap<>();
+
   private final SatelliteManager mSatelliteManager;
   private final SubscriptionManager mSubscriptionManager;
   private final TelephonyManager mTelephonyManager;
@@ -1286,6 +1292,38 @@
     return result;
   }
 
+  /** Request to get the {@link SatelliteSessionStatsWrapper} of the satellite service. */
+  public void requestSessionStats(
+          @NonNull @CallbackExecutor Executor executor,
+          @NonNull OutcomeReceiver<SatelliteSessionStatsWrapper,
+                  SatelliteExceptionWrapper> callback) {
+    OutcomeReceiver internalCallback =
+            new OutcomeReceiver<SatelliteSessionStats, SatelliteException>() {
+              @Override
+              public void onResult(SatelliteSessionStats result) {
+                SatelliteSessionStatsWrapper statsWrapper = new SatelliteSessionStatsWrapper
+                        .Builder()
+                        .setCountOfSuccessfulUserMessages(result.getCountOfSuccessfulUserMessages())
+                        .setCountOfUnsuccessfulUserMessages(
+                                result.getCountOfUnsuccessfulUserMessages())
+                        .setCountOfTimedOutUserMessagesWaitingForConnection(
+                                result.getCountOfTimedOutUserMessagesWaitingForConnection())
+                        .setCountOfTimedOutUserMessagesWaitingForAck(
+                                result.getCountOfTimedOutUserMessagesWaitingForAck())
+                        .setCountOfUserMessagesInQueueToBeSent(
+                                result.getCountOfUserMessagesInQueueToBeSent())
+                        .build();
+                callback.onResult(statsWrapper);
+              }
+
+              @Override
+              public void onError(SatelliteException exception) {
+                callback.onError(new SatelliteExceptionWrapper(exception.getErrorCode()));
+              }
+            };
+    mSatelliteManager.requestSessionStats(executor, internalCallback);
+  }
+
   /**
    * Unregisters for the satellite supported state changed. If callback was not registered before,
    * the request will be ignored.
@@ -1299,6 +1337,37 @@
     }
   }
 
+  /** Registers for the satellite communication allowed state changed. */
+  @SatelliteResult
+  public int registerForCommunicationAllowedStateChanged(
+          @NonNull @CallbackExecutor Executor executor,
+          @NonNull SatelliteCommunicationAllowedStateCallbackWrapper callback) {
+    SatelliteCommunicationAllowedStateCallback internalCallback =
+            new SatelliteCommunicationAllowedStateCallback() {
+              @Override
+              public void onSatelliteCommunicationAllowedStateChanged(boolean supported) {
+                callback.onSatelliteCommunicationAllowedStateChanged(supported);
+              }
+            };
+    sSatelliteCommunicationAllowedStateCallbackWrapperMap.put(callback, internalCallback);
+    int result = mSatelliteManager.registerForCommunicationAllowedStateChanged(executor,
+            internalCallback);
+    return result;
+  }
+
+  /**
+   * Unregisters for the satellite communication allowed state changed. If callback was not
+   * registered before, the request will be ignored.
+   */
+  public void unregisterForCommunicationAllowedStateChanged(
+          @NonNull SatelliteCommunicationAllowedStateCallbackWrapper callback) {
+    SatelliteCommunicationAllowedStateCallback internalCallback =
+            sSatelliteCommunicationAllowedStateCallbackWrapperMap.get(callback);
+    if (internalCallback != null) {
+      mSatelliteManager.unregisterForCommunicationAllowedStateChanged(internalCallback);
+    }
+  }
+
   @Nullable
   private ServiceState getServiceStateForSubscriptionId(int subId) {
     if (!mSubscriptionManager.isValidSubscriptionId(subId)) {
diff --git a/satellite_client/src/android/telephony/satellite/wrapper/SatelliteSessionStatsWrapper.java b/satellite_client/src/android/telephony/satellite/wrapper/SatelliteSessionStatsWrapper.java
new file mode 100644
index 0000000..81969e9
--- /dev/null
+++ b/satellite_client/src/android/telephony/satellite/wrapper/SatelliteSessionStatsWrapper.java
@@ -0,0 +1,220 @@
+/*
+ * 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.wrapper;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+public class SatelliteSessionStatsWrapper implements Parcelable {
+    private int mCountOfSuccessfulUserMessages;
+    private int mCountOfUnsuccessfulUserMessages;
+    private int mCountOfTimedOutUserMessagesWaitingForConnection;
+    private int mCountOfTimedOutUserMessagesWaitingForAck;
+    private int mCountOfUserMessagesInQueueToBeSent;
+
+    /**
+     * SatelliteSessionStats constructor
+     * @param  builder Builder to create SatelliteSessionStats object/
+     */
+    public SatelliteSessionStatsWrapper(@NonNull Builder builder) {
+        mCountOfSuccessfulUserMessages = builder.mCountOfSuccessfulUserMessages;
+        mCountOfUnsuccessfulUserMessages = builder.mCountOfUnsuccessfulUserMessages;
+        mCountOfTimedOutUserMessagesWaitingForConnection =
+                builder.mCountOfTimedOutUserMessagesWaitingForConnection;
+        mCountOfTimedOutUserMessagesWaitingForAck =
+                builder.mCountOfTimedOutUserMessagesWaitingForAck;
+        mCountOfUserMessagesInQueueToBeSent = builder.mCountOfUserMessagesInQueueToBeSent;
+    }
+
+    private SatelliteSessionStatsWrapper(Parcel in) {
+        readFromParcel(in);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel out, int flags) {
+        out.writeInt(mCountOfSuccessfulUserMessages);
+        out.writeInt(mCountOfUnsuccessfulUserMessages);
+        out.writeInt(mCountOfTimedOutUserMessagesWaitingForConnection);
+        out.writeInt(mCountOfTimedOutUserMessagesWaitingForAck);
+        out.writeInt(mCountOfUserMessagesInQueueToBeSent);
+    }
+
+    @NonNull
+    public static final Parcelable.Creator<SatelliteSessionStatsWrapper> CREATOR =
+            new Parcelable.Creator<>() {
+                @Override
+                public SatelliteSessionStatsWrapper createFromParcel(Parcel in) {
+                    return new SatelliteSessionStatsWrapper(in);
+                }
+
+                @Override
+                public SatelliteSessionStatsWrapper[] newArray(int size) {
+                    return new SatelliteSessionStatsWrapper[size];
+                }
+            };
+
+    @Override
+    @NonNull
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("countOfSuccessfulUserMessages:");
+        sb.append(mCountOfSuccessfulUserMessages);
+        sb.append(",");
+
+        sb.append("countOfUnsuccessfulUserMessages:");
+        sb.append(mCountOfUnsuccessfulUserMessages);
+        sb.append(",");
+
+        sb.append("countOfTimedOutUserMessagesWaitingForConnection:");
+        sb.append(mCountOfTimedOutUserMessagesWaitingForConnection);
+        sb.append(",");
+
+        sb.append("countOfTimedOutUserMessagesWaitingForAck:");
+        sb.append(mCountOfTimedOutUserMessagesWaitingForAck);
+        sb.append(",");
+
+        sb.append("countOfUserMessagesInQueueToBeSent:");
+        sb.append(mCountOfUserMessagesInQueueToBeSent);
+        return sb.toString();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        SatelliteSessionStatsWrapper that = (SatelliteSessionStatsWrapper) o;
+        return mCountOfSuccessfulUserMessages == that.mCountOfSuccessfulUserMessages
+                && mCountOfUnsuccessfulUserMessages == that.mCountOfUnsuccessfulUserMessages
+                && mCountOfTimedOutUserMessagesWaitingForConnection
+                == that.mCountOfTimedOutUserMessagesWaitingForConnection
+                && mCountOfTimedOutUserMessagesWaitingForAck
+                == that.mCountOfTimedOutUserMessagesWaitingForAck
+                && mCountOfUserMessagesInQueueToBeSent
+                == that.mCountOfUserMessagesInQueueToBeSent;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mCountOfSuccessfulUserMessages, mCountOfUnsuccessfulUserMessages,
+                mCountOfTimedOutUserMessagesWaitingForConnection,
+                mCountOfTimedOutUserMessagesWaitingForAck,
+                mCountOfUserMessagesInQueueToBeSent);
+    }
+
+    public int getCountOfSuccessfulUserMessages() {
+        return mCountOfSuccessfulUserMessages;
+    }
+
+    public int getCountOfUnsuccessfulUserMessages() {
+        return mCountOfUnsuccessfulUserMessages;
+    }
+
+    public int getCountOfTimedOutUserMessagesWaitingForConnection() {
+        return mCountOfTimedOutUserMessagesWaitingForConnection;
+    }
+
+    public int getCountOfTimedOutUserMessagesWaitingForAck() {
+        return mCountOfTimedOutUserMessagesWaitingForAck;
+    }
+
+    public int getCountOfUserMessagesInQueueToBeSent() {
+        return mCountOfUserMessagesInQueueToBeSent;
+    }
+
+    private void readFromParcel(Parcel in) {
+        mCountOfSuccessfulUserMessages = in.readInt();
+        mCountOfUnsuccessfulUserMessages = in.readInt();
+        mCountOfTimedOutUserMessagesWaitingForConnection = in.readInt();
+        mCountOfTimedOutUserMessagesWaitingForAck = in.readInt();
+        mCountOfUserMessagesInQueueToBeSent = in.readInt();
+    }
+
+    /**
+     * A builder class to create {@link SatelliteSessionStatsWrapper} data object.
+     */
+    public static final class Builder {
+        private int mCountOfSuccessfulUserMessages;
+        private int mCountOfUnsuccessfulUserMessages;
+        private int mCountOfTimedOutUserMessagesWaitingForConnection;
+        private int mCountOfTimedOutUserMessagesWaitingForAck;
+        private int mCountOfUserMessagesInQueueToBeSent;
+
+        /**
+         * Sets countOfSuccessfulUserMessages value of {@link SatelliteSessionStatsWrapper}
+         * and then returns the Builder class.
+         */
+        @NonNull
+        public Builder setCountOfSuccessfulUserMessages(int count) {
+            mCountOfSuccessfulUserMessages = count;
+            return this;
+        }
+
+        /**
+         * Sets countOfUnsuccessfulUserMessages value of {@link SatelliteSessionStatsWrapper}
+         * and then returns the Builder class.
+         */
+        @NonNull
+        public Builder setCountOfUnsuccessfulUserMessages(int count) {
+            mCountOfUnsuccessfulUserMessages = count;
+            return this;
+        }
+
+        /**
+         * Sets countOfTimedOutUserMessagesWaitingForConnection value of
+         * {@link SatelliteSessionStatsWrapper} and then returns the Builder class.
+         */
+        @NonNull
+        public Builder setCountOfTimedOutUserMessagesWaitingForConnection(int count) {
+            mCountOfTimedOutUserMessagesWaitingForConnection = count;
+            return this;
+        }
+
+        /**
+         * Sets countOfTimedOutUserMessagesWaitingForAck value of
+         * {@link SatelliteSessionStatsWrapper} and then returns the Builder class.
+         */
+        @NonNull
+        public Builder setCountOfTimedOutUserMessagesWaitingForAck(int count) {
+            mCountOfTimedOutUserMessagesWaitingForAck = count;
+            return this;
+        }
+
+        /**
+         * Sets countOfUserMessagesInQueueToBeSent value of {@link SatelliteSessionStatsWrapper}
+         * and then returns the Builder class.
+         */
+        @NonNull
+        public Builder setCountOfUserMessagesInQueueToBeSent(int count) {
+            mCountOfUserMessagesInQueueToBeSent = count;
+            return this;
+        }
+
+        /** Returns SatelliteSessionStats object. */
+        @NonNull
+        public SatelliteSessionStatsWrapper build() {
+            return new SatelliteSessionStatsWrapper(this);
+        }
+    }
+}