Merge "Add implementation and flags for new transparency callback APIs" into main
diff --git a/flags/misc.aconfig b/flags/misc.aconfig
index 2d6992a..303c0ff 100644
--- a/flags/misc.aconfig
+++ b/flags/misc.aconfig
@@ -78,6 +78,15 @@
bug: "309896524"
}
+# OWNER=rambowang TARGET=24Q3
+flag {
+ name: "reset_mobile_network_settings"
+ is_exported: true
+ namespace: "telephony"
+ description: "Allows applications to launch Reset Mobile Network Settings page in Settings app."
+ bug:"271921464"
+}
+
# OWNER=sangyun TARGET=24Q3
flag {
name: "roaming_notification_for_single_data_network"
diff --git a/flags/subscription.aconfig b/flags/subscription.aconfig
index 76485be..aea9bd0 100644
--- a/flags/subscription.aconfig
+++ b/flags/subscription.aconfig
@@ -81,3 +81,11 @@
purpose: PURPOSE_BUGFIX
}
}
+
+# OWNER=jmattis TARGET=25Q2
+flag {
+ name: "subscription_plan_allow_status_and_end_date"
+ namespace: "telephony"
+ description: "Provide APIs to retrieve the status and recurrence rule info on a subscription plan"
+ bug: "357272015"
+}
diff --git a/src/java/com/android/internal/telephony/RILUtils.java b/src/java/com/android/internal/telephony/RILUtils.java
index a81dbc8..cbf2330 100644
--- a/src/java/com/android/internal/telephony/RILUtils.java
+++ b/src/java/com/android/internal/telephony/RILUtils.java
@@ -4132,6 +4132,34 @@
}
/**
+ * This API is for fallback to support getAllowedCarriers too.
+ *
+ * Convert an array of CarrierInfo defined in
+ * radio/aidl/android/hardware/radio/sim/CarrierInfo.aidl to a list of CarrierIdentifiers.
+ *
+ * @param carrierInfos array of CarrierInfo defined in
+ * radio/aidl/android/hardware/radio/sim/CarrierInfo.aidl
+ * @return The converted list of CarrierIdentifiers
+ */
+ public static List<CarrierIdentifier> convertAidlCarrierInfoListToHalCarrierList(
+ android.hardware.radio.sim.CarrierInfo[] carrierInfos) {
+ List<CarrierIdentifier> ret = new ArrayList<>();
+ if (carrierInfos == null) {
+ return ret;
+ }
+ for (android.hardware.radio.sim.CarrierInfo carrierInfo : carrierInfos) {
+ String mcc = carrierInfo.mcc;
+ String mnc = carrierInfo.mnc;
+ String spn = carrierInfo.spn;
+ String imsi = carrierInfo.imsiPrefix;
+ String gid1 = carrierInfo.gid1;
+ String gid2 = carrierInfo.gid2;
+ ret.add(new CarrierIdentifier(mcc, mnc, spn, imsi, gid1, gid2));
+ }
+ return ret;
+ }
+
+ /**
* Convert the sim policy defined in
* radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl to the equivalent sim
* policy defined in android.telephony/CarrierRestrictionRules.MultiSimPolicy
diff --git a/src/java/com/android/internal/telephony/SimResponse.java b/src/java/com/android/internal/telephony/SimResponse.java
index 97692a0..12c9a3c 100644
--- a/src/java/com/android/internal/telephony/SimResponse.java
+++ b/src/java/com/android/internal/telephony/SimResponse.java
@@ -123,19 +123,34 @@
if (!carrierRestrictions.allowedCarriersPrioritized) {
carrierRestrictionDefault = CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_ALLOWED;
}
-
- CarrierRestrictionRules ret = CarrierRestrictionRules.newBuilder().setAllowedCarriers(
- RILUtils.convertHalCarrierList(
- carrierRestrictions.allowedCarriers)).setExcludedCarriers(
- RILUtils.convertHalCarrierList(
- carrierRestrictions.excludedCarriers)).setDefaultCarrierRestriction(
- carrierRestrictionDefault).setMultiSimPolicy(policy).setCarrierRestrictionStatus(
- carrierRestrictions.status).setAllowedCarrierInfo(
- RILUtils.convertAidlCarrierInfoList(
- carrierRestrictions.allowedCarrierInfoList)).setExcludedCarrierInfo(
- RILUtils.convertAidlCarrierInfoList(
- carrierRestrictions.excludedCarrierInfoList)).setCarrierLockInfoFeature(
- carrierLockInfoSupported).build();
+ CarrierRestrictionRules ret = null;
+ if (carrierLockInfoSupported) {
+ // In order to support the old API { @link TelephonyManager#getAllowedCarriers() } we
+ // are parsing the allowedCarrierInfoList to CarrierIdentifier List also along with
+ // CarrierInfo List
+ ret = CarrierRestrictionRules.newBuilder().setAllowedCarriers(
+ RILUtils.convertAidlCarrierInfoListToHalCarrierList(
+ carrierRestrictions.allowedCarrierInfoList)).setExcludedCarriers(
+ RILUtils.convertAidlCarrierInfoListToHalCarrierList(
+ carrierRestrictions.excludedCarrierInfoList)).
+ setDefaultCarrierRestriction(
+ carrierRestrictionDefault).setMultiSimPolicy(
+ policy).setCarrierRestrictionStatus(
+ carrierRestrictions.status).setAllowedCarrierInfo(
+ RILUtils.convertAidlCarrierInfoList(
+ carrierRestrictions.allowedCarrierInfoList)).setExcludedCarrierInfo(
+ RILUtils.convertAidlCarrierInfoList(
+ carrierRestrictions.excludedCarrierInfoList)).setCarrierLockInfoFeature(
+ true).build();
+ } else {
+ ret = CarrierRestrictionRules.newBuilder().setAllowedCarriers(
+ RILUtils.convertHalCarrierList(
+ carrierRestrictions.allowedCarriers)).setExcludedCarriers(
+ RILUtils.convertHalCarrierList(
+ carrierRestrictions.excludedCarriers)).setDefaultCarrierRestriction(
+ carrierRestrictionDefault).setMultiSimPolicy(
+ policy).build();
+ }
if (responseInfo.error == RadioError.NONE) {
RadioResponse.sendMessageResponse(rr.mResult, ret);
}
diff --git a/src/java/com/android/internal/telephony/SmsDispatchersController.java b/src/java/com/android/internal/telephony/SmsDispatchersController.java
index 77fd1f6..58f3490 100644
--- a/src/java/com/android/internal/telephony/SmsDispatchersController.java
+++ b/src/java/com/android/internal/telephony/SmsDispatchersController.java
@@ -1234,7 +1234,7 @@
boolean isOverIms, boolean isLastSmsPart, boolean success) {
notifySmsSentToEmergencyStateTracker(tracker.mDestAddress,
tracker.mMessageId, isOverIms, isLastSmsPart, success);
- notifySmsSentToDatagramDispatcher(tracker.mUniqueMessageId, success);
+ notifySmsSentToDatagramDispatcher(tracker.mUniqueMessageId, isLastSmsPart, success);
}
/**
@@ -1254,9 +1254,11 @@
}
}
- private void notifySmsSentToDatagramDispatcher(long messageId, boolean success) {
+ private void notifySmsSentToDatagramDispatcher(
+ long messageId, boolean isLastSmsPart, boolean success) {
if (SatelliteController.getInstance().shouldSendSmsToDatagramDispatcher(mPhone)) {
- DatagramDispatcher.getInstance().onSendSmsDone(mPhone.getSubId(), messageId, success);
+ DatagramDispatcher.getInstance().onSendSmsDone(
+ mPhone.getSubId(), messageId, isLastSmsPart, success);
}
}
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
index 3c2ad0cd..48cc7cb 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
@@ -601,6 +601,11 @@
releaseWakeLock();
((GsmCdmaPhone) mPhone).notifyEcbmTimerReset(Boolean.TRUE);
+ if (mFeatureFlags.emergencyCallbackModeNotification()) {
+ mPhone.stopEmergencyCallbackMode(EMERGENCY_CALLBACK_MODE_CALL,
+ STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED);
+ }
+
mOngoingCallProperties = 0;
mCallEmergencyModeFuture = new CompletableFuture<>();
setEmergencyMode(mPhone, EMERGENCY_TYPE_CALL, MODE_EMERGENCY_WWAN,
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
index 36d8b2b..d6b1a70 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
@@ -406,9 +406,10 @@
SomeArgs args = (SomeArgs) msg.obj;
int subId = (int) args.arg1;
long messageId = (long) args.arg2;
- boolean success = (boolean) args.arg3;
+ boolean isLastPartSms = (boolean) args.arg3;
+ boolean success = (boolean) args.arg4;
try {
- handleEventSendSmsDone(subId, messageId, success);
+ handleEventSendSmsDone(subId, messageId, isLastPartSms, success);
} finally {
args.recycle();
}
@@ -625,6 +626,13 @@
pendingDatagram.iterator().next().getValue();
if (mDatagramController.needsWaitingForSatelliteConnected(datagramArg.datagramType)) {
plogd("sendPendingDatagrams: wait for satellite connected");
+ mDatagramController.updateSendStatus(datagramArg.subId,
+ datagramArg.datagramType,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ getPendingMessagesCount(),
+ SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ startDatagramWaitForConnectedStateTimer(
+ datagramArg.datagramType);
return;
}
@@ -1144,16 +1152,23 @@
}
if (pendingSms != null && pendingSms.iterator().hasNext()) {
+ PendingRequest pendingRequest = pendingSms.iterator().next().getValue();
+ int datagramType = pendingRequest.isMtSmsPolling
+ ? DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS : DATAGRAM_TYPE_SMS;
if (mDatagramController.needsWaitingForSatelliteConnected(DATAGRAM_TYPE_SMS)) {
plogd("sendPendingSms: wait for satellite connected");
+ mDatagramController.updateSendStatus(subId,
+ datagramType,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ getPendingMessagesCount(),
+ SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ startDatagramWaitForConnectedStateTimer(datagramType);
return;
}
mSendingInProgress = true;
- PendingRequest pendingRequest = pendingSms.iterator().next().getValue();
mDatagramController.updateSendStatus(subId,
- pendingRequest.isMtSmsPolling ?
- DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS : DATAGRAM_TYPE_SMS,
+ datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
getPendingMessagesCount(), SATELLITE_RESULT_SUCCESS);
sendMessage(obtainMessage(CMD_SEND_SMS, pendingRequest));
@@ -1167,13 +1182,15 @@
* Sending MO SMS is completed.
* @param subId subscription ID
* @param messageId message ID of MO SMS
+ * @param isLastSmsPart whether this is the last sms part of MO SMS
* @param success boolean specifying whether MO SMS is successfully sent or not.
*/
- public void onSendSmsDone(int subId, long messageId, boolean success) {
+ public void onSendSmsDone(int subId, long messageId, boolean isLastSmsPart, boolean success) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = subId;
args.arg2 = messageId;
- args.arg3 = success;
+ args.arg3 = isLastSmsPart;
+ args.arg4 = success;
sendMessage(obtainMessage(EVENT_SEND_SMS_DONE, args));
}
@@ -1214,7 +1231,8 @@
pendingSmsMap.clear();
}
- private void handleEventSendSmsDone(int subId, long messageId, boolean success) {
+ private void handleEventSendSmsDone(
+ int subId, long messageId, boolean isLastPartSms, boolean success) {
synchronized (mLock) {
mSendingInProgress = false;
PendingRequest pendingSms = mPendingSmsMap.remove(messageId);
@@ -1222,12 +1240,16 @@
? DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS : DATAGRAM_TYPE_SMS;
plogd("handleEventSendSmsDone subId=" + subId + " messageId=" + messageId
- + " success=" + success);
+ + " isLastPartSms=" + isLastPartSms + " success=" + success
+ + " datagramType=" + datagramType);
+
if (success) {
- // Update send status for current datagram
- mDatagramController.updateSendStatus(subId, datagramType,
- SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS,
- getPendingMessagesCount(), SATELLITE_RESULT_SUCCESS);
+ if (isLastPartSms) {
+ // Update send status only after all parts of the SMS are sent
+ mDatagramController.updateSendStatus(subId, datagramType,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS,
+ getPendingMessagesCount(), SATELLITE_RESULT_SUCCESS);
+ }
if (datagramType == DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS) {
startMtSmsPollingThrottle();
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 245f00c..a23e505 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -22,6 +22,7 @@
import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC;
import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL;
import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_TYPE;
+import static android.telephony.CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY;
@@ -567,6 +568,11 @@
@GuardedBy("mSatelliteTokenProvisionedLock")
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected TreeMap<Integer, List<SubscriptionInfo>> mSubsInfoListPerPriority = new TreeMap<>();
+ // List of subscriber information and status at the time of last evaluation
+ @GuardedBy("mSatelliteTokenProvisionedLock")
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ private List<SatelliteSubscriberProvisionStatus> mLastEvaluatedSubscriberProvisionStatus =
+ new ArrayList<>();
// The ID of the satellite subscription that has highest priority and is provisioned.
@GuardedBy("mSatelliteTokenProvisionedLock")
private int mSelectedSatelliteSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -2748,11 +2754,6 @@
*/
@SatelliteManager.SatelliteResult public int registerForSatelliteProvisionStateChanged(
@NonNull ISatelliteProvisionStateCallback callback) {
- int error = evaluateOemSatelliteRequestAllowed(false);
- if (error != SATELLITE_RESULT_SUCCESS) {
- return error;
- }
-
mSatelliteProvisionStateChangedListeners.put(callback.asBinder(), callback);
boolean isProvisioned = Boolean.TRUE.equals(isDeviceProvisioned());
@@ -4445,6 +4446,7 @@
}
registerForSatelliteSupportedStateChanged();
selectBindingSatelliteSubscription(false);
+ notifySatelliteSupportedStateChanged(supported);
}
private void updateSatelliteEnabledState(boolean enabled, String caller) {
@@ -4772,7 +4774,9 @@
}
mIsSatelliteSupported = supported;
}
+ }
+ private void notifySatelliteSupportedStateChanged(boolean supported) {
List<ISatelliteSupportedStateCallback> deadCallersList = new ArrayList<>();
mSatelliteSupportedStateChangedListeners.values().forEach(listener -> {
try {
@@ -6788,6 +6792,11 @@
if (!isActive && !isNtnOnly) {
continue;
}
+ if (!isNtnOnly && !isCarrierConfigLoaded(subId)) {
+ // Skip to add priority list if the carrier config is not loaded properly
+ // for the given carrier subscription.
+ continue;
+ }
int keyPriority = (isESOSSupported && isActive && isDefaultSmsSubId) ? 0
: (isESOSSupported && isActive) ? 1
@@ -6828,9 +6837,15 @@
// If priority has changed, send broadcast for provisioned ESOS subs IDs
synchronized (mSatelliteTokenProvisionedLock) {
+ List<SatelliteSubscriberProvisionStatus> newEvaluatedSubscriberProvisionStatus =
+ getPrioritizedSatelliteSubscriberProvisionStatusList(
+ newSubsInfoListPerPriority);
if (isPriorityChanged(mSubsInfoListPerPriority, newSubsInfoListPerPriority)
+ || isSubscriberContentChanged(mLastEvaluatedSubscriberProvisionStatus,
+ newEvaluatedSubscriberProvisionStatus)
|| isChanged) {
mSubsInfoListPerPriority = newSubsInfoListPerPriority;
+ mLastEvaluatedSubscriberProvisionStatus = newEvaluatedSubscriberProvisionStatus;
sendBroadCastForProvisionedESOSSubs();
mHasSentBroadcast = true;
selectBindingSatelliteSubscription(false);
@@ -6838,6 +6853,14 @@
}
}
+ // to check if the contents of carrier config is loaded properly
+ private Boolean isCarrierConfigLoaded(int subId) {
+ PersistableBundle carrierConfig = mCarrierConfigManager
+ .getConfigForSubId(subId, KEY_CARRIER_CONFIG_APPLIED_BOOL);
+ return carrierConfig != null ? carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL) : false;
+ }
+
// The subscriberId for ntnOnly SIMs is the Iccid, whereas for ESOS supported SIMs, the
// subscriberId is the Imsi prefix 6 digit + phone number.
private Pair<String, Integer> getSubscriberIdAndType(@Nullable SubscriptionInfo info) {
@@ -6900,6 +6923,24 @@
return false;
}
+ // Checks if there are any changes between subscriberInfos. return false if the same.
+ // Note that, Use lists with the same priority so we can compare contents properly.
+ private boolean isSubscriberContentChanged(List<SatelliteSubscriberProvisionStatus> currentList,
+ List<SatelliteSubscriberProvisionStatus> newList) {
+ if (currentList.size() != newList.size()) {
+ return true;
+ }
+ for (int i = 0; i < currentList.size(); i++) {
+ SatelliteSubscriberProvisionStatus curSub = currentList.get(i);
+ SatelliteSubscriberProvisionStatus newSub = newList.get(i);
+ if (!curSub.getSatelliteSubscriberInfo().equals(newSub.getSatelliteSubscriberInfo())) {
+ logd("isSubscriberContentChanged: cur=" + curSub + " , new=" + newSub);
+ return true;
+ }
+ }
+ return false;
+ }
+
private void sendBroadCastForProvisionedESOSSubs() {
String packageName = getConfigSatelliteGatewayServicePackage();
String className = getConfigSatelliteCarrierRoamingEsosProvisionedClass();
@@ -6953,10 +6994,18 @@
private List<SatelliteSubscriberProvisionStatus>
getPrioritizedSatelliteSubscriberProvisionStatusList() {
+ synchronized (mSatelliteTokenProvisionedLock) {
+ return getPrioritizedSatelliteSubscriberProvisionStatusList(mSubsInfoListPerPriority);
+ }
+ }
+
+ private List<SatelliteSubscriberProvisionStatus>
+ getPrioritizedSatelliteSubscriberProvisionStatusList(
+ Map<Integer, List<SubscriptionInfo>> subsInfoListPerPriority) {
List<SatelliteSubscriberProvisionStatus> list = new ArrayList<>();
synchronized (mSatelliteTokenProvisionedLock) {
- for (int priority : mSubsInfoListPerPriority.keySet()) {
- List<SubscriptionInfo> infoList = mSubsInfoListPerPriority.get(priority);
+ for (int priority : subsInfoListPerPriority.keySet()) {
+ List<SubscriptionInfo> infoList = subsInfoListPerPriority.get(priority);
if (infoList == null) {
logd("getPrioritySatelliteSubscriberProvisionStatusList: no exist this "
+ "priority " + priority);
@@ -7815,7 +7864,8 @@
return carrierRoamingNtnSignalStrength;
}
- private void updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(@Nullable Phone phone) {
+ protected void updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(
+ @Nullable Phone phone) {
if (!mFeatureFlags.carrierRoamingNbIotNtn()) return;
if (phone == null) {
return;
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
index 19c3f65..d1d03a0 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
@@ -137,6 +137,7 @@
private static final int EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE = 12;
private static final int EVENT_SERVICE_STATE_CHANGED = 13;
protected static final int EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT = 14;
+
private static final long REBIND_INITIAL_DELAY = 2 * 1000; // 2 seconds
private static final long REBIND_MAXIMUM_DELAY = 64 * 1000; // 1 minute
private static final int REBIND_MULTIPLIER = 2;
@@ -182,16 +183,12 @@
boolean mIsScreenOn = true;
private boolean mIsDeviceAlignedWithSatellite = false;
- @GuardedBy("mLock")
- @NonNull private boolean mIsDisableCellularModemInProgress = false;
@NonNull private final SatelliteController mSatelliteController;
@NonNull private final DatagramController mDatagramController;
@Nullable private PersistentLogger mPersistentLogger = null;
@Nullable private DeviceStateMonitor mDeviceStateMonitor;
@NonNull private SessionMetricsStats mSessionMetricsStats;
@NonNull private FeatureFlags mFeatureFlags;
- @SatelliteManager.SatelliteModemState private int mModemStateFromController =
- SATELLITE_MODEM_STATE_UNKNOWN;
@NonNull private AlarmManager mAlarmManager;
private final AlarmManager.OnAlarmListener mAlarmListener = new AlarmManager.OnAlarmListener() {
@Override
@@ -386,10 +383,6 @@
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public void onSatelliteModemStateChanged(@SatelliteManager.SatelliteModemState int state) {
- if (mFeatureFlags.carrierRoamingNbIotNtn()) {
- plogd("onSatelliteModemStateChanged from SatelliteController : " + state);
- mModemStateFromController = state;
- }
sendMessage(EVENT_SATELLITE_MODEM_STATE_CHANGED, state);
}
@@ -695,9 +688,6 @@
mPreviousState = mCurrentState;
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_OFF;
mIsSendingTriggeredDuringTransferringState.set(false);
- synchronized (mLock) {
- mIsDisableCellularModemInProgress = false;
- }
unbindService();
stopNbIotInactivityTimer();
DemoSimulator.getInstance().onSatelliteModeOff();
@@ -899,7 +889,11 @@
Message onCompleted =
obtainMessage(EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE);
mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(true, onCompleted);
- notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ if (isConcurrentTnScanningSupported()) {
+ plogd("IDLE state is hidden from clients");
+ } else {
+ notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ }
}
@Override
@@ -914,7 +908,7 @@
break;
case EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE:
handleEventDisableCellularModemWhileSatelliteModeIsOnDone(
- (AsyncResult) msg.obj);
+ (AsyncResult) msg.obj);
break;
case EVENT_SATELLITE_ENABLEMENT_STARTED:
handleSatelliteEnablementStarted((boolean) msg.obj);
@@ -954,17 +948,13 @@
if ((datagramTransferState.sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING)
|| (datagramTransferState.receiveState
== SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING)) {
- if (mSatelliteController.isSatelliteAttachRequired()) {
- ploge("Unexpected transferring state received for NB-IOT NTN");
- } else {
- transitionTo(mTransferringState);
- }
+ transitionTo(mTransferringState);
} else if ((datagramTransferState.sendState
== SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT)
|| (datagramTransferState.receiveState
== SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT)) {
if (mSatelliteController.isSatelliteAttachRequired()) {
- disableCellularModemWhileSatelliteModeIsOn();
+ transitionTo(mNotConnectedState);
} else {
ploge("Unexpected transferring state received for non-NB-IOT NTN");
}
@@ -1012,57 +1002,32 @@
private void handleEventDisableCellularModemWhileSatelliteModeIsOnDone(
@NonNull AsyncResult result) {
- synchronized (mLock) {
- if (mIsDisableCellularModemInProgress) {
- int error = SatelliteServiceUtils.getSatelliteError(
- result, "DisableCellularModemWhileSatelliteModeIsOnDone");
- if (error == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
- if (mFeatureFlags.carrierRoamingNbIotNtn()
- && mModemStateFromController == SATELLITE_MODEM_STATE_CONNECTED) {
- ploge("mPreviousState : " + mPreviousState
- + " mModemStateFromController : "
- + mModemStateFromController + " I->C");
- transitionTo(mConnectedState);
- } else {
- transitionTo(mNotConnectedState);
- }
- }
- mIsDisableCellularModemInProgress = false;
- } else {
- ploge("DisableCellularModemWhileSatelliteModeIsOn is not in progress");
- }
- }
+ int error = SatelliteServiceUtils.getSatelliteError(
+ result, "DisableCellularModemWhileSatelliteModeIsOnDone");
+ plogd("Disable TN scanning done with result: " + error);
}
private void handleSatelliteModemStateChanged(@NonNull Message msg) {
int state = msg.arg1;
if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) {
transitionTo(mPowerOffState);
- }
- }
-
- private void disableCellularModemWhileSatelliteModeIsOn() {
- synchronized (mLock) {
- if (mIsDisableCellularModemInProgress) {
- plogd("Cellular scanning is already being disabled");
- return;
+ } else if (state == SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED
+ || state == SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED) {
+ if (isConcurrentTnScanningSupported()) {
+ plogd("Notifying the new state " + state + " to clients but still"
+ + " stay at IDLE state internally");
+ notifyStateChangedEvent(state);
+ } else {
+ plogd("Ignoring the modem state " + state);
}
-
- mIsDisableCellularModemInProgress = true;
- Message onCompleted =
- obtainMessage(EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE);
- mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(false,
- onCompleted);
}
}
@Override
public void exit() {
if (DBG) plogd("Exiting IdleState");
- if (!mSatelliteController.isSatelliteAttachRequired()) {
- // Disable cellular modem scanning
- mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(false, null);
- }
+ // Disable cellular modem scanning
+ mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(false, null);
}
}
@@ -1336,6 +1301,8 @@
startNbIotInactivityTimer();
evaluateStartingEsosInactivityTimer();
evaluateStartingP2pSmsInactivityTimer();
+ mSatelliteController.updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(
+ mSatelliteController.getSatellitePhone());
}
@Override
@@ -1989,6 +1956,16 @@
}
}
+ private boolean isConcurrentTnScanningSupported() {
+ try {
+ return mContext.getResources().getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning);
+ } catch (RuntimeException e) {
+ plogd("isConcurrentTnScanningSupported: ex=" + e);
+ return false;
+ }
+ }
+
private void plogd(@NonNull String log) {
logd(log);
if (mPersistentLogger != null) {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
index 32cca3c..df14080 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
@@ -1107,7 +1107,7 @@
verify(phone0, never()).exitEmergencyMode(any(Message.class));
verify(phone0, times(2)).startEmergencyCallbackMode(
eq(EMERGENCY_CALLBACK_MODE_CALL), anyLong());
- verify(phone0, never()).stopEmergencyCallbackMode(
+ verify(phone0, times(1)).stopEmergencyCallbackMode(
eq(EMERGENCY_CALLBACK_MODE_CALL), anyInt());
}
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 d964d88..1941518 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
@@ -824,7 +824,8 @@
eq(SATELLITE_RESULT_SUCCESS));
verify(mMockSmsDispatchersController).sendCarrierRoamingNbIotNtnText(eq(mPendingSms));
- mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.uniqueMessageId, true);
+ mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.uniqueMessageId,
+ true, true);
processAllMessages();
mInOrder.verify(mMockDatagramController)
@@ -858,7 +859,8 @@
eq(SATELLITE_RESULT_SUCCESS));
verify(mMockSmsDispatchersController).sendCarrierRoamingNbIotNtnText(eq(mPendingSms));
- mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.uniqueMessageId, false);
+ mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.uniqueMessageId,
+ true, false);
processAllMessages();
mInOrder.verify(mMockDatagramController)
@@ -1056,7 +1058,8 @@
eq(SATELLITE_RESULT_SUCCESS));
verify(mMockSmsDispatchersController).sendCarrierRoamingNbIotNtnText(eq(mPendingSms));
- mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.uniqueMessageId, true);
+ mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.uniqueMessageId,
+ true, true);
processAllMessages();
mInOrder.verify(mMockDatagramController)
@@ -1107,7 +1110,8 @@
processAllMessages();
verifyZeroInteractions(mMockSatelliteModemInterface);
- mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.uniqueMessageId, true);
+ mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.uniqueMessageId,
+ true, true);
processAllMessages();
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID), eq(datagramTypeSms),
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 3657f1a..876410c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -22,6 +22,7 @@
import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN;
import static android.hardware.devicestate.feature.flags.Flags.FLAG_DEVICE_STATE_PROPERTY_MIGRATION;
import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC;
+import static android.telephony.CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT;
@@ -1722,12 +1723,7 @@
}
};
int errorCode = mSatelliteControllerUT.registerForSatelliteProvisionStateChanged(callback);
- assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, errorCode);
-
- setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- errorCode = mSatelliteControllerUT.registerForSatelliteProvisionStateChanged(callback);
- assertEquals(SATELLITE_RESULT_NOT_SUPPORTED, errorCode);
+ assertEquals(SATELLITE_RESULT_SUCCESS, errorCode);
resetSatelliteControllerUT();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
@@ -1759,6 +1755,7 @@
semaphore, 1, "testRegisterForSatelliteProvisionStateChanged"));
mSatelliteControllerUT.unregisterForSatelliteProvisionStateChanged(callback);
+ semaphore.drainPermits();
cancelRemote = mSatelliteControllerUT.provisionSatelliteService(
TEST_SATELLITE_TOKEN,
testProvisionData, mIIntegerConsumer);
@@ -4495,6 +4492,7 @@
private void verifyRequestSatelliteSubscriberProvisionStatus() throws Exception {
setSatelliteSubscriberTesting();
List<SatelliteSubscriberInfo> list = getExpectedSatelliteSubscriberInfoList();
+ mCarrierConfigBundle.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
mCarrierConfigBundle.putString(KEY_SATELLITE_NIDD_APN_NAME_STRING, mNiddApn);
mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ESOS_SUPPORTED_BOOL, true);
for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
@@ -4810,6 +4808,7 @@
@Test
public void testCheckForSubscriberIdChange_changed() {
when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mCarrierConfigBundle.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
List<SubscriptionInfo> allSubInfos = new ArrayList<>();
String imsi = "012345";
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
index d67880d..8c1ae50 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
@@ -67,6 +67,7 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import com.android.internal.R;
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.flags.FeatureFlags;
@@ -146,6 +147,9 @@
Resources resources = mContext.getResources();
when(resources.getInteger(anyInt())).thenReturn(TEST_SATELLITE_TIMEOUT_MILLIS);
+ when(resources.getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning))
+ .thenReturn(false);
when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(false);
@@ -1526,23 +1530,6 @@
SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
- // Set up error response for the request to disable cellular scanning
- mSatelliteModemInterface.setErrorCode(SatelliteManager.SATELLITE_RESULT_MODEM_ERROR);
-
- // Start sending datagrams
- mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- DATAGRAM_TYPE_UNKNOWN);
- processAllMessages();
-
- // SatelliteSessionController should stay at IDLE state because it failed to disable
- // cellular scanning.
- assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
- assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
-
- mSatelliteModemInterface.setErrorCode(SatelliteManager.SATELLITE_RESULT_SUCCESS);
-
// Power off the modem.
mTestSatelliteSessionController.onSatelliteEnabledStateChanged(false);
processAllMessages();
@@ -1857,6 +1844,283 @@
assertEmergencyModeChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
}
+ @Test
+ public void testNotConnectedToIdleToNotConnectedStateTransition() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ when(mContext.getResources().getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning)).thenReturn(true);
+
+ assertNotNull(mTestSatelliteSessionController);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ setupDatagramTransferringState(true);
+
+ powerOnSatelliteModem();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
+ // is powered on.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be started.
+ assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Wait for timeout
+ moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
+ processAllMessages();
+
+ // SatelliteSessionController should move to IDLE state, but the state transition will
+ // be hidden because device does not support satellite modem IDLE state.
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be stopped.
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ // The transition is hidden and thus DatagramController is not notified.
+ verify(mMockDatagramController, never()).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ clearInvocations(mMockDatagramController);
+
+ // Start sending datagrams
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+ }
+
+ @Test
+ public void testNotConnectedToIdleToTransferringStateTransition() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ when(mContext.getResources().getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning)).thenReturn(true);
+
+ assertNotNull(mTestSatelliteSessionController);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ setupDatagramTransferringState(true);
+
+ powerOnSatelliteModem();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
+ // is powered on.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be started.
+ assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Wait for timeout
+ moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
+ processAllMessages();
+
+ // SatelliteSessionController should move to IDLE state, but the state transition will
+ // be hidden because device does not support satellite modem IDLE state.
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be stopped.
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ // The transition is hidden and thus DatagramController is not notified.
+ verify(mMockDatagramController, never()).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ clearInvocations(mMockDatagramController);
+
+ // Modem report CONNECTED state
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ processAllMessages();
+
+ // SatelliteSessionController should stay in IDLE state, but clients should be
+ // notified that modem has moved to CONNECTED state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Start sending datagrams
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // SatelliteSessionController should move to TRANSFERRING state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+ assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+ clearInvocations(mMockDatagramController);
+ }
+
+ @Test
+ public void testConnectedToIdleToTransferringStateTransition() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ when(mContext.getResources().getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning)).thenReturn(true);
+
+ assertNotNull(mTestSatelliteSessionController);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ setupDatagramTransferringState(false);
+
+ powerOnSatelliteModem();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
+ // is powered on.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Modem report CONNECTED state
+ setupDatagramTransferringState(true);
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ processAllMessages();
+
+ // SatelliteSessionController should move to CONNECTED state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be started.
+ assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Wait for timeout
+ moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
+ processAllMessages();
+
+ // SatelliteSessionController should move to IDLE state, but the state transition will
+ // be hidden because device does not support satellite modem IDLE state.
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be stopped.
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ // The transition is hidden and thus DatagramController is not notified.
+ verify(mMockDatagramController, never()).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ clearInvocations(mMockDatagramController);
+
+ // Start sending datagrams
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // SatelliteSessionController should move to TRANSFERRING state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+ assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+ clearInvocations(mMockDatagramController);
+ }
+
+ @Test
+ public void testConnectedToIdleToNotConnectedStateTransition() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ when(mContext.getResources().getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning)).thenReturn(true);
+
+ assertNotNull(mTestSatelliteSessionController);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ setupDatagramTransferringState(false);
+
+ powerOnSatelliteModem();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
+ // is powered on.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Modem report CONNECTED state
+ setupDatagramTransferringState(true);
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ processAllMessages();
+
+ // SatelliteSessionController should move to CONNECTED state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be started.
+ assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Wait for timeout
+ moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
+ processAllMessages();
+
+ // SatelliteSessionController should move to IDLE state, but the state transition will
+ // be hidden because device does not support satellite modem IDLE state.
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be stopped.
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ // The transition is hidden and thus DatagramController is not notified.
+ verify(mMockDatagramController, never()).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ clearInvocations(mMockDatagramController);
+
+ // Modem report NOT_CONNECTED state
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ processAllMessages();
+
+ // SatelliteSessionController should stay in IDLE state, but the clients
+ // should be notified that modem has moved to NOT_CONNECTED state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Start sending datagrams
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+ }
private void verifyEsosP2pSmsInactivityTimer(boolean esosTimer, boolean p2pSmsTimer) {
assertEquals(mTestSatelliteSessionController.isEsosInActivityTimerStarted(), esosTimer);
@@ -1878,9 +2142,9 @@
processAllMessages();
}
- private void setupDatagramTransferringState(boolean isTransferring) {
- when(mMockDatagramController.isSendingInIdleState()).thenReturn(isTransferring);
- when(mMockDatagramController.isPollingInIdleState()).thenReturn(isTransferring);
+ private void setupDatagramTransferringState(boolean isIdle) {
+ when(mMockDatagramController.isSendingInIdleState()).thenReturn(isIdle);
+ when(mMockDatagramController.isPollingInIdleState()).thenReturn(isIdle);
}
private void powerOnSatelliteModem() {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionPlanTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionPlanTest.java
new file mode 100644
index 0000000..2c13d3b
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionPlanTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.subscription;
+
+import static android.telephony.SubscriptionPlan.SUBSCRIPTION_STATUS_ACTIVE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
+
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.telephony.SubscriptionPlan;
+import android.testing.AndroidTestingRunner;
+
+import com.android.internal.telephony.flags.Flags;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.time.Period;
+import java.time.ZonedDateTime;
+
+@RunWith(AndroidTestingRunner.class)
+public class SubscriptionPlanTest {
+ private static final ZonedDateTime ZONED_DATE_TIME_START =
+ ZonedDateTime.parse("2007-03-14T00:00:00.000Z");
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public void testBuilderExpirationDateSetsCorrectly() {
+ ZonedDateTime endDate = ZonedDateTime.parse("2024-11-07T00:00:00.000Z");
+
+ SubscriptionPlan planNonRecurring = SubscriptionPlan.Builder
+ .createNonrecurring(ZONED_DATE_TIME_START, endDate)
+ .setTitle("unit test")
+ .build();
+ SubscriptionPlan planRecurring = SubscriptionPlan.Builder
+ .createRecurring(ZONED_DATE_TIME_START, Period.ofMonths(1))
+ .setTitle("unit test")
+ .build();
+
+ assertThat(planNonRecurring.getPlanEndDate()).isEqualTo(endDate);
+ assertNull(planRecurring.getPlanEndDate());
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public void testBuilderValidSubscriptionStatusSetsCorrectly() {
+ @SubscriptionPlan.SubscriptionStatus int status = SUBSCRIPTION_STATUS_ACTIVE;
+
+ SubscriptionPlan plan = SubscriptionPlan.Builder
+ .createRecurring(ZONED_DATE_TIME_START, Period.ofMonths(1))
+ .setSubscriptionStatus(status)
+ .setTitle("unit test")
+ .build();
+
+ assertThat(plan.getSubscriptionStatus()).isEqualTo(status);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public void testBuilderInvalidSubscriptionStatusThrowsError() {
+ int minInvalid = -1;
+ int maxInvalid = 5;
+
+ assertThrows(IllegalArgumentException.class, () -> {
+ SubscriptionPlan.Builder
+ .createRecurring(ZONED_DATE_TIME_START, Period.ofMonths(1))
+ .setSubscriptionStatus(minInvalid)
+ .setTitle("unit test")
+ .build();
+ });
+
+ assertThrows(IllegalArgumentException.class, () -> {
+ SubscriptionPlan.Builder
+ .createRecurring(ZONED_DATE_TIME_START, Period.ofMonths(1))
+ .setSubscriptionStatus(maxInvalid)
+ .setTitle("unit test")
+ .build();
+ });
+ }
+}