Merge "Add satellite log" into 24D1-dev
diff --git a/proto/src/persist_atoms.proto b/proto/src/persist_atoms.proto
index 46a2400..3847fcd 100644
--- a/proto/src/persist_atoms.proto
+++ b/proto/src/persist_atoms.proto
@@ -682,6 +682,7 @@
optional int32 count_of_incoming_datagram_success = 10;
optional int32 count_of_incoming_datagram_failed = 11;
optional bool is_demo_mode = 12;
+ optional int32 max_ntn_signal_strength_level = 13;
}
message SatelliteIncomingDatagram {
diff --git a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
index 61325316..0031c7e 100644
--- a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
+++ b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
@@ -1370,7 +1370,8 @@
satelliteSession.countOfOutgoingDatagramFailed,
satelliteSession.countOfIncomingDatagramSuccess,
satelliteSession.countOfIncomingDatagramFailed,
- satelliteSession.isDemoMode);
+ satelliteSession.isDemoMode,
+ satelliteSession.maxNtnSignalStrengthLevel);
}
private static StatsEvent buildStatsEvent(SatelliteIncomingDatagram stats) {
diff --git a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
index 979777b..8afdc36 100644
--- a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
+++ b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
@@ -2066,7 +2066,7 @@
}
/**
- * Returns SatelliteOutgoingDatagram atom that has same values or {@code null}
+ * Returns SatelliteSession atom that has same values or {@code null}
* if it does not exist.
*/
private @Nullable SatelliteSession find(
@@ -2085,7 +2085,8 @@
&& stats.countOfOutgoingDatagramFailed == key.countOfOutgoingDatagramFailed
&& stats.countOfIncomingDatagramSuccess == key.countOfIncomingDatagramSuccess
&& stats.countOfIncomingDatagramFailed == key.countOfIncomingDatagramFailed
- && stats.isDemoMode == key.isDemoMode) {
+ && stats.isDemoMode == key.isDemoMode
+ && stats.maxNtnSignalStrengthLevel == key.maxNtnSignalStrengthLevel) {
return stats;
}
}
@@ -2093,7 +2094,7 @@
}
/**
- * Returns SatelliteOutgoingDatagram atom that has same values or {@code null}
+ * Returns SatelliteSosMessageRecommender atom that has same values or {@code null}
* if it does not exist.
*/
private @Nullable SatelliteSosMessageRecommender find(
diff --git a/src/java/com/android/internal/telephony/metrics/SatelliteStats.java b/src/java/com/android/internal/telephony/metrics/SatelliteStats.java
index a9aab58..e097c62 100644
--- a/src/java/com/android/internal/telephony/metrics/SatelliteStats.java
+++ b/src/java/com/android/internal/telephony/metrics/SatelliteStats.java
@@ -16,6 +16,9 @@
package com.android.internal.telephony.metrics;
+import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE;
+
+import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.SatelliteManager;
import com.android.internal.telephony.PhoneFactory;
@@ -560,6 +563,7 @@
private final int mCountOfIncomingDatagramSuccess;
private final int mCountOfIncomingDatagramFailed;
private final boolean mIsDemoMode;
+ private final @NtnSignalStrength.NtnSignalStrengthLevel int mMaxNtnSignalStrengthLevel;
private SatelliteSessionParams(Builder builder) {
this.mSatelliteServiceInitializationResult =
@@ -575,6 +579,7 @@
this.mCountOfIncomingDatagramSuccess = builder.mCountOfIncomingDatagramSuccess;
this.mCountOfIncomingDatagramFailed = builder.mCountOfIncomingDatagramFailed;
this.mIsDemoMode = builder.mIsDemoMode;
+ this.mMaxNtnSignalStrengthLevel = builder.mMaxNtnSignalStrengthLevel;
}
public int getSatelliteServiceInitializationResult() {
@@ -621,6 +626,10 @@
return mIsDemoMode;
}
+ public @NtnSignalStrength.NtnSignalStrengthLevel int getMaxNtnSignalStrengthLevel() {
+ return mMaxNtnSignalStrengthLevel;
+ }
+
/**
* A builder class to create {@link SatelliteSessionParams} data structure class
*/
@@ -636,6 +645,8 @@
private int mCountOfIncomingDatagramSuccess = -1;
private int mCountOfIncomingDatagramFailed = -1;
private boolean mIsDemoMode = false;
+ private @NtnSignalStrength.NtnSignalStrengthLevel int mMaxNtnSignalStrengthLevel =
+ NTN_SIGNAL_STRENGTH_NONE;
/**
* Sets satelliteServiceInitializationResult value of {@link SatelliteSession}
@@ -711,6 +722,13 @@
return this;
}
+ /** Sets the max ntn signal strength for the satellite session */
+ public Builder setMaxNtnSignalStrengthLevel(
+ @NtnSignalStrength.NtnSignalStrengthLevel int maxNtnSignalStrengthLevel) {
+ this.mMaxNtnSignalStrengthLevel = maxNtnSignalStrengthLevel;
+ return this;
+ }
+
/**
* Returns SessionParams, which contains whole component of
* {@link SatelliteSession} atom
@@ -735,6 +753,7 @@
+ ", CountOfIncomingDatagramSuccess=" + mCountOfIncomingDatagramSuccess
+ ", CountOfIncomingDatagramFailed=" + mCountOfIncomingDatagramFailed
+ ", IsDemoMode=" + mIsDemoMode
+ + ", MaxNtnSignalStrengthLevel=" + mMaxNtnSignalStrengthLevel
+ ")";
}
}
@@ -1261,6 +1280,7 @@
proto.countOfIncomingDatagramSuccess = param.getCountOfIncomingDatagramSuccess();
proto.countOfIncomingDatagramFailed = param.getCountOfOutgoingDatagramFailed();
proto.isDemoMode = param.getIsDemoMode();
+ proto.maxNtnSignalStrengthLevel = param.getMaxNtnSignalStrengthLevel();
mAtomsStorage.addSatelliteSessionStats(proto);
}
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramController.java b/src/java/com/android/internal/telephony/satellite/DatagramController.java
index dbb586d..2f18796 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramController.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramController.java
@@ -29,6 +29,7 @@
import android.annotation.NonNull;
import android.content.Context;
+import android.content.res.Resources;
import android.os.Build;
import android.os.Looper;
import android.os.SystemProperties;
@@ -69,6 +70,8 @@
public static final int TIMEOUT_TYPE_WAIT_FOR_DATAGRAM_SENDING_RESPONSE = 3;
/** This type is used by CTS to override the time to datagram delay in demo mode */
public static final int TIMEOUT_TYPE_DATAGRAM_DELAY_IN_DEMO_MODE = 4;
+ /** This type is used by CTS to override wait for device alignment in demo datagram boolean */
+ public static final int BOOLEAN_TYPE_WAIT_FOR_DEVICE_ALIGNMENT_IN_DEMO_DATAGRAM = 1;
private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem";
private static final boolean DEBUG = !"user".equals(Build.TYPE);
@@ -101,6 +104,7 @@
private long mAlignTimeoutDuration = SATELLITE_ALIGN_TIMEOUT;
private long mDatagramWaitTimeForConnectedState;
private long mModemImageSwitchingDuration;
+ private boolean mWaitForDeviceAlignmentInDemoDatagram;
@GuardedBy("mLock")
@SatelliteManager.SatelliteModemState
private int mSatelltieModemState = SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN;
@@ -155,6 +159,8 @@
mDatagramWaitTimeForConnectedState = getDatagramWaitForConnectedStateTimeoutMillis();
mModemImageSwitchingDuration = getSatelliteModemImageSwitchingDurationMillis();
+ mWaitForDeviceAlignmentInDemoDatagram =
+ getWaitForDeviceAlignmentInDemoDatagramFromResources();
mDemoModeDatagramList = new ArrayList<>();
}
@@ -492,6 +498,36 @@
return true;
}
+ /**
+ * This API can be used by only CTS to override the boolean configs used by the
+ * DatagramController module.
+ *
+ * @param enable Whether to enable or disable boolean config.
+ * @return {@code true} if the boolean config is set successfully, {@code false} otherwise.
+ */
+ boolean setDatagramControllerBooleanConfig(
+ boolean reset, int booleanType, boolean enable) {
+ if (!isMockModemAllowed()) {
+ loge("Updating boolean config is not allowed");
+ return false;
+ }
+
+ logd("setDatagramControllerTimeoutDuration: booleanType=" + booleanType
+ + ", reset=" + reset + ", enable=" + enable);
+ if (booleanType == BOOLEAN_TYPE_WAIT_FOR_DEVICE_ALIGNMENT_IN_DEMO_DATAGRAM) {
+ if (reset) {
+ mWaitForDeviceAlignmentInDemoDatagram =
+ getWaitForDeviceAlignmentInDemoDatagramFromResources();
+ } else {
+ mWaitForDeviceAlignmentInDemoDatagram = enable;
+ }
+ } else {
+ loge("Invalid boolean type " + booleanType);
+ return false;
+ }
+ return true;
+ }
+
private boolean isMockModemAllowed() {
return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false));
}
@@ -546,6 +582,38 @@
}
}
+ /**
+ * Get whether to wait for device alignment with satellite before sending datagrams.
+ *
+ * @param isAligned if the device is aligned with satellite or not
+ * @return {@code true} if device is not aligned to satellite,
+ * and it is required to wait for alignment else {@code false}
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public boolean waitForAligningToSatellite(boolean isAligned) {
+ if (isAligned) {
+ return false;
+ }
+
+ return getWaitForDeviceAlignmentInDemoDatagram();
+ }
+
+ private boolean getWaitForDeviceAlignmentInDemoDatagram() {
+ return mWaitForDeviceAlignmentInDemoDatagram;
+ }
+
+ private boolean getWaitForDeviceAlignmentInDemoDatagramFromResources() {
+ boolean waitForDeviceAlignmentInDemoDatagram = false;
+ try {
+ waitForDeviceAlignmentInDemoDatagram = mContext.getResources().getBoolean(
+ R.bool.config_wait_for_device_alignment_in_demo_datagram);
+ } catch (Resources.NotFoundException ex) {
+ loge("getWaitForDeviceAlignmentInDemoDatagram: ex=" + ex);
+ }
+
+ return waitForDeviceAlignmentInDemoDatagram;
+ }
+
private static void logd(@NonNull String log) {
Rlog.d(TAG, log);
}
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
index 4fc8d55..f764b2b 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
@@ -239,7 +239,7 @@
if (mIsDemoMode && (error == SatelliteManager.SATELLITE_RESULT_SUCCESS)) {
if (argument.skipCheckingSatelliteAligned) {
logd("Satellite was already aligned. No need to check alignment again");
- } else if (!mIsAligned) {
+ } else if (mDatagramController.waitForAligningToSatellite(mIsAligned)) {
logd("Satellite is not aligned in demo mode, wait for the alignment.");
startSatelliteAlignedTimer(request);
break;
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
index 145b017..f1f0fde 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
@@ -620,7 +620,7 @@
DatagramReceiverHandlerRequest request = new DatagramReceiverHandlerRequest(
callback, phone, subId);
synchronized (mLock) {
- if (mIsAligned) {
+ if (!mDatagramController.waitForAligningToSatellite(mIsAligned)) {
Message msg = obtainMessage(EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE,
request);
AsyncResult.forMessage(msg, null, null);
diff --git a/src/java/com/android/internal/telephony/satellite/DemoSimulator.java b/src/java/com/android/internal/telephony/satellite/DemoSimulator.java
new file mode 100644
index 0000000..3c31ae8
--- /dev/null
+++ b/src/java/com/android/internal/telephony/satellite/DemoSimulator.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.satellite;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telephony.IIntegerConsumer;
+import android.telephony.satellite.stub.ISatelliteListener;
+import android.telephony.satellite.stub.NtnSignalStrength;
+import android.telephony.satellite.stub.SatelliteModemState;
+import android.telephony.satellite.stub.SatelliteResult;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
+public class DemoSimulator extends StateMachine {
+ private static final String TAG = "DemoSimulator";
+ private static final boolean DBG = true;
+
+ private static final int EVENT_SATELLITE_MODE_ON = 1;
+ private static final int EVENT_SATELLITE_MODE_OFF = 2;
+ private static final int EVENT_DEVICE_ALIGNED_WITH_SATELLITE = 3;
+ protected static final int EVENT_DEVICE_ALIGNED = 4;
+ protected static final int EVENT_DEVICE_NOT_ALIGNED = 5;
+
+ @NonNull private static DemoSimulator sInstance;
+
+ @NonNull private final Context mContext;
+ @NonNull private final SatelliteController mSatelliteController;
+ @NonNull private final PowerOffState mPowerOffState = new PowerOffState();
+ @NonNull private final NotConnectedState mNotConnectedState = new NotConnectedState();
+ @NonNull private final ConnectedState mConnectedState = new ConnectedState();
+ @NonNull private final Object mLock = new Object();
+ @GuardedBy("mLock")
+ private boolean mIsAligned = false;
+ private ISatelliteListener mISatelliteListener;
+
+ /**
+ * @return The singleton instance of DemoSimulator.
+ */
+ public static DemoSimulator getInstance() {
+ if (sInstance == null) {
+ Log.e(TAG, "DemoSimulator was not yet initialized.");
+ }
+ return sInstance;
+ }
+
+ /**
+ * Create the DemoSimulator singleton instance.
+ *
+ * @param context The Context for the DemoSimulator.
+ * @return The singleton instance of DemoSimulator.
+ */
+ public static DemoSimulator make(@NonNull Context context,
+ @NonNull SatelliteController satelliteController) {
+ if (sInstance == null) {
+ sInstance = new DemoSimulator(context, Looper.getMainLooper(), satelliteController);
+ }
+ return sInstance;
+ }
+
+ /**
+ * Create a DemoSimulator.
+ *
+ * @param context The Context for the DemoSimulator.
+ * @param looper The looper associated with the handler of this class.
+ */
+ protected DemoSimulator(@NonNull Context context, @NonNull Looper looper,
+ @NonNull SatelliteController satelliteController) {
+ super(TAG, looper);
+
+ mContext = context;
+ mSatelliteController = satelliteController;
+ addState(mPowerOffState);
+ addState(mNotConnectedState);
+ addState(mConnectedState);
+ setInitialState(mPowerOffState);
+ start();
+ }
+
+ private class PowerOffState extends State {
+ @Override
+ public void enter() {
+ logd("Entering PowerOffState");
+ }
+
+ @Override
+ public void exit() {
+ logd("Exiting PowerOffState");
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (DBG) log("PowerOffState: processing " + getWhatToString(msg.what));
+ switch (msg.what) {
+ case EVENT_SATELLITE_MODE_ON:
+ transitionTo(mNotConnectedState);
+ break;
+ }
+ // Ignore all unexpected events.
+ return HANDLED;
+ }
+ }
+
+ private class NotConnectedState extends State {
+ @Override
+ public void enter() {
+ logd("Entering NotConnectedState");
+
+ try {
+ NtnSignalStrength ntnSignalStrength = new NtnSignalStrength();
+ ntnSignalStrength.signalStrengthLevel = 0;
+ mISatelliteListener.onSatelliteModemStateChanged(
+ SatelliteModemState.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ mISatelliteListener.onNtnSignalStrengthChanged(ntnSignalStrength);
+
+ synchronized (mLock) {
+ if (mIsAligned) {
+ handleEventDeviceAlignedWithSatellite(true);
+ }
+ }
+ } catch (RemoteException e) {
+ loge("NotConnectedState: RemoteException " + e);
+ }
+ }
+
+ @Override
+ public void exit() {
+ logd("Exiting NotConnectedState");
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (DBG) log("NotConnectedState: processing " + getWhatToString(msg.what));
+ switch (msg.what) {
+ case EVENT_SATELLITE_MODE_OFF:
+ transitionTo(mPowerOffState);
+ break;
+ case EVENT_DEVICE_ALIGNED_WITH_SATELLITE:
+ handleEventDeviceAlignedWithSatellite((boolean) msg.obj);
+ break;
+ case EVENT_DEVICE_ALIGNED:
+ transitionTo(mConnectedState);
+ break;
+ }
+ // Ignore all unexpected events.
+ return HANDLED;
+ }
+
+ private void handleEventDeviceAlignedWithSatellite(boolean isAligned) {
+ if (isAligned && !hasMessages(EVENT_DEVICE_ALIGNED)) {
+ long durationMillis = mSatelliteController.getDemoPointingAlignedDurationMillis();
+ logd("NotConnectedState: handleEventAlignedWithSatellite isAligned=true."
+ + " Send delayed EVENT_DEVICE_ALIGNED message in"
+ + " durationMillis=" + durationMillis);
+ sendMessageDelayed(EVENT_DEVICE_ALIGNED, durationMillis);
+ } else if (!isAligned && hasMessages(EVENT_DEVICE_ALIGNED)) {
+ logd("NotConnectedState: handleEventAlignedWithSatellite isAligned=false."
+ + " Remove EVENT_DEVICE_ALIGNED message.");
+ removeMessages(EVENT_DEVICE_ALIGNED);
+ }
+ }
+ }
+
+ private class ConnectedState extends State {
+ @Override
+ public void enter() {
+ logd("Entering ConnectedState");
+
+ try {
+ NtnSignalStrength ntnSignalStrength = new NtnSignalStrength();
+ ntnSignalStrength.signalStrengthLevel = 2;
+ mISatelliteListener.onSatelliteModemStateChanged(
+ SatelliteModemState.SATELLITE_MODEM_STATE_CONNECTED);
+ mISatelliteListener.onNtnSignalStrengthChanged(ntnSignalStrength);
+
+ synchronized (mLock) {
+ if (!mIsAligned) {
+ handleEventDeviceAlignedWithSatellite(false);
+ }
+ }
+ } catch (RemoteException e) {
+ loge("ConnectedState: RemoteException " + e);
+ }
+ }
+
+ @Override
+ public void exit() {
+ logd("Exiting ConnectedState");
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (DBG) log("ConnectedState: processing " + getWhatToString(msg.what));
+ switch (msg.what) {
+ case EVENT_SATELLITE_MODE_OFF:
+ transitionTo(mPowerOffState);
+ break;
+ case EVENT_DEVICE_ALIGNED_WITH_SATELLITE:
+ handleEventDeviceAlignedWithSatellite((boolean) msg.obj);
+ break;
+ case EVENT_DEVICE_NOT_ALIGNED:
+ transitionTo(mNotConnectedState);
+ break;
+ }
+ // Ignore all unexpected events.
+ return HANDLED;
+ }
+
+ private void handleEventDeviceAlignedWithSatellite(boolean isAligned) {
+ if (!isAligned && !hasMessages(EVENT_DEVICE_NOT_ALIGNED)) {
+ long durationMillis =
+ mSatelliteController.getDemoPointingNotAlignedDurationMillis();
+ logd("ConnectedState: handleEventAlignedWithSatellite isAligned=false."
+ + " Send delayed EVENT_DEVICE_NOT_ALIGNED message"
+ + " in durationMillis=" + durationMillis);
+ sendMessageDelayed(EVENT_DEVICE_NOT_ALIGNED, durationMillis);
+ } else if (isAligned && hasMessages(EVENT_DEVICE_NOT_ALIGNED)) {
+ logd("ConnectedState: handleEventAlignedWithSatellite isAligned=true."
+ + " Remove EVENT_DEVICE_NOT_ALIGNED message.");
+ removeMessages(EVENT_DEVICE_NOT_ALIGNED);
+ }
+ }
+ }
+
+ /**
+ * @return the string for msg.what
+ */
+ @Override
+ protected String getWhatToString(int what) {
+ String whatString;
+ switch (what) {
+ case EVENT_SATELLITE_MODE_ON:
+ whatString = "EVENT_SATELLITE_MODE_ON";
+ break;
+ case EVENT_SATELLITE_MODE_OFF:
+ whatString = "EVENT_SATELLITE_MODE_OFF";
+ break;
+ case EVENT_DEVICE_ALIGNED_WITH_SATELLITE:
+ whatString = "EVENT_DEVICE_ALIGNED_WITH_SATELLITE";
+ break;
+ case EVENT_DEVICE_ALIGNED:
+ whatString = "EVENT_DEVICE_ALIGNED";
+ break;
+ case EVENT_DEVICE_NOT_ALIGNED:
+ whatString = "EVENT_DEVICE_NOT_ALIGNED";
+ break;
+ default:
+ whatString = "UNKNOWN EVENT " + what;
+ }
+ return whatString;
+ }
+
+ /**
+ * Register the callback interface with satellite service.
+ *
+ * @param listener The callback interface to handle satellite service indications.
+ */
+ public void setSatelliteListener(@NonNull ISatelliteListener listener) {
+ mISatelliteListener = listener;
+ }
+
+ /**
+ * Allow cellular modem scanning while satellite mode is on.
+ *
+ * @param enabled {@code true} to enable cellular modem while satellite mode is on
+ * and {@code false} to disable
+ * @param errorCallback The callback to receive the error code result of the operation.
+ */
+ public void enableCellularModemWhileSatelliteModeIsOn(boolean enabled,
+ @NonNull IIntegerConsumer errorCallback) {
+ try {
+ errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS);
+ } catch (RemoteException e) {
+ loge("enableCellularModemWhileSatelliteModeIsOn: RemoteException " + e);
+ }
+ }
+
+ /**
+ * This function is used by {@link SatelliteSessionController} to notify {@link DemoSimulator}
+ * that satellite mode is ON.
+ */
+ public void onSatelliteModeOn() {
+ if (mSatelliteController.isDemoModeEnabled()) {
+ sendMessage(EVENT_SATELLITE_MODE_ON);
+ }
+ }
+
+ /**
+ * This function is used by {@link SatelliteSessionController} to notify {@link DemoSimulator}
+ * that satellite mode is OFF.
+ */
+ public void onSatelliteModeOff() {
+ sendMessage(EVENT_SATELLITE_MODE_OFF);
+ }
+
+ /**
+ * Set whether the device is aligned with the satellite.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public void setDeviceAlignedWithSatellite(boolean isAligned) {
+ synchronized (mLock) {
+ if (mSatelliteController.isDemoModeEnabled()) {
+ mIsAligned = isAligned;
+ sendMessage(EVENT_DEVICE_ALIGNED_WITH_SATELLITE, isAligned);
+ }
+ }
+ }
+}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 1cc2977..35603ab 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -162,6 +162,10 @@
* to enable satellite.
*/
public static final int TIMEOUT_TYPE_WAIT_FOR_SATELLITE_ENABLING_RESPONSE = 1;
+ /** This is used by CTS to override demo pointing aligned duration. */
+ public static final int TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS = 2;
+ /** This is used by CTS to override demo pointing not aligned duration. */
+ public static final int TIMEOUT_TYPE_DEMO_POINTING_NOT_ALIGNED_DURATION_MILLIS = 3;
/** Key used to read/write OEM-enabled satellite provision status in shared preferences. */
private static final String OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY =
@@ -214,7 +218,8 @@
@NonNull private static SatelliteController sInstance;
@NonNull private final Context mContext;
@NonNull private final SatelliteModemInterface mSatelliteModemInterface;
- @NonNull private SatelliteSessionController mSatelliteSessionController;
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ @NonNull protected SatelliteSessionController mSatelliteSessionController;
@NonNull private final PointingAppController mPointingAppController;
@NonNull private final DatagramController mDatagramController;
@NonNull private final ControllerMetricsStats mControllerMetricsStats;
@@ -401,6 +406,8 @@
private final SparseArray<List<String>> mMergedPlmnListPerCarrier = new SparseArray<>();
private static AtomicLong sNextSatelliteEnableRequestId = new AtomicLong(0);
private long mWaitTimeForSatelliteEnablingResponse;
+ private long mDemoPointingAlignedDurationMillis;
+ private long mDemoPointingNotAlignedDurationMillis;
/** Key used to read/write satellite system notification done in shared preferences. */
private static final String SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY =
@@ -528,6 +535,9 @@
null);
loadSatelliteSharedPreferences();
mWaitTimeForSatelliteEnablingResponse = getWaitForSatelliteEnablingResponseTimeoutMillis();
+ mDemoPointingAlignedDurationMillis = getDemoPointingAlignedDurationMillisFromResources();
+ mDemoPointingNotAlignedDurationMillis =
+ getDemoPointingNotAlignedDurationMillisFromResources();
}
/**
@@ -2046,6 +2056,8 @@
logd("setDeviceAlignedWithSatellite: oemEnabledSatelliteFlag is disabled");
return;
}
+
+ DemoSimulator.getInstance().setDeviceAlignedWithSatellite(isAligned);
mDatagramController.setDeviceAlignedWithSatellite(isAligned);
}
@@ -2376,6 +2388,25 @@
}
/**
+ * This API can be used by only CTS to override the boolean configs used by the
+ * DatagramController module.
+ *
+ * @param enable Whether to enable or disable boolean config.
+ * @return {@code true} if the boolean config is set successfully, {@code false} otherwise.
+ */
+ public boolean setDatagramControllerBooleanConfig(
+ boolean reset, int booleanType, boolean enable) {
+ if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("setDatagramControllerBooleanConfig: oemEnabledSatelliteFlag is disabled");
+ return false;
+ }
+ logd("setDatagramControllerBooleanConfig: reset=" + reset + ", booleanType="
+ + booleanType + ", enable=" + enable);
+ return mDatagramController.setDatagramControllerBooleanConfig(
+ reset, booleanType, enable);
+ }
+
+ /**
* This API can be used by only CTS to override timeout durations used by SatelliteController
* module.
*
@@ -2402,6 +2433,20 @@
mWaitTimeForSatelliteEnablingResponse = timeoutMillis;
}
logd("mWaitTimeForSatelliteEnablingResponse=" + mWaitTimeForSatelliteEnablingResponse);
+ } else if (timeoutType == TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS) {
+ if (reset) {
+ mDemoPointingAlignedDurationMillis =
+ getDemoPointingAlignedDurationMillisFromResources();
+ } else {
+ mDemoPointingAlignedDurationMillis = timeoutMillis;
+ }
+ } else if (timeoutType == TIMEOUT_TYPE_DEMO_POINTING_NOT_ALIGNED_DURATION_MILLIS) {
+ if (reset) {
+ mDemoPointingNotAlignedDurationMillis =
+ getDemoPointingNotAlignedDurationMillisFromResources();
+ } else {
+ mDemoPointingNotAlignedDurationMillis = timeoutMillis;
+ }
} else {
logw("Invalid timeoutType=" + timeoutType);
return false;
@@ -3198,6 +3243,9 @@
}
mSatelliteSessionController = SatelliteSessionController.make(
mContext, getLooper(), supported);
+ logd("create a new SatelliteSessionController due to isSatelliteSupported state has "
+ + "changed to " + supported);
+
if (supported) {
registerForSatelliteProvisionStateChanged();
registerForPendingDatagramCount();
@@ -3386,6 +3434,7 @@
synchronized (mNtnSignalsStrengthLock) {
mNtnSignalStrength = ntnSignalStrength;
}
+ mSessionMetricsStats.updateMaxNtnSignalStrengthLevel(ntnSignalStrength.getLevel());
List<INtnSignalStrengthCallback> deadCallersList = new ArrayList<>();
mNtnSignalStrengthChangedListeners.values().forEach(listener -> {
@@ -3458,6 +3507,10 @@
}
}
mIsSatelliteSupported = supported;
+ mSatelliteSessionController = SatelliteSessionController.make(
+ mContext, getLooper(), supported);
+ logd("create a new SatelliteSessionController due to isSatelliteSupported state has "
+ + "changed to " + supported);
}
List<ISatelliteSupportedStateCallback> deadCallersList = new ArrayList<>();
@@ -4568,6 +4621,40 @@
}
}
+ private long getDemoPointingAlignedDurationMillisFromResources() {
+ long durationMillis = 15000L;
+ try {
+ durationMillis = mContext.getResources().getInteger(
+ R.integer.config_demo_pointing_aligned_duration_millis);
+ } catch (Resources.NotFoundException ex) {
+ loge("getPointingAlignedDurationMillis: ex=" + ex);
+ }
+
+ return durationMillis;
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public long getDemoPointingAlignedDurationMillis() {
+ return mDemoPointingAlignedDurationMillis;
+ }
+
+ private long getDemoPointingNotAlignedDurationMillisFromResources() {
+ long durationMillis = 30000L;
+ try {
+ durationMillis = mContext.getResources().getInteger(
+ R.integer.config_demo_pointing_not_aligned_duration_millis);
+ } catch (Resources.NotFoundException ex) {
+ loge("getPointingNotAlignedDurationMillis: ex=" + ex);
+ }
+
+ return durationMillis;
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public long getDemoPointingNotAlignedDurationMillis() {
+ return mDemoPointingNotAlignedDurationMillis;
+ }
+
private static void logd(@NonNull String log) {
Rlog.d(TAG, log);
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
index 2e99ae6..8a26fd2 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
@@ -42,6 +42,7 @@
import android.telephony.satellite.stub.ISatellite;
import android.telephony.satellite.stub.ISatelliteCapabilitiesConsumer;
import android.telephony.satellite.stub.ISatelliteListener;
+import android.telephony.satellite.stub.SatelliteModemState;
import android.telephony.satellite.stub.SatelliteService;
import android.text.TextUtils;
import android.util.Pair;
@@ -64,6 +65,9 @@
@NonNull private static SatelliteModemInterface sInstance;
@NonNull private final Context mContext;
+ @NonNull private final DemoSimulator mDemoSimulator;
+ @NonNull private final SatelliteListener mVendorListener;
+ @NonNull private final SatelliteListener mDemoListener;
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
@NonNull protected final ExponentialBackoff mExponentialBackoff;
@NonNull private final Object mLock = new Object();
@@ -96,7 +100,14 @@
@NonNull private final RegistrantList mSatelliteSupportedStateChangedRegistrants =
new RegistrantList();
- @NonNull private final ISatelliteListener mListener = new ISatelliteListener.Stub() {
+ private class SatelliteListener extends ISatelliteListener.Stub {
+
+ private final boolean mIsDemoListener;
+
+ SatelliteListener(boolean isDemoListener) {
+ mIsDemoListener = isDemoListener;
+ }
+
@Override
public void onSatelliteProvisionStateChanged(boolean provisioned) {
mSatelliteProvisionStateChangedRegistrants.notifyResult(provisioned);
@@ -105,15 +116,19 @@
@Override
public void onSatelliteDatagramReceived(
android.telephony.satellite.stub.SatelliteDatagram datagram, int pendingCount) {
- logd("onSatelliteDatagramReceived: pendingCount=" + pendingCount);
- mSatelliteDatagramsReceivedRegistrants.notifyResult(new Pair<>(
- SatelliteServiceUtils.fromSatelliteDatagram(datagram), pendingCount));
+ if (notifyResultIfExpectedListener()) {
+ logd("onSatelliteDatagramReceived: pendingCount=" + pendingCount);
+ mSatelliteDatagramsReceivedRegistrants.notifyResult(new Pair<>(
+ SatelliteServiceUtils.fromSatelliteDatagram(datagram), pendingCount));
+ }
}
@Override
public void onPendingDatagrams() {
- logd("onPendingDatagrams");
- mPendingDatagramsRegistrants.notifyResult(null);
+ if (notifyResultIfExpectedListener()) {
+ logd("onPendingDatagrams");
+ mPendingDatagramsRegistrants.notifyResult(null);
+ }
}
@Override
@@ -125,33 +140,39 @@
@Override
public void onSatelliteModemStateChanged(int state) {
- mSatelliteModemStateChangedRegistrants.notifyResult(
- SatelliteServiceUtils.fromSatelliteModemState(state));
- int datagramTransferState = SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN;
- switch (state) {
- case SatelliteManager.SATELLITE_MODEM_STATE_IDLE:
- datagramTransferState = SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
- break;
- case SatelliteManager.SATELLITE_MODEM_STATE_LISTENING:
- datagramTransferState =
- SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING;
- break;
- case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING:
- datagramTransferState =
- SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING;
- break;
- case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING:
- // keep previous state as this could be retrying sending or receiving
- break;
+ if (notifyModemStateChanged(state)) {
+ mSatelliteModemStateChangedRegistrants.notifyResult(
+ SatelliteServiceUtils.fromSatelliteModemState(state));
+ int datagramTransferState =
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN;
+ switch (state) {
+ case SatelliteManager.SATELLITE_MODEM_STATE_IDLE:
+ datagramTransferState =
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
+ break;
+ case SatelliteManager.SATELLITE_MODEM_STATE_LISTENING:
+ datagramTransferState =
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING;
+ break;
+ case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING:
+ datagramTransferState =
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING;
+ break;
+ case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING:
+ // keep previous state as this could be retrying sending or receiving
+ break;
+ }
+ mDatagramTransferStateChangedRegistrants.notifyResult(datagramTransferState);
}
- mDatagramTransferStateChangedRegistrants.notifyResult(datagramTransferState);
}
@Override
public void onNtnSignalStrengthChanged(
android.telephony.satellite.stub.NtnSignalStrength ntnSignalStrength) {
- mNtnSignalStrengthChangedRegistrants.notifyResult(
- SatelliteServiceUtils.fromNtnSignalStrength(ntnSignalStrength));
+ if (notifyResultIfExpectedListener()) {
+ mNtnSignalStrengthChangedRegistrants.notifyResult(
+ SatelliteServiceUtils.fromNtnSignalStrength(ntnSignalStrength));
+ }
}
@Override
@@ -165,7 +186,22 @@
public void onSatelliteSupportedStateChanged(boolean supported) {
mSatelliteSupportedStateChangedRegistrants.notifyResult(supported);
}
- };
+
+ private boolean notifyResultIfExpectedListener() {
+ // Demo listener should notify results only during demo mode
+ // Vendor listener should notify result only during real mode
+ return mIsDemoListener == mSatelliteController.isDemoModeEnabled();
+ }
+
+ private boolean notifyModemStateChanged(int state) {
+ if (notifyResultIfExpectedListener()) {
+ return true;
+ }
+
+ return state == SatelliteModemState.SATELLITE_MODEM_STATE_OFF
+ || state == SatelliteModemState.SATELLITE_MODEM_STATE_UNAVAILABLE;
+ }
+ }
/**
* @return The singleton instance of SatelliteModemInterface.
@@ -202,6 +238,9 @@
protected SatelliteModemInterface(@NonNull Context context,
SatelliteController satelliteController, @NonNull Looper looper) {
mContext = context;
+ mDemoSimulator = DemoSimulator.make(context, satelliteController);
+ mVendorListener = new SatelliteListener(false);
+ mDemoListener = new SatelliteListener(true);
mIsSatelliteServiceSupported = getSatelliteServiceSupport();
mSatelliteController = satelliteController;
mExponentialBackoff = new ExponentialBackoff(REBIND_INITIAL_DELAY, REBIND_MAXIMUM_DELAY,
@@ -314,7 +353,8 @@
mSatelliteService = ISatellite.Stub.asInterface(service);
mExponentialBackoff.stop();
try {
- mSatelliteService.setSatelliteListener(mListener);
+ mSatelliteService.setSatelliteListener(mVendorListener);
+ mDemoSimulator.setSatelliteListener(mDemoListener);
} catch (RemoteException e) {
// TODO: Retry setSatelliteListener
logd("setSatelliteListener: RemoteException " + e);
@@ -584,19 +624,26 @@
@Nullable Message message) {
if (mSatelliteService != null) {
try {
- mSatelliteService.enableCellularModemWhileSatelliteModeIsOn(enabled,
- new IIntegerConsumer.Stub() {
- @Override
- public void accept(int result) {
- int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("enableCellularModemWhileSatelliteModeIsOn: " + error);
- Binder.withCleanCallingIdentity(() -> {
- if (message != null) {
- sendMessageWithResult(message, null, error);
- }
- });
+ IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ int error = SatelliteServiceUtils.fromSatelliteError(result);
+ logd("enableCellularModemWhileSatelliteModeIsOn: " + error);
+ Binder.withCleanCallingIdentity(() -> {
+ if (message != null) {
+ sendMessageWithResult(message, null, error);
}
});
+ }
+ };
+
+ if (mSatelliteController.isDemoModeEnabled()) {
+ mDemoSimulator.enableCellularModemWhileSatelliteModeIsOn(
+ enabled, errorCallback);
+ } else {
+ mSatelliteService.enableCellularModemWhileSatelliteModeIsOn(
+ enabled, errorCallback);
+ }
} catch (RemoteException e) {
loge("enableCellularModemWhileSatelliteModeIsOn: RemoteException " + e);
if (message != null) {
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
index cd3c05b..dcf9bb0 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
@@ -39,7 +39,6 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemProperties;
-import android.telephony.Rlog;
import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.stub.ISatelliteGateway;
@@ -163,15 +162,9 @@
*/
public static SatelliteSessionController make(
@NonNull Context context, @NonNull Looper looper, boolean isSatelliteSupported) {
- if (sInstance == null) {
+ if (sInstance == null || isSatelliteSupported != sInstance.mIsSatelliteSupported) {
sInstance = new SatelliteSessionController(context, looper, isSatelliteSupported,
SatelliteModemInterface.getInstance());
- } else {
- if (isSatelliteSupported != sInstance.mIsSatelliteSupported) {
- Rlog.e(TAG, "New satellite support state " + isSatelliteSupported
- + " is different from existing state " + sInstance.mIsSatelliteSupported
- + ". Ignore the new state.");
- }
}
return sInstance;
}
@@ -450,6 +443,7 @@
}
unbindService();
stopNbIotInactivityTimer();
+ DemoSimulator.getInstance().onSatelliteModeOff();
notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_OFF);
}
@@ -520,6 +514,7 @@
} else {
transitionTo(mIdleState);
}
+ DemoSimulator.getInstance().onSatelliteModeOn();
} else {
/*
* During the state transition from ENABLING to NOT_CONNECTED, modem might be
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java
index c50db07..73ede60 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java
@@ -16,7 +16,10 @@
package com.android.internal.telephony.satellite.metrics;
+import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE;
+
import android.annotation.NonNull;
+import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.SatelliteManager;
import android.util.Log;
@@ -41,7 +44,7 @@
private int mCountOfSuccessfulIncomingDatagram;
private int mCountOfIncomingDatagramFailed;
private boolean mIsDemoMode;
-
+ private @NtnSignalStrength.NtnSignalStrengthLevel int mMaxNtnSignalStrengthLevel;
private SessionMetricsStats() {
initializeSessionMetricsParam();
@@ -144,6 +147,17 @@
return this;
}
+ /** Updates the max Ntn signal strength level for the session. */
+ public SessionMetricsStats updateMaxNtnSignalStrengthLevel(
+ @NtnSignalStrength.NtnSignalStrengthLevel int latestNtnSignalStrengthLevel) {
+ if (latestNtnSignalStrengthLevel > mMaxNtnSignalStrengthLevel) {
+ mMaxNtnSignalStrengthLevel = latestNtnSignalStrengthLevel;
+ }
+ logd("updateMaxNtnSignalsStrength: latest signal strength=" + latestNtnSignalStrengthLevel
+ + ", max signal strength=" + mMaxNtnSignalStrengthLevel);
+ return this;
+ }
+
/** Report the session metrics atoms to PersistAtomsStorage in telephony. */
public void reportSessionMetrics() {
SatelliteStats.SatelliteSessionParams sessionParams =
@@ -159,6 +173,7 @@
.setCountOfIncomingDatagramSuccess(mCountOfSuccessfulIncomingDatagram)
.setCountOfIncomingDatagramFailed(mCountOfIncomingDatagramFailed)
.setIsDemoMode(mIsDemoMode)
+ .setMaxNtnSignalStrengthLevel(mMaxNtnSignalStrengthLevel)
.build();
logd("reportSessionMetrics: " + sessionParams.toString());
SatelliteStats.getInstance().onSatelliteSessionMetrics(sessionParams);
@@ -187,6 +202,7 @@
mCountOfSuccessfulIncomingDatagram = 0;
mCountOfIncomingDatagramFailed = 0;
mIsDemoMode = false;
+ mMaxNtnSignalStrengthLevel = NTN_SIGNAL_STRENGTH_NONE;
}
private static void logd(@NonNull String log) {
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
index 3d07d47..7596754 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
@@ -1044,7 +1044,7 @@
throw new IllegalArgumentException("updateSubscription: subscription does not "
+ "exist. subId=" + subId);
}
- if (oldSubInfo.equals(newSubInfo)) return;
+ if (oldSubInfo.equalsDbItemsOnly(newSubInfo)) return;
if (updateDatabase(subId, createDeltaContentValues(oldSubInfo, newSubInfo)) > 0) {
mAllSubscriptionInfoInternalCache.put(subId, newSubInfo);
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
index bb77d5c..c6dee7c 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
@@ -454,12 +454,13 @@
*/
private final int mIsOnlyNonTerrestrialNetwork;
- // Below are the fields that do not exist in the SimInfo table.
+ // This field does not exist in the SimInfo table.
/**
* The card ID of the SIM card. This maps uniquely to {@link #mCardString}.
*/
private final int mCardId;
+ // This field does not exist in the SimInfo table.
/**
* Whether group of the subscription is disabled. This is only useful if it's a grouped
* opportunistic subscription. In this case, if all primary (non-opportunistic) subscriptions
@@ -1370,11 +1371,14 @@
+ "]";
}
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- SubscriptionInfoInternal that = (SubscriptionInfoInternal) o;
+ /**
+ * Campare only the columns existing in the SimInfo table and the mapped variables to see if
+ * they are equal.
+ *
+ * @param that SubscriptionInfoInternal to be compared
+ * @return {@code true} if equals.
+ */
+ public boolean equalsDbItemsOnly(@NonNull SubscriptionInfoInternal that) {
return mId == that.mId && mSimSlotIndex == that.mSimSlotIndex
&& mDisplayNameSource == that.mDisplayNameSource && mIconTint == that.mIconTint
&& mDataRoaming == that.mDataRoaming && mIsEmbedded == that.mIsEmbedded
@@ -1407,7 +1411,6 @@
&& mPortIndex == that.mPortIndex && mUsageSetting == that.mUsageSetting
&& mLastUsedTPMessageReference == that.mLastUsedTPMessageReference
&& mUserId == that.mUserId && mIsSatelliteEnabled == that.mIsSatelliteEnabled
- && mCardId == that.mCardId && mIsGroupDisabled == that.mIsGroupDisabled
&& mIccId.equals(that.mIccId) && mDisplayName.equals(that.mDisplayName)
&& mCarrierName.equals(that.mCarrierName) && mNumber.equals(that.mNumber)
&& mMcc.equals(that.mMcc) && mMnc.equals(that.mMnc) && mEhplmns.equals(
@@ -1431,6 +1434,15 @@
}
@Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SubscriptionInfoInternal that = (SubscriptionInfoInternal) o;
+ return equalsDbItemsOnly(that)
+ && mCardId == that.mCardId && mIsGroupDisabled == that.mIsGroupDisabled;
+ }
+
+ @Override
public int hashCode() {
int result = Objects.hash(mId, mIccId, mSimSlotIndex, mDisplayName, mCarrierName,
mDisplayNameSource, mIconTint, mNumber, mDataRoaming, mMcc, mMnc, mEhplmns, mHplmns,
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
index 3aad333..5e5cb9a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
@@ -1149,6 +1149,7 @@
mSatelliteSession1.countOfIncomingDatagramSuccess = 1;
mSatelliteSession1.countOfIncomingDatagramFailed = 0;
mSatelliteSession1.isDemoMode = false;
+ mSatelliteSession1.maxNtnSignalStrengthLevel = 2;
mSatelliteSession2 = new SatelliteSession();
mSatelliteSession2.satelliteServiceInitializationResult =
@@ -1156,16 +1157,17 @@
mSatelliteSession2.satelliteTechnology =
SatelliteProtoEnums.NT_RADIO_TECHNOLOGY_NB_IOT_NTN;
mSatelliteSession2.count = 1;
- mSatelliteSession1.satelliteServiceTerminationResult =
+ mSatelliteSession2.satelliteServiceTerminationResult =
SatelliteProtoEnums.SATELLITE_ERROR_NONE;
- mSatelliteSession1.initializationProcessingTimeMillis = 300;
- mSatelliteSession1.terminationProcessingTimeMillis = 100;
- mSatelliteSession1.sessionDurationSeconds = 10;
- mSatelliteSession1.countOfOutgoingDatagramSuccess = 0;
- mSatelliteSession1.countOfOutgoingDatagramFailed = 2;
- mSatelliteSession1.countOfIncomingDatagramSuccess = 0;
- mSatelliteSession1.countOfIncomingDatagramFailed = 1;
+ mSatelliteSession2.initializationProcessingTimeMillis = 300;
+ mSatelliteSession2.terminationProcessingTimeMillis = 100;
+ mSatelliteSession2.sessionDurationSeconds = 10;
+ mSatelliteSession2.countOfOutgoingDatagramSuccess = 0;
+ mSatelliteSession2.countOfOutgoingDatagramFailed = 2;
+ mSatelliteSession2.countOfIncomingDatagramSuccess = 0;
+ mSatelliteSession2.countOfIncomingDatagramFailed = 1;
mSatelliteSession2.isDemoMode = true;
+ mSatelliteSession2.maxNtnSignalStrengthLevel = 4;
mSatelliteSessions =
new SatelliteSession[] {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java
index 9a84224..bc665f8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java
@@ -16,6 +16,8 @@
package com.android.internal.telephony.metrics;
+import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_GOOD;
+
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -167,6 +169,7 @@
.setCountOfIncomingDatagramSuccess(1)
.setCountOfIncomingDatagramFailed(0)
.setIsDemoMode(false)
+ .setMaxNtnSignalStrengthLevel(NTN_SIGNAL_STRENGTH_GOOD)
.build();
mSatelliteStats.onSatelliteSessionMetrics(param);
@@ -189,6 +192,7 @@
stats.countOfIncomingDatagramSuccess);
assertEquals(param.getCountOfIncomingDatagramFailed(), stats.countOfIncomingDatagramFailed);
assertEquals(param.getIsDemoMode(), stats.isDemoMode);
+ assertEquals(param.getMaxNtnSignalStrengthLevel(), stats.maxNtnSignalStrengthLevel);
verifyNoMoreInteractions(mPersistAtomsStorage);
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
index ecec4cd..4896671 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
@@ -487,6 +487,7 @@
mDatagramDispatcherUT.setDemoMode(true);
mDatagramDispatcherUT.setDuration(TEST_EXPIRE_TIMER_SATELLITE_ALIGN);
mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false);
+ when(mMockDatagramController.waitForAligningToSatellite(false)).thenReturn(true);
int[] sosDatagramTypes = {DATAGRAM_TYPE1, DATAGRAM_TYPE4, DATAGRAM_TYPE5};
for (int datagramType : sosDatagramTypes) {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
index 361c638..79d3657 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
@@ -372,6 +372,7 @@
mTestDemoModeDatagramReceiver.setDemoMode(true);
mTestDemoModeDatagramReceiver.setDuration(TEST_EXPIRE_TIMER_SATELLITE_ALIGN);
mTestDemoModeDatagramReceiver.setDeviceAlignedWithSatellite(false);
+ when(mMockDatagramController.waitForAligningToSatellite(false)).thenReturn(true);
when(mMockDatagramController.popDemoModeDatagram()).thenReturn(mDatagram);
mTestDemoModeDatagramReceiver.pollPendingSatelliteDatagrams(SUB_ID, mResultListener::offer);
processAllMessages();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DemoSimulatorTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DemoSimulatorTest.java
new file mode 100644
index 0000000..319e39f
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DemoSimulatorTest.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.satellite;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Looper;
+import android.telephony.satellite.stub.ISatelliteListener;
+import android.telephony.satellite.stub.NtnSignalStrength;
+import android.telephony.satellite.stub.SatelliteModemState;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.internal.telephony.TelephonyTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit tests for DemoSimulator
+ */
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class DemoSimulatorTest extends TelephonyTest {
+ private static final String TAG = "DemoSimulatorTest";
+ private static final long TEST_DEVICE_POINTING_ALIGNED_DURATION_MILLIS = 200L;
+ private static final long TEST_DEVICE_POINTING_NOT_ALIGNED_DURATION_MILLIS = 300L;
+ private static final String STATE_POWER_OFF = "PowerOffState";
+ private static final String STATE_NOT_CONNECTED = "NotConnectedState";
+ private static final String STATE_CONNECTED = "ConnectedState";
+
+ private TestDemoSimulator mTestDemoSimulator;
+ @Mock private ISatelliteListener mISatelliteListener;
+
+ @Mock private SatelliteController mMockSatelliteController;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp(getClass().getSimpleName());
+ MockitoAnnotations.initMocks(this);
+
+ when(mMockSatelliteController.isDemoModeEnabled()).thenReturn(true);
+ when(mMockSatelliteController.getDemoPointingAlignedDurationMillis()).thenReturn(
+ TEST_DEVICE_POINTING_ALIGNED_DURATION_MILLIS);
+ when(mMockSatelliteController.getDemoPointingNotAlignedDurationMillis()).thenReturn(
+ TEST_DEVICE_POINTING_NOT_ALIGNED_DURATION_MILLIS);
+
+ mTestDemoSimulator = new TestDemoSimulator(mContext, Looper.myLooper(),
+ mMockSatelliteController);
+ mTestDemoSimulator.setSatelliteListener(mISatelliteListener);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @Test
+ public void testInitialState() {
+ assertNotNull(mTestDemoSimulator);
+ processAllMessages();
+ assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName());
+ }
+
+ @Test
+ public void testStateTransition() {
+ // State transitions: POWER_OFF -> NOT_CONNECTED -> CONNECTED
+ moveToConnectedState();
+
+ // Device is not aligned with satellite. EVENT_DEVICE_NOT_ALIGNED timer should start
+ mTestDemoSimulator.setDeviceAlignedWithSatellite(false);
+ processAllMessages();
+ assertTrue(mTestDemoSimulator.isDeviceNotAlignedTimerStarted());
+
+ // After timeout, DemoSimulator should move to NOT_CONNECTED state.
+ moveTimeForward(TEST_DEVICE_POINTING_NOT_ALIGNED_DURATION_MILLIS);
+ processAllMessages();
+ assertEquals(STATE_NOT_CONNECTED, mTestDemoSimulator.getCurrentStateName());
+
+ // Satellite mode is OFF. DemoSimulator should move to POWER_OFF state.
+ mTestDemoSimulator.onSatelliteModeOff();
+ processAllMessages();
+ assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName());
+ }
+
+ @Test
+ public void testNotConnectedState_enter() throws Exception {
+ clearInvocations(mISatelliteListener);
+
+ // State transitions: POWER_OFF -> NOT_CONNECTED
+ moveToNotConnectedState();
+
+ verify(mISatelliteListener).onSatelliteModemStateChanged(
+ SatelliteModemState.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ ArgumentCaptor<NtnSignalStrength> ntnSignalStrength = ArgumentCaptor.forClass(
+ NtnSignalStrength.class);
+ verify(mISatelliteListener).onNtnSignalStrengthChanged(ntnSignalStrength.capture());
+ assertEquals(0, ntnSignalStrength.getValue().signalStrengthLevel);
+ }
+
+ @Test
+ public void testNotConnectedState() {
+ // State transitions: POWER_OFF -> NOT_CONNECTED
+ moveToNotConnectedState();
+
+ // Device is aligned with satellite. EVENT_DEVICE_ALIGNED timer should start.
+ mTestDemoSimulator.setDeviceAlignedWithSatellite(true);
+ processAllMessages();
+ assertTrue(mTestDemoSimulator.isDeviceAlignedTimerStarted());
+
+ // Device is not aligned with satellite. EVENT_DEVICE_ALIGNED messages should be removed.
+ mTestDemoSimulator.setDeviceAlignedWithSatellite(false);
+ processAllMessages();
+ assertFalse(mTestDemoSimulator.isDeviceAlignedTimerStarted());
+ assertEquals(STATE_NOT_CONNECTED, mTestDemoSimulator.getCurrentStateName());
+
+ // Satellite mode is OFF. DemoSimulator should move to POWER_OFF state.
+ mTestDemoSimulator.onSatelliteModeOff();
+ processAllMessages();
+ assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName());
+ }
+
+ @Test
+ public void testConnectedState_enter() throws Exception {
+ clearInvocations(mISatelliteListener);
+
+ // State transitions: POWER_OFF -> NOT_CONNECTED -> CONNECTED
+ moveToConnectedState();
+
+ verify(mISatelliteListener).onSatelliteModemStateChanged(
+ SatelliteModemState.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ verify(mISatelliteListener).onSatelliteModemStateChanged(
+ SatelliteModemState.SATELLITE_MODEM_STATE_CONNECTED);
+ ArgumentCaptor<NtnSignalStrength> ntnSignalStrength = ArgumentCaptor.forClass(
+ NtnSignalStrength.class);
+ verify(mISatelliteListener, times(2))
+ .onNtnSignalStrengthChanged(ntnSignalStrength.capture());
+ NtnSignalStrength ntnSignalStrengthOnConnected = ntnSignalStrength.getAllValues().get(1);
+ assertEquals(2, ntnSignalStrengthOnConnected.signalStrengthLevel);
+ }
+
+ @Test
+ public void testConnectedState() {
+ // State transitions: POWER_OFF -> NOT_CONNECTED -> CONNECTED
+ moveToConnectedState();
+
+ // Device is not aligned with satellite. EVENT_DEVICE_NOT_ALIGNED timer should start
+ mTestDemoSimulator.setDeviceAlignedWithSatellite(false);
+ processAllMessages();
+ assertTrue(mTestDemoSimulator.isDeviceNotAlignedTimerStarted());
+
+ // Device is aligned with satellite before timeout.
+ // EVENT_DEVICE_NOT_ALIGNED messages should be removed.
+ mTestDemoSimulator.setDeviceAlignedWithSatellite(true);
+ processAllMessages();
+ assertFalse(mTestDemoSimulator.isDeviceNotAlignedTimerStarted());
+ assertEquals(STATE_CONNECTED, mTestDemoSimulator.getCurrentStateName());
+
+ // Satellite mode is off. DemoSimulator should move to POWER_OFF state
+ mTestDemoSimulator.onSatelliteModeOff();
+ processAllMessages();
+ assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName());
+ }
+
+ private void moveToNotConnectedState() {
+ // DemoSimulator will initially be in POWER_OFF state.
+ assertNotNull(mTestDemoSimulator);
+ processAllMessages();
+ assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName());
+
+ // Satellite mode is ON. DemoSimulator should move to NOT_CONNECTED state.
+ mTestDemoSimulator.onSatelliteModeOn();
+ processAllMessages();
+ assertEquals(STATE_NOT_CONNECTED, mTestDemoSimulator.getCurrentStateName());
+ }
+
+ private void moveToConnectedState() {
+ // DemoSimulator will initially be in POWER_OFF state.
+ assertNotNull(mTestDemoSimulator);
+ processAllMessages();
+ assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName());
+
+ // Satellite mode is ON. DemoSimulator should move to NOT_CONNECTED state.
+ mTestDemoSimulator.onSatelliteModeOn();
+ processAllMessages();
+ assertEquals(STATE_NOT_CONNECTED, mTestDemoSimulator.getCurrentStateName());
+
+ // Device is aligned with satellite. EVENT_DEVICE_ALIGNED timer should start.
+ mTestDemoSimulator.setDeviceAlignedWithSatellite(true);
+ processAllMessages();
+ assertTrue(mTestDemoSimulator.isDeviceAlignedTimerStarted());
+
+ // After timeout, DemoSimulator should move to CONNECTED state.
+ moveTimeForward(TEST_DEVICE_POINTING_ALIGNED_DURATION_MILLIS);
+ processAllMessages();
+ assertEquals(STATE_CONNECTED, mTestDemoSimulator.getCurrentStateName());
+ }
+
+ private static class TestDemoSimulator extends DemoSimulator {
+
+ TestDemoSimulator(@NonNull Context context, @NonNull Looper looper,
+ @NonNull SatelliteController satelliteController) {
+ super(context, looper, satelliteController);
+ }
+
+ String getCurrentStateName() {
+ return getCurrentState().getName();
+ }
+
+ boolean isDeviceAlignedTimerStarted() {
+ return hasMessages(EVENT_DEVICE_ALIGNED);
+ }
+
+ boolean isDeviceNotAlignedTimerStarted() {
+ return hasMessages(EVENT_DEVICE_NOT_ALIGNED);
+ }
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
index 1484b47..f8656bf 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -202,6 +202,7 @@
@Mock private TelephonyConfigUpdateInstallReceiver mMockTelephonyConfigUpdateInstallReceiver;
@Mock private SatelliteConfigParser mMockConfigParser;
@Mock private SatelliteConfig mMockConfig;
+ @Mock private DemoSimulator mMockDemoSimulator;
private Semaphore mIIntegerConsumerSemaphore = new Semaphore(0);
private IIntegerConsumer mIIntegerConsumer = new IIntegerConsumer.Stub() {
@@ -475,6 +476,7 @@
replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[]{mPhone, mPhone2});
replaceInstance(TelephonyConfigUpdateInstallReceiver.class, "sReceiverAdaptorInstance",
null, mMockTelephonyConfigUpdateInstallReceiver);
+ replaceInstance(DemoSimulator.class, "sInstance", null, mMockDemoSimulator);
mServiceState2 = Mockito.mock(ServiceState.class);
when(mPhone.getServiceState()).thenReturn(mServiceState);
@@ -785,6 +787,7 @@
setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
mIIntegerConsumer);
+ mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -1304,6 +1307,7 @@
.registerForSatelliteModemStateChanged(callback);
resetSatelliteControllerUTToSupportedAndProvisionedState();
+ mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
errorCode = mSatelliteControllerUT.registerForSatelliteModemStateChanged(
SUB_ID, callback);
@@ -1324,7 +1328,7 @@
.unregisterForSatelliteModemStateChanged(callback);
resetSatelliteControllerUTToSupportedAndProvisionedState();
-
+ mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
mSatelliteControllerUT.unregisterForModemStateChanged(SUB_ID, callback);
verify(mMockSatelliteSessionController).unregisterForSatelliteModemStateChanged(callback);
}
@@ -2250,6 +2254,7 @@
SATELLITE_MODEM_STATE_CONNECTED);
resetSatelliteControllerUTToSupportedAndProvisionedState();
+ mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
clearInvocations(mMockSatelliteSessionController);
clearInvocations(mMockDatagramController);
sendSatelliteModemStateChangedEvent(SATELLITE_MODEM_STATE_UNAVAILABLE, null);
@@ -4502,5 +4507,9 @@
protected long getElapsedRealtime() {
return elapsedRealtime;
}
+
+ void setSatelliteSessionController(SatelliteSessionController satelliteSessionController) {
+ mSatelliteSessionController = satelliteSessionController;
+ }
}
}