Merge "Add a bugfix feature for roaming notification" into main
diff --git a/flags/Android.bp b/flags/Android.bp
index 8f363b6..4646649 100644
--- a/flags/Android.bp
+++ b/flags/Android.bp
@@ -21,6 +21,7 @@
aconfig_declarations {
name: "telephony_flags",
package: "com.android.internal.telephony.flags",
+ container: "system",
srcs: [
"calling.aconfig",
"data.aconfig",
diff --git a/flags/calling.aconfig b/flags/calling.aconfig
index bdd0844..f121169 100644
--- a/flags/calling.aconfig
+++ b/flags/calling.aconfig
@@ -1,4 +1,5 @@
package: "com.android.internal.telephony.flags"
+container: "system"
# OWNER=breadley TARGET=24Q3
flag {
diff --git a/flags/data.aconfig b/flags/data.aconfig
index 54b6580..fbe63e1 100644
--- a/flags/data.aconfig
+++ b/flags/data.aconfig
@@ -1,4 +1,5 @@
package: "com.android.internal.telephony.flags"
+container: "system"
# OWNER=linggm TARGET=24Q3
flag {
diff --git a/flags/domainselection.aconfig b/flags/domainselection.aconfig
index 3bf5898..623c3b6 100644
--- a/flags/domainselection.aconfig
+++ b/flags/domainselection.aconfig
@@ -1,4 +1,5 @@
package: "com.android.internal.telephony.flags"
+container: "system"
# OWNER=forestchoi TARGET=24Q3
flag {
diff --git a/flags/ims.aconfig b/flags/ims.aconfig
index 4dbd8aa..6e6bfe9 100644
--- a/flags/ims.aconfig
+++ b/flags/ims.aconfig
@@ -1,4 +1,5 @@
package: "com.android.internal.telephony.flags"
+container: "system"
# OWNER=hyosunkim TARGET=24Q2
flag {
@@ -92,3 +93,14 @@
purpose: PURPOSE_BUGFIX
}
}
+
+# OWNER=joonhunshin TARGET=24Q3
+flag {
+ name: "notify_initial_ims_provisioning_status"
+ namespace: "telephony"
+ description: "This flag allows to notify initial IMS provisioning status when IFeatureProvisioningCallback registered or ImsService connected"
+ bug:"330082572"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/iwlan.aconfig b/flags/iwlan.aconfig
index 702e3f1..f16ee38 100644
--- a/flags/iwlan.aconfig
+++ b/flags/iwlan.aconfig
@@ -1,4 +1,5 @@
package: "com.android.internal.telephony.flags"
+container: "system"
# OWNER=jmunikrishna TARGET=24Q3
flag {
diff --git a/flags/messaging.aconfig b/flags/messaging.aconfig
index 57cfdb4..45df2d8 100644
--- a/flags/messaging.aconfig
+++ b/flags/messaging.aconfig
@@ -1,4 +1,5 @@
package: "com.android.internal.telephony.flags"
+container: "system"
# OWNER=linggm TARGET=24Q1
flag {
diff --git a/flags/misc.aconfig b/flags/misc.aconfig
index d7bed88..a491665 100644
--- a/flags/misc.aconfig
+++ b/flags/misc.aconfig
@@ -1,4 +1,5 @@
package: "com.android.internal.telephony.flags"
+container: "system"
# OWNER=tjstuart TARGET=24Q3
flag {
diff --git a/flags/network.aconfig b/flags/network.aconfig
index 7587be9..eae58d0 100644
--- a/flags/network.aconfig
+++ b/flags/network.aconfig
@@ -1,4 +1,5 @@
package: "com.android.internal.telephony.flags"
+container: "system"
# OWNER=nharold TARGET=24Q1
flag {
diff --git a/flags/satellite.aconfig b/flags/satellite.aconfig
index d9f1498..27ab0b1 100644
--- a/flags/satellite.aconfig
+++ b/flags/satellite.aconfig
@@ -1,4 +1,5 @@
package: "com.android.internal.telephony.flags"
+container: "system"
# OWNER=amallampati TARGET=24Q3
flag {
diff --git a/flags/subscription.aconfig b/flags/subscription.aconfig
index 5bc5340..60c0af1 100644
--- a/flags/subscription.aconfig
+++ b/flags/subscription.aconfig
@@ -1,4 +1,5 @@
package: "com.android.internal.telephony.flags"
+container: "system"
# OWNER=linggm TARGET=24Q3
flag {
diff --git a/flags/telephony.aconfig b/flags/telephony.aconfig
index 91e8cf3..07f2f9e 100644
--- a/flags/telephony.aconfig
+++ b/flags/telephony.aconfig
@@ -1,4 +1,5 @@
package: "com.android.internal.telephony.flags"
+container: "system"
# OWNER=joonhunshin TARGET=24Q3
flag {
diff --git a/flags/uicc.aconfig b/flags/uicc.aconfig
index 6576c87..8166853 100644
--- a/flags/uicc.aconfig
+++ b/flags/uicc.aconfig
@@ -1,4 +1,5 @@
package: "com.android.internal.telephony.flags"
+container: "system"
# OWNER=jayachandranc TARGET=24Q3
flag {
diff --git a/src/java/com/android/internal/telephony/cat/RilMessageDecoder.java b/src/java/com/android/internal/telephony/cat/RilMessageDecoder.java
index 4b10cae..f9261ff 100644
--- a/src/java/com/android/internal/telephony/cat/RilMessageDecoder.java
+++ b/src/java/com/android/internal/telephony/cat/RilMessageDecoder.java
@@ -24,6 +24,7 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.telephony.uicc.IccFileHandler;
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.util.State;
@@ -40,11 +41,14 @@
private static final int CMD_START = 1;
private static final int CMD_PARAMS_READY = 2;
+ private final Object mLock = new Object();
// members
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @GuardedBy("mLock")
private CommandParamsFactory mCmdParamsFactory = null;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private RilMessage mCurrentRilMessage = null;
+ @GuardedBy("mLock")
private Handler mCaller = null;
private static int mSimCount = 0;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -113,9 +117,13 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private void sendCmdForExecution(RilMessage rilMsg) {
- Message msg = mCaller.obtainMessage(CatService.MSG_ID_RIL_MSG_DECODED,
- new RilMessage(rilMsg));
- msg.sendToTarget();
+ synchronized (mLock) {
+ if (mCaller != null) {
+ Message msg = mCaller.obtainMessage(CatService.MSG_ID_RIL_MSG_DECODED,
+ new RilMessage(rilMsg));
+ msg.sendToTarget();
+ }
+ }
}
private RilMessageDecoder(Handler caller, IccFileHandler fh, Context context) {
@@ -125,8 +133,10 @@
addState(mStateCmdParamsReady);
setInitialState(mStateStart);
- mCaller = caller;
- mCmdParamsFactory = CommandParamsFactory.getInstance(this, fh, context);
+ synchronized (mLock) {
+ mCaller = caller;
+ mCmdParamsFactory = CommandParamsFactory.getInstance(this, fh, context);
+ }
}
private RilMessageDecoder() {
@@ -166,7 +176,7 @@
}
private boolean decodeMessageParams(RilMessage rilMsg) {
- boolean decodingStarted;
+ boolean decodingStarted = false;
mCurrentRilMessage = rilMsg;
switch(rilMsg.mId) {
@@ -188,16 +198,21 @@
decodingStarted = false;
break;
}
- try {
- // Start asynch parsing of the command parameters.
- mCmdParamsFactory.make(BerTlv.decode(rawData));
- decodingStarted = true;
- } catch (ResultException e) {
- // send to Service for proper RIL communication.
- CatLog.d(this, "decodeMessageParams: caught ResultException e=" + e);
- mCurrentRilMessage.mResCode = e.result();
- sendCmdForExecution(mCurrentRilMessage);
- decodingStarted = false;
+
+ synchronized (mLock) {
+ if (mCmdParamsFactory != null) {
+ try {
+ // Start asynch parsing of the command parameters.
+ mCmdParamsFactory.make(BerTlv.decode(rawData));
+ decodingStarted = true;
+ } catch (ResultException e) {
+ // send to Service for proper RIL communication.
+ CatLog.d(this, "decodeMessageParams: caught ResultException e=" + e);
+ mCurrentRilMessage.mResCode = e.result();
+ sendCmdForExecution(mCurrentRilMessage);
+ decodingStarted = false;
+ }
+ }
}
break;
default:
@@ -211,10 +226,16 @@
quitNow();
mStateStart = null;
mStateCmdParamsReady = null;
- mCmdParamsFactory.dispose();
- mCmdParamsFactory = null;
+
+ synchronized (mLock) {
+ if (mCmdParamsFactory != null) {
+ mCmdParamsFactory.dispose();
+ mCmdParamsFactory = null;
+ }
+ mCaller = null;
+ }
+
mCurrentRilMessage = null;
- mCaller = null;
mInstance = null;
}
}
diff --git a/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java b/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java
index 0db7844..85d5a35 100644
--- a/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java
+++ b/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java
@@ -20,12 +20,14 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
+import android.os.FileUtils;
import android.util.Log;
-import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.satellite.SatelliteConfig;
import com.android.internal.telephony.satellite.SatelliteConfigParser;
+import com.android.internal.telephony.util.TelephonyUtils;
import com.android.server.updates.ConfigUpdateInstallReceiver;
import libcore.io.IoUtils;
@@ -33,6 +35,8 @@
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
@@ -43,7 +47,8 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected static final String UPDATE_DIR = "/data/misc/telephonyconfig";
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- protected static final String UPDATE_CONTENT_PATH = "telephony_config.pb";
+ protected static final String NEW_CONFIG_CONTENT_PATH = "new_telephony_config.pb";
+ protected static final String VALID_CONFIG_CONTENT_PATH = "valid_telephony_config.pb";
protected static final String UPDATE_METADATA_PATH = "metadata/";
public static final String VERSION = "version";
@@ -66,7 +71,7 @@
}
public TelephonyConfigUpdateInstallReceiver() {
- super(UPDATE_DIR, UPDATE_CONTENT_PATH, UPDATE_METADATA_PATH, VERSION);
+ super(UPDATE_DIR, NEW_CONFIG_CONTENT_PATH, UPDATE_METADATA_PATH, VERSION);
}
/**
@@ -74,57 +79,94 @@
*/
@Nullable
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- public byte[] getCurrentContent() {
+ public byte[] getContentFromContentPath(@NonNull File contentPath) {
try {
- return IoUtils.readFileAsByteArray(updateContent.getCanonicalPath());
+ return IoUtils.readFileAsByteArray(contentPath.getCanonicalPath());
} catch (IOException e) {
- Slog.i(TAG, "Failed to read current content, assuming first update!");
+ Log.e(TAG, "Failed to read current content : " + contentPath);
return null;
}
}
+ /**
+ * @param parser target of validation.
+ * @return {@code true} if all the config data are valid {@code false} otherwise.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public boolean isValidSatelliteCarrierConfigData(@NonNull ConfigParser parser) {
+ SatelliteConfig satelliteConfig = (SatelliteConfig) parser.getConfig();
+ if (satelliteConfig == null) {
+ Log.e(TAG, "satelliteConfig is null");
+ return false;
+ }
+
+ // If no carrier config exist then it is considered as a valid config
+ Set<Integer> carrierIds = satelliteConfig.getAllSatelliteCarrierIds();
+ for (int carrierId : carrierIds) {
+ Map<String, Set<Integer>> plmnsServices =
+ satelliteConfig.getSupportedSatelliteServices(carrierId);
+ Set<String> plmns = plmnsServices.keySet();
+ for (String plmn : plmns) {
+ if (!TelephonyUtils.isValidPlmn(plmn)) {
+ Log.e(TAG, "found invalid plmn : " + plmn);
+ return false;
+ }
+ Set<Integer> serviceSet = plmnsServices.get(plmn);
+ for (int service : serviceSet) {
+ if (!TelephonyUtils.isValidService(service)) {
+ Log.e(TAG, "found invalid service : " + service);
+ return false;
+ }
+ }
+ }
+ }
+ Log.d(TAG, "the config data is valid");
+ return true;
+ }
+
+
@Override
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
public void postInstall(Context context, Intent intent) {
Log.d(TAG, "Telephony config is updated in file partition");
- ConfigParser updatedConfigParser = getNewConfigParser(DOMAIN_SATELLITE,
- getCurrentContent());
- if (updatedConfigParser == null) {
- Log.d(TAG, "updatedConfigParser is null");
+ ConfigParser newConfigParser = getNewConfigParser(DOMAIN_SATELLITE,
+ getContentFromContentPath(updateContent));
+
+ if (newConfigParser == null) {
+ Log.e(TAG, "newConfigParser is null");
return;
}
- boolean isParserChanged = false;
+ if (!isValidSatelliteCarrierConfigData(newConfigParser)) {
+ Log.e(TAG, "received config data has invalid satellite carrier config data");
+ return;
+ }
synchronized (getInstance().mConfigParserLock) {
- if (getInstance().mConfigParser == null) {
- getInstance().mConfigParser = updatedConfigParser;
- isParserChanged = true;
- } else {
- int updatedVersion = updatedConfigParser.mVersion;
+ if (getInstance().mConfigParser != null) {
+ int updatedVersion = newConfigParser.mVersion;
int previousVersion = getInstance().mConfigParser.mVersion;
Log.d(TAG, "previous version is " + previousVersion + " | updated version is "
+ updatedVersion);
- if (updatedVersion > previousVersion) {
- getInstance().mConfigParser = updatedConfigParser;
- isParserChanged = true;
+ if (updatedVersion <= previousVersion) {
+ Log.e(TAG, "updatedVersion is smaller than previousVersion");
+ return;
}
}
+ getInstance().mConfigParser = newConfigParser;
+ }
+
+ if (!getInstance().mCallbackHashMap.keySet().isEmpty()) {
+ Iterator<Executor> iterator = getInstance().mCallbackHashMap.keySet().iterator();
+ while (iterator.hasNext()) {
+ Executor executor = iterator.next();
+ getInstance().mCallbackHashMap.get(executor).onChanged(newConfigParser);
+ }
}
- if (isParserChanged) {
- if (getInstance().mCallbackHashMap.keySet().isEmpty()) {
- Log.d(TAG, "mCallbackHashMap.keySet().isEmpty");
- return;
- }
- Iterator<Executor> iterator =
- getInstance().mCallbackHashMap.keySet().iterator();
- while (iterator.hasNext()) {
- Executor executor = iterator.next();
- getInstance().mCallbackHashMap.get(executor).onChanged(
- updatedConfigParser);
- }
+ if (!copySourceFileToTargetFile(NEW_CONFIG_CONTENT_PATH, VALID_CONFIG_CONTENT_PATH)) {
+ Log.e(TAG, "fail to copy to the valid satellite carrier config data");
}
}
@@ -135,7 +177,9 @@
synchronized (getInstance().mConfigParserLock) {
if (getInstance().mConfigParser == null) {
Log.d(TAG, "CreateNewConfigParser with domain " + domain);
- getInstance().mConfigParser = getNewConfigParser(domain, getCurrentContent());
+ getInstance().mConfigParser = getNewConfigParser(
+ domain, getContentFromContentPath(new File(updateDir,
+ VALID_CONFIG_CONTENT_PATH)));
}
return getInstance().mConfigParser;
}
@@ -197,4 +241,35 @@
return null;
}
}
+
+ /**
+ * @param sourceFileName source file name
+ * @param targetFileName target file name
+ * @return {@code true} if successful, {@code false} otherwise
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public boolean copySourceFileToTargetFile(
+ @NonNull String sourceFileName, @NonNull String targetFileName) {
+ try {
+ File sourceFile = new File(UPDATE_DIR, sourceFileName);
+ File targetFile = new File(UPDATE_DIR, targetFileName);
+ Log.d(TAG, "copy " + sourceFile.getName() + " >> " + targetFile.getName());
+
+ if (sourceFile.exists()) {
+ if (targetFile.exists()) {
+ targetFile.delete();
+ }
+ FileUtils.copy(sourceFile, targetFile);
+ FileUtils.copyPermissions(sourceFile, targetFile);
+ Log.d(TAG, "success to copy the file " + sourceFile.getName() + " to "
+ + targetFile.getName());
+ return true;
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "copy error : " + e);
+ return false;
+ }
+ Log.d(TAG, "source file is not exist, no file to copy");
+ return false;
+ }
}
diff --git a/src/java/com/android/internal/telephony/data/DataNetwork.java b/src/java/com/android/internal/telephony/data/DataNetwork.java
index 99a3276..d130751 100644
--- a/src/java/com/android/internal/telephony/data/DataNetwork.java
+++ b/src/java/com/android/internal/telephony/data/DataNetwork.java
@@ -2457,8 +2457,8 @@
// If we find another data data profile that can support MMS on IWLAN, then remove
// the MMS capability from this cellular network. This will allow IWLAN to be
// brought up for MMS later.
- if (dataProfile != null && !dataProfile.equals(mDataProfile)) {
- log("Found a different data profile " + mDataProfile.getApn()
+ if (dataProfile != null && !dataProfile.getApn().equals(mDataProfile.getApn())) {
+ log("Found a different apn name " + mDataProfile.getApn()
+ " that can serve MMS on IWLAN.");
builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
}
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index b4aa1f0..aa461ff 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -2156,15 +2156,32 @@
}
/**
- * tethering and enterprise capabilities are not respected as restricted requests. For a request
- * with these capabilities, any soft disallowed reasons are honored.
+ * Check if a network request should be treated as a valid restricted network request that
+ * can bypass soft disallowed reasons, for example, mobile data off.
+ *
* @param networkRequest The network request to evaluate.
- * @return {@code true} if the request doesn't contain any exceptional capabilities, its
- * restricted capability, if any, is respected.
+ * @return {@code true} if the request can be considered as a valid restricted network request
+ * that can bypass any soft disallowed reasons, otherwise {@code false}.
*/
private boolean isValidRestrictedRequest(@NonNull TelephonyNetworkRequest networkRequest) {
- return !(networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
- || networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE));
+
+ if (!mFeatureFlags.satelliteInternet()) {
+ return !(networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
+ || networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE));
+ } else {
+ // tethering, enterprise and mms with restricted capabilities always honor soft
+ // disallowed reasons and not respected as restricted request
+ if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
+ || networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
+ || networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
+ return false;
+ }
+ // When the device is on satellite, internet with restricted capabilities always honor
+ // soft disallowed reasons and not respected as restricted request
+ return !(mServiceState.isUsingNonTerrestrialNetwork()
+ && networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+
+ }
}
/**
@@ -3183,7 +3200,13 @@
return;
}
- if (dataNetwork.isInternetSupported()) {
+ // Only track the networks that require validation.
+ // The criteria is base on NetworkMonitorUtils.java.
+ NetworkCapabilities capabilities = dataNetwork.getNetworkCapabilities();
+ if (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+ && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)) {
if (status == NetworkAgent.VALIDATION_STATUS_NOT_VALID
&& (dataNetwork.getCurrentState() == null || dataNetwork.isDisconnected())) {
log("Ignoring invalid validation status for disconnected DataNetwork");
diff --git a/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java b/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
index e3eed00..fddeb06 100644
--- a/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
+++ b/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
@@ -35,7 +35,9 @@
import android.telephony.DomainSelector;
import android.telephony.EmergencyRegistrationResult;
import android.telephony.NetworkRegistrationInfo;
+import android.telephony.PreciseDisconnectCause;
import android.telephony.data.ApnSetting;
+import android.telephony.ims.ImsReasonInfo;
import android.util.LocalLog;
import android.util.Log;
@@ -351,6 +353,10 @@
private boolean mIsTestMode = false;
+ private int mDisconnectCause = DisconnectCause.NOT_VALID;
+ private int mPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
+ private String mReasonMessage = null;
+
/**
* Creates an instance.
*
@@ -789,6 +795,51 @@
}
/**
+ * Save call disconnect info for error propagation.
+ * @param disconnectCause The code for the reason for the disconnect.
+ * @param preciseDisconnectCause The code for the precise reason for the disconnect.
+ * @param reasonMessage Description of the reason for the disconnect, not intended for the user
+ * to see.
+ */
+ public void setDisconnectCause(int disconnectCause, int preciseDisconnectCause,
+ String reasonMessage) {
+ mDisconnectCause = disconnectCause;
+ mPreciseDisconnectCause = preciseDisconnectCause;
+ mReasonMessage = reasonMessage;
+ }
+
+ public int getDisconnectCause() {
+ return mDisconnectCause;
+ }
+
+ public int getPreciseDisconnectCause() {
+ return mPreciseDisconnectCause;
+ }
+
+ public String getReasonMessage() {
+ return mReasonMessage;
+ }
+
+ /**
+ * @return imsReasonInfo Reason for the IMS call failure.
+ */
+ public @Nullable ImsReasonInfo getImsReasonInfo() {
+ if (getSelectionAttributes() == null) {
+ // Neither selectDomain(...) nor reselectDomain(...) has been called yet.
+ return null;
+ }
+
+ return getSelectionAttributes().getPsDisconnectCause();
+ }
+
+ /**
+ * @return phoneId To support localized message based on phoneId
+ */
+ public int getPhoneId() {
+ return getPhone().getPhoneId();
+ }
+
+ /**
* Dumps local log.
*/
public void dump(@NonNull PrintWriter printWriter) {
diff --git a/src/java/com/android/internal/telephony/domainselection/NormalCallDomainSelectionConnection.java b/src/java/com/android/internal/telephony/domainselection/NormalCallDomainSelectionConnection.java
index 0fd9201..095d61f 100644
--- a/src/java/com/android/internal/telephony/domainselection/NormalCallDomainSelectionConnection.java
+++ b/src/java/com/android/internal/telephony/domainselection/NormalCallDomainSelectionConnection.java
@@ -24,11 +24,9 @@
import android.telecom.PhoneAccount;
import android.telephony.AccessNetworkConstants.RadioAccessNetworkType;
import android.telephony.Annotation.DisconnectCauses;
-import android.telephony.DisconnectCause;
import android.telephony.DomainSelectionService;
import android.telephony.DomainSelectionService.EmergencyScanType;
import android.telephony.NetworkRegistrationInfo;
-import android.telephony.PreciseDisconnectCause;
import android.telephony.ims.ImsReasonInfo;
import com.android.internal.telephony.Phone;
@@ -41,9 +39,6 @@
public class NormalCallDomainSelectionConnection extends DomainSelectionConnection {
private static final boolean DBG = false;
- private int mDisconnectCause = DisconnectCause.NOT_VALID;
- private int mPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
- private String mReasonMessage = null;
private @Nullable DomainSelectionConnectionCallback mCallback;
@@ -130,49 +125,4 @@
}
return builder.build();
}
-
- /**
- * Save call disconnect info for error propagation.
- * @param disconnectCause The code for the reason for the disconnect.
- * @param preciseDisconnectCause The code for the precise reason for the disconnect.
- * @param reasonMessage Description of the reason for the disconnect, not intended for the user
- * to see.
- */
- public void setDisconnectCause(int disconnectCause, int preciseDisconnectCause,
- String reasonMessage) {
- mDisconnectCause = disconnectCause;
- mPreciseDisconnectCause = preciseDisconnectCause;
- mReasonMessage = reasonMessage;
- }
-
- public int getDisconnectCause() {
- return mDisconnectCause;
- }
-
- public int getPreciseDisconnectCause() {
- return mPreciseDisconnectCause;
- }
-
- public String getReasonMessage() {
- return mReasonMessage;
- }
-
- /**
- * @return imsReasonInfo Reason for the IMS call failure.
- */
- public @Nullable ImsReasonInfo getImsReasonInfo() {
- if (getSelectionAttributes() == null) {
- // Neither selectDomain(...) nor reselectDomain(...) has been called yet.
- return null;
- }
-
- return getSelectionAttributes().getPsDisconnectCause();
- }
-
- /**
- * @return phoneId To support localized message based on phoneId
- */
- public int getPhoneId() {
- return getPhone().getPhoneId();
- }
}
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
index 1c8b696..25d94cf 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
@@ -354,11 +354,26 @@
mOnEcmExitCompleteRunnable.run();
mOnEcmExitCompleteRunnable = null;
}
+ if (mPhone != null && mEmergencyMode == MODE_EMERGENCY_WWAN) {
+ // In cross sim redialing.
+ setEmergencyModeInProgress(true);
+ mWasEmergencyModeSetOnModem = true;
+ mPhone.setEmergencyMode(MODE_EMERGENCY_WWAN,
+ mHandler.obtainMessage(MSG_SET_EMERGENCY_MODE_DONE,
+ Integer.valueOf(EMERGENCY_TYPE_CALL)));
+ }
} else if (emergencyType == EMERGENCY_TYPE_SMS) {
if (mIsEmergencyCallStartedDuringEmergencySms) {
mIsEmergencyCallStartedDuringEmergencySms = false;
turnOnRadioAndSwitchDds(mPhone, EMERGENCY_TYPE_CALL,
mIsTestEmergencyNumber);
+ } else if (mPhone != null && mEmergencyMode == MODE_EMERGENCY_WWAN) {
+ // Starting emergency call while exiting emergency mode
+ setEmergencyModeInProgress(true);
+ mWasEmergencyModeSetOnModem = true;
+ mPhone.setEmergencyMode(MODE_EMERGENCY_WWAN,
+ mHandler.obtainMessage(MSG_SET_EMERGENCY_MODE_DONE,
+ Integer.valueOf(EMERGENCY_TYPE_CALL)));
} else if (mIsEmergencySmsStartedDuringScbm) {
mIsEmergencySmsStartedDuringScbm = false;
setEmergencyMode(mSmsPhone, emergencyType,
@@ -713,6 +728,16 @@
maybeNotifyTransportChangeCompleted(emergencyType, false);
return;
}
+
+ if (emergencyType == EMERGENCY_TYPE_CALL
+ && mode == MODE_EMERGENCY_WWAN
+ && isEmergencyModeInProgress() && !isInEmergencyMode()) {
+ // In cross sim redialing or ending emergency SMS, exitEmergencyMode is not completed.
+ mEmergencyMode = mode;
+ Rlog.i(TAG, "setEmergencyMode wait for the completion of exitEmergencyMode");
+ return;
+ }
+
mEmergencyMode = mode;
setEmergencyModeInProgress(true);
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramController.java b/src/java/com/android/internal/telephony/satellite/DatagramController.java
index 6783e38..204fc8e 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramController.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramController.java
@@ -16,10 +16,13 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_IDLE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_OFF;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import android.annotation.NonNull;
import android.content.Context;
@@ -72,7 +75,7 @@
private int mSendSubId;
@GuardedBy("mLock")
private @SatelliteManager.SatelliteDatagramTransferState int mSendDatagramTransferState =
- SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
@GuardedBy("mLock")
private int mSendPendingCount = 0;
@GuardedBy("mLock")
@@ -82,7 +85,7 @@
private int mReceiveSubId;
@GuardedBy("mLock")
private @SatelliteManager.SatelliteDatagramTransferState int mReceiveDatagramTransferState =
- SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
@GuardedBy("mLock")
private int mReceivePendingCount = 0;
@GuardedBy("mLock")
@@ -132,7 +135,7 @@
* about datagram transfer state changes.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- protected DatagramController(@NonNull Context context, @NonNull Looper looper,
+ public DatagramController(@NonNull Context context, @NonNull Looper looper,
@NonNull PointingAppController pointingAppController) {
mContext = context;
mPointingAppController = pointingAppController;
@@ -188,6 +191,7 @@
* @param callback The callback to get {@link SatelliteManager.SatelliteResult} of the request.
*/
public void pollPendingSatelliteDatagrams(int subId, @NonNull Consumer<Integer> callback) {
+ logd("pollPendingSatelliteDatagrams");
mDatagramReceiver.pollPendingSatelliteDatagrams(subId, callback);
}
@@ -213,7 +217,6 @@
public void sendSatelliteDatagram(int subId, @SatelliteManager.DatagramType int datagramType,
@NonNull SatelliteDatagram datagram, boolean needFullScreenPointingUI,
@NonNull Consumer<Integer> callback) {
- pushDemoModeDatagram(datagramType, datagram);
mDatagramDispatcher.sendSatelliteDatagram(subId, datagramType, datagram,
needFullScreenPointingUI, callback);
}
@@ -239,10 +242,10 @@
mSendDatagramTransferState = datagramTransferState;
mSendPendingCount = sendPendingCount;
mSendErrorCode = errorCode;
-
notifyDatagramTransferStateChangedToSessionController();
mPointingAppController.updateSendDatagramTransferState(mSendSubId,
mSendDatagramTransferState, mSendPendingCount, mSendErrorCode);
+ retryPollPendingDatagramsInDemoMode();
}
}
@@ -271,6 +274,7 @@
notifyDatagramTransferStateChangedToSessionController();
mPointingAppController.updateReceiveDatagramTransferState(mReceiveSubId,
mReceiveDatagramTransferState, mReceivePendingCount, mReceiveErrorCode);
+ retryPollPendingDatagramsInDemoMode();
}
if (isPollingInIdleState()) {
@@ -300,9 +304,16 @@
mDatagramReceiver.onSatelliteModemStateChanged(state);
}
- void setDeviceAlignedWithSatellite(boolean isAligned) {
+ /**
+ * Set whether the device is aligned with the satellite.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public void setDeviceAlignedWithSatellite(boolean isAligned) {
mDatagramDispatcher.setDeviceAlignedWithSatellite(isAligned);
mDatagramReceiver.setDeviceAlignedWithSatellite(isAligned);
+ if (isAligned) {
+ retryPollPendingDatagramsInDemoMode();
+ }
}
@VisibleForTesting
@@ -332,14 +343,14 @@
public boolean isSendingInIdleState() {
synchronized (mLock) {
return (mSendDatagramTransferState
- == SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
}
}
public boolean isPollingInIdleState() {
synchronized (mLock) {
return (mReceiveDatagramTransferState
- == SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
}
}
@@ -380,8 +391,8 @@
* @param datagramType datagram type, only DATAGRAM_TYPE_SOS_MESSAGE will be saved
* @param datagram datagram The last datagram saved when sendSatelliteDatagramForDemo is called
*/
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- protected void pushDemoModeDatagram(@SatelliteManager.DatagramType int datagramType,
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public void pushDemoModeDatagram(@SatelliteManager.DatagramType int datagramType,
SatelliteDatagram datagram) {
if (mIsDemoMode && datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) {
synchronized (mLock) {
@@ -484,6 +495,23 @@
mDatagramDispatcher.setShouldSendDatagramToModemInDemoMode(shouldSendToModemInDemoMode);
}
+ private void retryPollPendingDatagramsInDemoMode() {
+ synchronized (mLock) {
+ if (mIsDemoMode && isSendingInIdleState() && isPollingInIdleState()
+ && !mDemoModeDatagramList.isEmpty()) {
+ Consumer<Integer> internalCallback = new Consumer<Integer>() {
+ @Override
+ public void accept(Integer result) {
+ if (result != SATELLITE_RESULT_SUCCESS) {
+ logd("retryPollPendingDatagramsInDemoMode result: " + result);
+ }
+ }
+ };
+ pollPendingSatelliteDatagrams(DEFAULT_SUBSCRIPTION_ID, internalCallback);
+ }
+ }
+ }
+
private static void logd(@NonNull String log) {
Rlog.d(TAG, log);
}
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
index 83caf2e..1f98168 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
@@ -18,6 +18,7 @@
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import static com.android.internal.telephony.satellite.DatagramController.ROUNDING_UNIT;
@@ -62,7 +63,7 @@
private static final int EVENT_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMED_OUT = 4;
private static final int EVENT_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_TIMED_OUT = 5;
private static final int EVENT_ABORT_SENDING_SATELLITE_DATAGRAMS_DONE = 6;
- private static final int CMD_POLL_PENDING_SATELLITE_DATAGRAMS = 7;
+ private static final int EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT = 7;
private static final Long TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE = TimeUnit.SECONDS.toMillis(10);
@NonNull private static DatagramDispatcher sInstance;
@NonNull private final Context mContext;
@@ -238,7 +239,8 @@
break;
}
}
- logd("EVENT_SEND_SATELLITE_DATAGRAM_DONE error: " + error);
+ logd("EVENT_SEND_SATELLITE_DATAGRAM_DONE error: " + error
+ + ", mIsDemoMode=" + mIsDemoMode);
/*
* The response should be ignored if either of the following hold
@@ -271,11 +273,7 @@
getPendingDatagramCount(), error);
mControllerMetricsStats.reportOutgoingDatagramSuccessCount(
argument.datagramType);
- if (mIsDemoMode) {
- sendMessageDelayed(
- obtainMessage(CMD_POLL_PENDING_SATELLITE_DATAGRAMS, request),
- getDemoTimeoutDuration());
- }
+ startWaitForSimulatedPollDatagramsDelayTimer(request);
if (getPendingDatagramCount() > 0) {
// Send response for current datagram
argument.callback.accept(error);
@@ -323,13 +321,10 @@
handleEventDatagramWaitForConnectedStateTimedOut();
break;
- case CMD_POLL_PENDING_SATELLITE_DATAGRAMS:
- if (mIsDemoMode) {
- request = (DatagramDispatcherHandlerRequest) msg.obj;
- SendSatelliteDatagramArgument argument =
- (SendSatelliteDatagramArgument) request.argument;
- pollPendingSatelliteDatagrams(argument.subId);
- }
+ case EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT:
+ request = (DatagramDispatcherHandlerRequest) msg.obj;
+ handleEventWaitForSimulatedPollDatagramsDelayTimedOut(
+ (SendSatelliteDatagramArgument) request.argument);
break;
default:
@@ -413,8 +408,11 @@
logd("setDemoMode: mIsDemoMode=" + mIsDemoMode);
}
+ /**
+ * Set whether the device is aligned with the satellite.
+ */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- protected void setDeviceAlignedWithSatellite(boolean isAligned) {
+ public void setDeviceAlignedWithSatellite(boolean isAligned) {
synchronized (mLock) {
mIsAligned = isAligned;
logd("setDeviceAlignedWithSatellite: " + mIsAligned);
@@ -464,7 +462,7 @@
mSendSatelliteDatagramRequest = null;
SatelliteManager.SatelliteException exception =
new SatelliteManager.SatelliteException(
- SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
+ SATELLITE_RESULT_NOT_REACHABLE);
Message message = obtainMessage(EVENT_SEND_SATELLITE_DATAGRAM_DONE, request);
AsyncResult.forMessage(message, null, exception);
message.sendToTarget();
@@ -646,6 +644,7 @@
stopSatelliteAlignedTimer();
stopDatagramWaitForConnectedStateTimer();
stopWaitForDatagramSendingResponseTimer();
+ stopWaitForSimulatedPollDatagramsDelayTimer();
mIsDemoMode = false;
mSendSatelliteDatagramRequest = null;
mIsAligned = false;
@@ -703,12 +702,12 @@
mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
getPendingDatagramCount(),
- SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
+ SATELLITE_RESULT_NOT_REACHABLE);
mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
0, SatelliteManager.SATELLITE_RESULT_SUCCESS);
abortSendingPendingDatagrams(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
- SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
+ SATELLITE_RESULT_NOT_REACHABLE);
}
}
@@ -811,15 +810,38 @@
}
}
- private void pollPendingSatelliteDatagrams(int subId) {
- logd("pollPendingSatelliteDatagrams");
- Consumer<Integer> internalCallback = new Consumer<Integer>() {
- @Override
- public void accept(Integer result) {
- logd("pollPendingSatelliteDatagrams result: " + result);
- }
- };
- mDatagramController.pollPendingSatelliteDatagrams(subId, internalCallback);
+ private void startWaitForSimulatedPollDatagramsDelayTimer(
+ @NonNull DatagramDispatcherHandlerRequest request) {
+ if (mIsDemoMode) {
+ logd("startWaitForSimulatedPollDatagramsDelayTimer");
+ sendMessageDelayed(
+ obtainMessage(EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT, request),
+ getDemoTimeoutDuration());
+ } else {
+ logd("Should not start WaitForSimulatedPollDatagramsDelayTimer in non-demo mode");
+ }
+ }
+
+ private void stopWaitForSimulatedPollDatagramsDelayTimer() {
+ removeMessages(EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT);
+ }
+
+ private void handleEventWaitForSimulatedPollDatagramsDelayTimedOut(
+ @NonNull SendSatelliteDatagramArgument argument) {
+ if (mIsDemoMode) {
+ logd("handleEventWaitForSimulatedPollDatagramsDelayTimedOut");
+ mDatagramController.pushDemoModeDatagram(argument.datagramType, argument.datagram);
+ Consumer<Integer> internalCallback = new Consumer<Integer>() {
+ @Override
+ public void accept(Integer result) {
+ logd("pollPendingSatelliteDatagrams result: " + result);
+ }
+ };
+ mDatagramController.pollPendingSatelliteDatagrams(argument.subId, internalCallback);
+ } else {
+ logd("Unexpected EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT in "
+ + "non-demo mode");
+ }
}
long getDemoTimeoutDuration() {
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
index 6c52a8c..a4b1193 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
@@ -743,7 +743,7 @@
}
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- protected void setDeviceAlignedWithSatellite(boolean isAligned) {
+ public void setDeviceAlignedWithSatellite(boolean isAligned) {
synchronized (mLock) {
mIsAligned = isAligned;
logd("setDeviceAlignedWithSatellite: " + mIsAligned);
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java b/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java
index 60950f2..7aadf0d 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.util.ArraySet;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -139,6 +140,19 @@
}
/**
+ * Get carrier identifier set for the satellite
+ *
+ * @return carrier identifier set from the config data.
+ */
+ @NonNull
+ public Set<Integer> getAllSatelliteCarrierIds() {
+ if (mSupportedServicesPerCarrier != null) {
+ return new ArraySet<>(mSupportedServicesPerCarrier.keySet());
+ }
+ return new ArraySet<>();
+ }
+
+ /**
* @return satellite region country codes
*/
@NonNull
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 287f839..abaef23 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -78,6 +78,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
@@ -87,6 +88,7 @@
import android.telephony.satellite.ISatelliteDatagramCallback;
import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.ISatelliteProvisionStateCallback;
+import android.telephony.satellite.ISatelliteSupportedStateCallback;
import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.SatelliteCapabilities;
@@ -195,6 +197,7 @@
private static final int EVENT_SATELLITE_CAPABILITIES_CHANGED = 38;
private static final int EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT = 39;
private static final int EVENT_SATELLITE_CONFIG_DATA_UPDATED = 40;
+ private static final int EVENT_SATELLITE_SUPPORTED_STATE_CHANGED = 41;
@NonNull private static SatelliteController sInstance;
@NonNull private final Context mContext;
@@ -248,7 +251,10 @@
private final AtomicBoolean mRegisteredForNtnSignalStrengthChanged = new AtomicBoolean(false);
private final AtomicBoolean mRegisteredForSatelliteCapabilitiesChanged =
new AtomicBoolean(false);
- private final AtomicBoolean mShouldReportNtnSignalStrength = new AtomicBoolean(false);
+ private final AtomicBoolean mIsModemEnabledReportingNtnSignalStrength =
+ new AtomicBoolean(false);
+ private final AtomicBoolean mRegisteredForSatelliteSupportedStateChanged =
+ new AtomicBoolean(false);
/**
* Map key: subId, value: callback to get error code of the provision request.
*/
@@ -272,6 +278,11 @@
*/
private final ConcurrentHashMap<IBinder, ISatelliteCapabilitiesCallback>
mSatelliteCapabilitiesChangedListeners = new ConcurrentHashMap<>();
+ /**
+ * Map key: binder of the callback, value: callback to receive supported state changed events.
+ */
+ private final ConcurrentHashMap<IBinder, ISatelliteSupportedStateCallback>
+ mSatelliteSupportedStateChangedListeners = new ConcurrentHashMap<>();
private final Object mIsSatelliteSupportedLock = new Object();
@GuardedBy("mIsSatelliteSupportedLock")
private Boolean mIsSatelliteSupported = null;
@@ -333,6 +344,14 @@
@NonNull private final SparseBooleanArray
mWasSatelliteConnectedViaCarrier = new SparseBooleanArray();
+ /**
+ * Key: Subscription ID; Value: set of
+ * {@link android.telephony.NetworkRegistrationInfo.ServiceType}
+ */
+ @GuardedBy("mSatelliteConnectedLock")
+ @NonNull private final Map<Integer, List<Integer>>
+ mSatModeCapabilitiesForCarrierRoaming = new HashMap<>();
+
@GuardedBy("mSatelliteConnectedLock")
@NonNull private final SparseBooleanArray
mIsSatelliteConnectedViaCarrierHysteresisTimeExpired = new SparseBooleanArray();
@@ -375,6 +394,8 @@
private static final String NOTIFICATION_CHANNEL_ID = "satellite";
private final RegistrantList mSatelliteConfigUpdateChangedRegistrants = new RegistrantList();
+ private final BTWifiNFCStateReceiver mBTWifiNFCSateReceiver;
+ private final UwbAdapterStateCallback mUwbAdapterStateCallback;
/**
* @return The singleton instance of SatelliteController.
@@ -444,6 +465,8 @@
mContentResolver = mContext.getContentResolver();
mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
+ mBTWifiNFCSateReceiver = new BTWifiNFCStateReceiver();
+ mUwbAdapterStateCallback = new UwbAdapterStateCallback();
initializeSatelliteModeRadios();
ContentObserver satelliteModeRadiosContentObserver = new ContentObserver(this) {
@@ -507,11 +530,12 @@
* Get satelliteConfig from SatelliteConfigParser
*/
public SatelliteConfig getSatelliteConfig() {
- if (getSatelliteConfigParser() == null) {
- Log.d(TAG, "getSatelliteConfigParser() is not ready");
+ SatelliteConfigParser satelliteConfigParser = getSatelliteConfigParser();
+ if (satelliteConfigParser == null) {
+ Log.d(TAG, "satelliteConfigParser is not ready");
return null;
}
- return (SatelliteConfig) getSatelliteConfigParser().getConfig();
+ return satelliteConfigParser.getConfig();
}
/**
@@ -526,8 +550,6 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected void initializeSatelliteModeRadios() {
if (mContentResolver != null) {
- BTWifiNFCStateReceiver bTWifiNFCSateReceiver = new BTWifiNFCStateReceiver();
- UwbAdapterStateCallback uwbAdapterStateCallback = new UwbAdapterStateCallback();
IntentFilter radioStateIntentFilter = new IntentFilter();
synchronized (mRadioStateLock) {
@@ -581,7 +603,14 @@
radioStateIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
}
}
- mContext.registerReceiver(bTWifiNFCSateReceiver, radioStateIntentFilter);
+
+ try {
+ // Unregister receiver before registering it.
+ mContext.unregisterReceiver(mBTWifiNFCSateReceiver);
+ } catch (IllegalArgumentException e) {
+ logd("initializeSatelliteModeRadios: unregisterReceiver, e=" + e);
+ }
+ mContext.registerReceiver(mBTWifiNFCSateReceiver, radioStateIntentFilter);
if (satelliteModeRadios.contains(Settings.Global.RADIO_UWB)) {
UwbManager uwbManager = mContext.getSystemService(UwbManager.class);
@@ -590,8 +619,10 @@
mUwbStateEnabled = uwbManager.isUwbEnabled();
final long identity = Binder.clearCallingIdentity();
try {
+ // Unregister callback before registering it.
+ uwbManager.unregisterAdapterStateCallback(mUwbAdapterStateCallback);
uwbManager.registerAdapterStateCallback(mContext.getMainExecutor(),
- uwbAdapterStateCallback);
+ mUwbAdapterStateCallback);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -938,6 +969,8 @@
mWaitingForDisableSatelliteModemResponse = false;
}
}
+ // Request Ntn signal strength report when satellite enabled or disabled done.
+ updateNtnSignalStrengthReporting(argument.enableSatellite);
} else {
synchronized (mSatelliteEnabledRequestLock) {
if (mSatelliteEnabledRequest != null &&
@@ -1265,24 +1298,7 @@
if (DBG) {
logd("CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING: shouldReport=" + shouldReport);
}
- request = new SatelliteControllerHandlerRequest(shouldReport,
- SatelliteServiceUtils.getPhone());
- if (SATELLITE_RESULT_SUCCESS != evaluateOemSatelliteRequestAllowed(true)) {
- return;
- }
- if (!isSatelliteEnabled() || mShouldReportNtnSignalStrength.get() == shouldReport) {
- if (DBG) {
- logd("CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING: ignore request.");
- }
- return;
- }
- onCompleted = obtainMessage(EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE,
- request);
- if (shouldReport) {
- mSatelliteModemInterface.startSendingNtnSignalStrength(onCompleted);
- } else {
- mSatelliteModemInterface.stopSendingNtnSignalStrength(onCompleted);
- }
+ handleCmdUpdateNtnSignalStrengthReporting(shouldReport);
break;
}
@@ -1291,9 +1307,10 @@
request = (SatelliteControllerHandlerRequest) ar.userObj;
boolean shouldReport = (boolean) request.argument;
int errorCode = SatelliteServiceUtils.getSatelliteError(ar,
- "EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE");
+ "EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE: shouldReport="
+ + shouldReport);
if (errorCode == SATELLITE_RESULT_SUCCESS) {
- mShouldReportNtnSignalStrength.set(shouldReport);
+ mIsModemEnabledReportingNtnSignalStrength.set(shouldReport);
} else {
loge(((boolean) request.argument ? "startSendingNtnSignalStrength"
: "stopSendingNtnSignalStrength") + "returns " + errorCode);
@@ -1316,6 +1333,16 @@
break;
}
+ case EVENT_SATELLITE_SUPPORTED_STATE_CHANGED: {
+ ar = (AsyncResult) msg.obj;
+ if (ar.result == null) {
+ loge("EVENT_SATELLITE_SUPPORTED_STATE_CHANGED: result is null");
+ } else {
+ handleEventSatelliteSupportedStateChanged((boolean) ar.result);
+ }
+ break;
+ }
+
case EVENT_SATELLITE_CONFIG_DATA_UPDATED: {
handleEventConfigDataUpdated();
mSatelliteConfigUpdateChangedRegistrants.notifyRegistrants();
@@ -2166,6 +2193,43 @@
}
/**
+ * Registers for the satellite supported state changed.
+ *
+ * @param subId The subId of the subscription to register for supported state changed.
+ * @param callback The callback to handle the satellite supported state changed event.
+ *
+ * @return The {@link SatelliteManager.SatelliteResult} result of the operation.
+ */
+ @SatelliteManager.SatelliteResult public int registerForSatelliteSupportedStateChanged(
+ int subId, @NonNull ISatelliteSupportedStateCallback callback) {
+ if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("registerForSatelliteSupportedStateChanged: oemEnabledSatelliteFlag is disabled");
+ return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
+ }
+
+ mSatelliteSupportedStateChangedListeners.put(callback.asBinder(), callback);
+ return SATELLITE_RESULT_SUCCESS;
+ }
+
+ /**
+ * Unregisters for the satellite supported state changed.
+ * If callback was not registered before, the request will be ignored.
+ *
+ * @param subId The subId of the subscription to unregister for supported state changed.
+ * @param callback The callback that was passed to
+ * {@link #registerForSatelliteSupportedStateChanged(int, ISatelliteSupportedStateCallback)}.
+ */
+ public void unregisterForSatelliteSupportedStateChanged(
+ int subId, @NonNull ISatelliteSupportedStateCallback callback) {
+ if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("unregisterForSatelliteSupportedStateChanged: "
+ + "oemEnabledSatelliteFlag is disabled");
+ return;
+ }
+ mSatelliteSupportedStateChangedListeners.remove(callback.asBinder());
+ }
+
+ /**
* This API can be used by only CTS to update satellite vendor service package name.
*
* @param servicePackageName The package name of the satellite vendor service.
@@ -2579,33 +2643,92 @@
return true;
}
for (Phone phone : PhoneFactory.getPhones()) {
- if (isSatelliteSupportedViaCarrier(phone.getSubId())) {
- synchronized (mSatelliteConnectedLock) {
- Boolean isHysteresisTimeExpired =
- mIsSatelliteConnectedViaCarrierHysteresisTimeExpired.get(
- phone.getSubId());
- if (isHysteresisTimeExpired != null && isHysteresisTimeExpired) {
- continue;
- }
-
- Long lastDisconnectedTime =
- mLastSatelliteDisconnectedTimesMillis.get(phone.getSubId());
- long satelliteConnectionHysteresisTime =
- getSatelliteConnectionHysteresisTimeMillis(phone.getSubId());
- if (lastDisconnectedTime != null
- && (getElapsedRealtime() - lastDisconnectedTime)
- <= satelliteConnectionHysteresisTime) {
- return true;
- } else {
- mIsSatelliteConnectedViaCarrierHysteresisTimeExpired.put(
- phone.getSubId(), true);
- }
- }
+ if (isInSatelliteModeForCarrierRoaming(phone)) {
+ logd("isSatelliteConnectedViaCarrierWithinHysteresisTime: "
+ + "subId:" + phone.getSubId()
+ + " is connected to satellite within hysteresis time");
+ return true;
}
}
return false;
}
+ /**
+ * Get whether device is connected to satellite via carrier.
+ *
+ * @param phone phone object
+ * @return {@code true} if the device is connected to satellite using the phone within the
+ * {@link CarrierConfigManager#KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT}
+ * duration, {@code false} otherwise.
+ */
+ public boolean isInSatelliteModeForCarrierRoaming(@Nullable Phone phone) {
+ if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
+ logd("isInSatelliteModeForCarrierRoaming: carrierEnabledSatelliteFlag is disabled");
+ return false;
+ }
+
+ if (phone == null) {
+ return false;
+ }
+
+ if (!isSatelliteSupportedViaCarrier(phone.getSubId())) {
+ return false;
+ }
+
+ ServiceState serviceState = phone.getServiceState();
+ if (serviceState != null && serviceState.isUsingNonTerrestrialNetwork()) {
+ return true;
+ }
+
+ synchronized (mSatelliteConnectedLock) {
+ Boolean isHysteresisTimeExpired =
+ mIsSatelliteConnectedViaCarrierHysteresisTimeExpired.get(
+ phone.getSubId());
+ if (isHysteresisTimeExpired != null && isHysteresisTimeExpired) {
+ return false;
+ }
+
+ Long lastDisconnectedTime =
+ mLastSatelliteDisconnectedTimesMillis.get(phone.getSubId());
+ long satelliteConnectionHysteresisTime =
+ getSatelliteConnectionHysteresisTimeMillis(phone.getSubId());
+ if (lastDisconnectedTime != null
+ && (getElapsedRealtime() - lastDisconnectedTime)
+ <= satelliteConnectionHysteresisTime) {
+ return true;
+ } else {
+ mIsSatelliteConnectedViaCarrierHysteresisTimeExpired.put(
+ phone.getSubId(), true);
+ mSatModeCapabilitiesForCarrierRoaming.remove(phone.getSubId());
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Return capabilities of carrier roaming satellite network.
+ *
+ * @param phone phone object
+ * @return The list of services supported by the carrier associated with the {@code subId}
+ */
+ @NonNull
+ public List<Integer> getCapabilitiesForCarrierRoamingSatelliteMode(Phone phone) {
+ if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
+ logd("getCapabilitiesForCarrierRoamingSatelliteMode: carrierEnabledSatelliteFlag"
+ + " is disabled");
+ return new ArrayList<>();
+ }
+
+ synchronized (mSatelliteConnectedLock) {
+ int subId = phone.getSubId();
+ if (mSatModeCapabilitiesForCarrierRoaming.containsKey(subId)) {
+ return mSatModeCapabilitiesForCarrierRoaming.get(subId);
+ }
+ }
+
+ return new ArrayList<>();
+ }
+
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected long getElapsedRealtime() {
return SystemClock.elapsedRealtime();
@@ -2888,6 +3011,7 @@
registerForSatelliteModemStateChanged();
registerForNtnSignalStrengthChanged();
registerForCapabilitiesChanged();
+ registerForSatelliteSupportedStateChanged();
requestIsSatelliteProvisioned(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
new ResultReceiver(this) {
@@ -2927,7 +3051,7 @@
loge(caller + ": mSatelliteSessionController is not initialized yet");
}
if (!enabled) {
- mShouldReportNtnSignalStrength.set(false);
+ mIsModemEnabledReportingNtnSignalStrength.set(false);
}
}
@@ -2991,6 +3115,16 @@
}
}
+ private void registerForSatelliteSupportedStateChanged() {
+ if (mSatelliteModemInterface.isSatelliteServiceSupported()) {
+ if (!mRegisteredForSatelliteSupportedStateChanged.get()) {
+ mSatelliteModemInterface.registerForSatelliteSupportedStateChanged(
+ this, EVENT_SATELLITE_SUPPORTED_STATE_CHANGED, null);
+ mRegisteredForSatelliteSupportedStateChanged.set(true);
+ }
+ }
+ }
+
private void handleEventSatelliteProvisionStateChanged(boolean provisioned) {
logd("handleSatelliteProvisionStateChangedEvent: provisioned=" + provisioned);
@@ -3099,6 +3233,53 @@
});
}
+ private void handleEventSatelliteSupportedStateChanged(boolean supported) {
+ logd("handleSatelliteSupportedStateChangedEvent: supported=" + supported);
+
+ synchronized (mIsSatelliteSupportedLock) {
+ if (mIsSatelliteSupported != null && mIsSatelliteSupported == supported) {
+ if (DBG) {
+ logd("current satellite support state and new supported state are matched,"
+ + " ignore update.");
+ }
+ return;
+ }
+ /* In case satellite has been reported as not support from modem, but satellite is
+ enabled, request disable satellite. */
+ synchronized (mIsSatelliteEnabledLock) {
+ if (!supported && mIsSatelliteEnabled != null && mIsSatelliteEnabled) {
+ logd("Invoke requestSatelliteEnabled(), supported=false, "
+ + "mIsSatelliteEnabled=true");
+ requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ false /* enableSatellite */, false /* enableDemoMode */,
+ new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ logd("handleSatelliteSupportedStateChangedEvent: request "
+ + "satellite disable, result="
+ + result);
+ }
+ });
+
+ }
+ }
+ mIsSatelliteSupported = supported;
+ }
+
+ List<ISatelliteSupportedStateCallback> deadCallersList = new ArrayList<>();
+ mSatelliteSupportedStateChangedListeners.values().forEach(listener -> {
+ try {
+ listener.onSatelliteSupportedStateChanged(supported);
+ } catch (RemoteException e) {
+ logd("handleSatelliteSupportedStateChangedEvent RemoteException: " + e);
+ deadCallersList.add(listener);
+ }
+ });
+ deadCallersList.forEach(listener -> {
+ mSatelliteSupportedStateChangedListeners.remove(listener.asBinder());
+ });
+ }
+
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected void setSettingsKeyForSatelliteMode(int val) {
logd("setSettingsKeyForSatelliteMode val: " + val);
@@ -3224,12 +3405,17 @@
private void updatePlmnListPerCarrier(int subId) {
synchronized (mSupportedSatelliteServicesLock) {
List<String> carrierPlmnList, entitlementPlmnList;
- entitlementPlmnList = mEntitlementPlmnListPerCarrier.get(subId,
- new ArrayList<>()).stream().toList();
- if (!entitlementPlmnList.isEmpty()) {
- mMergedPlmnListPerCarrier.put(subId, entitlementPlmnList);
- logd("update it using entitlementPlmnList=" + entitlementPlmnList);
- return;
+ if (getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL,
+ false)) {
+ entitlementPlmnList = mEntitlementPlmnListPerCarrier.get(subId,
+ new ArrayList<>()).stream().toList();
+ logd("updatePlmnListPerCarrier: entitlementPlmnList=" + entitlementPlmnList
+ + " size=" + entitlementPlmnList.size());
+ if (!entitlementPlmnList.isEmpty()) {
+ mMergedPlmnListPerCarrier.put(subId, entitlementPlmnList);
+ logd("update it using entitlementPlmnList=" + entitlementPlmnList);
+ return;
+ }
}
SatelliteConfig satelliteConfig = getSatelliteConfig();
@@ -3356,8 +3542,10 @@
}
}
- /** If there is no cached entitlement plmn list, read it from the db and use it if it is not an
- * empty list. */
+ /**
+ * If there is no cached entitlement plmn list, read it from the db and use it if it is not an
+ * empty list.
+ */
private void updateEntitlementPlmnListPerCarrier(int subId) {
if (!getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false)) {
logd("don't support entitlement");
@@ -3371,7 +3559,7 @@
List<String> entitlementPlmnList =
mSubscriptionManagerService.getSatelliteEntitlementPlmnList(subId);
if (entitlementPlmnList.isEmpty()) {
- loge("updateEntitlementPlmnListPerCarrier: no data for subId(" + subId + ")");
+ logd("updateEntitlementPlmnListPerCarrier: read empty list");
return;
}
logd("updateEntitlementPlmnListPerCarrier: entitlementPlmnList="
@@ -3722,6 +3910,14 @@
mWasSatelliteConnectedViaCarrier.put(phone.getSubId(), true);
mIsSatelliteConnectedViaCarrierHysteresisTimeExpired.put(
phone.getSubId(), false);
+
+ for (NetworkRegistrationInfo nri
+ : serviceState.getNetworkRegistrationInfoList()) {
+ if (nri.isNonTerrestrialNetwork()) {
+ mSatModeCapabilitiesForCarrierRoaming.put(phone.getSubId(),
+ nri.getAvailableServices());
+ }
+ }
} else {
Boolean connected = mWasSatelliteConnectedViaCarrier.get(phone.getSubId());
if (connected != null && connected) {
@@ -3925,6 +4121,49 @@
}
}
+ private void handleCmdUpdateNtnSignalStrengthReporting(boolean shouldReport) {
+ if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("handleCmdUpdateNtnSignalStrengthReporting: oemEnabledSatelliteFlag is "
+ + "disabled");
+ return;
+ }
+
+ if (!isSatelliteEnabled()) {
+ logd("handleCmdUpdateNtnSignalStrengthReporting: ignore request, satellite is "
+ + "disabled");
+ return;
+ }
+
+ if (mIsModemEnabledReportingNtnSignalStrength.get() == shouldReport) {
+ logd("handleCmdUpdateNtnSignalStrengthReporting: ignore request. "
+ + "mIsModemEnabledReportingNtnSignalStrength="
+ + mIsModemEnabledReportingNtnSignalStrength.get());
+ return;
+ }
+
+ updateNtnSignalStrengthReporting(shouldReport);
+ }
+
+ private void updateNtnSignalStrengthReporting(boolean shouldReport) {
+ if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("updateNtnSignalStrengthReporting: oemEnabledSatelliteFlag is "
+ + "disabled");
+ return;
+ }
+
+ SatelliteControllerHandlerRequest request = new SatelliteControllerHandlerRequest(
+ shouldReport, SatelliteServiceUtils.getPhone());
+ Message onCompleted = obtainMessage(EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE,
+ request);
+ if (shouldReport) {
+ logd("updateNtnSignalStrengthReporting: startSendingNtnSignalStrength");
+ mSatelliteModemInterface.startSendingNtnSignalStrength(onCompleted);
+ } else {
+ logd("updateNtnSignalStrengthReporting: stopSendingNtnSignalStrength");
+ mSatelliteModemInterface.stopSendingNtnSignalStrength(onCompleted);
+ }
+ }
+
/**
* This API can be used by only CTS to override the cached value for the device overlay config
* value : config_send_satellite_datagram_to_modem_in_demo_mode, which determines whether
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
index e51042f..7432d91 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
@@ -93,6 +93,8 @@
new RegistrantList();
@NonNull private final RegistrantList mSatelliteCapabilitiesChangedRegistrants =
new RegistrantList();
+ @NonNull private final RegistrantList mSatelliteSupportedStateChangedRegistrants =
+ new RegistrantList();
@NonNull private final ISatelliteListener mListener = new ISatelliteListener.Stub() {
@Override
@@ -158,6 +160,11 @@
mSatelliteCapabilitiesChangedRegistrants.notifyResult(
SatelliteServiceUtils.fromSatelliteCapabilities(satelliteCapabilities));
}
+
+ @Override
+ public void onSatelliteSupportedStateChanged(boolean supported) {
+ mSatelliteSupportedStateChangedRegistrants.notifyResult(supported);
+ }
};
/**
@@ -505,6 +512,27 @@
}
/**
+ * Registers for the satellite supported state changed.
+ *
+ * @param h Handler for notification message.
+ * @param what User-defined message code.
+ * @param obj User object.
+ */
+ public void registerForSatelliteSupportedStateChanged(
+ @NonNull Handler h, int what, @Nullable Object obj) {
+ mSatelliteSupportedStateChangedRegistrants.add(h, what, obj);
+ }
+
+ /**
+ * Unregisters for the satellite supported state changed.
+ *
+ * @param h Handler to be removed from the registrant list.
+ */
+ public void unregisterForSatelliteSupportedStateChanged(@NonNull Handler h) {
+ mSatelliteSupportedStateChangedRegistrants.remove(h);
+ }
+
+ /**
* Request to enable or disable the satellite service listening mode.
* Listening mode allows the satellite service to listen for incoming pages.
*
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
index 82af4e8..bb77d5c 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
@@ -1217,7 +1217,22 @@
* @return {@code true} if the subscription is visible to the user.
*/
public boolean isVisible() {
- return !isOpportunistic() || TextUtils.isEmpty(mGroupUuid);
+ // Provisioning profile
+ if (getProfileClass() == SubscriptionManager.PROFILE_CLASS_PROVISIONING) {
+ return false;
+ }
+
+ // Satellite profile
+ if (getOnlyNonTerrestrialNetwork() == 1) {
+ return false;
+ }
+
+ // Opportunistic profile
+ if (isOpportunistic() && !TextUtils.isEmpty(mGroupUuid)) {
+ return false;
+ }
+
+ return true;
}
/**
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
index fcbd9d0..d96c549 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
@@ -124,6 +124,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
@@ -3720,16 +3721,15 @@
enforceTelephonyFeatureWithException(callingPackage, "getPhoneNumber");
final long identity = Binder.clearCallingIdentity();
-
- SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
- .getSubscriptionInfoInternal(subId);
-
- if (subInfo == null) {
- loge("Invalid sub id " + subId + ", callingPackage=" + callingPackage);
- return "";
- }
-
try {
+ SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
+ .getSubscriptionInfoInternal(subId);
+
+ if (subInfo == null) {
+ loge("Invalid sub id " + subId + ", callingPackage=" + callingPackage);
+ return "";
+ }
+
switch(source) {
case SubscriptionManager.PHONE_NUMBER_SOURCE_UICC:
Phone phone = PhoneFactory.getPhone(getSlotIndex(subId));
@@ -4412,13 +4412,12 @@
public List<String> getSatelliteEntitlementPlmnList(int subId) {
SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternal(
subId);
- if (subInfo == null) {
- loge("getSatelliteEntitlementPlmnList: invalid subId=" + subId);
- return new ArrayList<>();
- }
- return Arrays.stream(subInfo.getSatelliteEntitlementPlmns().split(",")).collect(
- Collectors.toList());
+ return Optional.ofNullable(subInfo)
+ .map(SubscriptionInfoInternal::getSatelliteEntitlementPlmns)
+ .filter(s -> !s.isEmpty())
+ .map(s -> Arrays.stream(s.split(",")).collect(Collectors.toList()))
+ .orElse(new ArrayList<>());
}
/**
diff --git a/tests/telephonytests/src/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiverTest.java b/tests/telephonytests/src/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiverTest.java
index 629327d..0563481 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiverTest.java
@@ -16,34 +16,47 @@
package com.android.internal.telephony.configupdate;
-import static com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver.UPDATE_CONTENT_PATH;
+import static android.telephony.NetworkRegistrationInfo.FIRST_SERVICE_TYPE;
+import static android.telephony.NetworkRegistrationInfo.LAST_SERVICE_TYPE;
+
+import static com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver.NEW_CONFIG_CONTENT_PATH;
import static com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver.UPDATE_DIR;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.atLeast;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.content.Intent;
+import android.util.ArraySet;
import androidx.annotation.Nullable;
import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.satellite.SatelliteConfig;
import com.android.internal.telephony.satellite.SatelliteConfigParser;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.io.File;
import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -74,7 +87,7 @@
TelephonyConfigUpdateInstallReceiver testReceiver =
new TelephonyConfigUpdateInstallReceiver();
assertEquals(UPDATE_DIR, testReceiver.getUpdateDir().toString());
- assertEquals(new File(new File(UPDATE_DIR), UPDATE_CONTENT_PATH).toString(),
+ assertEquals(new File(new File(UPDATE_DIR), NEW_CONFIG_CONTENT_PATH).toString(),
testReceiver.getUpdateContent().toString());
}
@@ -92,38 +105,133 @@
// create spyTelephonyConfigUpdateInstallReceiver
TelephonyConfigUpdateInstallReceiver spyTelephonyConfigUpdateInstallReceiver =
spy(new TelephonyConfigUpdateInstallReceiver());
-
- // mock BeforeParser
- String mBase64StrForPBByteArray =
- "CjYIBBIeCAESDgoGMzEwMTYwEAEQAhADEgoKBjMxMDIyMBADGhIKCjAxMjM0NTY3ODkSAlVTGAE=";
- byte[] mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
- doReturn(mBytesProtoBuffer).when(
- spyTelephonyConfigUpdateInstallReceiver).getCurrentContent();
- SatelliteConfigParser mMockSatelliteConfigParserBefore =
- spy(new SatelliteConfigParser(mBytesProtoBuffer));
- doReturn(mMockSatelliteConfigParserBefore).when(
- spyTelephonyConfigUpdateInstallReceiver).getConfigParser(DOMAIN_SATELLITE);
-
- // mock UpdatedParser
- SatelliteConfigParser spySatelliteConfigParserAfter =
- spy(new SatelliteConfigParser(mBytesProtoBuffer));
- doReturn(5).when(spySatelliteConfigParserAfter).getVersion();
- doReturn(spySatelliteConfigParserAfter).when(spyTelephonyConfigUpdateInstallReceiver)
- .getNewConfigParser(any(), any());
-
+ doReturn(true).when(spyTelephonyConfigUpdateInstallReceiver)
+ .copySourceFileToTargetFile(any(), any());
replaceInstance(TelephonyConfigUpdateInstallReceiver.class, "sReceiverAdaptorInstance",
null, spyTelephonyConfigUpdateInstallReceiver);
assertSame(spyTelephonyConfigUpdateInstallReceiver,
TelephonyConfigUpdateInstallReceiver.getInstance());
+ // valid config data case
+ // mVersion:4 | mSupportedServicesPerCarrier:{1={310160=[1, 2, 3], 310220=[3]}} |
+ // mSatelliteRegionCountryCodes:[US] | mIsSatelliteRegionAllowed:true | s2CellFile size:10
+ String mBase64StrForPBByteArray =
+ "CjYIBBIeCAESDgoGMzEwMTYwEAEQAhADEgoKBjMxMDIyMBADGhIKCjAxMjM0NTY3ODkSAlVTGAE=";
+ byte[] mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
+ doReturn(mBytesProtoBuffer).when(
+ spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
+
+ // mock UpdatedParser
+ SatelliteConfigParser spyValidParser =
+ spy(new SatelliteConfigParser(mBytesProtoBuffer));
+
ConcurrentHashMap<Executor, ConfigProviderAdaptor.Callback> spyCallbackHashMap = spy(
new ConcurrentHashMap<>());
spyCallbackHashMap.put(mExecutor, mCallback);
spyTelephonyConfigUpdateInstallReceiver.setCallbackMap(spyCallbackHashMap);
+
spyTelephonyConfigUpdateInstallReceiver.postInstall(mContext, new Intent());
- verify(spyCallbackHashMap, atLeast(1)).keySet();
+ verify(spyCallbackHashMap, times(2)).keySet();
+ verify(spyTelephonyConfigUpdateInstallReceiver, times(1))
+ .copySourceFileToTargetFile(any(), any());
+ Mockito.clearInvocations(spyCallbackHashMap);
+ Mockito.clearInvocations(spyTelephonyConfigUpdateInstallReceiver);
+
+ replaceInstance(TelephonyConfigUpdateInstallReceiver.class, "mConfigParser",
+ spyTelephonyConfigUpdateInstallReceiver, spyValidParser);
+
+ // valid config data but smaller version case
+ // mVersion:3 | mSupportedServicesPerCarrier:{1={12345=[1, 2]}} |
+ // mSatelliteRegionCountryCodes:[US] | mIsSatelliteRegionAllowed:true | s2CellFile size:10
+ mBase64StrForPBByteArray =
+ "CicIAxIPCAESCwoFMTIzNDUQARACGhIKCjAxMjM0NTY3ODkSAlVTGAE=";
+ mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
+
+ // mock UpdatedParser
+ SatelliteConfigParser spyInvalidParser =
+ spy(new SatelliteConfigParser(mBytesProtoBuffer));
+ doReturn(spyInvalidParser).when(spyTelephonyConfigUpdateInstallReceiver)
+ .getNewConfigParser(any(), any());
+
+ spyTelephonyConfigUpdateInstallReceiver.postInstall(mContext, new Intent());
+
+ verify(spyCallbackHashMap, times(0)).keySet();
+ verify(spyTelephonyConfigUpdateInstallReceiver, times(0))
+ .copySourceFileToTargetFile(any(), any());
+ Mockito.clearInvocations(spyCallbackHashMap);
+ Mockito.clearInvocations(spyTelephonyConfigUpdateInstallReceiver);
+
+ // Empty config data case which is valid
+ // mSupportedServicesPerCarrier:{} | mSatelliteRegionCountryCodes:[US] |
+ // mIsSatelliteRegionAllowed:true | s2CellFile size:30
+ mBase64StrForPBByteArray =
+ "CioIDBomCh4wMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkSAlVTGAE=";
+ mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
+ doReturn(mBytesProtoBuffer).when(
+ spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
+
+ // mock UpdatedParser
+ SatelliteConfigParser spyValidEmptyParser =
+ spy(new SatelliteConfigParser(mBytesProtoBuffer));
+ doReturn(spyValidEmptyParser).when(spyTelephonyConfigUpdateInstallReceiver)
+ .getNewConfigParser(any(), any());
+
+ spyTelephonyConfigUpdateInstallReceiver.postInstall(mContext, new Intent());
+ verify(spyCallbackHashMap, times(2)).keySet();
+ verify(spyTelephonyConfigUpdateInstallReceiver, times(1))
+ .copySourceFileToTargetFile(any(), any());
+ Mockito.clearInvocations(spyCallbackHashMap);
+ Mockito.clearInvocations(spyTelephonyConfigUpdateInstallReceiver);
+
+ // Wrong plmn("1234") config data case
+ // mSupportedServicesPerCarrier:{1={"1234"=[1, 2, 3]}} |
+ // mSatelliteRegionCountryCodes:[US]
+ // | mIsSatelliteRegionAllowed:true | s2CellFile size:10
+ mBase64StrForPBByteArray =
+ "CigIDBIQCAESDAoEMTIzNBABEAIQAxoSCgowMTIzNDU2Nzg5EgJVUxgB";
+ mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
+ doReturn(mBytesProtoBuffer).when(
+ spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
+
+ // mock UpdatedParser
+ spyInvalidParser =
+ spy(new SatelliteConfigParser(mBytesProtoBuffer));
+ doReturn(spyInvalidParser).when(spyTelephonyConfigUpdateInstallReceiver)
+ .getNewConfigParser(any(), any());
+
+ spyTelephonyConfigUpdateInstallReceiver.postInstall(mContext, new Intent());
+
+ verify(spyCallbackHashMap, times(0)).keySet();
+ verify(spyTelephonyConfigUpdateInstallReceiver, times(0))
+ .copySourceFileToTargetFile(any(), any());
+ Mockito.clearInvocations(spyCallbackHashMap);
+ Mockito.clearInvocations(spyTelephonyConfigUpdateInstallReceiver);
+
+ // Wrong service("8") config data case
+ // mSupportedServicesPerCarrier:{1={12345=[6, "8"]}} |
+ // mSatelliteRegionCountryCodes:[US] |
+ // mIsSatelliteRegionAllowed:true | s2CellFile size:10
+ mBase64StrForPBByteArray =
+ "CicIDBIPCAESCwoFMTIzNDUQBhAIGhIKCjAxMjM0NTY3ODkSAlVTGAE=";
+ mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
+ doReturn(mBytesProtoBuffer).when(
+ spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
+
+ // mock UpdatedParser
+ spyInvalidParser =
+ spy(new SatelliteConfigParser(mBytesProtoBuffer));
+ doReturn(spyInvalidParser).when(spyTelephonyConfigUpdateInstallReceiver)
+ .getNewConfigParser(any(), any());
+
+ spyTelephonyConfigUpdateInstallReceiver.postInstall(mContext, new Intent());
+
+ verify(spyCallbackHashMap, times(0)).keySet();
+ verify(spyTelephonyConfigUpdateInstallReceiver, times(0))
+ .copySourceFileToTargetFile(any(), any());
+ Mockito.clearInvocations(spyCallbackHashMap);
+ Mockito.clearInvocations(spyTelephonyConfigUpdateInstallReceiver);
}
@@ -133,7 +241,7 @@
spy(new TelephonyConfigUpdateInstallReceiver());
doReturn(null).when(
- spyTelephonyConfigUpdateInstallReceiver).getCurrentContent();
+ spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
replaceInstance(TelephonyConfigUpdateInstallReceiver.class, "sReceiverAdaptorInstance",
null, spyTelephonyConfigUpdateInstallReceiver);
@@ -144,7 +252,7 @@
"CjYIBBIeCAESDgoGMzEwMTYwEAEQAhADEgoKBjMxMDIyMBADGhIKCjAxMjM0NTY3ODkSAlVTGAE=";
byte[] mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
doReturn(mBytesProtoBuffer).when(
- spyTelephonyConfigUpdateInstallReceiver).getCurrentContent();
+ spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
replaceInstance(TelephonyConfigUpdateInstallReceiver.class, "sReceiverAdaptorInstance",
null, spyTelephonyConfigUpdateInstallReceiver);
@@ -172,4 +280,59 @@
testReceiver.unregisterCallback(testCallback);
assertEquals(0, testReceiver.getCallbackMap().size());
}
+
+ @Test
+ public void testIsValidSatelliteCarrierConfigData() {
+ TelephonyConfigUpdateInstallReceiver spyTelephonyConfigUpdateInstallReceiver =
+ spy(new TelephonyConfigUpdateInstallReceiver());
+ SatelliteConfigParser mockParser = mock(SatelliteConfigParser.class);
+ SatelliteConfig mockConfig = mock(SatelliteConfig.class);
+ doReturn(new ArraySet<>()).when(mockConfig).getAllSatelliteCarrierIds();
+ doReturn(mockConfig).when(mockParser).getConfig();
+
+ assertTrue(spyTelephonyConfigUpdateInstallReceiver
+ .isValidSatelliteCarrierConfigData(mockParser));
+
+ doReturn(Set.of(1)).when(mockConfig).getAllSatelliteCarrierIds();
+ Map<String, Set<Integer>> validPlmnsServices = new HashMap<>();
+ validPlmnsServices.put("123456", Set.of(FIRST_SERVICE_TYPE, 3, LAST_SERVICE_TYPE));
+ validPlmnsServices.put("12345", Set.of(FIRST_SERVICE_TYPE, 4, LAST_SERVICE_TYPE));
+ doReturn(validPlmnsServices).when(mockConfig).getSupportedSatelliteServices(anyInt());
+ doReturn(mockConfig).when(mockParser).getConfig();
+
+ assertTrue(spyTelephonyConfigUpdateInstallReceiver
+ .isValidSatelliteCarrierConfigData(mockParser));
+
+ doReturn(Set.of(1)).when(mockConfig).getAllSatelliteCarrierIds();
+ Map<String, Set<Integer>> invalidPlmnsServices1 = new HashMap<>();
+ invalidPlmnsServices1.put("123456", Set.of(FIRST_SERVICE_TYPE - 1, 3, LAST_SERVICE_TYPE));
+ doReturn(invalidPlmnsServices1).when(mockConfig).getSupportedSatelliteServices(anyInt());
+ doReturn(mockConfig).when(mockParser).getConfig();
+ assertFalse(spyTelephonyConfigUpdateInstallReceiver
+ .isValidSatelliteCarrierConfigData(mockParser));
+
+ doReturn(Set.of(1)).when(mockConfig).getAllSatelliteCarrierIds();
+ Map<String, Set<Integer>> invalidPlmnsServices2 = new HashMap<>();
+ invalidPlmnsServices2.put("123456", Set.of(FIRST_SERVICE_TYPE, 3, LAST_SERVICE_TYPE + 1));
+ doReturn(invalidPlmnsServices2).when(mockConfig).getSupportedSatelliteServices(anyInt());
+ doReturn(mockConfig).when(mockParser).getConfig();
+ assertFalse(spyTelephonyConfigUpdateInstallReceiver
+ .isValidSatelliteCarrierConfigData(mockParser));
+
+ doReturn(Set.of(1)).when(mockConfig).getAllSatelliteCarrierIds();
+ Map<String, Set<Integer>> invalidPlmnsServices3 = new HashMap<>();
+ invalidPlmnsServices3.put("1234", Set.of(FIRST_SERVICE_TYPE, 3, LAST_SERVICE_TYPE));
+ doReturn(invalidPlmnsServices3).when(mockConfig).getSupportedSatelliteServices(anyInt());
+ doReturn(mockConfig).when(mockParser).getConfig();
+ assertFalse(spyTelephonyConfigUpdateInstallReceiver
+ .isValidSatelliteCarrierConfigData(mockParser));
+
+ doReturn(Set.of(1)).when(mockConfig).getAllSatelliteCarrierIds();
+ Map<String, Set<Integer>> invalidPlmnsServices4 = new HashMap<>();
+ invalidPlmnsServices4.put("1234567", Set.of(FIRST_SERVICE_TYPE, 3, LAST_SERVICE_TYPE));
+ doReturn(invalidPlmnsServices4).when(mockConfig).getSupportedSatelliteServices(anyInt());
+ doReturn(mockConfig).when(mockParser).getConfig();
+ assertFalse(spyTelephonyConfigUpdateInstallReceiver
+ .isValidSatelliteCarrierConfigData(mockParser));
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
index fecadd6..0ef6fe7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -51,6 +51,7 @@
import android.net.NetworkCapabilities;
import android.net.NetworkPolicyManager;
import android.net.NetworkRequest;
+import android.net.Uri;
import android.net.vcn.VcnManager.VcnNetworkPolicyChangeListener;
import android.net.vcn.VcnNetworkPolicyResult;
import android.os.AsyncResult;
@@ -1745,6 +1746,107 @@
}
@Test
+ public void testMobileDataDisabledIsValidRestrictedRequestWithSatelliteInternetRequest() {
+ mIsNonTerrestrialNetwork = true;
+
+ //Mobile Data Disabled
+ mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
+ TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
+ processAllMessages();
+
+ // Data is not supported for cellular transport network request while using satellite
+ // network
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+ // Set network request transport as Satellite with restricted capability + internet
+ NetworkCapabilities netCaps = new NetworkCapabilities();
+ netCaps.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
+ new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags));
+ processAllMessages();
+
+ // Verify data is not connected since Network request cannot satisfy by transport
+ verify(mMockedDataNetworkControllerCallback, never())
+ .onConnectedInternetDataNetworksChanged(any());
+
+ mIsNonTerrestrialNetwork = false;
+ }
+
+ @Test
+ public void testMobileDataDisabledIsValidRestrictedRequestWithTransportSatelliteMMSRequest()
+ throws Exception {
+ mIsNonTerrestrialNetwork = true;
+
+ // Data disabled
+ mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
+ TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
+ // Always allow MMS off
+ mDataNetworkControllerUT.getDataSettingsManager().setMobileDataPolicy(TelephonyManager
+ .MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED, false);
+ processAllMessages();
+
+ // Data is not supported for cellular transport network request while using satellite
+ // network
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+ // Set network request transport as Cellular+Satellite with restricted capability + mms
+ NetworkCapabilities netCaps = new NetworkCapabilities();
+ netCaps.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+ netCaps.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
+ netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
+ new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags));
+ processAllMessages();
+
+ // Verify mms is not connected
+ verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
+
+ mIsNonTerrestrialNetwork = false;
+ }
+
+ @Test
+ public void testOnMmsAlwaysALlowedIsValidRestrictedRequestWithTransportSatelliteMMSRequest()
+ throws Exception {
+ mIsNonTerrestrialNetwork = true;
+
+ // Data disabled
+ mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
+ TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
+ // Always allow MMS On
+ mDataNetworkControllerUT.getDataSettingsManager().setMobileDataPolicy(TelephonyManager
+ .MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED, true);
+ processAllMessages();
+
+ // Data is not supported for cellular transport network request while using satellite
+ // network
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+ // Set network request transport as Cellular+Satellite with restricted capability + mms
+ NetworkCapabilities netCaps = new NetworkCapabilities();
+ netCaps.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+ netCaps.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
+ netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
+ new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags));
+ processAllMessages();
+
+ // Verify mms is connected if mms always allowed is on
+ verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_MMS);
+
+ mIsNonTerrestrialNetwork = false;
+ }
+
+ @Test
public void testIsNetworkRequestSatisfiedByTransportSatelliteTransportRequest_Terrestrial() {
// Set network request transport as satellite in satellite network
NetworkCapabilities netCaps = new NetworkCapabilities();
@@ -4050,6 +4152,41 @@
}
@Test
+ public void testNetworkValidationStatusChangeCallback() throws Exception {
+ // Request not restricted network
+ TelephonyNetworkRequest request = createNetworkRequest(
+ NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ mDataNetworkControllerUT.addNetworkRequest(request);
+ processAllMessages();
+ TelephonyNetworkAgent agent = getPrivateField(getDataNetworks().get(0), "mNetworkAgent",
+ TelephonyNetworkAgent.class);
+ agent.onValidationStatus(1/*status*/, Uri.EMPTY);
+ processAllMessages();
+
+ // Verify notify
+ verify(mMockedDataNetworkControllerCallback)
+ .onInternetDataNetworkValidationStatusChanged(1);
+
+ // Request restricted network
+ mDataNetworkControllerUT.removeNetworkRequest(request);
+ getDataNetworks().get(0).tearDown(DataNetwork.TEAR_DOWN_REASON_NONE);
+ mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(0, false, "");
+ processAllMessages();
+ clearInvocations(mMockedDataNetworkControllerCallback);
+ mDataNetworkControllerUT.addNetworkRequest(createNetworkRequest(
+ true, NetworkCapabilities.NET_CAPABILITY_INTERNET));
+ processAllMessages();
+ agent = getPrivateField(getDataNetworks().get(0), "mNetworkAgent",
+ TelephonyNetworkAgent.class);
+ agent.onValidationStatus(1/*status*/, Uri.EMPTY);
+ processAllMessages();
+
+ // Verify not notified
+ verify(mMockedDataNetworkControllerCallback, never())
+ .onInternetDataNetworkValidationStatusChanged(anyInt());
+ }
+
+ @Test
public void testImsGracefulTearDown() throws Exception {
setImsRegistered(true);
setRcsRegistered(true);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
index 9f2a3e7..3676900 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
@@ -2383,6 +2383,32 @@
// Now QNS prefers MMS on IWLAN
doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager)
.getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
+ // Verify an mms apn that shares the same apn name doesn't count as an alternative.
+ ApnSetting mmsApnWithSameApn = new ApnSetting.Builder()
+ .setId(2164)
+ .setOperatorNumeric("12345")
+ .setEntryName("fake_mms_apn")
+ .setApnName("fake_apn")
+ .setApnTypeBitmask(ApnSetting.TYPE_MMS)
+ .setProtocol(ApnSetting.PROTOCOL_IPV6)
+ .setRoamingProtocol(ApnSetting.PROTOCOL_IP)
+ .setCarrierEnabled(true)
+ .setNetworkTypeBitmask((int) TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN)
+ .build();
+ doReturn(new DataProfile.Builder().setApnSetting(mmsApnWithSameApn)
+ .setTrafficDescriptor(new TrafficDescriptor("fake_apn", null))
+ .build()).when(mDataProfileManager).getDataProfileForNetworkRequest(
+ any(TelephonyNetworkRequest.class),
+ eq(TelephonyManager.NETWORK_TYPE_IWLAN), eq(false), eq(false), eq(false));
+ accessNetworksManagerCallbackArgumentCaptor.getValue()
+ .onPreferredTransportChanged(NetworkCapabilities.NET_CAPABILITY_MMS, false);
+ processAllMessages();
+
+ // Check if MMS capability remains intact.
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)).isTrue();
+
+ // Verify MMS capability is removed if using a valid MMS alternative APN.
doReturn(mMmsDataProfile).when(mDataProfileManager).getDataProfileForNetworkRequest(
any(TelephonyNetworkRequest.class),
eq(TelephonyManager.NETWORK_TYPE_IWLAN), eq(false), eq(false), eq(false));
diff --git a/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java
index 47f8ce2..5fd7a77 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java
@@ -22,6 +22,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -42,8 +43,10 @@
import android.telecom.PhoneAccount;
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
+import android.telephony.DisconnectCause;
import android.telephony.DomainSelectionService;
import android.telephony.EmergencyRegistrationResult;
+import android.telephony.PreciseDisconnectCause;
import android.telephony.data.ApnSetting;
import android.telephony.ims.ImsReasonInfo;
import android.testing.AndroidTestingRunner;
@@ -773,6 +776,26 @@
verify(mDomainSelectionController, times(1)).selectDomain(any(), eq(transportCallback));
}
+ @Test
+ @SmallTest
+ public void testSetDisconnectCause() throws Exception {
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDomainSelectionController);
+
+ assertEquals(DisconnectCause.NOT_VALID, mDsc.getDisconnectCause());
+ assertEquals(PreciseDisconnectCause.NOT_VALID, mDsc.getPreciseDisconnectCause());
+ assertEquals(mPhone.getPhoneId(), mDsc.getPhoneId());
+
+ String reason = "No SIM or SIM error";
+ mDsc.setDisconnectCause(DisconnectCause.ICC_ERROR,
+ PreciseDisconnectCause.NO_VALID_SIM, reason);
+
+ assertEquals(DisconnectCause.ICC_ERROR, mDsc.getDisconnectCause());
+ assertEquals(PreciseDisconnectCause.NO_VALID_SIM, mDsc.getPreciseDisconnectCause());
+ assertEquals(reason, mDsc.getReasonMessage());
+ assertEquals(mPhone.getPhoneId(), mDsc.getPhoneId());
+ }
+
private DomainSelectionConnection createConnection(Phone phone, int selectorType,
boolean isEmergency, DomainSelectionController controller) throws Exception {
DomainSelectionConnection dsc = new DomainSelectionConnection(phone,
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 699ee7b..ce85e53 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
@@ -2837,6 +2837,94 @@
verify(mContext, never()).sendStickyBroadcastAsUser(any(), any());
}
+ @Test
+ @SmallTest
+ public void testEnsureExecutionOrderOfExitEmergencyModeThenSetEmergencyMode() {
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+ Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
+ /* isRadioOn= */ true);
+ setUpAsyncResultForSetEmergencyMode(phone0, E_REG_RESULT);
+
+ // First trial
+ CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(phone0,
+ mTestConnection1, false);
+ processAllMessages();
+
+ assertTrue(emergencyStateTracker.isInEmergencyMode());
+ assertTrue(emergencyStateTracker.isInEmergencyCall());
+ verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+
+ ArgumentCaptor<Message> msgCaptor = ArgumentCaptor.forClass(Message.class);
+ emergencyStateTracker.endCall(mTestConnection1);
+ processAllMessages();
+
+ verify(phone0, times(1)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+ verify(phone0).exitEmergencyMode(msgCaptor.capture());
+
+ Message msg = msgCaptor.getValue();
+
+ assertNotNull(msg);
+
+ // Second trial
+ CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(phone0,
+ mTestConnection2, false);
+ processAllMessages();
+
+ assertFalse(future.isDone());
+ verify(phone0, times(1)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+
+ AsyncResult.forMessage(msg, null, null);
+ msg.sendToTarget();
+ processAllMessages();
+
+ verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+ }
+
+ @Test
+ @SmallTest
+ public void testEnsureExecutionOrderOfExitEmergencyModeThenSetEmergencyModeWithSms() {
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+ Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ false,
+ /* isRadioOn= */ true);
+ setUpAsyncResultForSetEmergencyMode(phone0, E_REG_RESULT);
+ CompletableFuture<Integer> future = emergencyStateTracker.startEmergencySms(phone0,
+ TEST_SMS_ID, false);
+ processAllMessages();
+
+ assertTrue(emergencyStateTracker.isInEmergencyMode());
+ verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+
+ assertTrue(emergencyStateTracker.getEmergencyRegistrationResult().equals(E_REG_RESULT));
+ // Expect: DisconnectCause#NOT_DISCONNECTED.
+ assertEquals(future.getNow(DisconnectCause.ERROR_UNSPECIFIED),
+ Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
+
+ ArgumentCaptor<Message> msgCaptor = ArgumentCaptor.forClass(Message.class);
+ emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_CS);
+
+ verify(phone0).exitEmergencyMode(msgCaptor.capture());
+
+ Message msg = msgCaptor.getValue();
+
+ assertNotNull(msg);
+
+ // Dial emergency call
+ future = emergencyStateTracker.startEmergencyCall(phone0,
+ mTestConnection2, false);
+ processAllMessages();
+
+ assertFalse(future.isDone());
+ verify(phone0, times(1)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+
+ AsyncResult.forMessage(msg, null, null);
+ msg.sendToTarget();
+ processAllMessages();
+
+ verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+ }
+
private EmergencyStateTracker setupEmergencyStateTracker(
boolean isSuplDdsSwitchRequiredForEmergencyCall) {
doReturn(mPhoneSwitcher).when(mPhoneSwitcherProxy).getPhoneSwitcher();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
new file mode 100644
index 0000000..e6689dd
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.satellite;
+
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.os.Looper;
+import android.telephony.satellite.SatelliteDatagram;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.internal.telephony.TelephonyTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.function.Consumer;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class DatagramControllerTest extends TelephonyTest {
+ private static final String TAG = "DatagramControllerTest";
+
+ private DatagramController mDatagramControllerUT;
+
+ @Mock private DatagramReceiver mMockDatagramReceiver;
+ @Mock private DatagramDispatcher mMockDatagramDispatcher;
+ @Mock private PointingAppController mMockPointingAppController;
+ @Mock private SatelliteSessionController mMockSatelliteSessionController;
+
+ private static final int SUB_ID = 0;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp(getClass().getSimpleName());
+ MockitoAnnotations.initMocks(this);
+ logd(TAG + " Setup!");
+
+ replaceInstance(DatagramDispatcher.class, "sInstance", null,
+ mMockDatagramDispatcher);
+ replaceInstance(DatagramReceiver.class, "sInstance", null,
+ mMockDatagramReceiver);
+ replaceInstance(SatelliteSessionController.class, "sInstance", null,
+ mMockSatelliteSessionController);
+ when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+ mDatagramControllerUT = new DatagramController(
+ mContext, Looper.myLooper(), mMockPointingAppController);
+
+ // Move both send and receive to IDLE state
+ mDatagramControllerUT.updateSendStatus(SUB_ID, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ 0, SATELLITE_RESULT_SUCCESS);
+ mDatagramControllerUT.updateReceiveStatus(SUB_ID, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ 0, SATELLITE_RESULT_SUCCESS);
+ pushDemoModeSosDatagram();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ logd(TAG + " tearDown");
+ super.tearDown();
+ }
+
+ @Test
+ public void testUpdateSendStatus() throws Exception {
+ testUpdateSendStatus(true, SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING);
+ testUpdateSendStatus(true, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ testUpdateSendStatus(false, SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING);
+ }
+
+ @Test
+ public void testUpdateReceiveStatus() throws Exception {
+ testUpdateReceiveStatus(true, SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ testUpdateReceiveStatus(true, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ testUpdateReceiveStatus(false, SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ }
+
+ @Test
+ public void testSetDeviceAlignedWithSatellite() throws Exception {
+ testSetDeviceAlignedWithSatellite(true);
+ testSetDeviceAlignedWithSatellite(false);
+ }
+
+ private void testUpdateSendStatus(boolean isDemoMode, int sendState) {
+ mDatagramControllerUT.setDemoMode(isDemoMode);
+ clearAllInvocations();
+
+ int sendPendingCount = 1;
+ int errorCode = SATELLITE_RESULT_SUCCESS;
+ mDatagramControllerUT.updateSendStatus(SUB_ID, sendState, sendPendingCount, errorCode);
+
+ verify(mMockSatelliteSessionController)
+ .onDatagramTransferStateChanged(eq(sendState), anyInt());
+ verify(mMockPointingAppController).updateSendDatagramTransferState(
+ eq(SUB_ID), eq(sendState), eq(sendPendingCount), eq(errorCode));
+
+ if (isDemoMode) {
+ if (sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE) {
+ verify(mMockDatagramReceiver).pollPendingSatelliteDatagrams(
+ anyInt(), any(Consumer.class));
+ }
+ } else {
+ verify(mMockDatagramReceiver, never()).pollPendingSatelliteDatagrams(
+ anyInt(), any(Consumer.class));
+ }
+ }
+
+ private void testUpdateReceiveStatus(boolean isDemoMode, int receiveState) {
+ mDatagramControllerUT.setDemoMode(isDemoMode);
+ clearAllInvocations();
+
+ int receivePendingCount = 1;
+ int errorCode = SATELLITE_RESULT_SUCCESS;
+ mDatagramControllerUT.updateReceiveStatus(
+ SUB_ID, receiveState, receivePendingCount, errorCode);
+
+ verify(mMockSatelliteSessionController)
+ .onDatagramTransferStateChanged(anyInt(), eq(receiveState));
+ verify(mMockPointingAppController).updateReceiveDatagramTransferState(
+ eq(SUB_ID), eq(receiveState), eq(receivePendingCount), eq(errorCode));
+
+ if (isDemoMode && receiveState == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE) {
+ verify(mMockDatagramReceiver).pollPendingSatelliteDatagrams(
+ anyInt(), any(Consumer.class));
+ } else {
+ verify(mMockDatagramReceiver, never()).pollPendingSatelliteDatagrams(
+ anyInt(), any(Consumer.class));
+ }
+ }
+
+ private void testSetDeviceAlignedWithSatellite(boolean isAligned) {
+ mDatagramControllerUT.setDemoMode(true);
+ clearAllInvocations();
+
+ mDatagramControllerUT.setDeviceAlignedWithSatellite(isAligned);
+ verify(mMockDatagramDispatcher).setDeviceAlignedWithSatellite(eq(isAligned));
+ verify(mMockDatagramReceiver).setDeviceAlignedWithSatellite(eq(isAligned));
+ if (isAligned) {
+ verify(mMockDatagramReceiver).pollPendingSatelliteDatagrams(
+ anyInt(), any(Consumer.class));
+ } else {
+ verify(mMockDatagramReceiver, never()).pollPendingSatelliteDatagrams(
+ anyInt(), any(Consumer.class));
+ }
+ }
+
+ private void clearAllInvocations() {
+ clearInvocations(mMockSatelliteSessionController);
+ clearInvocations(mMockPointingAppController);
+ clearInvocations(mMockDatagramReceiver);
+ clearInvocations(mMockDatagramDispatcher);
+ }
+
+ private void pushDemoModeSosDatagram() {
+ String testMessage = "This is a test datagram message";
+ SatelliteDatagram datagram = new SatelliteDatagram(testMessage.getBytes());
+ mDatagramControllerUT.setDemoMode(true);
+ mDatagramControllerUT.pushDemoModeDatagram(DATAGRAM_TYPE_SOS_MESSAGE, datagram);
+ }
+}
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 79f1928..cfb8a8d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony.satellite;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import static com.android.internal.telephony.satellite.DatagramController.SATELLITE_ALIGN_TIMEOUT;
@@ -91,8 +92,7 @@
TimeUnit.SECONDS.toMillis(60);
private static final Long TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE = TimeUnit.SECONDS.toMillis(10);
- private DatagramDispatcher mDatagramDispatcherUT;
- private TestDatagramDispatcher mTestDemoModeDatagramDispatcher;
+ private TestDatagramDispatcher mDatagramDispatcherUT;
@Mock private DatagramController mMockDatagramController;
@Mock private DatagramReceiver mMockDatagramReceiver;
@@ -139,9 +139,7 @@
mMockSatelliteSessionController);
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
- mDatagramDispatcherUT = DatagramDispatcher.make(mContext, Looper.myLooper(),
- mMockDatagramController);
- mTestDemoModeDatagramDispatcher = new TestDatagramDispatcher(mContext, Looper.myLooper(),
+ mDatagramDispatcherUT = new TestDatagramDispatcher(mContext, Looper.myLooper(),
mMockDatagramController);
mResultListener = new LinkedBlockingQueue<>(1);
@@ -155,7 +153,6 @@
logd(TAG + " tearDown");
mDatagramDispatcherUT.destroy();
mDatagramDispatcherUT = null;
- mTestDemoModeDatagramDispatcher = null;
mResultListener = null;
mDatagram = null;
mInOrder = null;
@@ -185,7 +182,7 @@
mInOrder.verify(mMockDatagramController).needsWaitingForSatelliteConnected();
mInOrder.verify(mMockDatagramController).updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT), eq(1),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState();
verifyZeroInteractions(mMockSatelliteModemInterface);
assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
@@ -198,21 +195,21 @@
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
verifyNoMoreInteractions(mMockDatagramController);
verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
- assertThat(mResultListener.peek()).isEqualTo(SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_SUCCESS);
clearInvocations(mMockSatelliteModemInterface);
clearInvocations(mMockDatagramController);
@@ -239,7 +236,7 @@
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
assertEquals(1, mResultListener.size());
assertThat(mResultListener.peek()).isEqualTo(
SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
@@ -308,19 +305,19 @@
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
verifyNoMoreInteractions(mMockDatagramController);
verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
- assertThat(mResultListener.peek()).isEqualTo(SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_SUCCESS);
clearInvocations(mMockSatelliteModemInterface);
clearInvocations(mMockDatagramController);
@@ -338,7 +335,7 @@
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED), eq(1),
@@ -346,7 +343,7 @@
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
verifyNoMoreInteractions(mMockDatagramController);
verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
@@ -378,7 +375,7 @@
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED), eq(0),
@@ -386,7 +383,7 @@
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
verifyNoMoreInteractions(mMockDatagramController);
assertThat(mResultListener.peek()).isEqualTo(
@@ -397,16 +394,16 @@
public void testSendSatelliteDatagram_DemoMode_Align_Success() throws Exception {
doAnswer(invocation -> {
Message message = (Message) invocation.getArguments()[3];
- mTestDemoModeDatagramDispatcher.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
+ mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
new AsyncResult(message.obj, null, null))
.sendToTarget();
return null;
}).when(mMockSatelliteModemInterface).sendSatelliteDatagram(any(SatelliteDatagram.class),
anyBoolean(), anyBoolean(), any(Message.class));
- mTestDemoModeDatagramDispatcher.setDemoMode(true);
- mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(true);
+ mDatagramDispatcherUT.setDemoMode(true);
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
- mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
true, mResultListener::offer);
processAllMessages();
@@ -416,43 +413,43 @@
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
- assertThat(mResultListener.peek()).isEqualTo(SatelliteManager.SATELLITE_RESULT_SUCCESS);
- mTestDemoModeDatagramDispatcher.setDemoMode(false);
- mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(false);
+ eq(SATELLITE_RESULT_SUCCESS));
+ assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_SUCCESS);
+ mDatagramDispatcherUT.setDemoMode(false);
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false);
}
@Test
public void testSendSatelliteDatagram_DemoMode_Align_failed() throws Exception {
doAnswer(invocation -> {
Message message = (Message) invocation.getArguments()[3];
- mTestDemoModeDatagramDispatcher.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
+ mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
new AsyncResult(message.obj, null, null))
.sendToTarget();
return null;
}).when(mMockSatelliteModemInterface).sendSatelliteDatagram(any(SatelliteDatagram.class),
anyBoolean(), anyBoolean(), any(Message.class));
- long previousTimer = mTestDemoModeDatagramDispatcher.getSatelliteAlignedTimeoutDuration();
- mTestDemoModeDatagramDispatcher.setDemoMode(true);
- mTestDemoModeDatagramDispatcher.setDuration(TEST_EXPIRE_TIMER_SATELLITE_ALIGN);
- mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(false);
+ long previousTimer = mDatagramDispatcherUT.getSatelliteAlignedTimeoutDuration();
+ mDatagramDispatcherUT.setDemoMode(true);
+ mDatagramDispatcherUT.setDuration(TEST_EXPIRE_TIMER_SATELLITE_ALIGN);
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false);
- mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
true, mResultListener::offer);
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
processAllFutureMessages();
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
@@ -461,12 +458,15 @@
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
assertThat(mResultListener.peek()).isEqualTo(
SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
- mTestDemoModeDatagramDispatcher.setDemoMode(false);
- mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(false);
- mTestDemoModeDatagramDispatcher.setDuration(previousTimer);
+ verify(mMockDatagramController, never()).pollPendingSatelliteDatagrams(anyInt(), any());
+ verify(mMockDatagramController, never()).pushDemoModeDatagram(
+ anyInt(), any(SatelliteDatagram.class));
+ mDatagramDispatcherUT.setDemoMode(false);
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false);
+ mDatagramDispatcherUT.setDuration(previousTimer);
}
@Test
@@ -474,16 +474,16 @@
doAnswer(invocation -> {
Message message = (Message) invocation.getArguments()[3];
mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
- new AsyncResult(message.obj, SatelliteManager.SATELLITE_RESULT_SUCCESS,
+ new AsyncResult(message.obj, SATELLITE_RESULT_SUCCESS,
null)).sendToTarget();
return null;
}).when(mMockSatelliteModemInterface).sendSatelliteDatagram(any(SatelliteDatagram.class),
anyBoolean(), anyBoolean(), any(Message.class));
- mTestDemoModeDatagramDispatcher.setDemoMode(true);
- mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(true);
+ mDatagramDispatcherUT.setDemoMode(true);
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[] {mPhone});
- mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE2, mDatagram,
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE2, mDatagram,
true, mResultListener::offer);
processAllMessages();
@@ -493,22 +493,22 @@
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
- assertThat(mResultListener.peek()).isEqualTo(SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_SUCCESS);
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
- mTestDemoModeDatagramDispatcher.setDemoMode(false);
- mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(false);
+ mDatagramDispatcherUT.setDemoMode(false);
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false);
}
@Test
@@ -549,7 +549,7 @@
mInOrder.verify(mMockDatagramController)
.updateSendStatus(anyInt(),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
- eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(0), eq(SATELLITE_RESULT_SUCCESS));
}
@Test
@@ -562,7 +562,7 @@
mInOrder.verify(mMockDatagramController)
.updateSendStatus(anyInt(),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
- eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(0), eq(SATELLITE_RESULT_SUCCESS));
}
@Test
@@ -572,68 +572,84 @@
doAnswer(invocation -> {
Message message = (Message) invocation.getArguments()[3];
- mTestDemoModeDatagramDispatcher.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
+ mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
new AsyncResult(message.obj, null, null))
.sendToTarget();
return null;
}).when(mMockSatelliteModemInterface).sendSatelliteDatagram(any(SatelliteDatagram.class),
anyBoolean(), anyBoolean(), any(Message.class));
- mTestDemoModeDatagramDispatcher.setDemoMode(true);
- mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(true);
+ mDatagramDispatcherUT.setDemoMode(true);
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
mIntegerConsumerSemaphore.drainPermits();
// Test when overlay config config_send_satellite_datagram_to_modem_in_demo_mode is true
- mTestDemoModeDatagramDispatcher.setShouldSendDatagramToModemInDemoMode(null);
+ mDatagramDispatcherUT.setShouldSendDatagramToModemInDemoMode(null);
mContextFixture.putBooleanResource(mConfigSendSatelliteDatagramToModemInDemoMode, true);
- mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
true, mIntegerConsumer);
processAllMessages();
+ moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
+ processAllMessages();
waitForIntegerConsumerResult(1);
- assertEquals(SatelliteManager.SATELLITE_RESULT_SUCCESS,
+ assertEquals(SATELLITE_RESULT_SUCCESS,
(int) mIntegerConsumerResult.get(0));
mIntegerConsumerResult.clear();
verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
+ moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
+ processAllMessages();
+ verify(mMockDatagramController).pushDemoModeDatagram(
+ anyInt(), any(SatelliteDatagram.class));
+ verify(mMockDatagramController).pollPendingSatelliteDatagrams(anyInt(), any());
+
// Test when overlay config config_send_satellite_datagram_to_modem_in_demo_mode is false
reset(mMockSatelliteModemInterface);
- mTestDemoModeDatagramDispatcher.setShouldSendDatagramToModemInDemoMode(null);
+ mDatagramDispatcherUT.setShouldSendDatagramToModemInDemoMode(null);
mContextFixture.putBooleanResource(mConfigSendSatelliteDatagramToModemInDemoMode, false);
- mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
true, mIntegerConsumer);
processAllMessages();
moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
processAllMessages();
- verify(mMockDatagramController).pollPendingSatelliteDatagrams(anyInt(), any());
-
waitForIntegerConsumerResult(1);
- assertEquals(SatelliteManager.SATELLITE_RESULT_SUCCESS,
+ assertEquals(SATELLITE_RESULT_SUCCESS,
(int) mIntegerConsumerResult.get(0));
mIntegerConsumerResult.clear();
verify(mMockSatelliteModemInterface, never()).sendSatelliteDatagram(
any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
+ moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
+ processAllMessages();
+ verify(mMockDatagramController, times(2)).pushDemoModeDatagram(
+ anyInt(), any(SatelliteDatagram.class));
+ verify(mMockDatagramController, times(2)).pollPendingSatelliteDatagrams(anyInt(), any());
+
// Send datagram one more time
reset(mMockSatelliteModemInterface);
- mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
true, mIntegerConsumer);
processAllMessages();
moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
processAllMessages();
- verify(mMockDatagramController, times(2)).pollPendingSatelliteDatagrams(anyInt(), any());
-
waitForIntegerConsumerResult(1);
- assertEquals(SatelliteManager.SATELLITE_RESULT_SUCCESS,
+ assertEquals(SATELLITE_RESULT_SUCCESS,
(int) mIntegerConsumerResult.get(0));
mIntegerConsumerResult.clear();
verify(mMockSatelliteModemInterface, never()).sendSatelliteDatagram(
any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
- mTestDemoModeDatagramDispatcher.setDemoMode(false);
- mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(false);
- mTestDemoModeDatagramDispatcher.setShouldSendDatagramToModemInDemoMode(null);
+ moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
+ processAllMessages();
+ verify(mMockDatagramController, times(3)).pushDemoModeDatagram(
+ anyInt(), any(SatelliteDatagram.class));
+ verify(mMockDatagramController, times(3)).pollPendingSatelliteDatagrams(anyInt(), any());
+
+ mDatagramDispatcherUT.setDemoMode(false);
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false);
+ mDatagramDispatcherUT.setShouldSendDatagramToModemInDemoMode(null);
}
private boolean waitForIntegerConsumerResult(int expectedNumberOfEvents) {
@@ -665,7 +681,7 @@
}
@Override
- protected void setDeviceAlignedWithSatellite(boolean isAligned) {
+ public void setDeviceAlignedWithSatellite(boolean isAligned) {
super.setDeviceAlignedWithSatellite(isAligned);
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
index 5a1a8f7..0a07f03 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
@@ -324,6 +324,7 @@
mTestDemoModeDatagramReceiver.setDemoMode(true);
mTestDemoModeDatagramReceiver.setDeviceAlignedWithSatellite(true);
when(mMockDatagramController.popDemoModeDatagram()).thenReturn(mDatagram);
+
mTestDemoModeDatagramReceiver.pollPendingSatelliteDatagrams(SUB_ID, mResultListener::offer);
processAllMessages();
verify(mMockDatagramController, times(1)).popDemoModeDatagram();
@@ -478,7 +479,7 @@
}
@Override
- protected void setDeviceAlignedWithSatellite(boolean isAligned) {
+ public void setDeviceAlignedWithSatellite(boolean isAligned) {
super.setDeviceAlignedWithSatellite(isAligned);
}
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 0f77e31..b6e4b6b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -106,6 +106,7 @@
import android.telephony.satellite.ISatelliteDatagramCallback;
import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.ISatelliteProvisionStateCallback;
+import android.telephony.satellite.ISatelliteSupportedStateCallback;
import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.SatelliteCapabilities;
@@ -2477,12 +2478,16 @@
processAllMessages();
mSatelliteControllerUT.elapsedRealtime = 0;
assertFalse(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+ assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone));
+ assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone2));
when(mServiceState.isUsingNonTerrestrialNetwork()).thenReturn(false);
when(mServiceState2.isUsingNonTerrestrialNetwork()).thenReturn(false);
sendServiceStateChangedEvent();
processAllMessages();
assertFalse(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+ assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone));
+ assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone2));
// Last satellite connected time of Phone2 should be 0
when(mServiceState2.isUsingNonTerrestrialNetwork()).thenReturn(true);
@@ -2492,6 +2497,8 @@
mSatelliteControllerUT.elapsedRealtime = 2 * 60 * 1000;
// But Phone2 is connected to NTN right now
assertTrue(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+ assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone));
+ assertTrue(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone2));
// Last satellite disconnected time of Phone2 should be 2 * 60 * 1000
when(mServiceState2.isUsingNonTerrestrialNetwork()).thenReturn(false);
@@ -2499,10 +2506,14 @@
processAllMessages();
// Current time (2) - last disconnected time (2) < hysteresis timeout (1)
assertTrue(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+ assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone));
+ assertTrue(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone2));
// Current time (4) - last disconnected time (2) > hysteresis timeout (1)
mSatelliteControllerUT.elapsedRealtime = 4 * 60 * 1000;
assertFalse(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+ assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone));
+ assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone2));
}
@Test
@@ -2669,67 +2680,41 @@
throws Exception {
logd("testPassSatellitePlmnToModemAfterUpdateSatelliteEntitlementStatus");
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+
replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
mSatelliteControllerUT, new SparseArray<>());
- List<String> overlayConfigPlmnList = new ArrayList<>();
+ List<String> overlayConfigPlmnList = new ArrayList<>();
replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
mSatelliteControllerUT, overlayConfigPlmnList);
+ mCarrierConfigBundle.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+ mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ true);
- // If the PlmnListPerCarrier and the overlay config plmn list are empty verify passing to
- // the modem.
+ // If the entitlement plmn list, the carrier plmn list and the overlay config plmn list
+ // are empty verify not passing to the modem.
+ reset(mMockSatelliteModemInterface);
List<String> entitlementPlmnList = new ArrayList<>();
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
entitlementPlmnList, mIIntegerConsumer);
+ verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(anyBoolean(),
+ anyBoolean(), any(Message.class));
- List<String> plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(
- SUB_ID);
- List<String> allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
- plmnListPerCarrier, overlayConfigPlmnList);
-
- assertEquals(new ArrayList<>(), plmnListPerCarrier);
- assertEquals(new ArrayList<>(), allSatellitePlmnList);
- verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
- eq(plmnListPerCarrier), eq(allSatellitePlmnList), any(Message.class));
-
- // If the PlmnListPerCarrier and the overlay config plmn list are exist but
- // KEY_SATELLITE_ATTACH_SUPPORTED_BOOL is false, verify passing to the modem.
+ // If the entitlement plmn list and the overlay config plmn list are available and the
+ // carrier plmn list is empty verify passing to the modem.
+ reset(mMockSatelliteModemInterface);
entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "00103"}).toList();
+ List<String> mergedPlmnList = entitlementPlmnList;
overlayConfigPlmnList =
Arrays.stream(new String[]{"00101", "00102", "00104"}).toList();
replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
mSatelliteControllerUT, overlayConfigPlmnList);
+ verifyPassingToModemAfterQueryCompleted(entitlementPlmnList, mergedPlmnList,
+ overlayConfigPlmnList);
- mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, true,
- entitlementPlmnList, mIIntegerConsumer);
-
- plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(SUB_ID);
- assertEquals(new ArrayList<>(), plmnListPerCarrier);
- allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
- entitlementPlmnList, overlayConfigPlmnList);
- verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
- eq(entitlementPlmnList), eq(allSatellitePlmnList), any(Message.class));
-
- // If the PlmnListPerCarrier and the overlay config plmn list are exist and
- // KEY_SATELLITE_ATTACH_SUPPORTED_BOOL is true verify passing the modem.
+ // If the entitlement plmn list, the overlay config plmn list and the carrier plmn list
+ // are available, verify passing to the modem.
reset(mMockSatelliteModemInterface);
- mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
- true);
-
- mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, true,
- entitlementPlmnList, mIIntegerConsumer);
-
- plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(SUB_ID);
- allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
- plmnListPerCarrier, overlayConfigPlmnList);
-
- assertEquals(entitlementPlmnList, plmnListPerCarrier);
- verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
- eq(plmnListPerCarrier), eq(allSatellitePlmnList), any(Message.class));
-
- // If the PlmnListPerCarrier and the overlay config plmn list are exist verify passing
- // the modem.
- reset(mMockSatelliteModemInterface);
- entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "00103"}).toList();
Map<Integer, Map<String, Set<Integer>>>
satelliteServicesSupportedByCarriers = new HashMap<>();
List<String> carrierConfigPlmnList = Arrays.stream(new String[]{"00105", "00106"}).toList();
@@ -2739,19 +2724,32 @@
satelliteServicesSupportedByCarriers.put(SUB_ID, plmnAndService);
replaceInstance(SatelliteController.class, "mSatelliteServicesSupportedByCarriers",
mSatelliteControllerUT, satelliteServicesSupportedByCarriers);
- overlayConfigPlmnList = Arrays.stream(new String[]{"00101", "00102", "00104"}).toList();
- replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
- mSatelliteControllerUT, overlayConfigPlmnList);
- List<String> mergedPlmnList = entitlementPlmnList;
+ verifyPassingToModemAfterQueryCompleted(entitlementPlmnList, mergedPlmnList,
+ overlayConfigPlmnList);
- mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, true,
+ // If the entitlement plmn list is empty and the overlay config plmn list and the carrier
+ // plmn list are available, verify not passing to the modem.
+ reset(mMockSatelliteModemInterface);
+ entitlementPlmnList = new ArrayList<>();
+ mergedPlmnList = carrierConfigPlmnList;
+ verifyPassingToModemAfterQueryCompleted(entitlementPlmnList, mergedPlmnList,
+ overlayConfigPlmnList);
+ }
+
+ private void verifyPassingToModemAfterQueryCompleted(List<String> entitlementPlmnList,
+ List<String> mergedPlmnList, List<String> overlayConfigPlmnList) {
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
entitlementPlmnList, mIIntegerConsumer);
- plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(SUB_ID);
- allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
+ List<String> plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(
+ SUB_ID);
+ List<String> allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
plmnListPerCarrier, overlayConfigPlmnList);
assertEquals(mergedPlmnList, plmnListPerCarrier);
+ if (overlayConfigPlmnList.isEmpty()) {
+ assertEquals(plmnListPerCarrier, allSatellitePlmnList);
+ }
verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
eq(plmnListPerCarrier), eq(allSatellitePlmnList), any(Message.class));
}
@@ -2879,8 +2877,11 @@
public void testUpdatePlmnListPerCarrier() throws Exception {
logd("testUpdatePlmnListPerCarrier");
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+
replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
mSatelliteControllerUT, new SparseArray<>());
+ mCarrierConfigBundle.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
List<String> plmnListPerCarrier;
// verify whether an empty list is returned with conditions below
@@ -2996,8 +2997,8 @@
logd("testUpdateEntitlementPlmnListPerCarrier");
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
- // If the Satellite entitlement plmn list read from the DB is empty and carrier config
- // plmn list also is empty , check whether an empty list is returned when calling
+ // If the Satellite entitlement plmn list read from the DB is empty list and carrier
+ // config plmn list also is empty , check whether an empty list is returned when calling
// getSatellitePlmnsForCarrier before the entitlement query.
doReturn(new ArrayList<>()).when(
mMockSubscriptionManagerService).getSatelliteEntitlementPlmnList(anyInt());
@@ -3196,6 +3197,212 @@
verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
}
+ @Test
+ public void testUpdateNtnSignalStrentghReportWithFeatureFlagEnabled() {
+ when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+
+ mIsSatelliteEnabledSemaphore.drainPermits();
+ mIIntegerConsumerResults.clear();
+ resetSatelliteControllerUT();
+
+ // Successfully provisioned
+ reset(mMockSatelliteModemInterface);
+ doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ sendProvisionedStateChangedEvent(true, null);
+ setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ sendProvisionedStateChangedEvent(true, null);
+ processAllMessages();
+ verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+
+ // startSendingNtnSignalStrength should be invoked when satellite is enabled
+ mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
+ setUpResponseForRequestSatelliteEnabled(true, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+ assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
+ assertEquals(
+ SATELLITE_MODE_ENABLED_TRUE, mSatelliteControllerUT.satelliteModeSettingValue);
+ verify(mMockSatelliteModemInterface, times(1)).startSendingNtnSignalStrength(
+ any(Message.class));
+
+ // Ignore request ntn signal strength for redundant enable request
+ reset(mMockSatelliteModemInterface);
+ doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+ verify(mMockSatelliteModemInterface, never()).startSendingNtnSignalStrength(
+ any(Message.class));
+
+ // stopSendingNtnSignalStrength should be invoked when satellite is successfully off.
+ mIIntegerConsumerResults.clear();
+ reset(mMockSatelliteModemInterface);
+ doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+ setUpResponseForRequestSatelliteEnabled(false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+ verify(mMockSatelliteModemInterface, times(1)).stopSendingNtnSignalStrength(
+ any(Message.class));
+
+ // Ignore redundant request for stop reporting ntn signal strength.
+ mIIntegerConsumerResults.clear();
+ reset(mMockSatelliteModemInterface);
+ doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+ mIIntegerConsumerResults.clear();
+ setUpResponseForRequestSatelliteEnabled(false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+ verify(mMockSatelliteModemInterface, never()).stopSendingNtnSignalStrength(
+ any(Message.class));
+
+ // startSendingNtnSignalStrength is invoked when satellite is enabled again.
+ mIIntegerConsumerResults.clear();
+ reset(mMockSatelliteModemInterface);
+ doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+ mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
+ setUpResponseForRequestSatelliteEnabled(true, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+ assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
+ assertEquals(
+ SATELLITE_MODE_ENABLED_TRUE, mSatelliteControllerUT.satelliteModeSettingValue);
+ verify(mMockSatelliteModemInterface, times(1)).startSendingNtnSignalStrength(
+ any(Message.class));
+ }
+
+ @Test
+ public void testRegisterForSatelliteSupportedStateChanged_WithFeatureFlagEnabled() {
+ when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+
+ Semaphore semaphore = new Semaphore(0);
+ final boolean[] isSupported = new boolean[1];
+ ISatelliteSupportedStateCallback callback =
+ new ISatelliteSupportedStateCallback.Stub() {
+ @Override
+ public void onSatelliteSupportedStateChanged(boolean supported) {
+ logd("onSatelliteSupportedStateChanged: supported=" + supported);
+ isSupported[0] = supported;
+ try {
+ semaphore.release();
+ } catch (Exception ex) {
+ loge("onSatelliteSupportedStateChanged: Got exception in releasing "
+ + "semaphore, ex=" + ex);
+ }
+ }
+ };
+
+ resetSatelliteControllerUT();
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ int errorCode = mSatelliteControllerUT.registerForSatelliteSupportedStateChanged(
+ SUB_ID, callback);
+ assertEquals(SATELLITE_RESULT_SUCCESS, errorCode);
+
+ sendSatelliteSupportedStateChangedEvent(true, null);
+ processAllMessages();
+ // Verify redundant report is ignored
+ assertFalse(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSupportedStateChanged"));
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+
+ // Verify updated state is reported
+ sendSatelliteSupportedStateChangedEvent(false, null);
+ processAllMessages();
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSupportedStateChanged"));
+ assertEquals(false, isSupported[0]);
+ verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
+
+ // Verify redundant report is ignored
+ sendSatelliteSupportedStateChangedEvent(false, null);
+ processAllMessages();
+ assertFalse(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSupportedStateChanged"));
+ verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
+
+ // Verify updated state is reported
+ sendSatelliteSupportedStateChangedEvent(true, null);
+ processAllMessages();
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSupportedStateChanged"));
+ assertEquals(true, isSupported[0]);
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+
+ // Successfully enable satellite
+ sendProvisionedStateChangedEvent(true, null);
+ processAllMessages();
+ verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ mIIntegerConsumerResults.clear();
+ setUpResponseForRequestSatelliteEnabled(true, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+
+ // Send satellite is not supported state from modem to disable satellite
+ setUpResponseForRequestSatelliteEnabled(false, false, SATELLITE_RESULT_SUCCESS);
+ sendSatelliteSupportedStateChangedEvent(false, null);
+ processAllMessages();
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSupportedStateChanged"));
+ assertEquals(false, isSupported[0]);
+
+ // It is needed to set satellite as support to check whether satellite is enabled or not
+ sendSatelliteSupportedStateChangedEvent(true, null);
+ processAllMessages();
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSupportedStateChanged"));
+ assertEquals(true, isSupported[0]);
+ // Verify satellite was disabled
+ verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+
+ mSatelliteControllerUT.unregisterForSatelliteSupportedStateChanged(SUB_ID, callback);
+ sendSatelliteSupportedStateChangedEvent(true, null);
+ processAllMessages();
+ assertFalse(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSupportedStateChanged"));
+ }
+
+ @Test
+ public void testRegisterForSatelliteSupportedStateChanged_WithFeatureFlagDisabled() {
+ when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
+
+ Semaphore semaphore = new Semaphore(0);
+ ISatelliteSupportedStateCallback callback =
+ new ISatelliteSupportedStateCallback.Stub() {
+ @Override
+ public void onSatelliteSupportedStateChanged(boolean supported) {
+ logd("onSatelliteSupportedStateChanged: supported=" + supported);
+ try {
+ semaphore.release();
+ } catch (Exception ex) {
+ loge("onSatelliteSupportedStateChanged: Got exception in releasing "
+ + "semaphore, ex=" + ex);
+ }
+ }
+ };
+ int errorCode = mSatelliteControllerUT.registerForSatelliteSupportedStateChanged(
+ SUB_ID, callback);
+ assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, errorCode);
+ }
+
private void resetSatelliteControllerUTEnabledState() {
logd("resetSatelliteControllerUTEnabledState");
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
@@ -3713,6 +3920,13 @@
msg.sendToTarget();
}
+ private void sendSatelliteSupportedStateChangedEvent(boolean supported, Throwable exception) {
+ Message msg = mSatelliteControllerUT.obtainMessage(
+ 41 /* EVENT_SATELLITE_SUPPORTED_STATE_CHANGED */);
+ msg.obj = new AsyncResult(null, supported, exception);
+ msg.sendToTarget();
+ }
+
private void setRadioPower(boolean on) {
mSimulatedCommands.setRadioPower(on, false, false, null);
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
index 6e2c5bf..de43b85 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
@@ -341,4 +341,69 @@
assertThat(subInfoNull.getCountryIso()).isEqualTo("");
assertThat(subInfoNull.getGroupOwner()).isEqualTo("");
}
+
+ @Test
+ public void testIsVisible() {
+ // Regular profile
+ SubscriptionInfoInternal regularSub =
+ new SubscriptionInfoInternal.Builder()
+ .setId(2)
+ .setIccId(SubscriptionDatabaseManagerTest.FAKE_ICCID1)
+ .setSimSlotIndex(0)
+ .setProfileClass(SubscriptionManager.PROFILE_CLASS_OPERATIONAL)
+ .setOnlyNonTerrestrialNetwork(0)
+ .setOpportunistic(0)
+ .setGroupUuid(SubscriptionDatabaseManagerTest.FAKE_UUID1)
+ .build();
+ assertThat(regularSub.isVisible()).isTrue();
+
+ // Provisioning profile
+ SubscriptionInfoInternal provSub =
+ new SubscriptionInfoInternal.Builder()
+ .setId(2)
+ .setIccId(SubscriptionDatabaseManagerTest.FAKE_ICCID1)
+ .setSimSlotIndex(0)
+ .setProfileClass(SubscriptionManager.PROFILE_CLASS_PROVISIONING)
+ .setOnlyNonTerrestrialNetwork(0)
+ .setOpportunistic(0)
+ .build();
+ assertThat(provSub.isVisible()).isFalse();
+
+ // NTN profile
+ SubscriptionInfoInternal ntnSub =
+ new SubscriptionInfoInternal.Builder()
+ .setId(2)
+ .setIccId(SubscriptionDatabaseManagerTest.FAKE_ICCID1)
+ .setSimSlotIndex(0)
+ .setOnlyNonTerrestrialNetwork(1)
+ .setProfileClass(SubscriptionManager.PROFILE_CLASS_OPERATIONAL)
+ .setOpportunistic(0)
+ .build();
+ assertThat(ntnSub.isVisible()).isFalse();
+
+ // Opportunistic profile without group UUID
+ SubscriptionInfoInternal opportunisticSub =
+ new SubscriptionInfoInternal.Builder()
+ .setId(2)
+ .setIccId(SubscriptionDatabaseManagerTest.FAKE_ICCID1)
+ .setSimSlotIndex(0)
+ .setOnlyNonTerrestrialNetwork(0)
+ .setProfileClass(SubscriptionManager.PROFILE_CLASS_OPERATIONAL)
+ .setOpportunistic(1)
+ .build();
+ assertThat(opportunisticSub.isVisible()).isTrue();
+
+ // Opportunistic profile with group UUID
+ SubscriptionInfoInternal opportunisticSubUuid =
+ new SubscriptionInfoInternal.Builder()
+ .setId(2)
+ .setIccId(SubscriptionDatabaseManagerTest.FAKE_ICCID1)
+ .setSimSlotIndex(0)
+ .setOnlyNonTerrestrialNetwork(0)
+ .setProfileClass(SubscriptionManager.PROFILE_CLASS_OPERATIONAL)
+ .setOpportunistic(1)
+ .setGroupUuid(SubscriptionDatabaseManagerTest.FAKE_UUID1)
+ .build();
+ assertThat(opportunisticSubUuid.isVisible()).isFalse();
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
index defa730..9fee311 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
@@ -43,13 +43,16 @@
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_PHONE_NUMBER2;
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_RCS_CONFIG1;
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_RCS_CONFIG2;
+import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SATELLITE_ENTITLEMENT_PLMNS1;
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SUBSCRIPTION_INFO1;
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SUBSCRIPTION_INFO2;
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_UUID1;
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -131,11 +134,13 @@
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
+import java.util.stream.Collectors;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -3202,4 +3207,60 @@
System.setProperty("persist.radio.allow_mock_modem", "false");
doReturn(false).when(mFlags).oemEnabledSatelliteFlag();
}
+
+ @Test
+ public void testGetSatelliteEntitlementPlmnList() throws Exception {
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
+
+ // When the empty list is stored, verify whether SubscriptionInfoInternal returns an
+ // empty string and SubscriptionManagerService returns an empty List.
+ insertSubscription(FAKE_SUBSCRIPTION_INFO1);
+ List<String> expectedPlmnList = new ArrayList<>();
+ int subId = 1;
+
+ SubscriptionInfoInternal subInfo = mSubscriptionManagerServiceUT
+ .getSubscriptionInfoInternal(subId);
+ assertTrue(subInfo.getSatelliteEntitlementPlmns().isEmpty());
+ assertEquals(expectedPlmnList,
+ mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnList(subId));
+
+ // When the list is stored as [123123,12310], verify whether SubscriptionInfoInternal
+ // returns the string as "123123,12310" and SubscriptionManagerService returns the List as
+ // [123123,12310].
+ insertSubscription(FAKE_SUBSCRIPTION_INFO2);
+ String expectedPlmn = FAKE_SATELLITE_ENTITLEMENT_PLMNS1;
+ expectedPlmnList = Arrays.stream(expectedPlmn.split(",")).collect(Collectors.toList());
+ subId = 2;
+
+ subInfo = mSubscriptionManagerServiceUT.getSubscriptionInfoInternal(subId);
+ assertEquals(expectedPlmn, subInfo.getSatelliteEntitlementPlmns());
+ assertEquals(expectedPlmnList,
+ mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnList(subId));
+
+ // When calling SubscriptionDatabaseManager#getSubscriptionInfoInternalreturns returns a
+ // null, then verify the SubscriptionManagerService returns an empty List.
+ SubscriptionDatabaseManager mockSubscriptionDatabaseManager = Mockito.mock(
+ SubscriptionDatabaseManager.class);
+ Field field = SubscriptionManagerService.class.getDeclaredField(
+ "mSubscriptionDatabaseManager");
+ field.setAccessible(true);
+ field.set(mSubscriptionManagerServiceUT, mockSubscriptionDatabaseManager);
+
+ doReturn(null).when(mockSubscriptionDatabaseManager).getSubscriptionInfoInternal(anyInt());
+ expectedPlmnList = new ArrayList<>();
+ assertEquals(expectedPlmnList,
+ mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnList(subId));
+
+ // When calling SubscriptionDatabaseManager#getSubscriptionInfoInternalreturns returns a
+ // non null. And when calling SubscriptionInfoInternal#getSatelliteEntitlementPlmns
+ // returns a null, then verify the SubscriptionManagerService returns an empty List.
+ SubscriptionInfoInternal mockSubscriptionInfoInternal = Mockito.mock(
+ SubscriptionInfoInternal.class);
+ doReturn(mockSubscriptionInfoInternal).when(
+ mockSubscriptionDatabaseManager).getSubscriptionInfoInternal(anyInt());
+ doReturn(null).when(mockSubscriptionInfoInternal).getSatelliteEntitlementPlmns();
+
+ assertEquals(expectedPlmnList,
+ mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnList(subId));
+ }
}