Merge "Google Contrigution item #12 - subitem #2, opt [VZW-Skylo] apply Idle Mode Scanning for Terrestrial Network" into main
diff --git a/Android.bp b/Android.bp
index c3b4373..da32208 100644
--- a/Android.bp
+++ b/Android.bp
@@ -116,4 +116,7 @@
obfuscate: false,
proguard_flags_files: ["proguard.flags"],
},
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
diff --git a/flags/satellite.aconfig b/flags/satellite.aconfig
index 4806789..825ea78 100644
--- a/flags/satellite.aconfig
+++ b/flags/satellite.aconfig
@@ -61,4 +61,12 @@
metadata {
purpose: PURPOSE_BUGFIX
}
+}
+
+# OWNER=rambowang TARGET=25Q2
+flag {
+ name: "satellite_state_change_listener"
+ namespace: "telephony"
+ description: "Introduce SatelliteManager APIs for carrier apps to monitor satellite state change"
+ bug: "357638490"
}
\ No newline at end of file
diff --git a/lint-baseline.xml b/lint-baseline.xml
new file mode 100644
index 0000000..491d013
--- /dev/null
+++ b/lint-baseline.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.4.0-alpha08" type="baseline" client="" dependencies="true" name="" variant="all" version="8.4.0-alpha08">
+
+ <issue
+ id="SimpleManualPermissionEnforcement"
+ message="IEuiccCardController permission check should be converted to @EnforcePermission annotation"
+ errorLine1=" mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "Requires DUMP");"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/opt/telephony/src/java/com/android/internal/telephony/euicc/EuiccCardController.java"
+ line="1525"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SimpleManualPermissionEnforcement"
+ message="IEuiccController permission check can be converted to @EnforcePermission annotation"
+ errorLine1=" mContext.enforceCallingPermission(Manifest.permission.MASTER_CLEAR,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/opt/telephony/src/java/com/android/internal/telephony/euicc/EuiccController.java"
+ line="1679"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SimpleManualPermissionEnforcement"
+ message="IEuiccController permission check should be converted to @EnforcePermission annotation"
+ errorLine1=" mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "Requires DUMP");"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/opt/telephony/src/java/com/android/internal/telephony/euicc/EuiccController.java"
+ line="1812"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SimpleManualPermissionEnforcement"
+ message="ISub permission check should be converted to @EnforcePermission annotation"
+ errorLine1=" mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/opt/telephony/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java"
+ line="4800"
+ column="9"/>
+ </issue>
+
+</issues>
diff --git a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index 47c701c..1aaa1d3 100644
--- a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -26,6 +26,7 @@
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.LinkCapacityEstimate;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneCapability;
import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseCallState;
@@ -340,6 +341,13 @@
sender.getSubId(), eligible);
}
+ @Override
+ public void notifyCarrierRoamingNtnAvailableServicesChanged(
+ Phone sender, @NetworkRegistrationInfo.ServiceType int[] availableServices) {
+ mTelephonyRegistryMgr.notifyCarrierRoamingNtnAvailableServicesChanged(
+ sender.getSubId(), availableServices);
+ }
+
/**
* Convert the {@link Call.State} enum into the PreciseCallState.PRECISE_CALL_STATE_* constants
* for the public API.
diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java
index 0106516..011e67b 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -66,6 +66,7 @@
import android.telephony.SmsMessage;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Pair;
@@ -759,6 +760,11 @@
return Intents.RESULT_SMS_HANDLED;
}
+ if (isMtSmsPollingMessage(smsb)) {
+ log("Received MT SMS polling message. Ignored.");
+ return Intents.RESULT_SMS_HANDLED;
+ }
+
int result = dispatchMessageRadioSpecific(smsb, smsSource, token);
// In case of error, add to metrics. This is not required in case of success, as the
@@ -1982,6 +1988,17 @@
sendMessage(EVENT_BROADCAST_COMPLETE);
}
+ private boolean isMtSmsPollingMessage(@NonNull SmsMessageBase smsb) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()
+ || !mContext.getResources().getBoolean(R.bool.config_enabled_mt_sms_polling)) {
+ return false;
+ }
+ String mtSmsPollingText = mContext.getResources()
+ .getString(R.string.config_mt_sms_polling_text);
+ return !TextUtils.isEmpty(mtSmsPollingText)
+ && mtSmsPollingText.equals(smsb.getMessageBody());
+ }
+
/** Checks whether the flag to skip new message notification is set in the bitmask returned
* from the carrier app.
*/
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index 61f1d45..1a8c046 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -5368,6 +5368,15 @@
mNotifier.notifyCarrierRoamingNtnEligibleStateChanged(this, eligible);
}
+ /**
+ * Notify external listeners that carrier roaming non-terrestrial available services changed.
+ * @param availableServices The list of the supported services.
+ */
+ public void notifyCarrierRoamingNtnAvailableServicesChanged(
+ @NetworkRegistrationInfo.ServiceType int[] availableServices) {
+ mNotifier.notifyCarrierRoamingNtnAvailableServicesChanged(this, availableServices);
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("Phone: subId=" + getSubId());
pw.println(" mPhoneId=" + mPhoneId);
diff --git a/src/java/com/android/internal/telephony/PhoneNotifier.java b/src/java/com/android/internal/telephony/PhoneNotifier.java
index a43ff72..f652370 100644
--- a/src/java/com/android/internal/telephony/PhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/PhoneNotifier.java
@@ -26,6 +26,7 @@
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.LinkCapacityEstimate;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneCapability;
import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseDataConnectionState;
@@ -164,4 +165,8 @@
/** Notify eligibility to connect to carrier roaming non-terrestrial network changed. */
void notifyCarrierRoamingNtnEligibleStateChanged(Phone sender, boolean eligible);
+
+ /** Notify carrier roaming non-terrestrial available services changed. */
+ void notifyCarrierRoamingNtnAvailableServicesChanged(
+ Phone sender, @NetworkRegistrationInfo.ServiceType int[] availableServices);
}
diff --git a/src/java/com/android/internal/telephony/SmsDispatchersController.java b/src/java/com/android/internal/telephony/SmsDispatchersController.java
index b60ded5..023680a 100644
--- a/src/java/com/android/internal/telephony/SmsDispatchersController.java
+++ b/src/java/com/android/internal/telephony/SmsDispatchersController.java
@@ -29,6 +29,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Resources;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Binder;
@@ -46,6 +47,7 @@
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.telephony.TelephonyManager;
+import android.telephony.SubscriptionManager;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.satellite.SatelliteManager;
import android.text.TextUtils;
@@ -65,6 +67,7 @@
import com.android.internal.telephony.gsm.GsmSMSDispatcher;
import com.android.internal.telephony.satellite.DatagramDispatcher;
import com.android.internal.telephony.satellite.SatelliteController;
+import com.android.internal.R;
import com.android.telephony.Rlog;
import java.io.FileDescriptor;
@@ -245,13 +248,15 @@
public final long messageId;
public final boolean skipShortCodeCheck;
public final long uniqueMessageId;
+ public final boolean isMtSmsPolling;
public PendingRequest(int type, SMSDispatcher.SmsTracker tracker, String callingPackage,
int callingUser, String destAddr, String scAddr,
ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents,
boolean isForVvm, byte[] data, int destPort, ArrayList<String> texts,
Uri messageUri, boolean persistMessage, int priority, boolean expectMore,
- int validityPeriod, long messageId, boolean skipShortCodeCheck) {
+ int validityPeriod, long messageId, boolean skipShortCodeCheck,
+ boolean isMtSmsPolling) {
this.type = type;
this.tracker = tracker;
this.callingPackage = callingPackage;
@@ -278,6 +283,7 @@
} else {
this.uniqueMessageId = getNextUniqueMessageId();
}
+ this.isMtSmsPolling = isMtSmsPolling;
}
public static long getNextUniqueMessageId() {
@@ -834,7 +840,7 @@
null, UserHandle.USER_NULL, null, null,
null, null, false, null, 0,
null, null, false,
- 0, false, 0, 0L, false);
+ 0, false, 0, 0L, false, false);
args.arg3 = "sendRetrySms";
sendMessage(obtainMessage(EVENT_REQUEST_DOMAIN_SELECTION, args));
return;
@@ -1622,7 +1628,7 @@
destAddr, scAddr, asArrayList(sentIntent),
asArrayList(deliveryIntent), isForVvm, data, destPort, null,
null, false, 0, false, 0,
- 0L, false),
+ 0L, false, false),
"sendData");
return;
}
@@ -1858,7 +1864,7 @@
callingPkg, callingUser, destAddr, scAddr, asArrayList(sentIntent),
asArrayList(deliveryIntent), isForVvm, null, 0, asArrayList(text),
messageUri, persistMessage, priority, expectMore, validityPeriod, messageId,
- skipShortCodeCheck);
+ skipShortCodeCheck, false);
if (SatelliteController.getInstance().isInCarrierRoamingNbIotNtn(mPhone)) {
// Send P2P SMS using carrier roaming NB IOT NTN
@@ -2023,7 +2029,7 @@
PendingRequest pendingRequest = new PendingRequest(PendingRequest.TYPE_MULTIPART_TEXT, null,
callingPkg, callingUser, destAddr, scAddr, sentIntents, deliveryIntents, false,
null, 0, parts, messageUri, persistMessage, priority, expectMore,
- validityPeriod, messageId, false);
+ validityPeriod, messageId, false, false);
if (SatelliteController.getInstance().isInCarrierRoamingNbIotNtn(mPhone)) {
// Send multipart P2P SMS using carrier roaming NB IOT NTN
@@ -2200,7 +2206,7 @@
*/
public void sendCarrierRoamingNbIotNtnText(@NonNull PendingRequest request) {
if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
- logd("onSendCarrierRoamingNbIotNtnTextError: carrier roaming nb iot ntn "
+ logd("sendCarrierRoamingNbIotNtnText: carrier roaming nb iot ntn "
+ "feature flag is disabled");
return;
}
@@ -2228,6 +2234,42 @@
sendMessage(obtainMessage(EVENT_SEND_TEXT_OVER_NTN_ERROR, pendingRequest));
}
+ /**
+ * This API should be used only by {@link DatagramDispatcher} to send MT SMS Polling message
+ * over non-terrestrial network.
+ * To enable users to receive incoming messages, the device needs to send an MO SMS to itself
+ * to trigger SMSC to send all pending SMS to the particular subscription.
+ */
+ public void sendMtSmsPollingMessage() {
+ if (!SatelliteController.getInstance().isInCarrierRoamingNbIotNtn(mPhone)) {
+ logd("sendMtSmsPollingMessage: not in roaming nb iot ntn");
+ return;
+ }
+
+ SubscriptionManager subscriptionManager = (SubscriptionManager) mContext
+ .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ String destAddr = subscriptionManager.getPhoneNumber(mPhone.getSubId());
+ if (TextUtils.isEmpty(destAddr)) {
+ logd("sendMtSmsPollingMessage: destAddr is null or empty.");
+ return;
+ }
+
+ String mtSmsPollingText = mContext.getResources()
+ .getString(R.string.config_mt_sms_polling_text);
+ if (TextUtils.isEmpty(mtSmsPollingText)) {
+ logd("sendMtSmsPollingMessage: mtSmsPollingText is null or empty.");
+ return;
+ }
+
+ String callingPackage = mContext.getPackageName();
+ PendingRequest pendingRequest = new PendingRequest(PendingRequest.TYPE_TEXT, null,
+ callingPackage, Binder.getCallingUserHandle().getIdentifier(), destAddr,
+ getSmscAddressFromUSIMWithPhoneIdentity(callingPackage), asArrayList(null),
+ asArrayList(null), false, null, 0, asArrayList(mtSmsPollingText), null, false, 0,
+ false, 5, 0L, true, true);
+
+ DatagramDispatcher.getInstance().sendSms(pendingRequest);
+ }
public interface SmsInjectionCallback {
void onSmsInjectedResult(int result);
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
index 42aa2aa..1517064 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
@@ -16,9 +16,12 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS;
import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SMS;
import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NETWORK_ERROR;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE;
@@ -75,6 +78,7 @@
private static final int EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT = 7;
private static final int CMD_SEND_SMS = 8;
private static final int EVENT_SEND_SMS_DONE = 9;
+ private static final int EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT = 10;
private static final Long TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE = TimeUnit.SECONDS.toMillis(10);
@NonNull private static DatagramDispatcher sInstance;
@NonNull private final Context mContext;
@@ -130,6 +134,15 @@
private int mLastSendRequestDatagramType = DATAGRAM_TYPE_UNKNOWN;
@Nullable private PersistentLogger mPersistentLogger = null;
+ @GuardedBy("mLock")
+ private int mModemState = SATELLITE_MODEM_STATE_UNKNOWN;
+ @GuardedBy("mLock")
+ private boolean mHasEnteredConnectedState = false;
+ @GuardedBy("mLock")
+ private boolean mShouldPollMtSms = false;
+ @GuardedBy("mLock")
+ private boolean mIsMtSmsPollingThrottled = false;
+
/**
* Create the DatagramDispatcher singleton instance.
* @param context The Context to use to create the DatagramDispatcher.
@@ -402,6 +415,16 @@
break;
}
+ case EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT: {
+ synchronized (mLock) {
+ mIsMtSmsPollingThrottled = false;
+ if (mIsAligned && mModemState == SATELLITE_MODEM_STATE_CONNECTED) {
+ sendMtSmsPollingMessage();
+ }
+ }
+ break;
+ }
+
default:
plogw("DatagramDispatcherHandler: unexpected message code: " + msg.what);
break;
@@ -491,6 +514,10 @@
mIsAligned = isAligned;
plogd("setDeviceAlignedWithSatellite: " + mIsAligned);
if (isAligned && mIsDemoMode) handleEventSatelliteAligned();
+ if (isAligned && !mIsMtSmsPollingThrottled
+ && mModemState == SATELLITE_MODEM_STATE_CONNECTED) {
+ sendMtSmsPollingMessage();
+ }
}
}
@@ -759,6 +786,7 @@
*/
public void onSatelliteModemStateChanged(@SatelliteManager.SatelliteModemState int state) {
synchronized (mLock) {
+ mModemState = state;
if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF
|| state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE) {
plogd("onSatelliteModemStateChanged: cleaning up resources");
@@ -767,10 +795,22 @@
sendPendingMessages();
}
- if (state == SATELLITE_MODEM_STATE_CONNECTED
- && isDatagramWaitForConnectedStateTimerStarted()) {
- stopDatagramWaitForConnectedStateTimer();
- sendPendingMessages();
+ if (state == SATELLITE_MODEM_STATE_CONNECTED) {
+ mHasEnteredConnectedState = true;
+ if (isDatagramWaitForConnectedStateTimerStarted()) {
+ stopDatagramWaitForConnectedStateTimer();
+ sendPendingMessages();
+ }
+ if (mIsAligned && !mIsMtSmsPollingThrottled) {
+ sendMtSmsPollingMessage();
+ }
+ }
+
+ if (state == SATELLITE_MODEM_STATE_NOT_CONNECTED) {
+ if (mHasEnteredConnectedState) {
+ mHasEnteredConnectedState = false;
+ mShouldPollMtSms = shouldPollMtSms();
+ }
}
}
}
@@ -803,6 +843,10 @@
mSendSatelliteDatagramRequest = null;
mIsAligned = false;
mLastSendRequestDatagramType = DATAGRAM_TYPE_UNKNOWN;
+ mModemState = SATELLITE_MODEM_STATE_UNKNOWN;
+ mHasEnteredConnectedState = false;
+ mShouldPollMtSms = false;
+ stopMtSmsPollingThrottle();
}
/** @return {@code true} if already sent an emergency datagram during a session. */
@@ -1060,7 +1104,8 @@
synchronized (mLock) {
// Add SMS to pending list
mPendingSmsMap.put(messageId, pendingSms);
- int datagramType = SatelliteManager.DATAGRAM_TYPE_SMS;
+ int datagramType = pendingSms.isMtSmsPolling ?
+ DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS : DATAGRAM_TYPE_SMS;
mLastSendRequestDatagramType = datagramType;
if (mDatagramController.needsWaitingForSatelliteConnected(datagramType)) {
@@ -1106,7 +1151,9 @@
mSendingInProgress = true;
PendingRequest pendingRequest = pendingSms.iterator().next().getValue();
- mDatagramController.updateSendStatus(subId, DATAGRAM_TYPE_SMS,
+ mDatagramController.updateSendStatus(subId,
+ pendingRequest.isMtSmsPolling ?
+ DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS : DATAGRAM_TYPE_SMS,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
getPendingMessagesCount(), SATELLITE_RESULT_SUCCESS);
sendMessage(obtainMessage(CMD_SEND_SMS, pendingRequest));
@@ -1170,8 +1217,9 @@
private void handleEventSendSmsDone(int subId, long messageId, boolean success) {
synchronized (mLock) {
mSendingInProgress = false;
- mPendingSmsMap.remove(messageId);
- int datagramType = DATAGRAM_TYPE_SMS;
+ PendingRequest pendingSms = mPendingSmsMap.remove(messageId);
+ int datagramType = pendingSms != null && pendingSms.isMtSmsPolling
+ ? DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS : DATAGRAM_TYPE_SMS;
plogd("handleEventSendSmsDone subId=" + subId + " messageId=" + messageId
+ " success=" + success);
@@ -1180,6 +1228,9 @@
mDatagramController.updateSendStatus(subId, datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS,
getPendingMessagesCount(), SATELLITE_RESULT_SUCCESS);
+ if (datagramType == DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS) {
+ startMtSmsPollingThrottle();
+ }
} else {
mDatagramController.updateSendStatus(subId, datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
@@ -1196,6 +1247,67 @@
}
}
+ private boolean isEnabledMtSmsPolling() {
+ return mContext.getResources().getBoolean(R.bool.config_enabled_mt_sms_polling);
+ }
+
+ private long getMtSmsPollingThrottleMillis() {
+ return mContext.getResources().getInteger(
+ R.integer.config_mt_sms_polling_throttle_millis);
+ }
+
+ private boolean shouldPollMtSms() {
+ return isEnabledMtSmsPolling()
+ && SatelliteController.getInstance().isInCarrierRoamingNbIotNtn();
+ }
+
+ @GuardedBy("mLock")
+ private void sendMtSmsPollingMessage() {
+ if (!mShouldPollMtSms) {
+ return;
+ }
+
+ plogd("sendMtSmsPollingMessage");
+ mShouldPollMtSms = false;
+
+ for (Entry<Long, PendingRequest> entry : mPendingSmsMap.entrySet()) {
+ PendingRequest pendingRequest = entry.getValue();
+ if (pendingRequest.isMtSmsPolling) {
+ plogd("sendMtSmsPollingMessage: mPendingSmsMap already has the polling message.");
+ return;
+ }
+ }
+
+ Phone satellitePhone = SatelliteController.getInstance().getSatellitePhone();
+ if (satellitePhone == null) {
+ ploge("sendMtSmsPollingMessage: satellitePhone is null.");
+ return;
+ }
+
+ SmsDispatchersController smsDispatchersController =
+ satellitePhone.getSmsDispatchersController();
+ if (smsDispatchersController == null) {
+ ploge("sendMtSmsPollingMessage: smsDispatchersController is null.");
+ return;
+ }
+
+ smsDispatchersController.sendMtSmsPollingMessage();
+ }
+
+ @GuardedBy("mLock")
+ private void startMtSmsPollingThrottle() {
+ plogd("startMtSmsPollingThrottle");
+ mIsMtSmsPollingThrottled = true;
+ sendMessageDelayed(obtainMessage(EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT),
+ getMtSmsPollingThrottleMillis());
+ }
+
+ @GuardedBy("mLock")
+ private void stopMtSmsPollingThrottle() {
+ mIsMtSmsPollingThrottled = false;
+ removeMessages(EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT);
+ }
+
private static void logd(@NonNull String log) {
Rlog.d(TAG, log);
}
diff --git a/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java b/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
index dfc7919..4b53178 100644
--- a/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
+++ b/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
@@ -52,7 +52,8 @@
logd("Registered to satellite PLMN " + satellitePlmn);
networkRegistrationInfo.setIsNonTerrestrialNetwork(true);
networkRegistrationInfo.setAvailableServices(
- satelliteController.getSupportedSatelliteServices(subId, satellitePlmn));
+ satelliteController.getSupportedSatelliteServicesForPlmn(
+ subId, satellitePlmn));
break;
}
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 089a0ad..353bf54 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -75,6 +75,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -1741,12 +1742,13 @@
case EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT: {
synchronized (mSatellitePhoneLock) {
mNtnEligibilityHysteresisTimedOut = true;
- boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone);
- plogd("EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT:"
- + " isCarrierRoamingNtnEligible=" + eligible);
- if (eligible) {
- requestIsSatelliteAllowedForCurrentLocation();
- }
+ }
+
+ boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone);
+ plogd("EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT:"
+ + " isCarrierRoamingNtnEligible=" + eligible);
+ if (eligible) {
+ requestIsSatelliteAllowedForCurrentLocation();
}
break;
}
@@ -1817,8 +1819,8 @@
mIsWifiConnected = (boolean) ar.result;
plogd("EVENT_WIFI_CONNECTIVITY_STATE_CHANGED: mIsWifiConnected="
+ mIsWifiConnected);
- handleStateChangedForCarrierRoamingNtnEligibility();
}
+ handleStateChangedForCarrierRoamingNtnEligibility();
break;
}
case EVENT_SATELLITE_ACCESS_RESTRICTION_CHECKING_RESULT: {
@@ -3369,7 +3371,7 @@
* the satellite network {@code plmn}.
*/
@NonNull
- public List<Integer> getSupportedSatelliteServices(int subId, String plmn) {
+ public List<Integer> getSupportedSatelliteServicesForPlmn(int subId, String plmn) {
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
logd("getSupportedSatelliteServices: carrierEnabledSatelliteFlag is disabled");
return new ArrayList<>();
@@ -4707,6 +4709,7 @@
if (activeSubIds != null) {
for (int subId : activeSubIds) {
updateSupportedSatelliteServices(subId);
+ handleCarrierRoamingNtnAvailableServicesChanged(subId);
}
} else {
loge("updateSupportedSatelliteServicesForActiveSubscriptions: "
@@ -5465,11 +5468,11 @@
return;
}
- synchronized (mSatellitePhoneLock) {
- boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone);
- plogd("handleStateChangedForCarrierRoamingNtnEligibility: "
- + "isCarrierRoamingNtnEligible=" + eligible);
+ boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone);
+ plogd("handleStateChangedForCarrierRoamingNtnEligibility: "
+ + "isCarrierRoamingNtnEligible=" + eligible);
+ synchronized (mSatellitePhoneLock) {
if (eligible) {
if (shouldStartNtnEligibilityHysteresisTimer(eligible)) {
startNtnEligibilityHysteresisTimer();
@@ -6820,7 +6823,7 @@
@NetworkRegistrationInfo.ServiceType int serviceType) {
List<String> satellitePlmnList = getSatellitePlmnsForCarrier(subId);
for (String satellitePlmn : satellitePlmnList) {
- if (getSupportedSatelliteServices(subId, satellitePlmn).contains(serviceType)) {
+ if (getSupportedSatelliteServicesForPlmn(subId, satellitePlmn).contains(serviceType)) {
return true;
}
}
@@ -7008,7 +7011,8 @@
return result;
}
- private String getConfigSatelliteGatewayServicePackage() {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected String getConfigSatelliteGatewayServicePackage() {
if (!mChangeIntentComponent) {
return getStringFromOverlayConfig(
R.string.config_satellite_gateway_service_package);
@@ -7079,8 +7083,10 @@
} else {
mOverrideNtnEligibility.set(state);
}
- if (this.mSatellitePhone != null) {
- updateLastNotifiedNtnEligibilityAndNotify(state);
+ synchronized (mSatellitePhoneLock) {
+ if (this.mSatellitePhone != null) {
+ updateLastNotifiedNtnEligibilityAndNotify(state);
+ }
}
}
return true;
@@ -7107,4 +7113,100 @@
}
}
}
+
+ private void handleCarrierRoamingNtnAvailableServicesChanged(int subId) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("handleCarrierRoamingNtnAvailableServicesChanged: "
+ + "carrierRoamingNbIotNtn flag is disabled");
+ return;
+ }
+ updateLastNotifiedNtnAvailableServicesAndNotify(subId);
+ }
+
+ private void updateLastNotifiedNtnAvailableServicesAndNotify(int subId) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("notifyNtnAvailableServices: carrierRoamingNbIotNtn flag is disabled");
+ return;
+ }
+ synchronized (mSatellitePhoneLock) {
+ if (mSatellitePhone == null) {
+ plogd("updateLastNotifiedNtnAvailableServicesAndNotify: phone is null");
+ return;
+ }
+ if (isSatelliteSupportedViaCarrier(subId)) {
+ int[] services = getSupportedSatelliteServicesForCarrier(subId);
+ if (isP2PSmsDisallowedOnCarrierRoamingNtn(mSatellitePhone)) {
+ services = Arrays.stream(services).filter(
+ value -> value != NetworkRegistrationInfo.SERVICE_TYPE_SMS).toArray();
+ }
+ mSatellitePhone.notifyCarrierRoamingNtnAvailableServicesChanged(services);
+ } else {
+ mSatellitePhone.notifyCarrierRoamingNtnAvailableServicesChanged(new int[0]);
+ }
+ }
+ }
+
+ /**
+ * Whether the P2P SMS over carrier roaming satellite is disallowed or not.
+ *
+ * @param phone phone object
+ * return {@code true} when the phone does not support P2P SMS over carrier roaming satellite
+ * {@code false} otherwise
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public boolean isP2PSmsDisallowedOnCarrierRoamingNtn(@NonNull Phone phone) {
+ int subId = phone.getSubId();
+ int carrierRoamingNtnConnectType = getCarrierRoamingNtnConnectType(subId);
+ if (carrierRoamingNtnConnectType == CARRIER_ROAMING_NTN_CONNECT_MANUAL) {
+ // Manual Connected
+ plogd("isP2PSmsDisallowedOnCarrierRoamingNtn: manual connect");
+ String msgPackageName = Telephony.Sms.getDefaultSmsPackage(mContext);
+ String sgPackageName = getConfigSatelliteGatewayServicePackage();
+ if (!isApplicationSupportsP2P(msgPackageName)
+ || !isApplicationSupportsP2P(sgPackageName)) {
+ plogd("isP2PSmsSupportedOnCarrierRoamingNtn APKs do not supports P2P");
+ return true;
+ }
+ }
+ plogd("isP2PSmsDisallowedOnCarrierRoamingNtn [phoneId="
+ + phone.getPhoneId() + "]: P2P is supported");
+ return false;
+ }
+
+ @NonNull
+ private int[] getSupportedSatelliteServicesForCarrier(int subId) {
+ PersistableBundle config = getPersistableBundle(subId);
+ int[] availableServices = config.getIntArray(
+ KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY);
+ if (availableServices == null) {
+ logd("getSupportedSatelliteServicesForCarrier: defaultCapabilities is null");
+ return new int[0];
+ }
+ logd("getSupportedSatelliteServicesForCarrier: subId=" + subId
+ + ", return default values " + Arrays.toString(availableServices));
+ return availableServices;
+ }
+
+/**
+ * Whether application supports the P2P SMS to connect to carrier roaming non-terrestrial network.
+ *
+ * @param packageName application's default package name
+ * return {@code true} when the application supports P2P SMS over the roaming satellite
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public boolean isApplicationSupportsP2P(String packageName) {
+ PackageManager pm = mContext.getPackageManager();
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ try {
+ applicationInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
+ } catch (PackageManager.NameNotFoundException e) {
+ logd("isApplicationSupportsP2P pkgName: " + packageName + " is not installed.");
+ }
+ if (applicationInfo == null || applicationInfo.metaData == null) {
+ logd("isApplicationSupportsP2P pkgName: " + packageName + " meta-data info is empty.");
+ return false;
+ }
+ return applicationInfo.metaData.getBoolean(
+ SatelliteManager.METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT);
+ }
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
index 4138df3..3d92e2a 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
@@ -40,18 +40,22 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AlarmManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.AsyncResult;
import android.os.Build;
+import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.WorkSource;
import android.telephony.DropBoxManagerLoggerBackend;
import android.telephony.PersistentLogger;
import android.telephony.ServiceState;
@@ -183,8 +187,15 @@
@Nullable private PersistentLogger mPersistentLogger = null;
@Nullable private DeviceStateMonitor mDeviceStateMonitor;
@NonNull private SessionMetricsStats mSessionMetricsStats;
-
@NonNull private FeatureFlags mFeatureFlags;
+ @NonNull private AlarmManager mAlarmManager;
+ private final AlarmManager.OnAlarmListener mAlarmListener = new AlarmManager.OnAlarmListener() {
+ @Override
+ public void onAlarm() {
+ plogd("onAlarm: screen off timer expired");
+ sendMessage(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT);
+ }
+ };
/**
* @return The singleton instance of SatelliteSessionController.
@@ -296,6 +307,7 @@
}
mDeviceStateMonitor = satellitePhone.getDeviceStateMonitor();
mSessionMetricsStats = SessionMetricsStats.getInstance();
+ mAlarmManager = mContext.getSystemService(AlarmManager.class);
if (mFeatureFlags.carrierRoamingNbIotNtn()) {
// Register to received Cellular service state
@@ -594,6 +606,9 @@
plogd("cleanUpResource");
mIsDeviceAlignedWithSatellite = false;
unregisterForScreenStateChanged();
+ if (mAlarmManager != null) {
+ mAlarmManager.cancel(mAlarmListener);
+ }
if (mFeatureFlags.carrierRoamingNbIotNtn()) {
// Register to received Cellular service state
@@ -621,6 +636,16 @@
sendMessage(EVENT_SERVICE_STATE_CHANGED, new AsyncResult(null, serviceState, null));
}
+ /**
+ * Uses this function to set AlarmManager object for testing.
+ *
+ * @param alarmManager The instance of AlarmManager.
+ */
+ @VisibleForTesting
+ public void setAlarmManager(AlarmManager alarmManager) {
+ mAlarmManager = alarmManager;
+ }
+
private boolean isDemoMode() {
return mIsDemoMode;
}
@@ -1672,13 +1697,26 @@
if (!screenOn) {
// Screen off, start timer
int timeoutMillis = getScreenOffInactivityTimeoutDurationSec() * 1000;
- sendMessageDelayed(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT, timeoutMillis);
+ if (mAlarmManager == null) {
+ plogd("handleEventScreenStateChanged: can not access AlarmManager to start timer");
+ return;
+ }
+
+ mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + timeoutMillis,
+ TAG, new HandlerExecutor(getHandler()), new WorkSource(), mAlarmListener);
plogd("handleEventScreenStateChanged: start timer " + timeoutMillis);
} else {
// Screen on, stop timer
removeMessages(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT);
+ if (mAlarmManager == null) {
+ plogd("handleEventScreenStateChanged: can not access AlarmManager to stop timer");
+ return;
+ }
+
+ mAlarmManager.cancel(mAlarmListener);
plogd("handleEventScreenStateChanged: stop timer");
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
index da4bf50..8720171 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
@@ -438,4 +438,15 @@
verify(mTelephonyRegistryManager).notifyCarrierRoamingNtnEligibleStateChanged(
eq(subId), eq(true));
}
+
+ @Test
+ @SmallTest
+ public void testCarrierRoamingNtnAvailableServicesChanged() {
+ int subId = mPhone.getSubId();
+ int[] testServices = {3, 6};
+ mDefaultPhoneNotifierUT.notifyCarrierRoamingNtnAvailableServicesChanged(
+ mPhone, testServices);
+ verify(mTelephonyRegistryManager).notifyCarrierRoamingNtnAvailableServicesChanged(
+ eq(subId), eq(testServices));
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index 9bee1ac..70bdcba 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
@@ -3503,7 +3503,7 @@
doReturn(Arrays.asList("10123")).when(mSatelliteController).getSatellitePlmnsForCarrier(
anyInt());
doReturn(satelliteSupportedServiceList).when(mSatelliteController)
- .getSupportedSatelliteServices(sst.mSubId, "10123");
+ .getSupportedSatelliteServicesForPlmn(sst.mSubId, "10123");
assertFalse(sst.mSS.isUsingNonTerrestrialNetwork());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
index 8f0cbbb..53ecac3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
@@ -1391,6 +1391,6 @@
SmsDispatchersController.PendingRequest.TYPE_TEXT, null, "test-app",
mCallingUserId, "1111", "2222", asArrayList(mSentIntent), asArrayList(null),
false, null, 0, asArrayList("text"), null,
- false, 0, false, 10, 100L, false);
+ false, 0, false, 10, 100L, false, false);
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
index ed45fac..1f5a26b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
@@ -128,6 +128,7 @@
private long mCallbackModeDurationMillis;
private boolean mCarrierRoamingNtnMode;
private boolean mCarrierRoamingNtnEligible;
+ private List<Integer> mCarrierRoamingNtnAvailableServices;
// All events contribute to TelephonyRegistry#isPhoneStatePermissionRequired
private static final Set<Integer> READ_PHONE_STATE_EVENTS;
@@ -333,6 +334,12 @@
invocationCount.incrementAndGet();
mCarrierRoamingNtnEligible = eligible;
}
+
+ @Override
+ public void onCarrierRoamingNtnAvailableServicesChanged(List<Integer> services) {
+ invocationCount.incrementAndGet();
+ mCarrierRoamingNtnAvailableServices = services;
+ }
}
private void addTelephonyRegistryService() {
@@ -1698,4 +1705,23 @@
processAllMessages();
assertTrue(mCarrierRoamingNtnEligible);
}
+
+ @Test
+ @EnableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ public void testNotifyCarrierRoamingNtnAvailableServicesChanged() {
+ int subId = INVALID_SUBSCRIPTION_ID;
+ doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
+ doReturn(0/*slotIndex*/).when(mMockSubInfo).getSimSlotIndex();
+ int[] events = {TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_AVAILABLE_SERVICES_CHANGED};
+
+ mTelephonyRegistry.listenWithEventList(false, false, subId, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), mTelephonyCallback.callback, events, true);
+
+ int[] services = {3, 6};
+ mTelephonyRegistry.notifyCarrierRoamingNtnAvailableServicesChanged(subId, services);
+ processAllMessages();
+ int[] carrierServices = mCarrierRoamingNtnAvailableServices.stream()
+ .mapToInt(Integer::intValue).toArray();
+ assertTrue(Arrays.equals(carrierServices, services));
+ }
}
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 142e70a..d964d88 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
@@ -1204,6 +1204,6 @@
SmsDispatchersController.PendingRequest.TYPE_TEXT, null, "test-app",
Binder.getCallingUserHandle().getIdentifier(), "1111", "2222", asArrayList(null),
asArrayList(null), false, null, 0, asArrayList("text"), null, false, 0, false,
- 10, 100L, false);
+ 10, 100L, false, false);
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java
index 873078e..354b20f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java
@@ -80,7 +80,7 @@
doReturn(Arrays.asList(SATELLITE_PLMN_ARRAY))
.when(mMockSatelliteController).getSatellitePlmnsForCarrier(anyInt());
doReturn(mSatelliteSupportedServiceList).when(mMockSatelliteController)
- .getSupportedSatelliteServices(SUB_ID, SATELLITE_PLMN);
+ .getSupportedSatelliteServicesForPlmn(SUB_ID, SATELLITE_PLMN);
}
@After
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 65152d5..c043074 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -49,6 +49,7 @@
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_NEXT_VISIBILITY;
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_PROVISIONED;
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_SUPPORTED;
+import static android.telephony.satellite.SatelliteManager.METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT;
import static android.telephony.satellite.SatelliteManager.NT_RADIO_TECHNOLOGY_EMTC_NTN;
import static android.telephony.satellite.SatelliteManager.NT_RADIO_TECHNOLOGY_NB_IOT_NTN;
import static android.telephony.satellite.SatelliteManager.NT_RADIO_TECHNOLOGY_NR_NTN;
@@ -115,6 +116,8 @@
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.hardware.devicestate.DeviceState;
import android.os.AsyncResult;
@@ -251,6 +254,7 @@
@Mock private Resources mResources;
@Mock private SubscriptionManager mSubscriptionManager;
@Mock private SubscriptionInfo mSubscriptionInfo;
+ @Mock private PackageManager mMockPManager;
private Semaphore mIIntegerConsumerSemaphore = new Semaphore(0);
private IIntegerConsumer mIIntegerConsumer = new IIntegerConsumer.Stub() {
@@ -2016,7 +2020,7 @@
SUB_ID);
assertEquals(EMPTY_STRING_ARRAY.length, satellitePlmnList.size());
List<Integer> supportedSatelliteServices =
- mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00101");
+ mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(SUB_ID, "00101");
assertTrue(supportedSatelliteServices.isEmpty());
String[] satelliteProviderStrArray = {"00101", "00102"};
@@ -2043,7 +2047,7 @@
satellitePlmnList = testSatelliteController.getSatellitePlmnsForCarrier(SUB_ID);
assertTrue(satellitePlmnList.isEmpty());
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00101");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00101");
assertTrue(supportedSatelliteServices.isEmpty());
// Add entitlement provided PLMNs.
@@ -2059,16 +2063,16 @@
processAllMessages();
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00102");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
assertTrue(supportedSatelliteServices.isEmpty());
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00103");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
assertTrue(supportedSatelliteServices.isEmpty());
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00104");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00104");
assertTrue(supportedSatelliteServices.isEmpty());
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00105");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00105");
assertTrue(supportedSatelliteServices.isEmpty());
// Trigger carrier config changed with carrierEnabledSatelliteFlag enabled
@@ -2087,27 +2091,27 @@
assertTrue(Arrays.equals(
expectedSupportedSatellitePlmns, satellitePlmnList.stream().toArray()));
supportedSatelliteServices =
- mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00102");
+ mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
// "00101" should return carrier config assigned value, though it is in allowed list.
assertTrue(Arrays.equals(expectedSupportedServices2,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00103");
+ mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
assertTrue(Arrays.equals(expectedSupportedServices3,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
// "00104", and "00105" should return default supported service.
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00104");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00104");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00105");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00105");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
@@ -2128,33 +2132,33 @@
assertTrue(satellitePlmnList.isEmpty());
// "00102" and "00103" should return default supported service for SUB_ID.
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00102");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00103");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
// "00104", and "00105" should return default supported service for SUB_ID.
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00104");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00104");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00105");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00105");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00102");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID1, "00102");
assertNotNull(supportedSatelliteServices);
assertTrue(Arrays.equals(expectedSupportedServices2,
supportedSatelliteServices.stream()
@@ -2162,20 +2166,20 @@
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00103");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID1, "00103");
assertTrue(Arrays.equals(expectedSupportedServices3,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
/* "00104", and "00105" should return default supported service. */
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00104");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID1, "00104");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00105");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID1, "00105");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
@@ -3299,7 +3303,8 @@
setConfigData(new ArrayList<>());
setCarrierConfigDataPlmnList(new ArrayList<>());
invokeCarrierConfigChanged();
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "31016");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "31016");
assertEquals(new ArrayList<>(), servicesPerPlmn);
// Verify whether the carrier config plmn list is returned with conditions below
@@ -3308,13 +3313,16 @@
setConfigData(new ArrayList<>());
setCarrierConfigDataPlmnList(Arrays.asList("00101", "00102", "00104"));
invokeCarrierConfigChanged();
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00101");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00101");
assertEquals(Arrays.asList(2).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00102");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00102");
assertEquals(Arrays.asList(1, 3).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00104");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00104");
assertEquals(Arrays.asList(2).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
@@ -3324,15 +3332,19 @@
setConfigData(Arrays.asList("00101", "00102", "31024"));
setCarrierConfigDataPlmnList(Arrays.asList("00101", "00102", "00104"));
invokeCarrierConfigChanged();
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00101");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00101");
assertEquals(Arrays.asList(1).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00102");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00102");
assertEquals(Arrays.asList(3).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00104");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00104");
assertEquals(new ArrayList<>(), servicesPerPlmn.stream().sorted().toList());
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "31024");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "31024");
assertEquals(Arrays.asList(5).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
}
@@ -4801,6 +4813,56 @@
eq(SUB_ID), eq(true));
}
+ @Test
+ public void testIsCarrierRoamingNtnAvailableServicesForManualConnect() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+ // CARRIER_ROAMING_NTN_CONNECT_MANUAL: 1
+ mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 1);
+
+ mSatelliteControllerUT.setSatellitePhone(1);
+ processAllMessages();
+ when(mContext.getPackageManager()).thenReturn(mMockPManager);
+ try {
+ when(mMockPManager.getApplicationInfo(anyString(),
+ anyInt())).thenReturn(getApplicationInfo());
+ } catch (PackageManager.NameNotFoundException e) {
+ logd("NameNotFoundException");
+ }
+ assertTrue(mSatelliteControllerUT
+ .isP2PSmsDisallowedOnCarrierRoamingNtn(mPhone));
+ }
+
+ @Test
+ public void testIsCarrierRoamingNtnAvailableServicesForAutomaticConnect() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+ // CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC: 0
+ mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 0);
+
+ mSatelliteControllerUT.setSatellitePhone(1);
+ processAllMessages();
+ when(mContext.getPackageManager()).thenReturn(mMockPManager);
+ try {
+ when(mMockPManager.getApplicationInfo(anyString(),
+ anyInt())).thenReturn(getApplicationInfo());
+ } catch (PackageManager.NameNotFoundException e) {
+ logd("NameNotFoundException");
+ }
+ // If it is automatic connection case, it is not support the callback.
+ assertFalse(mSatelliteControllerUT
+ .isP2PSmsDisallowedOnCarrierRoamingNtn(mPhone));
+ }
+
+ ApplicationInfo getApplicationInfo() {
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.metaData = new Bundle();
+ applicationInfo.metaData.putBoolean(
+ METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT, true);
+ return applicationInfo;
+ }
private void verifyProvisionStatusPerSubscriberIdGetFromDb(boolean provision) {
doReturn(provision).when(
mMockSubscriptionManagerService).isSatelliteProvisionedForNonIpDatagram(anyInt());
@@ -5558,6 +5620,7 @@
public int satelliteModeSettingValue = SATELLITE_MODE_ENABLED_FALSE;
public boolean setSettingsKeyToAllowDeviceRotationCalled = false;
public OutcomeReceiver<Boolean, SatelliteException> isSatelliteAllowedCallback = null;
+ public String packageName = "com.example.app";
TestSatelliteController(
Context context, Looper looper, @NonNull FeatureFlags featureFlags) {
@@ -5637,6 +5700,11 @@
"DEFAULT" /* name */).build()));
}
+ @Override
+ protected String getConfigSatelliteGatewayServicePackage() {
+ return packageName;
+ }
+
void setSatelliteProvisioned(@Nullable Boolean isProvisioned) {
synchronized (mSatelliteViaOemProvisionLock) {
mIsSatelliteViaOemProvisioned = isProvisioned;
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 9518da4..eb9103a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
@@ -39,6 +39,8 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
@@ -50,6 +52,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AlarmManager;
import android.content.Context;
import android.content.res.Resources;
import android.os.AsyncResult;
@@ -80,6 +83,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -117,9 +121,12 @@
@Mock private DatagramController mMockDatagramController;
@Mock private ServiceState mMockServiceState;
@Mock private SessionMetricsStats mMockSessionMetricsStats;
+ @Mock private AlarmManager mAlarmManager;
@Captor ArgumentCaptor<Handler> mHandlerCaptor;
@Captor ArgumentCaptor<Integer> mMsgCaptor;
+ @Captor ArgumentCaptor<Executor> mExecutorArgumentCaptor;
+ @Captor ArgumentCaptor<AlarmManager.OnAlarmListener> mOnAlarmListenerArgumentCaptor;
@Before
public void setUp() throws Exception {
@@ -161,6 +168,7 @@
mTestSatelliteModemStateCallback);
assertSuccessfulModemStateChangedCallback(
mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ mTestSatelliteSessionController.setAlarmManager(mAlarmManager);
}
@After
@@ -238,11 +246,18 @@
processAllMessages();
clearInvocations(mMockSatelliteController);
- // Verify that the screen off inactivity timer is started.
- assertTrue(mTestSatelliteSessionController.isScreenOffInActivityTimerStarted());
-
- // Time shift to cause timeout
- moveTimeForward(SCREEN_OFF_INACTIVITY_TIMEOUT_SEC * 1000);
+ // Verify that the screen off inactivity timer is set.
+ verify(mAlarmManager).setExact(
+ eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
+ anyLong(),
+ anyString(),
+ mExecutorArgumentCaptor.capture(),
+ any(),
+ mOnAlarmListenerArgumentCaptor.capture()
+ );
+ // Notify alarm expired
+ mExecutorArgumentCaptor.getValue().execute(
+ () -> mOnAlarmListenerArgumentCaptor.getValue().onAlarm());
processAllMessages();
// Verify that SatelliteController#requestSatelliteEnabled() was called.
@@ -288,15 +303,23 @@
sendScreenStateChanged(mHandlerCaptor.getValue(), mMsgCaptor.getValue(), false);
processAllMessages();
- // Verify that the screen off inactivity timer is started.
- assertTrue(mTestSatelliteSessionController.isScreenOffInActivityTimerStarted());
+ // Verify that the screen off inactivity timer is set.
+ verify(mAlarmManager).setExact(
+ eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
+ anyLong(),
+ anyString(),
+ mExecutorArgumentCaptor.capture(),
+ any(),
+ mOnAlarmListenerArgumentCaptor.capture()
+ );
// Notify Screen on
sendScreenStateChanged(mHandlerCaptor.getValue(), mMsgCaptor.getValue(), true);
+
processAllMessages();
- // Verify that the screen off inactivity timer is stopped
- assertFalse(mTestSatelliteSessionController.isScreenOffInActivityTimerStarted());
+ // Verify that the screen off inactivity timer is clear.
+ verify(mAlarmManager).cancel(eq(mOnAlarmListenerArgumentCaptor.getValue()));
}
@Test
@@ -2036,10 +2059,6 @@
return hasDeferredMessages(event);
}
- boolean isScreenOffInActivityTimerStarted() {
- return hasMessages(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT);
- }
-
protected boolean isSatelliteEnabledForNtnOnlySubscription() {
return mSatelliteEnabledForNtnOnlySubscription;
}