[automerger skipped] Merge "Added flag and tests for SubscriptionPlan changes" into main am: e73da557d5 am: fb84ddc28b -s ours
am skip reason: Merged-In I25b70907eda6b3bcbf34f786ed86d64432c7331f with SHA-1 52a56a8a69 is already in history
Original change: https://android-review.googlesource.com/c/platform/frameworks/opt/telephony/+/3344423
Change-Id: Icf77838333e17974b3d6ada67b48e25cd4dfcf49
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/flags/Android.bp b/flags/Android.bp
index 1885032..edcfc3f 100644
--- a/flags/Android.bp
+++ b/flags/Android.bp
@@ -33,6 +33,7 @@
"subscription.aconfig",
"uicc.aconfig",
"satellite.aconfig",
- "iwlan.aconfig"
+ "iwlan.aconfig",
+ "carrier.aconfig",
],
}
diff --git a/flags/calling.aconfig b/flags/calling.aconfig
index a5757d8..906abfc 100644
--- a/flags/calling.aconfig
+++ b/flags/calling.aconfig
@@ -62,3 +62,11 @@
purpose: PURPOSE_BUGFIX
}
}
+
+# OWNER=yongnamcha TARGET=25Q2
+flag {
+ name: "emergency_callback_mode_notification"
+ namespace: "telephony"
+ description: "Used to notify the emergency callback mode for call/SMS to other applications."
+ bug:"359064059"
+}
diff --git a/flags/carrier.aconfig b/flags/carrier.aconfig
new file mode 100644
index 0000000..265d258
--- /dev/null
+++ b/flags/carrier.aconfig
@@ -0,0 +1,23 @@
+package: "com.android.internal.telephony.flags"
+container: "system"
+
+# OWNER=nharold TARGET=24Q4
+flag {
+ name: "async_init_carrier_privileges_tracker"
+ is_exported: true
+ namespace: "telephony"
+ description: "Offload the heavyweight initialization of CarrierPrivilegesTracker to a worker thread"
+ bug:"357096337"
+}
+
+# OWNER=melhuishj TARGET=25Q1
+flag {
+ name: "cleanup_carrier_app_update_enabled_state_logic"
+ is_exported: true
+ namespace: "telephony"
+ description: "Improve readability of update state logic"
+ bug:"232141900"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/data.aconfig b/flags/data.aconfig
index 0fd094d..ccd5db4 100644
--- a/flags/data.aconfig
+++ b/flags/data.aconfig
@@ -132,3 +132,10 @@
}
}
+# OWNER=TBD TARGET=TBD
+flag {
+ name: "oem_paid_private"
+ namespace: "telephony"
+ description: "Support OEM_PAID and OEM_PRIVATE networks"
+ bug: "366194627"
+}
diff --git a/flags/ims.aconfig b/flags/ims.aconfig
index d2401fe..4ce7508 100644
--- a/flags/ims.aconfig
+++ b/flags/ims.aconfig
@@ -137,3 +137,30 @@
purpose: PURPOSE_BUGFIX
}
}
+
+# OWNER=breadley TARGET=25Q1
+flag {
+ name: "ims_resolver_user_aware"
+ namespace: "telephony"
+ description: "When enabled, it makes ImsResolver mult-user aware for configurations like HSUM."
+ bug:"371272669"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=meghapatil TARGET=25Q2
+flag {
+ name: "support_sms_over_ims_apis"
+ namespace: "telephony"
+ description: "Used to expose SMS related hidden APIs for SMS over IMS to public API."
+ bug:"359721349"
+}
+
+# OWNER=jhyoon TARGET=25Q2
+flag {
+ name: "support_ims_mmtel_interface"
+ namespace: "telephony"
+ description: "This flag controls the type of API regarding MmTelFeature, either hidden or system type."
+ bug:"359721349"
+}
diff --git a/flags/misc.aconfig b/flags/misc.aconfig
index 860c864..303c0ff 100644
--- a/flags/misc.aconfig
+++ b/flags/misc.aconfig
@@ -80,15 +80,6 @@
# OWNER=rambowang TARGET=24Q3
flag {
- name: "show_call_id_and_call_waiting_in_additional_settings_menu"
- is_exported: true
- namespace: "telephony"
- description: "Expose carrier config KEY_ADDITIONAL_SETTINGS_CALLER_ID_VISIBILITY_BOOL and KEY_ADDITIONAL_SETTINGS_CALL_WAITING_VISIBILITY_BOOL."
- bug: "310264981"
-}
-
-# OWNER=rambowang TARGET=24Q3
-flag {
name: "reset_mobile_network_settings"
is_exported: true
namespace: "telephony"
diff --git a/flags/satellite.aconfig b/flags/satellite.aconfig
index 4806789..8662572 100644
--- a/flags/satellite.aconfig
+++ b/flags/satellite.aconfig
@@ -61,4 +61,21 @@
metadata {
purpose: PURPOSE_BUGFIX
}
-}
\ No newline at end of file
+}
+
+# OWNER=amallampati TARGET=25Q2
+flag {
+ name: "satellite_system_apis"
+ is_exported: true
+ namespace: "telephony"
+ description: "Convert hidden SatelliteManager APIs to system APIs."
+ bug:"373436320"
+}
+
+# OWNER=rambowang TARGET=25Q2
+flag {
+ name: "satellite_state_change_listener"
+ namespace: "telephony"
+ description: "Introduce SatelliteManager APIs for carrier apps to monitor satellite state change"
+ bug: "357638490"
+}
diff --git a/flags/subscription.aconfig b/flags/subscription.aconfig
index 87c7408..aea9bd0 100644
--- a/flags/subscription.aconfig
+++ b/flags/subscription.aconfig
@@ -58,14 +58,6 @@
}
}
-# OWNER=jmattis TARGET=25Q2
-flag {
- name: "subscription_plan_allow_status_and_end_date"
- namespace: "telephony"
- description: "Provide APIs to retrieve the status and recurrence rule info on a subscription plan"
- bug: "357272015"
-}
-
# OWNER=songferngwang TARGET=24Q3
flag {
name: "reset_primary_sim_default_values"
@@ -89,3 +81,11 @@
purpose: PURPOSE_BUGFIX
}
}
+
+# OWNER=jmattis TARGET=25Q2
+flag {
+ name: "subscription_plan_allow_status_and_end_date"
+ namespace: "telephony"
+ description: "Provide APIs to retrieve the status and recurrence rule info on a subscription plan"
+ bug: "357272015"
+}
diff --git a/flags/uicc.aconfig b/flags/uicc.aconfig
index 14341d9..abe4296 100644
--- a/flags/uicc.aconfig
+++ b/flags/uicc.aconfig
@@ -69,3 +69,22 @@
description: "This flag controls optimization of apdu sender class."
bug:"335257880"
}
+
+# OWNER=arunvoddu TARGET=24Q4
+flag {
+ name: "ignore_carrierid_reset_for_sim_removal"
+ namespace: "telephony"
+ description: "This flag controls the carrierId reset while imsi key deletion time upon sim ejection."
+ bug:"366178705"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=jhyoon TARGET=25Q2
+flag {
+ name: "support_isim_record"
+ namespace: "telephony"
+ description: "This flag controls the type of API that retrieves ISIM records, either hidden or system type."
+ bug:"359721349"
+}
diff --git a/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java b/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java
index 6f84521..1667b7d 100644
--- a/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java
+++ b/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java
@@ -146,9 +146,9 @@
.createForSubscriptionId(mPhone.getSubId());
if (Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
- } else {
- mUserManager = mContext.getSystemService(UserManager.class);
}
+ mUserManager = mContext.getSystemService(UserManager.class);
+
CarrierConfigManager carrierConfigManager = mContext.getSystemService(
CarrierConfigManager.class);
// Callback which directly handle config change should be executed on handler thread
@@ -170,17 +170,29 @@
TelephonyManager.class)
.createForSubscriptionId(subId);
}
- mCarrierId = carrierId;
+ if (Flags.ignoreCarrieridResetForSimRemoval()) {
+ if (carrierId > 0) {
+ mCarrierId = carrierId;
+ }
+ } else {
+ mCarrierId = carrierId;
+ }
updateSimOperator();
// If device is screen locked do not proceed to handle
// EVENT_ALARM_OR_CONFIG_CHANGE
- if (mKeyguardManager.isDeviceLocked()) {
- logd("Device is Locked");
+ printDeviceLockStatus();
+ if (Flags.ignoreCarrieridResetForSimRemoval()) {
+ if (!mUserManager.isUserUnlocked()) {
+ mIsRequiredToHandleUnlock = true;
+ return;
+ }
+ } else if (mKeyguardManager.isDeviceLocked()) {
mIsRequiredToHandleUnlock = true;
- } else {
- logd("Carrier Config changed: slotIndex=" + slotIndex);
- sendEmptyMessage(EVENT_ALARM_OR_CONFIG_CHANGE);
+ return;
}
+ logd("Carrier Config changed: slotIndex=" + slotIndex);
+ sendEmptyMessage(EVENT_ALARM_OR_CONFIG_CHANGE);
+
}
} else {
boolean isUserUnlocked = mUserManager.isUserUnlocked();
@@ -199,6 +211,11 @@
mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
}
+ private void printDeviceLockStatus() {
+ logd(" Device Status: isDeviceLocked = " + mKeyguardManager.isDeviceLocked()
+ + " iss User unlocked = " + mUserManager.isUserUnlocked());
+ }
+
// TODO remove this method upon imsiKeyRetryDownloadOnPhoneUnlock enabled.
private final BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() {
@Override
@@ -307,11 +324,16 @@
if (downloadStartedSuccessfully) {
unregisterDefaultNetworkCb(slotIndex);
} else {
- // If download fails due to the device lock, we will reattempt once the
- // device is unlocked.
- mIsRequiredToHandleUnlock = mKeyguardManager.isDeviceLocked();
+ // If download fails due to the device user lock, we will reattempt once
+ // the device is unlocked.
+ if (Flags.ignoreCarrieridResetForSimRemoval()) {
+ mIsRequiredToHandleUnlock = !mUserManager.isUserUnlocked();
+ } else {
+ mIsRequiredToHandleUnlock = mKeyguardManager.isDeviceLocked();
+ }
+
loge("hasActiveDataConnection = " + hasActiveDataNetwork
- + " isDeviceLocked = " + mIsRequiredToHandleUnlock);
+ + " isDeviceUserLocked = " + mIsRequiredToHandleUnlock);
if (!hasActiveDataNetwork) {
registerDefaultNetworkCb(slotIndex);
}
@@ -538,14 +560,19 @@
carrierKeyDownloadIdentifier);
}
parseJsonAndPersistKey(jsonStr, mccMnc, carrierId);
+ logd("Completed downloading keys");
} catch (Exception e) {
loge( "Error in download:" + carrierKeyDownloadIdentifier
+ ". " + e);
} finally {
mDownloadManager.remove(carrierKeyDownloadIdentifier);
}
+ } else {
+ loge("Download Failed reason = " + cursor.getInt(columnIndex)
+ + "Failed Status reason" + cursor.getInt(
+ cursor.getColumnIndex(DownloadManager.COLUMN_REASON)));
+ printDeviceLockStatus();
}
- logd("Completed downloading keys");
}
cursor.close();
}
@@ -796,6 +823,7 @@
} catch (Exception e) {
loge( "exception trying to download key from url: " + mURL + ", Exception = "
+ e.getMessage());
+ printDeviceLockStatus();
return false;
}
return true;
diff --git a/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java b/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
index 522cf77..6326d6c 100644
--- a/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
+++ b/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
@@ -46,6 +46,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
@@ -68,7 +69,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.telephony.flags.FeatureFlags;
-import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.telephony.uicc.UiccPort;
import com.android.internal.telephony.uicc.UiccProfile;
import com.android.telephony.Rlog;
@@ -80,7 +80,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -179,6 +178,8 @@
private static final int ACTION_SET_TEST_OVERRIDE_CARRIER_SERVICE_PACKAGE = 11;
private final Context mContext;
+ @NonNull
+ private final FeatureFlags mFeatureFlags;
private final Phone mPhone;
private final PackageManager mPackageManager;
private final UserManager mUserManager;
@@ -198,7 +199,7 @@
@Nullable private List<UiccAccessRule> mTestOverrideRules = null;
@Nullable private String mTestOverrideCarrierServicePackage = null;
// Map of PackageName -> Certificate hashes for that Package
- @NonNull private final Map<String, Set<String>> mInstalledPackageCerts = new ArrayMap<>();
+ @NonNull private final Map<String, Set<Integer>> mInstalledPackageCertHashes = new ArrayMap<>();
// Map of PackageName -> UIDs for that Package
@NonNull private final Map<String, Set<Integer>> mCachedUids = new ArrayMap<>();
@@ -226,8 +227,7 @@
"mPrivilegedPackageInfoLock.writeLock()"})
private boolean mSimIsReadyButNotLoaded = false;
- @NonNull
- private final FeatureFlags mFeatureFlags;
+ private volatile Handler mCurrentHandler;
/** Small snapshot to hold package names and UIDs of privileged packages. */
private static final class PrivilegedPackageInfo {
@@ -303,7 +303,9 @@
return;
}
- sendMessage(obtainMessage(ACTION_SIM_STATE_UPDATED, slotId, simState));
+ mCurrentHandler.sendMessage(
+ mCurrentHandler.obtainMessage(
+ ACTION_SIM_STATE_UPDATED, slotId, simState));
break;
}
case Intent.ACTION_PACKAGE_ADDED: // fall through
@@ -335,19 +337,21 @@
? ACTION_PACKAGE_REMOVED_OR_DISABLED_BY_USER
: ACTION_PACKAGE_ADDED_REPLACED_OR_CHANGED;
- sendMessage(obtainMessage(what, pkgName));
+ mCurrentHandler.sendMessage(
+ mCurrentHandler.obtainMessage(what, pkgName));
break;
}
}
}
};
- public CarrierPrivilegesTracker(@NonNull Looper looper, @NonNull Phone phone,
- @NonNull Context context, @NonNull FeatureFlags flags) {
+ public CarrierPrivilegesTracker(
+ @NonNull Looper looper, @NonNull Phone phone,
+ @NonNull Context context, @NonNull FeatureFlags featureFlags) {
super(looper);
- mContext = context;
- mFeatureFlags = flags;
mPhone = phone;
+ mContext = context;
+ mFeatureFlags = featureFlags;
mPackageManager = mContext.getPackageManager();
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mCarrierConfigManager =
@@ -363,6 +367,56 @@
(TelephonyRegistryManager)
mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+ if (mFeatureFlags.asyncInitCarrierPrivilegesTracker()) {
+ final Object localLock = new Object();
+ HandlerThread initializerThread =
+ new HandlerThread("CarrierPrivilegesTracker Initializer") {
+ @Override
+ protected void onLooperPrepared() {
+ synchronized (localLock) {
+ localLock.notifyAll();
+ }
+ }
+ };
+ synchronized (localLock) {
+ initializerThread.start();
+ while (true) {
+ try {
+ localLock.wait();
+ break;
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+ mCurrentHandler = new Handler(initializerThread.getLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ case ACTION_INITIALIZE_TRACKER:
+ handleInitializeTracker();
+ if (!hasMessagesOrCallbacks()) {
+ mCurrentHandler = CarrierPrivilegesTracker.this;
+ initializerThread.quitSafely();
+ }
+ break;
+ default:
+ Message m = CarrierPrivilegesTracker.this.obtainMessage();
+ m.copyFrom(msg);
+ m.sendToTarget();
+ if (!hasMessagesOrCallbacks()) {
+ mCurrentHandler = CarrierPrivilegesTracker.this;
+ initializerThread.quitSafely();
+ }
+ break;
+ }
+ }
+ };
+ } else {
+ mCurrentHandler = this;
+ }
+
+ mCurrentHandler.sendMessage(obtainMessage(ACTION_INITIALIZE_TRACKER));
+
IntentFilter certFilter = new IntentFilter();
certFilter.addAction(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED);
certFilter.addAction(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED);
@@ -391,7 +445,6 @@
mContext.registerReceiver(mIntentReceiver, packageFilter);
}
- sendMessage(obtainMessage(ACTION_INITIALIZE_TRACKER));
}
@Override
@@ -499,7 +552,7 @@
&& mClearUiccRulesUptimeMillis == CLEAR_UICC_RULE_NOT_SCHEDULED) {
mClearUiccRulesUptimeMillis =
SystemClock.uptimeMillis() + CLEAR_UICC_RULES_DELAY_MILLIS;
- sendMessageAtTime(obtainMessage(ACTION_CLEAR_UICC_RULES),
+ mCurrentHandler.sendMessageAtTime(obtainMessage(ACTION_CLEAR_UICC_RULES),
mClearUiccRulesUptimeMillis);
mLocalLog.log("SIM is gone, simState=" + TelephonyManager.simStateToString(simState)
+ ". Delay " + TimeUnit.MILLISECONDS.toSeconds(
@@ -556,25 +609,29 @@
return uiccProfile.getCarrierPrivilegeAccessRules();
}
- private void handlePackageAddedReplacedOrChanged(@Nullable String pkgName) {
- if (pkgName == null) return;
+ private PackageInfo getPackageInfoForPackage(@Nullable String pkgName) {
+ if (pkgName == null) return null;
PackageInfo pkg;
try {
- pkg =
- mFeatureFlags.supportCarrierServicesForHsum()
- ? mPackageManager.getPackageInfoAsUser(
- pkgName,
- INSTALLED_PACKAGES_QUERY_FLAGS,
- ActivityManager.getCurrentUser())
- : mPackageManager.getPackageInfo(
- pkgName, INSTALLED_PACKAGES_QUERY_FLAGS);
+ return mFeatureFlags.supportCarrierServicesForHsum()
+ ? mPackageManager.getPackageInfoAsUser(
+ pkgName,
+ INSTALLED_PACKAGES_QUERY_FLAGS,
+ ActivityManager.getCurrentUser())
+ : mPackageManager.getPackageInfo(
+ pkgName, INSTALLED_PACKAGES_QUERY_FLAGS);
} catch (NameNotFoundException e) {
Rlog.e(TAG, "Error getting installed package: " + pkgName, e);
- return;
+ return null;
}
+ }
- updateCertsForPackage(pkg);
+ private void handlePackageAddedReplacedOrChanged(@Nullable String pkgName) {
+ PackageInfo pkg = getPackageInfoForPackage(pkgName);
+ if (pkg == null) return;
+
+ updateCertHashHashesForPackage(pkg);
// Invalidate cache because this may be a package already on the device but getting
// installed for a user it wasn't installed in before, which means there will be an
// additional UID.
@@ -582,30 +639,46 @@
if (VDBG) {
Rlog.d(TAG, "Package added/replaced/changed:"
+ " pkg=" + Rlog.pii(TAG, pkgName)
- + " cert hashes=" + mInstalledPackageCerts.get(pkgName));
+ + " cert hashes=" + mInstalledPackageCertHashes.get(pkgName));
}
maybeUpdatePrivilegedPackagesAndNotifyRegistrants();
}
- private void updateCertsForPackage(@NonNull PackageInfo pkg) {
- Set<String> certs = new ArraySet<>(1);
+ private void updateCertHashHashesForPackage(@NonNull PackageInfo pkg) {
+ Set<Integer> certs = new ArraySet<>(2);
List<Signature> signatures = UiccAccessRule.getSignatures(pkg);
for (Signature signature : signatures) {
byte[] sha1 = UiccAccessRule.getCertHash(signature, SHA_1);
- certs.add(IccUtils.bytesToHexString(sha1).toUpperCase(Locale.ROOT));
+ certs.add(UiccAccessRule.getCertificateHashHashCode(sha1));
byte[] sha256 = UiccAccessRule.getCertHash(signature, SHA_256);
- certs.add(IccUtils.bytesToHexString(sha256).toUpperCase(Locale.ROOT));
+ certs.add(UiccAccessRule.getCertificateHashHashCode(sha256));
}
- mInstalledPackageCerts.put(pkg.packageName, certs);
+ mInstalledPackageCertHashes.put(pkg.packageName, certs);
+ }
+
+ private Set<byte[]> getCertsForPackage(@NonNull String pkgName) {
+ PackageInfo pkg = getPackageInfoForPackage(pkgName);
+ if (pkg == null) return Collections.emptySet();
+
+ List<Signature> signatures = UiccAccessRule.getSignatures(pkg);
+
+ ArraySet<byte[]> certs = new ArraySet<>(2);
+ for (Signature signature : signatures) {
+ certs.add(UiccAccessRule.getCertHash(signature, SHA_1));
+ certs.add(UiccAccessRule.getCertHash(signature, SHA_256));
+ }
+
+ return certs;
}
private void handlePackageRemovedOrDisabledByUser(@Nullable String pkgName) {
if (pkgName == null) return;
- if (mInstalledPackageCerts.remove(pkgName) == null || mCachedUids.remove(pkgName) == null) {
+ if (mInstalledPackageCertHashes.remove(pkgName) == null
+ || mCachedUids.remove(pkgName) == null) {
Rlog.e(TAG, "Unknown package was uninstalled or disabled by user: " + pkgName);
return;
}
@@ -637,7 +710,7 @@
msg +=
" installed pkgs="
+ getObfuscatedPackages(
- mInstalledPackageCerts.entrySet(),
+ mInstalledPackageCertHashes.entrySet(),
e -> "pkg(" + Rlog.pii(TAG, e.getKey()) + ")=" + e.getValue());
}
mLocalLog.log(msg);
@@ -651,7 +724,7 @@
? ActivityManager.getCurrentUser()
: UserHandle.SYSTEM.getIdentifier());
for (PackageInfo pkg : installedPackages) {
- updateCertsForPackage(pkg);
+ updateCertHashHashesForPackage(pkg);
// This may be unnecessary before initialization, but invalidate the cache all the time
// just in case to ensure consistency.
getUidsForPackage(pkg.packageName, /* invalidateCache= */ true);
@@ -740,8 +813,12 @@
Set<String> carrierServiceEligiblePackages = new ArraySet<>();
Set<String> privilegedPackageNames = new ArraySet<>();
Set<Integer> privilegedUids = new ArraySet<>();
- for (Map.Entry<String, Set<String>> e : mInstalledPackageCerts.entrySet()) {
- final int priv = getPackagePrivilegedStatus(e.getKey(), e.getValue());
+ for (Map.Entry<String, Set<Integer>> e : mInstalledPackageCertHashes.entrySet()) {
+ if (!isPackageMaybePrivileged(e.getKey(), e.getValue())) continue;
+
+ Set<byte[]> fullCerts = getCertsForPackage(e.getKey());
+
+ final int priv = getPackagePrivilegedStatus(e.getKey(), fullCerts);
switch (priv) {
case PACKAGE_PRIVILEGED_FROM_SIM:
case PACKAGE_PRIVILEGED_FROM_CARRIER_SERVICE_TEST_OVERRIDE: // fallthrough
@@ -760,32 +837,58 @@
getCarrierService(carrierServiceEligiblePackages));
}
+ private boolean isPackageMaybePrivileged(
+ @NonNull String pkgName, @NonNull Set<Integer> hashHashes) {
+ for (Integer hashHash : hashHashes) {
+ // Non-null (whether empty or not) test override rule will ignore the UICC and CC rules
+ if (mTestOverrideRules != null) {
+ for (UiccAccessRule rule : mTestOverrideRules) {
+ if (rule.hasMatchingCertificateHashHashAndPackageName(hashHash, pkgName)) {
+ return true;
+ }
+ }
+ } else {
+ for (UiccAccessRule rule : mUiccRules) {
+ if (rule.hasMatchingCertificateHashHashAndPackageName(hashHash, pkgName)) {
+ return true;
+ }
+ }
+ for (UiccAccessRule rule : mCarrierConfigRules) {
+ if (rule.hasMatchingCertificateHashHashAndPackageName(hashHash, pkgName)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
/**
* Returns the privilege status of the provided package.
*
* <p>Returned privilege status depends on whether a package matches the certificates from
* carrier config, from test overrides or from certificates stored on the SIM.
*/
- private int getPackagePrivilegedStatus(@NonNull String pkgName, @NonNull Set<String> certs) {
+ private int getPackagePrivilegedStatus(@NonNull String pkgName, @NonNull Set<byte[]> certs) {
// Double-nested for loops, but each collection should contain at most 2 elements in nearly
// every case.
// TODO(b/184382310) find a way to speed this up
- for (String cert : certs) {
+ for (byte[] cert : certs) {
// Non-null (whether empty or not) test override rule will ignore the UICC and CC rules
if (mTestOverrideRules != null) {
for (UiccAccessRule rule : mTestOverrideRules) {
- if (rule.matches(cert, pkgName)) {
+ if (rule.hasMatchingCertificateHashAndPackageName(cert, pkgName)) {
return PACKAGE_PRIVILEGED_FROM_SIM;
}
}
} else {
for (UiccAccessRule rule : mUiccRules) {
- if (rule.matches(cert, pkgName)) {
+ if (rule.hasMatchingCertificateHashAndPackageName(cert, pkgName)) {
return PACKAGE_PRIVILEGED_FROM_SIM;
}
}
for (UiccAccessRule rule : mCarrierConfigRules) {
- if (rule.matches(cert, pkgName)) {
+ if (rule.hasMatchingCertificateHashAndPackageName(cert, pkgName)) {
return pkgName.equals(mTestOverrideCarrierServicePackage)
? PACKAGE_PRIVILEGED_FROM_CARRIER_SERVICE_TEST_OVERRIDE
: PACKAGE_PRIVILEGED_FROM_CARRIER_CONFIG;
@@ -856,7 +959,7 @@
pw.println(
"CarrierPrivilegesTracker - Obfuscated Pkgs + Certs: "
+ getObfuscatedPackages(
- mInstalledPackageCerts.entrySet(),
+ mInstalledPackageCertHashes.entrySet(),
e -> "pkg(" + Rlog.pii(TAG, e.getKey()) + ")=" + e.getValue()));
}
pw.println("mClearUiccRulesUptimeMillis: " + mClearUiccRulesUptimeMillis);
@@ -872,7 +975,8 @@
* @see TelephonyManager#setCarrierTestOverride
*/
public void setTestOverrideCarrierPrivilegeRules(@Nullable String carrierPrivilegeRules) {
- sendMessage(obtainMessage(ACTION_SET_TEST_OVERRIDE_RULE, carrierPrivilegeRules));
+ mCurrentHandler.sendMessage(
+ obtainMessage(ACTION_SET_TEST_OVERRIDE_RULE, carrierPrivilegeRules));
}
/**
@@ -888,7 +992,7 @@
* @see TelephonyManager#setCarrierServicePackageOverride
*/
public void setTestOverrideCarrierServicePackage(@Nullable String carrierServicePackage) {
- sendMessage(obtainMessage(
+ mCurrentHandler.sendMessage(obtainMessage(
ACTION_SET_TEST_OVERRIDE_CARRIER_SERVICE_PACKAGE, carrierServicePackage));
}
diff --git a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
index 55baecc..4f9d84d 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony;
import android.annotation.NonNull;
+import android.app.ActivityManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -161,7 +162,11 @@
};
public CarrierServiceBindHelper(Context context) {
- mContext = context.createContextAsUser(Process.myUserHandle(), 0);
+ mContext =
+ context.createContextAsUser(
+ Flags.supportCarrierServicesForHsum()
+ ? UserHandle.of(ActivityManager.getCurrentUser())
+ : Process.myUserHandle(), 0);
updateBindingsAndSimStates();
diff --git a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
index d47c2c4..b470e2e 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
@@ -75,7 +75,8 @@
@VisibleForTesting
- public static final String ACTION_NEVER_ASK_AGAIN = "SilenceNoWifiEmrgCallingNotification";
+ public static final String ACTION_NEVER_ASK_AGAIN =
+ "com.android.internal.telephony.action.SILENCE_WIFI_CALLING_NOTIFICATION";
public final NotificationActionReceiver mActionReceiver = new NotificationActionReceiver();
@VisibleForTesting
@@ -733,6 +734,7 @@
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_NEVER_ASK_AGAIN)) {
Rlog.i(LOG_TAG, "NotificationActionReceiver: ACTION_NEVER_ASK_AGAIN");
+ dismissEmergencyCallingNotification();
// insert a key to silence future notifications
SharedPreferences.Editor editor =
PreferenceManager.getDefaultSharedPreferences(context).edit();
@@ -743,5 +745,22 @@
context.unregisterReceiver(mActionReceiver);
}
}
+
+ /**
+ * Dismiss the notification when the "Do Not Ask Again" button is clicked
+ */
+ private void dismissEmergencyCallingNotification() {
+ if (!mFeatureFlags.stopSpammingEmergencyNotification()) {
+ return;
+ }
+ try {
+ NotificationType t = mNotificationTypeMap.get(NOTIFICATION_EMERGENCY_NETWORK);
+ if (t != null) {
+ cancelNotification(t);
+ }
+ } catch (Exception e) {
+ Rlog.e(LOG_TAG, "dismissEmergencyCallingNotification", e);
+ }
+ }
}
}
diff --git a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index da17f60..732582f 100644
--- a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -26,6 +26,7 @@
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.LinkCapacityEstimate;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneCapability;
import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseCallState;
@@ -40,6 +41,7 @@
import android.telephony.ims.ImsCallSession;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.MediaQualityStatus;
+import android.telephony.satellite.NtnSignalStrength;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.telephony.Rlog;
@@ -303,14 +305,28 @@
}
@Override
- public void notifyCallbackModeStarted(Phone sender, @EmergencyCallbackModeType int type) {
- mTelephonyRegistryMgr.notifyCallBackModeStarted(sender.getPhoneId(),
- sender.getSubId(), type);
+ public void notifyCallbackModeStarted(Phone sender, @EmergencyCallbackModeType int type,
+ long durationMillis) {
+ if (!mFeatureFlags.emergencyCallbackModeNotification()) return;
+
+ mTelephonyRegistryMgr.notifyCallbackModeStarted(sender.getPhoneId(),
+ sender.getSubId(), type, durationMillis);
+ }
+
+ @Override
+ public void notifyCallbackModeRestarted(Phone sender, @EmergencyCallbackModeType int type,
+ long durationMillis) {
+ if (!mFeatureFlags.emergencyCallbackModeNotification()) return;
+
+ mTelephonyRegistryMgr.notifyCallbackModeRestarted(sender.getPhoneId(),
+ sender.getSubId(), type, durationMillis);
}
@Override
public void notifyCallbackModeStopped(Phone sender, @EmergencyCallbackModeType int type,
@EmergencyCallbackModeStopReason int reason) {
+ if (!mFeatureFlags.emergencyCallbackModeNotification()) return;
+
mTelephonyRegistryMgr.notifyCallbackModeStopped(sender.getPhoneId(),
sender.getSubId(), type, reason);
}
@@ -326,6 +342,20 @@
sender.getSubId(), eligible);
}
+ @Override
+ public void notifyCarrierRoamingNtnAvailableServicesChanged(
+ Phone sender, @NetworkRegistrationInfo.ServiceType int[] availableServices) {
+ mTelephonyRegistryMgr.notifyCarrierRoamingNtnAvailableServicesChanged(
+ sender.getSubId(), availableServices);
+ }
+
+ @Override
+ public void notifyCarrierRoamingNtnSignalStrengthChanged(Phone sender,
+ @NonNull NtnSignalStrength ntnSignalStrength) {
+ mTelephonyRegistryMgr.notifyCarrierRoamingNtnSignalStrengthChanged(
+ sender.getSubId(), ntnSignalStrength);
+ }
+
/**
* Convert the {@link Call.State} enum into the PreciseCallState.PRECISE_CALL_STATE_* constants
* for the public API.
diff --git a/src/java/com/android/internal/telephony/GbaManager.java b/src/java/com/android/internal/telephony/GbaManager.java
index 7c5f636..047d5d5 100644
--- a/src/java/com/android/internal/telephony/GbaManager.java
+++ b/src/java/com/android/internal/telephony/GbaManager.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony;
+import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -27,6 +28,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.telephony.IBootstrapAuthenticationCallback;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -75,7 +77,8 @@
private Handler mHandler;
private String mServicePackageName;
- private String mServicePackageNameOverride;
+ @UserIdInt
+ private int mUserId = UserHandle.USER_SYSTEM;
private int mReleaseTime;
private int mRetryTimes = 0;
@@ -426,8 +429,9 @@
try {
logv("Trying to bind " + servicePackage);
mServiceConnection = new GbaServiceConnection();
- if (!mContext.bindService(intent, mServiceConnection,
- Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE)) {
+ if (!mContext.bindServiceAsUser(intent, mServiceConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+ UserHandle.of(mUserId))) {
logd("Cannot bind to the service.");
retryBind();
return;
@@ -462,12 +466,13 @@
}
/** override GBA service package name to be connected */
- public boolean overrideServicePackage(String packageName) {
+ public boolean overrideServicePackage(String packageName, @UserIdInt int userId) {
synchronized (this) {
- if (!TextUtils.equals(mServicePackageName, packageName)) {
+ if (!TextUtils.equals(mServicePackageName, packageName) || userId != mUserId) {
logv("Service package name is changed from " + mServicePackageName
- + " to " + packageName);
+ + " to " + packageName + ", user id from " + mUserId + " to " + userId);
mServicePackageName = packageName;
+ mUserId = userId;
if (!mHandler.hasMessages(EVENT_CONFIG_CHANGED)) {
mHandler.sendEmptyMessage(EVENT_CONFIG_CHANGED);
}
diff --git a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
index 26d4e1b..14bd273 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
@@ -509,7 +509,8 @@
obtainCompleteMessage());
}
};
- EmergencyStateTracker.getInstance().exitEmergencyCallbackMode(onComplete);
+ EmergencyStateTracker.getInstance().exitEmergencyCallbackMode(onComplete,
+ TelephonyManager.STOP_REASON_OUTGOING_NORMAL_CALL_INITIATED);
} else {
mPhone.exitEmergencyCallbackMode();
mPhone.setOnEcbModeExitResponse(this, EVENT_EXIT_ECM_RESPONSE_CDMA, null);
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 5d59327..a91000e 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -42,7 +42,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
import android.database.SQLException;
import android.hardware.radio.modem.ImeiInfo;
import android.net.Uri;
@@ -391,8 +390,8 @@
mCarrierResolver = mTelephonyComponentFactory.inject(CarrierResolver.class.getName())
.makeCarrierResolver(this, featureFlags);
- mCarrierPrivilegesTracker = new CarrierPrivilegesTracker(Looper.myLooper(), this, context,
- featureFlags);
+ mCarrierPrivilegesTracker = new CarrierPrivilegesTracker(
+ Looper.myLooper(), this, context, featureFlags);
getCarrierActionAgent().registerForCarrierAction(
CarrierActionAgent.CARRIER_ACTION_SET_METERED_APNS_ENABLED, this,
@@ -470,12 +469,6 @@
}
};
- private boolean hasCalling() {
- if (!TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)) return true;
- return mContext.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_TELEPHONY_CALLING);
- }
-
private void initOnce(CommandsInterface ci) {
if (ci instanceof SimulatedRadioControl) {
mSimulatedRadioControl = (SimulatedRadioControl) ci;
diff --git a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
index 3141406..9eebc60 100644
--- a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
+++ b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
@@ -48,6 +48,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
+import com.android.internal.telephony.emergency.EmergencyNumberTracker;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
import com.android.internal.telephony.uicc.IccConstants;
@@ -1511,8 +1512,7 @@
@VisibleForTesting
public void notifyIfOutgoingEmergencySms(String destAddr) {
Phone[] allPhones = mPhoneFactoryProxy.getPhones();
- EmergencyNumber emergencyNumber = mPhone.getEmergencyNumberTracker().getEmergencyNumber(
- destAddr);
+ EmergencyNumber emergencyNumber = getEmergencyNumber(mPhone, destAddr);
if (emergencyNumber != null) {
mPhone.notifyOutgoingEmergencySms(emergencyNumber);
} else if (allPhones.length > 1) {
@@ -1522,8 +1522,7 @@
if (phone.getPhoneId() == mPhone.getPhoneId()) {
continue;
}
- emergencyNumber = phone.getEmergencyNumberTracker()
- .getEmergencyNumber(destAddr);
+ emergencyNumber = getEmergencyNumber(phone, destAddr);
if (emergencyNumber != null) {
mPhone.notifyOutgoingEmergencySms(emergencyNumber);
break;
@@ -1532,6 +1531,13 @@
}
}
+ private EmergencyNumber getEmergencyNumber(Phone phone, String number) {
+ if (!phone.hasCalling()) return null;
+ EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
+ if (tracker == null) return null;
+ return tracker.getEmergencyNumber(number);
+ }
+
private void returnUnspecifiedFailure(PendingIntent pi) {
if (pi != null) {
try {
diff --git a/src/java/com/android/internal/telephony/ImsSmsDispatcher.java b/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
index c94480e..6955a55 100644
--- a/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
+++ b/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
@@ -202,8 +202,7 @@
tracker.onSent(mContext);
mTrackers.remove(token);
mPhone.notifySmsSent(tracker.mDestAddress);
- mSmsDispatchersController.notifySmsSent(
- tracker.mDestAddress, tracker.mMessageId, true,
+ mSmsDispatchersController.notifySmsSent(tracker, true,
tracker.isSinglePartOrLastPart(), true /*success*/);
break;
case ImsSmsImplBase.SEND_STATUS_ERROR:
diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java
index ca03f5d..f404e04 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -66,6 +66,7 @@
import android.telephony.SmsMessage;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Pair;
@@ -77,6 +78,7 @@
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.metrics.TelephonyMetrics;
+import com.android.internal.telephony.satellite.SatelliteController;
import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteSessionStats;
import com.android.internal.telephony.util.NotificationChannelController;
import com.android.internal.telephony.util.TelephonyUtils;
@@ -687,6 +689,16 @@
result = RESULT_SMS_DISPATCH_FAILURE;
}
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ if (result == Intents.RESULT_SMS_HANDLED) {
+ SatelliteController satelliteController = SatelliteController.getInstance();
+ if (satelliteController != null
+ && satelliteController.shouldSendSmsToDatagramDispatcher(mPhone)) {
+ satelliteController.onSmsReceived(mPhone.getSubId());
+ }
+ }
+ }
+
// RESULT_OK means that the SMS will be acknowledged by special handling,
// e.g. for SMS-PP data download. Any other result, we should ack here.
if (result != Activity.RESULT_OK) {
@@ -747,6 +759,11 @@
return Intents.RESULT_SMS_HANDLED;
}
+ if (isMtSmsPollingMessage(smsb)) {
+ log("Received MT SMS polling message. Ignored.");
+ return Intents.RESULT_SMS_HANDLED;
+ }
+
int result = dispatchMessageRadioSpecific(smsb, smsSource, token);
// In case of error, add to metrics. This is not required in case of success, as the
@@ -754,8 +771,7 @@
if (result != Intents.RESULT_SMS_HANDLED && result != Activity.RESULT_OK) {
mMetrics.writeIncomingSmsError(mPhone.getPhoneId(), is3gpp2(), smsSource, result);
mPhone.getSmsStats().onIncomingSmsError(is3gpp2(), smsSource, result,
- TelephonyManager.from(mContext)
- .isEmergencyNumber(smsb.getOriginatingAddress()));
+ isEmergencyNumber(smsb.getOriginatingAddress()));
if (mPhone != null) {
TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
if (telephonyAnalytics != null) {
@@ -1034,7 +1050,7 @@
logeWithLocalLog(errorMsg, tracker.getMessageId());
mPhone.getSmsStats().onIncomingSmsError(
is3gpp2(), tracker.getSource(), RESULT_SMS_NULL_PDU,
- TelephonyManager.from(mContext).isEmergencyNumber(tracker.getAddress()));
+ isEmergencyNumber(tracker.getAddress()));
if (mPhone != null) {
TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
if (telephonyAnalytics != null) {
@@ -1064,8 +1080,7 @@
tracker.getMessageId());
mPhone.getSmsStats().onIncomingSmsWapPush(tracker.getSource(),
messageCount, RESULT_SMS_NULL_MESSAGE, tracker.getMessageId(),
- TelephonyManager.from(mContext)
- .isEmergencyNumber(tracker.getAddress()));
+ isEmergencyNumber(tracker.getAddress()));
return false;
}
}
@@ -1100,8 +1115,7 @@
mMetrics.writeIncomingWapPush(mPhone.getPhoneId(), tracker.getSource(),
format, timestamps, wapPushResult, tracker.getMessageId());
mPhone.getSmsStats().onIncomingSmsWapPush(tracker.getSource(), messageCount,
- result, tracker.getMessageId(), TelephonyManager.from(mContext)
- .isEmergencyNumber(tracker.getAddress()));
+ result, tracker.getMessageId(), isEmergencyNumber(tracker.getAddress()));
// result is Activity.RESULT_OK if an ordered broadcast was sent
if (result == Activity.RESULT_OK) {
return true;
@@ -1122,7 +1136,7 @@
format, timestamps, block, tracker.getMessageId());
mPhone.getSmsStats().onIncomingSmsSuccess(is3gpp2(), tracker.getSource(),
messageCount, block, tracker.getMessageId(),
- TelephonyManager.from(mContext).isEmergencyNumber(tracker.getAddress()));
+ isEmergencyNumber(tracker.getAddress()));
CarrierRoamingSatelliteSessionStats sessionStats =
CarrierRoamingSatelliteSessionStats.getInstance(mPhone.getSubId());
sessionStats.onIncomingSms(mPhone.getSubId());
@@ -1160,6 +1174,13 @@
return true;
}
+ private boolean isEmergencyNumber(String number) {
+ if (!mPhone.hasCalling()) return false;
+ TelephonyManager manager = TelephonyManager.from(mContext);
+ if (manager == null) return false;
+ return manager.isEmergencyNumber(number);
+ }
+
/**
* Processes the message part while the credential-encrypted storage is still locked.
*
@@ -1970,6 +1991,17 @@
sendMessage(EVENT_BROADCAST_COMPLETE);
}
+ private boolean isMtSmsPollingMessage(@NonNull SmsMessageBase smsb) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()
+ || !mContext.getResources().getBoolean(R.bool.config_enabled_mt_sms_polling)) {
+ return false;
+ }
+ String mtSmsPollingText = mContext.getResources()
+ .getString(R.string.config_mt_sms_polling_text);
+ return !TextUtils.isEmpty(mtSmsPollingText)
+ && mtSmsPollingText.equals(smsb.getMessageBody());
+ }
+
/** Checks whether the flag to skip new message notification is set in the bitmask returned
* from the carrier app.
*/
diff --git a/src/java/com/android/internal/telephony/MultiSimSettingController.java b/src/java/com/android/internal/telephony/MultiSimSettingController.java
index 3c35f1a..881adde 100644
--- a/src/java/com/android/internal/telephony/MultiSimSettingController.java
+++ b/src/java/com/android/internal/telephony/MultiSimSettingController.java
@@ -513,8 +513,8 @@
SatelliteController satelliteController = SatelliteController.getInstance();
boolean isSatelliteEnabledOrBeingEnabled = false;
if (satelliteController != null) {
- isSatelliteEnabledOrBeingEnabled = satelliteController.isSatelliteEnabled()
- || satelliteController.isSatelliteBeingEnabled();
+ isSatelliteEnabledOrBeingEnabled =
+ satelliteController.isSatelliteEnabledOrBeingEnabled();
}
if (DBG) {
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index 6a331cf..081a5c8 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -170,7 +170,6 @@
@Override
public void onQosSessionsChanged(
@NonNull List<QosBearerSession> qosBearerSessions) {
- if (!mIsTimerResetEnabledOnVoiceQos) return;
sendMessage(obtainMessage(EVENT_QOS_SESSION_CHANGED, qosBearerSessions));
}
@@ -233,6 +232,8 @@
private int mLastAnchorNrCellId = PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN;
private boolean mDoesPccListIndicateIdle = false;
+ private boolean mInVoiceCall = false;
+
/**
* NetworkTypeController constructor.
*
@@ -714,21 +715,22 @@
break;
case EVENT_QOS_SESSION_CHANGED:
List<QosBearerSession> qosBearerSessions = (List<QosBearerSession>) msg.obj;
- boolean inVoiceCall = false;
+ mInVoiceCall = false;
for (QosBearerSession session : qosBearerSessions) {
// TS 23.203 23.501 - 1 means conversational voice
- if (session.getQos() instanceof EpsQos qos) {
- inVoiceCall = qos.getQci() == 1;
- } else if (session.getQos() instanceof NrQos qos) {
- inVoiceCall = qos.get5Qi() == 1;
- }
- if (inVoiceCall) {
- if (DBG) log("Device in voice call, reset all timers");
- resetAllTimers();
- transitionToCurrentState();
+ if (session.getQos() instanceof EpsQos qos && qos.getQci() == 1) {
+ mInVoiceCall = true;
+ break;
+ } else if (session.getQos() instanceof NrQos qos && qos.get5Qi() == 1) {
+ mInVoiceCall = true;
break;
}
}
+ if (mIsTimerResetEnabledOnVoiceQos && mInVoiceCall) {
+ if (DBG) log("Device in voice call, reset all timers");
+ resetAllTimers();
+ transitionToCurrentState();
+ }
break;
default:
throw new RuntimeException("Received invalid event: " + msg.what);
@@ -1371,6 +1373,8 @@
if (mIsPrimaryTimerActive) {
log("Transition without timer from " + getCurrentState().getName() + " to " + destName
+ " due to existing " + mPrimaryTimerState + " primary timer.");
+ } else if (mIsTimerResetEnabledOnVoiceQos && mInVoiceCall) {
+ log("Skip primary timer to " + destName + " due to in call");
} else {
if (DBG) {
log("Transition with primary timer from " + mPreviousState + " to " + destName);
@@ -1395,7 +1399,10 @@
log("Transition with secondary timer from " + currentName + " to "
+ destState.getName());
}
- if (!mIsDeviceIdleMode && rule != null && rule.getSecondaryTimer(currentName) > 0) {
+ if (mIsTimerResetEnabledOnVoiceQos && mInVoiceCall) {
+ log("Skip secondary timer from " + currentName + " to "
+ + destState.getName() + " due to in call");
+ } else if (!mIsDeviceIdleMode && rule != null && rule.getSecondaryTimer(currentName) > 0) {
int duration = rule.getSecondaryTimer(currentName);
if (mLastShownNrDueToAdvancedBand && mNrAdvancedBandsSecondaryTimer > 0) {
duration = mNrAdvancedBandsSecondaryTimer;
@@ -1754,6 +1761,7 @@
pw.println("mPrimaryCellChangedWhileIdle=" + mPrimaryCellChangedWhileIdle);
pw.println("mEnableNrAdvancedWhileRoaming=" + mEnableNrAdvancedWhileRoaming);
pw.println("mIsDeviceIdleMode=" + mIsDeviceIdleMode);
+ pw.println("mIsTimerResetEnabledOnVoiceQos=" + mIsTimerResetEnabledOnVoiceQos);
pw.decreaseIndent();
pw.flush();
}
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index 69b19aa..ab9be76 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -74,6 +74,7 @@
import android.telephony.ims.RegistrationManager;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.telephony.satellite.NtnSignalStrength;
import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Log;
@@ -126,6 +127,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -659,7 +661,7 @@
mSmsStorageMonitor = mTelephonyComponentFactory.inject(SmsStorageMonitor.class.getName())
.makeSmsStorageMonitor(this, mFeatureFlags);
mSmsUsageMonitor = mTelephonyComponentFactory.inject(SmsUsageMonitor.class.getName())
- .makeSmsUsageMonitor(context);
+ .makeSmsUsageMonitor(context, mFeatureFlags);
mUiccController = UiccController.getInstance();
mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
mSimActivationTracker = mTelephonyComponentFactory
@@ -1965,6 +1967,13 @@
}
/**
+ * @return true if this device supports calling, false otherwise.
+ */
+ public boolean hasCalling() {
+ return TelephonyCapabilities.supportsTelephonyCalling(mFeatureFlags, mContext);
+ }
+
+ /**
* Retrieves the EmergencyNumberTracker of the phone instance.
*/
public EmergencyNumberTracker getEmergencyNumberTracker() {
@@ -5295,22 +5304,43 @@
}
/**
- * Start callback mode
+ * Start the emergency callback mode
* @param type for callback mode entry.
+ * @param durationMillis is the number of milliseconds remaining in the emergency callback
+ * mode.
*/
- public void startCallbackMode(@TelephonyManager.EmergencyCallbackModeType int type) {
- Rlog.d(mLogTag, "startCallbackMode:type=" + type);
- mNotifier.notifyCallbackModeStarted(this, type);
+ public void startEmergencyCallbackMode(@TelephonyManager.EmergencyCallbackModeType int type,
+ long durationMillis) {
+ if (!mFeatureFlags.emergencyCallbackModeNotification()) return;
+
+ Rlog.d(mLogTag, "startEmergencyCallbackMode:type=" + type);
+ mNotifier.notifyCallbackModeStarted(this, type, durationMillis);
}
/**
- * Stop callback mode
+ * Restart the emergency callback mode
+ * @param type for callback mode entry.
+ * @param durationMillis is the number of milliseconds remaining in the emergency callback
+ * mode.
+ */
+ public void restartEmergencyCallbackMode(@TelephonyManager.EmergencyCallbackModeType int type,
+ long durationMillis) {
+ if (!mFeatureFlags.emergencyCallbackModeNotification()) return;
+
+ Rlog.d(mLogTag, "restartEmergencyCallbackMode:type=" + type);
+ mNotifier.notifyCallbackModeRestarted(this, type, durationMillis);
+ }
+
+ /**
+ * Stop the emergency callback mode
* @param type for callback mode exit.
* @param reason for stopping callback mode.
*/
- public void stopCallbackMode(@TelephonyManager.EmergencyCallbackModeType int type,
+ public void stopEmergencyCallbackMode(@TelephonyManager.EmergencyCallbackModeType int type,
@TelephonyManager.EmergencyCallbackModeStopReason int reason) {
- Rlog.d(mLogTag, "stopCallbackMode:type=" + type + ", reason=" + reason);
+ if (!mFeatureFlags.emergencyCallbackModeNotification()) return;
+
+ Rlog.d(mLogTag, "stopEmergencyCallbackMode:type=" + type + ", reason=" + reason);
mNotifier.notifyCallbackModeStopped(this, type, reason);
}
@@ -5347,6 +5377,29 @@
mNotifier.notifyCarrierRoamingNtnEligibleStateChanged(this, eligible);
}
+ /**
+ * Notify external listeners that carrier roaming non-terrestrial available services changed.
+ * @param availableServices The list of the supported services.
+ */
+ public void notifyCarrierRoamingNtnAvailableServicesChanged(
+ @NetworkRegistrationInfo.ServiceType int[] availableServices) {
+ logd("notifyCarrierRoamingNtnAvailableServicesChanged availableServices:"
+ + Arrays.toString(availableServices));
+ mNotifier.notifyCarrierRoamingNtnAvailableServicesChanged(this, availableServices);
+ }
+
+ /**
+ * Notify external listeners that carrier roaming non-terrestrial network
+ * signal strength changed.
+ * @param ntnSignalStrength non-terrestrial network signal strength.
+ */
+ public void notifyCarrierRoamingNtnSignalStrengthChanged(
+ @NonNull NtnSignalStrength ntnSignalStrength) {
+ logd("notifyCarrierRoamingNtnSignalStrengthChanged: ntnSignalStrength="
+ + ntnSignalStrength.getLevel());
+ mNotifier.notifyCarrierRoamingNtnSignalStrengthChanged(this, ntnSignalStrength);
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("Phone: subId=" + getSubId());
pw.println(" mPhoneId=" + mPhoneId);
diff --git a/src/java/com/android/internal/telephony/PhoneNotifier.java b/src/java/com/android/internal/telephony/PhoneNotifier.java
index 3f388fb..faf4fd1 100644
--- a/src/java/com/android/internal/telephony/PhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/PhoneNotifier.java
@@ -26,6 +26,7 @@
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.LinkCapacityEstimate;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneCapability;
import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseDataConnectionState;
@@ -37,6 +38,7 @@
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.MediaQualityStatus;
+import android.telephony.satellite.NtnSignalStrength;
import java.util.List;
import java.util.Set;
@@ -145,7 +147,12 @@
List<LinkCapacityEstimate> linkCapacityEstimateList);
/** Notify callback mode started. */
- void notifyCallbackModeStarted(Phone sender, @EmergencyCallbackModeType int type);
+ void notifyCallbackModeStarted(Phone sender, @EmergencyCallbackModeType int type,
+ long durationMillis);
+
+ /** Notify callback mode restarted. */
+ void notifyCallbackModeRestarted(Phone sender, @EmergencyCallbackModeType int type,
+ long durationMillis);
/** Notify callback mode stopped. */
void notifyCallbackModeStopped(Phone sender, @EmergencyCallbackModeType int type,
@@ -159,4 +166,12 @@
/** Notify eligibility to connect to carrier roaming non-terrestrial network changed. */
void notifyCarrierRoamingNtnEligibleStateChanged(Phone sender, boolean eligible);
+
+ /** Notify carrier roaming non-terrestrial available services changed. */
+ void notifyCarrierRoamingNtnAvailableServicesChanged(
+ Phone sender, @NetworkRegistrationInfo.ServiceType int[] availableServices);
+
+ /** Notify carrier roaming non-terrestrial network signal strength changed. */
+ void notifyCarrierRoamingNtnSignalStrengthChanged(Phone sender,
+ @NonNull NtnSignalStrength ntnSignalStrength);
}
diff --git a/src/java/com/android/internal/telephony/PhoneSubInfoController.java b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
index 7ee3de2..c40193e 100644
--- a/src/java/com/android/internal/telephony/PhoneSubInfoController.java
+++ b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
@@ -53,7 +53,9 @@
import com.android.telephony.Rlog;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.stream.Collectors;
public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
private static final String TAG = "PhoneSubInfoController";
@@ -477,39 +479,37 @@
*
* @param subId subscriptionId
* @param callingPackage package name of the caller
- * @param callingFeatureId feature Id of the caller
* @return List of public user identities of type android.net.Uri or empty list if
* EF_IMPU is not available.
* @throws IllegalArgumentException if the subscriptionId is not valid
* @throws IllegalStateException in case the ISIM hasn’t been loaded.
* @throws SecurityException if the caller does not have the required permission
*/
- public List<Uri> getImsPublicUserIdentities(int subId, String callingPackage,
- String callingFeatureId) {
- if (TelephonyPermissions.
- checkCallingOrSelfReadPrivilegedPhoneStatePermissionOrReadPhoneNumber(
- mContext, subId, callingPackage, callingFeatureId, "getImsPublicUserIdentities")) {
-
- enforceTelephonyFeatureWithException(callingPackage,
- PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getImsPublicUserIdentities");
-
- Phone phone = getPhone(subId);
- assert phone != null;
- IsimRecords isimRecords = phone.getIsimRecords();
- if (isimRecords != null) {
- String[] impus = isimRecords.getIsimImpu();
- List<Uri> impuList = new ArrayList<>();
- for (String impu : impus) {
- if (impu != null && impu.trim().length() > 0) {
- impuList.add(Uri.parse(impu));
- }
- }
- return impuList;
- }
- throw new IllegalStateException("ISIM is not loaded");
- } else {
- throw new IllegalArgumentException("Invalid SubscriptionID = " + subId);
+ public List<Uri> getImsPublicUserIdentities(int subId, String callingPackage) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ throw new IllegalArgumentException("Invalid subscription: " + subId);
}
+
+ TelephonyPermissions
+ .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ mContext, subId, "getImsPublicUserIdentities");
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getImsPublicUserIdentities");
+
+ Phone phone = getPhone(subId);
+ assert phone != null;
+ IsimRecords isimRecords = phone.getIsimRecords();
+ if (isimRecords != null) {
+ String[] impus = isimRecords.getIsimImpu();
+ List<Uri> impuList = new ArrayList<>();
+ for (String impu : impus) {
+ if (impu != null && impu.trim().length() > 0) {
+ impuList.add(Uri.parse(impu));
+ }
+ }
+ return impuList;
+ }
+ throw new IllegalStateException("ISIM is not loaded");
}
/**
@@ -546,6 +546,45 @@
}
/**
+ * Fetches the IMS Proxy Call Session Control Function(P-CSCF) based on the subscription.
+ *
+ * @param subId subscriptionId
+ * @param callingPackage package name of the caller
+ * @return List of IMS Proxy Call Session Control Function strings.
+ * @throws IllegalArgumentException if the subscriptionId is not valid
+ * @throws IllegalStateException in case the ISIM hasn’t been loaded.
+ * @throws SecurityException if the caller does not have the required permission
+ */
+ public List<String> getImsPcscfAddresses(int subId, String callingPackage) {
+ if (!mFeatureFlags.supportIsimRecord()) {
+ return new ArrayList<>();
+ }
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ throw new IllegalArgumentException("Invalid subscription: " + subId);
+ }
+
+ TelephonyPermissions
+ .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ mContext, subId, "getImsPcscfAddresses");
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getImsPcscfAddresses");
+
+ Phone phone = getPhone(subId);
+ assert phone != null;
+ IsimRecords isimRecords = phone.getIsimRecords();
+ if (isimRecords != null) {
+ String[] pcscfs = isimRecords.getIsimPcscf();
+ List<String> pcscfList = Arrays.stream(pcscfs)
+ .filter(u -> u != null)
+ .map(u -> u.trim())
+ .filter(u -> u.length() > 0)
+ .collect(Collectors.toList());
+ return pcscfList;
+ }
+ throw new IllegalStateException("ISIM is not loaded");
+ }
+
+ /**
* Returns the USIM service table that fetched from EFUST elementary field that are loaded
* based on the appType.
*/
diff --git a/src/java/com/android/internal/telephony/RILUtils.java b/src/java/com/android/internal/telephony/RILUtils.java
index a81dbc8..cbf2330 100644
--- a/src/java/com/android/internal/telephony/RILUtils.java
+++ b/src/java/com/android/internal/telephony/RILUtils.java
@@ -4132,6 +4132,34 @@
}
/**
+ * This API is for fallback to support getAllowedCarriers too.
+ *
+ * Convert an array of CarrierInfo defined in
+ * radio/aidl/android/hardware/radio/sim/CarrierInfo.aidl to a list of CarrierIdentifiers.
+ *
+ * @param carrierInfos array of CarrierInfo defined in
+ * radio/aidl/android/hardware/radio/sim/CarrierInfo.aidl
+ * @return The converted list of CarrierIdentifiers
+ */
+ public static List<CarrierIdentifier> convertAidlCarrierInfoListToHalCarrierList(
+ android.hardware.radio.sim.CarrierInfo[] carrierInfos) {
+ List<CarrierIdentifier> ret = new ArrayList<>();
+ if (carrierInfos == null) {
+ return ret;
+ }
+ for (android.hardware.radio.sim.CarrierInfo carrierInfo : carrierInfos) {
+ String mcc = carrierInfo.mcc;
+ String mnc = carrierInfo.mnc;
+ String spn = carrierInfo.spn;
+ String imsi = carrierInfo.imsiPrefix;
+ String gid1 = carrierInfo.gid1;
+ String gid2 = carrierInfo.gid2;
+ ret.add(new CarrierIdentifier(mcc, mnc, spn, imsi, gid1, gid2));
+ }
+ return ret;
+ }
+
+ /**
* Convert the sim policy defined in
* radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl to the equivalent sim
* policy defined in android.telephony/CarrierRestrictionRules.MultiSimPolicy
diff --git a/src/java/com/android/internal/telephony/SMSDispatcher.java b/src/java/com/android/internal/telephony/SMSDispatcher.java
index 2f2b62a..871cabc 100644
--- a/src/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/SMSDispatcher.java
@@ -20,6 +20,7 @@
import static com.android.internal.telephony.IccSmsInterfaceManager.SMS_MESSAGE_PERIOD_NOT_SPECIFIED;
import static com.android.internal.telephony.IccSmsInterfaceManager.SMS_MESSAGE_PRIORITY_NOT_SPECIFIED;
+import static com.android.internal.telephony.SmsDispatchersController.PendingRequest;
import static com.android.internal.telephony.SmsResponse.NO_ERROR_CODE;
import android.annotation.UserIdInt;
@@ -1016,8 +1017,8 @@
*/
protected void notifySmsSentFailedToEmergencyStateTracker(SmsTracker tracker,
boolean isOverIms) {
- mSmsDispatchersController.notifySmsSent(tracker.mDestAddress, tracker.mMessageId,
- isOverIms, true /*isLastSmsPart*/, false /*success*/);
+ mSmsDispatchersController.notifySmsSent(tracker, isOverIms,
+ true /*isLastSmsPart*/, false /*success*/);
}
/**
@@ -1052,9 +1053,8 @@
}
tracker.onSent(mContext);
mPhone.notifySmsSent(tracker.mDestAddress);
- mSmsDispatchersController.notifySmsSent(
- tracker.mDestAddress, tracker.mMessageId, false,
- tracker.isSinglePartOrLastPart(), true /*success*/);
+ mSmsDispatchersController.notifySmsSent(tracker, false,
+ tracker.isSinglePartOrLastPart(), true /*success*/);
mPhone.getSmsStats().onOutgoingSms(
tracker.mImsRetry > 0 /* isOverIms */,
@@ -1399,7 +1399,7 @@
@UnsupportedAppUsage
protected void sendData(String callingPackage, int callingUser, String destAddr, String scAddr,
int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent,
- boolean isForVvm) {
+ boolean isForVvm, long uniqueMessageId) {
int messageRef = nextMessageRef();
SmsMessageBase.SubmitPduBase pdu = getSubmitPdu(
scAddr, destAddr, destPort, data, (deliveryIntent != null), messageRef);
@@ -1408,7 +1408,8 @@
SmsTracker tracker = getSmsTracker(callingPackage, callingUser, map, sentIntent,
deliveryIntent, getFormat(), null /*messageUri*/, false /*expectMore*/,
null /*fullMessageText*/, false /*isText*/,
- true /*persistMessage*/, isForVvm, 0L /* messageId */, messageRef);
+ true /*persistMessage*/, isForVvm, 0L /* messageId */, messageRef,
+ uniqueMessageId);
if (!sendSmsByCarrierApp(true /* isDataSms */, tracker)) {
sendSubmitPdu(tracker);
@@ -1526,7 +1527,7 @@
long messageId) {
sendText(destAddr, scAddr, text, sentIntent, deliveryIntent, messageUri, callingPkg,
callingUser, persistMessage, priority, expectMore, validityPeriod, isForVvm,
- messageId, false);
+ messageId, false, PendingRequest.getNextUniqueMessageId());
}
/**
@@ -1634,7 +1635,7 @@
PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri,
String callingPkg, int callingUser, boolean persistMessage, int priority,
boolean expectMore, int validityPeriod, boolean isForVvm,
- long messageId, boolean skipShortCodeCheck) {
+ long messageId, boolean skipShortCodeCheck, long uniqueMessageId) {
Rlog.d(TAG, "sendText id: " + SmsController.formatCrossStackMessageId(messageId));
int messageRef = nextMessageRef();
SmsMessageBase.SubmitPduBase pdu = getSubmitPdu(
@@ -1645,7 +1646,7 @@
SmsTracker tracker = getSmsTracker(callingPkg, callingUser, map, sentIntent,
deliveryIntent, getFormat(), messageUri, expectMore, text, true /*isText*/,
persistMessage, priority, validityPeriod, isForVvm, messageId, messageRef,
- skipShortCodeCheck);
+ skipShortCodeCheck, uniqueMessageId);
if (!sendSmsByCarrierApp(false /* isDataSms */, tracker)) {
sendSubmitPdu(tracker);
@@ -1827,7 +1828,7 @@
ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg,
int callingUser, boolean persistMessage, int priority, boolean expectMore,
- int validityPeriod, long messageId) {
+ int validityPeriod, long messageId, long uniqueMessageId) {
final String fullMessageText = getMultipartMessageText(parts);
int refNumber = getNextConcatenatedRef() & 0x00FF;
int encoding = SmsConstants.ENCODING_UNKNOWN;
@@ -1890,7 +1891,7 @@
smsHeader, encoding, sentIntent, deliveryIntent, (i == (msgCount - 1)),
unsentPartCount, anyPartFailed, messageUri,
fullMessageText, priority, expectMore, validityPeriod, messageId,
- messageRef);
+ messageRef, uniqueMessageId);
if (trackers[i] == null) {
triggerSentIntentForFailure(sentIntents);
return;
@@ -1926,7 +1927,7 @@
int encoding, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart,
AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
String fullMessageText, int priority, boolean expectMore, int validityPeriod,
- long messageId, int messageRef) {
+ long messageId, int messageRef, long uniqueMessageId) {
if (isCdmaMo()) {
UserData uData = new UserData();
uData.payloadStr = message;
@@ -1956,7 +1957,7 @@
deliveryIntent, getFormat(), unsentPartCount, anyPartFailed, messageUri,
smsHeader, (!lastPart || expectMore), fullMessageText, /*isText*/
true, /*persistMessage*/ true, priority, validityPeriod, /* isForVvm */
- false, messageId, messageRef, false);
+ false, messageId, messageRef, false, uniqueMessageId);
} else {
Rlog.e(TAG, "CdmaSMSDispatcher.getNewSubmitPduTracker(): getSubmitPdu() returned "
+ "null " + SmsController.formatCrossStackMessageId(messageId));
@@ -1975,7 +1976,7 @@
messageUri, smsHeader, (!lastPart || expectMore),
fullMessageText, /*isText*/
true, /*persistMessage*/ false, priority, validityPeriod, /* isForVvm */
- false, messageId, messageRef, false);
+ false, messageId, messageRef, false, uniqueMessageId);
} else {
Rlog.e(TAG, "GsmSMSDispatcher.getNewSubmitPduTracker(): getSubmitPdu() returned "
+ "null " + SmsController.formatCrossStackMessageId(messageId));
@@ -2119,7 +2120,7 @@
}
}
- if (mTelephonyManager.isEmergencyNumber(trackers[0].mDestAddress)) {
+ if (mPhone.hasCalling() && mTelephonyManager.isEmergencyNumber(trackers[0].mDestAddress)) {
new AsyncEmergencyContactNotifier(mContext).execute();
}
}
@@ -2492,6 +2493,7 @@
private int mCarrierId;
private boolean mSkipShortCodeDestAddrCheck;
+ public final long mUniqueMessageId;
// SMS anomaly uuid -- unexpected error from RIL
private final UUID mAnomalyUnexpectedErrorFromRilUUID =
UUID.fromString("43043600-ea7a-44d2-9ae6-a58567ac7886");
@@ -2502,7 +2504,8 @@
SmsHeader smsHeader, boolean expectMore, String fullMessageText, int subId,
boolean isText, boolean persistMessage, int userId, int priority,
int validityPeriod, boolean isForVvm, long messageId, int carrierId,
- int messageRef, boolean skipShortCodeDestAddrCheck) {
+ int messageRef, boolean skipShortCodeDestAddrCheck,
+ long uniqueMessageId) {
mData = data;
mSentIntent = sentIntent;
mDeliveryIntent = deliveryIntent;
@@ -2529,6 +2532,26 @@
mMessageId = messageId;
mCarrierId = carrierId;
mSkipShortCodeDestAddrCheck = skipShortCodeDestAddrCheck;
+ mUniqueMessageId = uniqueMessageId;
+ }
+
+ @VisibleForTesting
+ public SmsTracker(String destAddr, long messageId) {
+ mData = null;
+ mSentIntent = null;
+ mDeliveryIntent = null;
+ mAppInfo = null;
+ mDestAddress = destAddr;
+ mUsesImsServiceForIms = false;
+ mSmsHeader = null;
+ mMessageId = messageId;
+ mUserId = 0;
+ mPriority = 0;
+ mValidityPeriod = 0;
+ mIsForVvm = false;
+ mCarrierId = 0;
+ mSkipShortCodeDestAddrCheck = false;
+ mUniqueMessageId = 0;
}
public HashMap<String, Object> getData() {
@@ -2820,7 +2843,8 @@
AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
SmsHeader smsHeader, boolean expectMore, String fullMessageText, boolean isText,
boolean persistMessage, int priority, int validityPeriod, boolean isForVvm,
- long messageId, int messageRef, boolean skipShortCodeCheck) {
+ long messageId, int messageRef, boolean skipShortCodeCheck,
+ long uniqueMessageId) {
if (!Flags.smsMmsDeliverBroadcastsRedirectToMainUser()) {
callingUser = UserHandle.getUserHandleForUid(Binder.getCallingUid()).getIdentifier();
}
@@ -2841,31 +2865,33 @@
unsentPartCount, anyPartFailed, messageUri, smsHeader, expectMore,
fullMessageText, getSubId(), isText, persistMessage, callingUser, priority,
validityPeriod, isForVvm, messageId, mPhone.getCarrierId(), messageRef,
- skipShortCodeCheck);
+ skipShortCodeCheck, uniqueMessageId);
}
protected SmsTracker getSmsTracker(String callingPackage, int callingUser,
HashMap<String, Object> data, PendingIntent sentIntent, PendingIntent deliveryIntent,
String format, Uri messageUri, boolean expectMore, String fullMessageText,
boolean isText, boolean persistMessage, boolean isForVvm,
- long messageId, int messageRef) {
+ long messageId, int messageRef, long uniqueMessageId) {
return getSmsTracker(callingPackage, callingUser , data, sentIntent, deliveryIntent,
format, /*unsentPartCount*/ null, /*anyPartFailed*/ null, messageUri, /*smsHeader*/
null, expectMore, fullMessageText, isText,
persistMessage, SMS_MESSAGE_PRIORITY_NOT_SPECIFIED,
SMS_MESSAGE_PERIOD_NOT_SPECIFIED,
- isForVvm, messageId, messageRef, false);
+ isForVvm, messageId, messageRef, false, uniqueMessageId);
}
protected SmsTracker getSmsTracker(String callingPackage, int callingUser,
HashMap<String, Object> data, PendingIntent sentIntent, PendingIntent deliveryIntent,
String format, Uri messageUri, boolean expectMore, String fullMessageText,
boolean isText, boolean persistMessage, int priority, int validityPeriod,
- boolean isForVvm, long messageId, int messageRef, boolean skipShortCodeCheck) {
+ boolean isForVvm, long messageId, int messageRef, boolean skipShortCodeCheck,
+ long uniqueMessageId) {
return getSmsTracker(callingPackage, callingUser, data, sentIntent, deliveryIntent,
format, /*unsentPartCount*/ null, /*anyPartFailed*/ null, messageUri, /*smsHeader*/
null, expectMore, fullMessageText, isText, persistMessage, priority,
- validityPeriod, isForVvm, messageId, messageRef, skipShortCodeCheck);
+ validityPeriod, isForVvm, messageId, messageRef, skipShortCodeCheck,
+ uniqueMessageId);
}
protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr,
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index e7500a2..3309d21 100644
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -327,18 +327,10 @@
private boolean mImsRegistrationOnOff = false;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private boolean mDeviceShuttingDown = false;
+ private CarrierDisplayNameData mCarrierDisplayNameData =
+ new CarrierDisplayNameData.Builder().build();
/** Keep track of SPN display rules, so we only broadcast intent if something changes. */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private String mCurSpn = null;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private String mCurDataSpn = null;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private String mCurPlmn = null;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private boolean mCurShowPlmn = false;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private boolean mCurShowSpn = false;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@VisibleForTesting
public int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private int mPrevSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -452,7 +444,7 @@
// Once sub id becomes valid, we need to update the service provider name
// displayed on the UI again. The old SPN update intents sent to
// MobileSignalController earlier were actually ignored due to invalid sub id.
- updateSpnDisplay();
+ updateCarrierDisplayName();
}
mSubId = curSubId;
}
@@ -559,12 +551,12 @@
pollState();
// Depends on modem, ServiceState is not necessarily updated, so make sure updating
// SPN.
- updateSpnDisplay();
+ updateCarrierDisplayName();
} else if (action.equals(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED)) {
String lastKnownNetworkCountry = intent.getStringExtra(
TelephonyManager.EXTRA_LAST_KNOWN_NETWORK_COUNTRY);
if (!mLastKnownNetworkCountry.equals(lastKnownNetworkCountry)) {
- updateSpnDisplay();
+ updateCarrierDisplayName();
}
}
}
@@ -1245,7 +1237,7 @@
if (mUiccApplication == null
|| mUiccApplication.getState() != AppState.APPSTATE_READY) {
mIsSimReady = false;
- updateSpnDisplay();
+ updateCarrierDisplayName();
}
break;
@@ -1424,7 +1416,7 @@
updateOtaspState();
if (mPhone.isPhoneTypeGsm()) {
mCdnr.updateEfFromUsim((SIMRecords) mIccRecords);
- updateSpnDisplay();
+ updateCarrierDisplayName();
}
break;
@@ -1531,7 +1523,7 @@
case EVENT_IMS_CAPABILITY_CHANGED:
if (DBG) log("EVENT_IMS_CAPABILITY_CHANGED");
- updateSpnDisplay();
+ updateCarrierDisplayName();
mImsCapabilityChangedRegistrants.notifyRegistrants();
break;
@@ -1623,7 +1615,7 @@
mCdnr.updateEfFromRuim((RuimRecords) mIccRecords);
updatePhoneObject();
if (mPhone.isPhoneTypeCdma()) {
- updateSpnDisplay();
+ updateCarrierDisplayName();
} else {
RuimRecords ruim = (RuimRecords) mIccRecords;
if (ruim != null) {
@@ -2761,53 +2753,34 @@
}
}
- private void notifySpnDisplayUpdate(CarrierDisplayNameData data) {
- int subId = mPhone.getSubId();
- // Update ACTION_SERVICE_PROVIDERS_UPDATED if any value changes
- if (mSubId != subId
- || data.shouldShowPlmn() != mCurShowPlmn
- || data.shouldShowSpn() != mCurShowSpn
- || !TextUtils.equals(data.getSpn(), mCurSpn)
- || !TextUtils.equals(data.getDataSpn(), mCurDataSpn)
- || !TextUtils.equals(data.getPlmn(), mCurPlmn)) {
+ private void notifyCarrierDisplayNameDataChanged() {
+ final String log = String.format("notifyCarrierDisplayNameDataChanged: "
+ + "changed sending intent, "
+ + "rule=%d, CarrierDisplayNameData=%s, subId=%d",
+ getCarrierNameDisplayBitmask(mSS),
+ mCarrierDisplayNameData,
+ mPhone.getSubId());
+ mCdnrLogs.log(log);
+ if (DBG) log(log);
- final String log = String.format("updateSpnDisplay: changed sending intent, "
- + "rule=%d, showPlmn='%b', plmn='%s', showSpn='%b', spn='%s', "
- + "dataSpn='%s', subId='%d'",
- getCarrierNameDisplayBitmask(mSS),
- data.shouldShowPlmn(),
- data.getPlmn(),
- data.shouldShowSpn(),
- data.getSpn(),
- data.getDataSpn(),
- subId);
- mCdnrLogs.log(log);
- if (DBG) log("updateSpnDisplay: " + log);
- Intent intent = new Intent(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED);
- intent.putExtra(TelephonyManager.EXTRA_SHOW_SPN, data.shouldShowSpn());
- intent.putExtra(TelephonyManager.EXTRA_SPN, data.getSpn());
- intent.putExtra(TelephonyManager.EXTRA_DATA_SPN, data.getDataSpn());
- intent.putExtra(TelephonyManager.EXTRA_SHOW_PLMN, data.shouldShowPlmn());
- intent.putExtra(TelephonyManager.EXTRA_PLMN, data.getPlmn());
- SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
- mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);
-
- if (SubscriptionManager.isValidSubscriptionId(subId)) {
- mSubscriptionManagerService.setCarrierName(subId, TextUtils.emptyIfNull(
- getCarrierName(data.shouldShowPlmn(), data.getPlmn(),
- data.shouldShowSpn(), data.getSpn())));
- }
- }
- mCurShowSpn = data.shouldShowSpn();
- mCurShowPlmn = data.shouldShowPlmn();
- mCurSpn = data.getSpn();
- mCurDataSpn = data.getDataSpn();
- mCurPlmn = data.getPlmn();
+ Intent intent = new Intent(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED);
+ intent.putExtra(TelephonyManager.EXTRA_SHOW_SPN, mCarrierDisplayNameData.shouldShowSpn());
+ intent.putExtra(TelephonyManager.EXTRA_SPN, mCarrierDisplayNameData.getSpn());
+ intent.putExtra(TelephonyManager.EXTRA_DATA_SPN, mCarrierDisplayNameData.getDataSpn());
+ intent.putExtra(TelephonyManager.EXTRA_SHOW_PLMN, mCarrierDisplayNameData.shouldShowPlmn());
+ intent.putExtra(TelephonyManager.EXTRA_PLMN, mCarrierDisplayNameData.getPlmn());
+ SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
+ mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
@NonNull
- private String getCarrierName(boolean showPlmn, String plmn, boolean showSpn, String spn) {
+ private String getCarrierName(CarrierDisplayNameData cdnd) {
+ boolean showPlmn = cdnd.shouldShowPlmn();
+ boolean showSpn = cdnd.shouldShowSpn();
+ String plmn = cdnd.getPlmn();
+ String spn = cdnd.getSpn();
+
String carrierName = "";
if (showPlmn) {
carrierName = plmn;
@@ -2825,29 +2798,34 @@
} else if (showSpn) {
carrierName = spn;
}
- return carrierName;
+ return TextUtils.emptyIfNull(carrierName);
}
- private void updateSpnDisplayCdnr() {
- log("updateSpnDisplayCdnr+");
- CarrierDisplayNameData data = mCdnr.getCarrierDisplayNameData();
- notifySpnDisplayUpdate(data);
- log("updateSpnDisplayCdnr-");
- }
-
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@VisibleForTesting
- public void updateSpnDisplay() {
- if (mCarrierConfig.getBoolean(
- CarrierConfigManager.KEY_ENABLE_CARRIER_DISPLAY_NAME_RESOLVER_BOOL)) {
- updateSpnDisplayCdnr();
- } else {
- updateSpnDisplayLegacy();
+ public void updateCarrierDisplayName() {
+ final boolean useCdnr = mCarrierConfig.getBoolean(
+ CarrierConfigManager.KEY_ENABLE_CARRIER_DISPLAY_NAME_RESOLVER_BOOL);
+
+ final CarrierDisplayNameData cdnd = useCdnr
+ ? mCdnr.getCarrierDisplayNameData()
+ : getCarrierDisplayNameLegacy();
+
+ final int subId = mPhone.getSubId();
+
+ // Avoid sending unnecessary updates
+ if (subId == mSubId && cdnd.equals(mCarrierDisplayNameData)) return;
+
+ if (SubscriptionManager.isValidSubscriptionId(subId)) {
+ mSubscriptionManagerService.setCarrierName(subId, getCarrierName(cdnd));
}
+
+ mCarrierDisplayNameData = cdnd; // notify...() relies on the updated value
+ notifyCarrierDisplayNameDataChanged();
+
}
- private void updateSpnDisplayLegacy() {
- log("updateSpnDisplayLegacy+");
+ private @NonNull CarrierDisplayNameData getCarrierDisplayNameLegacy() {
+ log("getCarrierDisplayNameLegacy+");
String spn = null;
String dataSpn = null;
@@ -2888,11 +2866,12 @@
.getStringArray(com.android.internal.R.array.wfcSpnFormats);
if (voiceIdx < 0 || voiceIdx >= wfcSpnFormats.length) {
- loge("updateSpnDisplay: KEY_WFC_SPN_FORMAT_IDX_INT out of bounds: " + voiceIdx);
+ loge("updateCarrierDisplayName: KEY_WFC_SPN_FORMAT_IDX_INT out of bounds: "
+ + voiceIdx);
voiceIdx = 0;
}
if (dataIdx < 0 || dataIdx >= wfcSpnFormats.length) {
- loge("updateSpnDisplay: KEY_WFC_DATA_SPN_FORMAT_IDX_INT out of bounds: "
+ loge("updateCarrierDisplayName: KEY_WFC_DATA_SPN_FORMAT_IDX_INT out of bounds: "
+ dataIdx);
dataIdx = 0;
}
@@ -2926,7 +2905,7 @@
.getStringArray(R.array.crossSimSpnFormats);
if (crossSimSpnFormatIdx < 0 || crossSimSpnFormatIdx >= crossSimSpnFormats.length) {
- loge("updateSpnDisplay: KEY_CROSS_SIM_SPN_FORMAT_INT out of bounds: "
+ loge("updateCarrierDisplayName: KEY_CROSS_SIM_SPN_FORMAT_INT out of bounds: "
+ crossSimSpnFormatIdx);
crossSimSpnFormatIdx = 0;
}
@@ -2971,21 +2950,25 @@
.toString();
noService = true;
}
- if (DBG) log("updateSpnDisplay: radio is on but out " +
- "of service, set plmn='" + plmn + "'");
+ if (DBG) {
+ log("updateCarrierDisplayName: radio is on but out "
+ + "of service, set plmn='" + plmn + "'");
+ }
} else if (combinedRegState == ServiceState.STATE_IN_SERVICE) {
// In either home or roaming service
plmn = mSS.getOperatorAlpha();
showPlmn = !TextUtils.isEmpty(plmn) &&
((rule & CARRIER_NAME_DISPLAY_BITMASK_SHOW_PLMN)
== CARRIER_NAME_DISPLAY_BITMASK_SHOW_PLMN);
- if (DBG) log("updateSpnDisplay: rawPlmn = " + plmn);
+ if (DBG) log("updateCarrierDisplayName: rawPlmn = " + plmn);
} else {
// Power off state, such as airplane mode, show plmn as null
showPlmn = true;
plmn = null;
- if (DBG) log("updateSpnDisplay: radio is off w/ showPlmn="
- + showPlmn + " plmn=" + plmn);
+ if (DBG) {
+ log("updateCarrierDisplayName: radio is off w/ showPlmn="
+ + showPlmn + " plmn=" + plmn);
+ }
}
// The value of spn/showSpn are same in different scenarios.
@@ -2997,7 +2980,7 @@
showSpn = !noService && !TextUtils.isEmpty(spn)
&& ((rule & CARRIER_NAME_DISPLAY_BITMASK_SHOW_SPN)
== CARRIER_NAME_DISPLAY_BITMASK_SHOW_SPN);
- if (DBG) log("updateSpnDisplay: rawSpn = " + spn);
+ if (DBG) log("updateCarrierDisplayName: rawSpn = " + spn);
if (!TextUtils.isEmpty(crossSimSpnFormat)) {
if (!TextUtils.isEmpty(spn)) {
// Show SPN + Cross-SIM Calling If SIM has SPN and SPN display condition
@@ -3056,7 +3039,7 @@
// mOperatorAlpha contains the ERI text
plmn = mSS.getOperatorAlpha();
- if (DBG) log("updateSpnDisplay: cdma rawPlmn = " + plmn);
+ if (DBG) log("updateCarrierDisplayName: cdma rawPlmn = " + plmn);
showPlmn = plmn != null;
@@ -3068,8 +3051,8 @@
// todo: temporary hack; should have a better fix. This is to avoid using operator
// name from ServiceState (populated in processIwlanRegistrationInfo()) until
// wifi calling is actually enabled
- log("updateSpnDisplay: overwriting plmn from " + plmn + " to null as radio " +
- "state is off");
+ log("updateCarrierDisplayName: overwriting plmn from "
+ + plmn + " to null as radio " + "state is off");
plmn = null;
}
@@ -3077,20 +3060,21 @@
plmn = Resources.getSystem().getText(com.android.internal.R.string
.lockscreen_carrier_default).toString();
if (DBG) {
- log("updateSpnDisplay: radio is on but out of svc, set plmn='" + plmn + "'");
+ log("updateCarrierDisplayName: radio is on but out of svc, set plmn='"
+ + plmn + "'");
}
}
-
}
- notifySpnDisplayUpdate(new CarrierDisplayNameData.Builder()
+ log("getCarrierDisplayNameLegacy-");
+
+ return new CarrierDisplayNameData.Builder()
.setSpn(spn)
.setDataSpn(dataSpn)
.setShowSpn(showSpn)
.setPlmn(plmn)
.setShowPlmn(showPlmn)
- .build());
- log("updateSpnDisplayLegacy-");
+ .build();
}
/**
@@ -3299,7 +3283,7 @@
mImsRegistrationOnOff = registered;
// It's possible ServiceState changes did not trigger SPN display update; we update it here.
- updateSpnDisplay();
+ updateCarrierDisplayName();
}
public void onImsCapabilityChanged() {
@@ -3713,11 +3697,11 @@
String eriText = mPhone.getCdmaEriText();
boolean hasEriChanged = !TextUtils.equals(mEriText, eriText);
mEriText = eriText;
- // Trigger updateSpnDisplay when
+ // Trigger updateCarrierDisplayName when
// 1. Service state is changed.
// 2. phone type is Cdma or CdmaLte and ERI text has changed.
if (hasChanged || (!mPhone.isPhoneTypeGsm() && hasEriChanged)) {
- updateSpnDisplay();
+ updateCarrierDisplayName();
}
if (hasChanged) {
@@ -5279,11 +5263,7 @@
pw.println(" mStartedGprsRegCheck=" + mStartedGprsRegCheck);
pw.println(" mReportedGprsNoReg=" + mReportedGprsNoReg);
pw.println(" mNotification=" + mNotification);
- pw.println(" mCurSpn=" + mCurSpn);
- pw.println(" mCurDataSpn=" + mCurDataSpn);
- pw.println(" mCurShowSpn=" + mCurShowSpn);
- pw.println(" mCurPlmn=" + mCurPlmn);
- pw.println(" mCurShowPlmn=" + mCurShowPlmn);
+ pw.println(" mCarrierDisplayNameData=" + mCarrierDisplayNameData);
pw.flush();
pw.println(" mCurrentOtaspMode=" + mCurrentOtaspMode);
pw.println(" mRoamingIndicator=" + mRoamingIndicator);
diff --git a/src/java/com/android/internal/telephony/SimResponse.java b/src/java/com/android/internal/telephony/SimResponse.java
index 97692a0..12c9a3c 100644
--- a/src/java/com/android/internal/telephony/SimResponse.java
+++ b/src/java/com/android/internal/telephony/SimResponse.java
@@ -123,19 +123,34 @@
if (!carrierRestrictions.allowedCarriersPrioritized) {
carrierRestrictionDefault = CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_ALLOWED;
}
-
- CarrierRestrictionRules ret = CarrierRestrictionRules.newBuilder().setAllowedCarriers(
- RILUtils.convertHalCarrierList(
- carrierRestrictions.allowedCarriers)).setExcludedCarriers(
- RILUtils.convertHalCarrierList(
- carrierRestrictions.excludedCarriers)).setDefaultCarrierRestriction(
- carrierRestrictionDefault).setMultiSimPolicy(policy).setCarrierRestrictionStatus(
- carrierRestrictions.status).setAllowedCarrierInfo(
- RILUtils.convertAidlCarrierInfoList(
- carrierRestrictions.allowedCarrierInfoList)).setExcludedCarrierInfo(
- RILUtils.convertAidlCarrierInfoList(
- carrierRestrictions.excludedCarrierInfoList)).setCarrierLockInfoFeature(
- carrierLockInfoSupported).build();
+ CarrierRestrictionRules ret = null;
+ if (carrierLockInfoSupported) {
+ // In order to support the old API { @link TelephonyManager#getAllowedCarriers() } we
+ // are parsing the allowedCarrierInfoList to CarrierIdentifier List also along with
+ // CarrierInfo List
+ ret = CarrierRestrictionRules.newBuilder().setAllowedCarriers(
+ RILUtils.convertAidlCarrierInfoListToHalCarrierList(
+ carrierRestrictions.allowedCarrierInfoList)).setExcludedCarriers(
+ RILUtils.convertAidlCarrierInfoListToHalCarrierList(
+ carrierRestrictions.excludedCarrierInfoList)).
+ setDefaultCarrierRestriction(
+ carrierRestrictionDefault).setMultiSimPolicy(
+ policy).setCarrierRestrictionStatus(
+ carrierRestrictions.status).setAllowedCarrierInfo(
+ RILUtils.convertAidlCarrierInfoList(
+ carrierRestrictions.allowedCarrierInfoList)).setExcludedCarrierInfo(
+ RILUtils.convertAidlCarrierInfoList(
+ carrierRestrictions.excludedCarrierInfoList)).setCarrierLockInfoFeature(
+ true).build();
+ } else {
+ ret = CarrierRestrictionRules.newBuilder().setAllowedCarriers(
+ RILUtils.convertHalCarrierList(
+ carrierRestrictions.allowedCarriers)).setExcludedCarriers(
+ RILUtils.convertHalCarrierList(
+ carrierRestrictions.excludedCarriers)).setDefaultCarrierRestriction(
+ carrierRestrictionDefault).setMultiSimPolicy(
+ policy).build();
+ }
if (responseInfo.error == RadioError.NONE) {
RadioResponse.sendMessageResponse(rr.mResult, ret);
}
diff --git a/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java b/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java
index 0b427f8..12cc2fa 100644
--- a/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java
+++ b/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java
@@ -366,9 +366,8 @@
SubscriptionInfo subInfo =
SubscriptionManagerService.getInstance().getSubscriptionInfo(subId);
- if (mFeatureFlags.dataOnlyCellularService() &&
- subId > SubscriptionManager.INVALID_SUBSCRIPTION_ID && subInfo != null &&
- subInfo.getServiceCapabilities()
+ if (subId > SubscriptionManager.INVALID_SUBSCRIPTION_ID && subInfo != null
+ && subInfo.getServiceCapabilities()
.contains(SubscriptionManager.SERVICE_CAPABILITY_VOICE)) {
Log.v(LOG_TAG, "generateVoiceCapablePhoneMapBasedOnUserAssociation: adding "
+ "phoneId = " + phone.getPhoneId());
diff --git a/src/java/com/android/internal/telephony/SmsController.java b/src/java/com/android/internal/telephony/SmsController.java
index e3c409d..051fbbd 100644
--- a/src/java/com/android/internal/telephony/SmsController.java
+++ b/src/java/com/android/internal/telephony/SmsController.java
@@ -276,6 +276,7 @@
}
UserHandle callingUser = Binder.getCallingUserHandle();
+
Rlog.d(LOG_TAG, "sendTextForSubscriber caller=" + callingPackage);
if (skipFdnCheck || skipShortCodeCheck) {
@@ -1194,8 +1195,9 @@
}
// Skip FDN check for emergency numbers
+ if (!TelephonyCapabilities.supportsTelephonyCalling(mFlags, mContext)) return false;
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- if (tm.isEmergencyNumber(destAddr)) {
+ if (tm != null && tm.isEmergencyNumber(destAddr)) {
return false;
}
diff --git a/src/java/com/android/internal/telephony/SmsDispatchersController.java b/src/java/com/android/internal/telephony/SmsDispatchersController.java
index 7795955..77fd1f6 100644
--- a/src/java/com/android/internal/telephony/SmsDispatchersController.java
+++ b/src/java/com/android/internal/telephony/SmsDispatchersController.java
@@ -45,12 +45,14 @@
import android.telephony.ServiceState;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.satellite.SatelliteManager;
import android.text.TextUtils;
import com.android.ims.ImsManager;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
import com.android.internal.telephony.cdma.CdmaInboundSmsHandler;
@@ -75,6 +77,7 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicLong;
/**
*
@@ -220,6 +223,7 @@
public static final int TYPE_TEXT = 2;
public static final int TYPE_MULTIPART_TEXT = 3;
public static final int TYPE_RETRY_SMS = 4;
+ private static final AtomicLong sNextUniqueMessageId = new AtomicLong(0);
public final int type;
public final SMSDispatcher.SmsTracker tracker;
@@ -242,13 +246,16 @@
public final int validityPeriod;
public final long messageId;
public final boolean skipShortCodeCheck;
+ public final long uniqueMessageId;
+ public final boolean isMtSmsPolling;
public PendingRequest(int type, SMSDispatcher.SmsTracker tracker, String callingPackage,
int callingUser, String destAddr, String scAddr,
ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents,
boolean isForVvm, byte[] data, int destPort, ArrayList<String> texts,
Uri messageUri, boolean persistMessage, int priority, boolean expectMore,
- int validityPeriod, long messageId, boolean skipShortCodeCheck) {
+ int validityPeriod, long messageId, boolean skipShortCodeCheck,
+ boolean isMtSmsPolling) {
this.type = type;
this.tracker = tracker;
this.callingPackage = callingPackage;
@@ -270,6 +277,17 @@
this.validityPeriod = validityPeriod;
this.messageId = messageId;
this.skipShortCodeCheck = skipShortCodeCheck;
+ if (tracker != null) {
+ this.uniqueMessageId = tracker.mUniqueMessageId;
+ } else {
+ this.uniqueMessageId = getNextUniqueMessageId();
+ }
+ this.isMtSmsPolling = isMtSmsPolling;
+ }
+
+ public static long getNextUniqueMessageId() {
+ return sNextUniqueMessageId.getAndUpdate(
+ id -> ((id + 1) % Long.MAX_VALUE));
}
}
@@ -811,8 +829,7 @@
if (!tracker.mUsesImsServiceForIms) {
if (isSmsDomainSelectionEnabled()) {
- TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- boolean isEmergency = tm.isEmergencyNumber(tracker.mDestAddress);
+ boolean isEmergency = isEmergencyNumber(tracker.mDestAddress);
// This may be invoked by another thread, so this operation is posted and
// handled through the execution flow of SmsDispatchersController.
SomeArgs args = SomeArgs.obtain();
@@ -821,7 +838,7 @@
null, UserHandle.USER_NULL, null, null,
null, null, false, null, 0,
null, null, false,
- 0, false, 0, 0L, false);
+ 0, false, 0, 0L, false, false);
args.arg3 = "sendRetrySms";
sendMessage(obtainMessage(EVENT_REQUEST_DOMAIN_SELECTION, args));
return;
@@ -867,8 +884,8 @@
// should never come here...
Rlog.e(TAG, "sendRetrySms failed to re-encode per missing fields!");
tracker.onFailed(mContext, SmsManager.RESULT_SMS_SEND_RETRY_FAILED, NO_ERROR_CODE);
- notifySmsSent(tracker.mDestAddress, tracker.mMessageId,
- !retryUsingImsService, true /*isLastSmsPart*/, false /*success*/);
+ notifySmsSent(tracker, !retryUsingImsService,
+ true /*isLastSmsPart*/, false /*success*/);
return;
}
String scAddr = (String) map.get("scAddr");
@@ -876,8 +893,8 @@
if (destAddr == null) {
Rlog.e(TAG, "sendRetrySms failed due to null destAddr");
tracker.onFailed(mContext, SmsManager.RESULT_SMS_SEND_RETRY_FAILED, NO_ERROR_CODE);
- notifySmsSent(tracker.mDestAddress, tracker.mMessageId,
- !retryUsingImsService, true /*isLastSmsPart*/, false /*success*/);
+ notifySmsSent(tracker, !retryUsingImsService,
+ true /*isLastSmsPart*/, false /*success*/);
return;
}
@@ -918,8 +935,8 @@
+ "scAddr: %s, "
+ "destPort: %s", scAddr, map.get("destPort")));
tracker.onFailed(mContext, SmsManager.RESULT_SMS_SEND_RETRY_FAILED, NO_ERROR_CODE);
- notifySmsSent(tracker.mDestAddress, tracker.mMessageId,
- !retryUsingImsService, true /*isLastSmsPart*/, false /*success*/);
+ notifySmsSent(tracker, !retryUsingImsService,
+ true /*isLastSmsPart*/, false /*success*/);
return;
}
// replace old smsc and pdu with newly encoded ones
@@ -1201,8 +1218,7 @@
private void handleSmsSentCompletedUsingDomainSelection(@NonNull String destAddr,
long messageId, boolean success, boolean isOverIms, boolean isLastSmsPart) {
if (mEmergencyStateTracker != null) {
- TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- if (tm.isEmergencyNumber(destAddr)) {
+ if (isEmergencyNumber(destAddr)) {
mEmergencyStateTracker.endSms(String.valueOf(messageId), success,
isOverIms ? NetworkRegistrationInfo.DOMAIN_PS
: NetworkRegistrationInfo.DOMAIN_CS,
@@ -1214,11 +1230,11 @@
/**
* Called when MO SMS is sent.
*/
- protected void notifySmsSent(@NonNull String destAddr, long messageId, boolean isOverIms,
- boolean isLastSmsPart, boolean success) {
- notifySmsSentToEmergencyStateTracker(
- destAddr, messageId, isOverIms, isLastSmsPart, success);
- notifySmsSentToDatagramDispatcher(messageId, success);
+ protected void notifySmsSent(@NonNull SMSDispatcher.SmsTracker tracker,
+ boolean isOverIms, boolean isLastSmsPart, boolean success) {
+ notifySmsSentToEmergencyStateTracker(tracker.mDestAddress,
+ tracker.mMessageId, isOverIms, isLastSmsPart, success);
+ notifySmsSentToDatagramDispatcher(tracker.mUniqueMessageId, success);
}
/**
@@ -1239,7 +1255,7 @@
}
private void notifySmsSentToDatagramDispatcher(long messageId, boolean success) {
- if (SatelliteController.getInstance().isInCarrierRoamingNbIotNtn()) {
+ if (SatelliteController.getInstance().shouldSendSmsToDatagramDispatcher(mPhone)) {
DatagramDispatcher.getInstance().onSendSmsDone(mPhone.getSubId(), messageId, success);
}
}
@@ -1251,8 +1267,7 @@
*/
private void handleSmsReceivedViaIms(@Nullable String origAddr) {
if (mEmergencyStateTracker != null) {
- TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- if (origAddr != null && tm.isEmergencyNumber(origAddr)) {
+ if (origAddr != null && isEmergencyNumber(origAddr)) {
mEmergencyStateTracker.onEmergencySmsReceived();
}
}
@@ -1270,7 +1285,9 @@
private boolean isTestEmergencyNumber(String number) {
try {
+ if (!mPhone.hasCalling()) return false;
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ if (tm == null) return false;
Map<Integer, List<EmergencyNumber>> eMap = tm.getEmergencyNumberList();
return eMap.values().stream().flatMap(Collection::stream).anyMatch(eNumber ->
eNumber.isFromSources(EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST)
@@ -1402,15 +1419,18 @@
if (domain == NetworkRegistrationInfo.DOMAIN_PS) {
mImsSmsDispatcher.sendData(request.callingPackage, request.callingUser,
request.destAddr, request.scAddr, request.destPort, request.data,
- request.sentIntents.get(0), request.deliveryIntents.get(0), request.isForVvm);
+ request.sentIntents.get(0), request.deliveryIntents.get(0), request.isForVvm,
+ request.uniqueMessageId);
} else if (isCdmaMo(domain)) {
mCdmaDispatcher.sendData(request.callingPackage, request.callingUser, request.destAddr,
request.scAddr, request.destPort, request.data,
- request.sentIntents.get(0), request.deliveryIntents.get(0), request.isForVvm);
+ request.sentIntents.get(0), request.deliveryIntents.get(0), request.isForVvm,
+ request.uniqueMessageId);
} else {
mGsmDispatcher.sendData(request.callingPackage, request.callingUser, request.destAddr,
request.scAddr, request.destPort, request.data,
- request.sentIntents.get(0), request.deliveryIntents.get(0), request.isForVvm);
+ request.sentIntents.get(0), request.deliveryIntents.get(0), request.isForVvm,
+ request.uniqueMessageId);
}
}
@@ -1430,7 +1450,7 @@
request.messageUri, request.callingPackage, request.callingUser,
request.persistMessage, request.priority, /*request.expectMore*/ false,
request.validityPeriod, request.isForVvm, request.messageId,
- request.skipShortCodeCheck);
+ request.skipShortCodeCheck, request.uniqueMessageId);
} else {
if (isCdmaMo(domain)) {
mCdmaDispatcher.sendText(request.destAddr, request.scAddr, request.texts.get(0),
@@ -1438,14 +1458,14 @@
request.messageUri, request.callingPackage, request.callingUser,
request.persistMessage, request.priority, request.expectMore,
request.validityPeriod, request.isForVvm, request.messageId,
- request.skipShortCodeCheck);
+ request.skipShortCodeCheck, request.uniqueMessageId);
} else {
mGsmDispatcher.sendText(request.destAddr, request.scAddr, request.texts.get(0),
request.sentIntents.get(0), request.deliveryIntents.get(0),
request.messageUri, request.callingPackage, request.callingUser,
request.persistMessage, request.priority, request.expectMore,
request.validityPeriod, request.isForVvm, request.messageId,
- request.skipShortCodeCheck);
+ request.skipShortCodeCheck, request.uniqueMessageId);
}
}
}
@@ -1465,25 +1485,29 @@
request.sentIntents, request.deliveryIntents, request.messageUri,
request.callingPackage, request.callingUser, request.persistMessage,
request.priority, false /*request.expectMore*/, request.validityPeriod,
- request.messageId);
+ request.messageId, request.uniqueMessageId);
} else {
if (isCdmaMo(domain)) {
mCdmaDispatcher.sendMultipartText(request.destAddr, request.scAddr, request.texts,
request.sentIntents, request.deliveryIntents, request.messageUri,
request.callingPackage, request.callingUser, request.persistMessage,
request.priority, request.expectMore, request.validityPeriod,
- request.messageId);
+ request.messageId, request.uniqueMessageId);
} else {
mGsmDispatcher.sendMultipartText(request.destAddr, request.scAddr, request.texts,
request.sentIntents, request.deliveryIntents, request.messageUri,
request.callingPackage, request.callingUser, request.persistMessage,
request.priority, request.expectMore, request.validityPeriod,
- request.messageId);
+ request.messageId, request.uniqueMessageId);
}
}
}
- private void triggerSentIntentForFailure(@NonNull PendingIntent sentIntent) {
+ private void triggerSentIntentForFailure(PendingIntent sentIntent) {
+ if (sentIntent == null) {
+ logd("sentIntent is null");
+ return;
+ }
try {
sentIntent.send(SmsManager.RESULT_ERROR_GENERIC_FAILURE);
} catch (CanceledException e) {
@@ -1491,7 +1515,11 @@
}
}
- private void triggerSentIntentForFailure(@NonNull List<PendingIntent> sentIntents) {
+ private void triggerSentIntentForFailure(List<PendingIntent> sentIntents) {
+ if (sentIntents == null) {
+ logd("sentIntents is null");
+ return;
+ }
for (PendingIntent sentIntent : sentIntents) {
triggerSentIntentForFailure(sentIntent);
}
@@ -1598,20 +1626,23 @@
destAddr, scAddr, asArrayList(sentIntent),
asArrayList(deliveryIntent), isForVvm, data, destPort, null,
null, false, 0, false, 0,
- 0L, false),
+ 0L, false, false),
"sendData");
return;
}
if (mImsSmsDispatcher.isAvailable()) {
mImsSmsDispatcher.sendData(callingPackage, callingUser, destAddr, scAddr, destPort,
- data, sentIntent, deliveryIntent, isForVvm);
+ data, sentIntent, deliveryIntent, isForVvm,
+ PendingRequest.getNextUniqueMessageId());
} else if (isCdmaMo()) {
mCdmaDispatcher.sendData(callingPackage, callingUser, destAddr, scAddr, destPort, data,
- sentIntent, deliveryIntent, isForVvm);
+ sentIntent, deliveryIntent, isForVvm,
+ PendingRequest.getNextUniqueMessageId());
} else {
mGsmDispatcher.sendData(callingPackage, callingUser, destAddr, scAddr, destPort, data,
- sentIntent, deliveryIntent, isForVvm);
+ sentIntent, deliveryIntent, isForVvm,
+ PendingRequest.getNextUniqueMessageId());
}
}
@@ -1831,9 +1862,9 @@
callingPkg, callingUser, destAddr, scAddr, asArrayList(sentIntent),
asArrayList(deliveryIntent), isForVvm, null, 0, asArrayList(text),
messageUri, persistMessage, priority, expectMore, validityPeriod, messageId,
- skipShortCodeCheck);
+ skipShortCodeCheck, false);
- if (SatelliteController.getInstance().isInCarrierRoamingNbIotNtn()) {
+ if (SatelliteController.getInstance().shouldSendSmsToDatagramDispatcher(mPhone)) {
// Send P2P SMS using carrier roaming NB IOT NTN
DatagramDispatcher.getInstance().sendSms(pendingRequest);
return;
@@ -1843,10 +1874,10 @@
}
private void sendTextInternal(PendingRequest request) {
- logd("sendTextInternal: messageId=" + request.messageId);
+ logd("sendTextInternal: messageId=" + request.messageId
+ + ", uniqueMessageId=" + request.uniqueMessageId);
if (isSmsDomainSelectionEnabled()) {
- TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- boolean isEmergency = tm.isEmergencyNumber(request.destAddr);
+ boolean isEmergency = isEmergencyNumber(request.destAddr);
sendSmsUsingDomainSelection(getDomainSelectionConnectionHolder(isEmergency),
request, "sendText");
return;
@@ -1859,7 +1890,7 @@
request.messageUri, request.callingPackage, request.callingUser,
request.persistMessage, request.priority, false /*expectMore*/,
request.validityPeriod, request.isForVvm, request.messageId,
- request.skipShortCodeCheck);
+ request.skipShortCodeCheck, request.uniqueMessageId);
} else {
if (isCdmaMo()) {
mCdmaDispatcher.sendText(request.destAddr, request.scAddr, request.texts.get(0),
@@ -1867,14 +1898,14 @@
request.messageUri, request.callingPackage, request.callingUser,
request.persistMessage, request.priority, request.expectMore,
request.validityPeriod, request.isForVvm, request.messageId,
- request.skipShortCodeCheck);
+ request.skipShortCodeCheck, request.uniqueMessageId);
} else {
mGsmDispatcher.sendText(request.destAddr, request.scAddr, request.texts.get(0),
request.sentIntents.get(0), request.deliveryIntents.get(0),
request.messageUri, request.callingPackage, request.callingUser,
request.persistMessage, request.priority, request.expectMore,
request.validityPeriod, request.isForVvm, request.messageId,
- request.skipShortCodeCheck);
+ request.skipShortCodeCheck, request.uniqueMessageId);
}
}
}
@@ -1995,9 +2026,9 @@
PendingRequest pendingRequest = new PendingRequest(PendingRequest.TYPE_MULTIPART_TEXT, null,
callingPkg, callingUser, destAddr, scAddr, sentIntents, deliveryIntents, false,
null, 0, parts, messageUri, persistMessage, priority, expectMore,
- validityPeriod, messageId, false);
+ validityPeriod, messageId, false, false);
- if (SatelliteController.getInstance().isInCarrierRoamingNbIotNtn()) {
+ if (SatelliteController.getInstance().shouldSendSmsToDatagramDispatcher(mPhone)) {
// Send multipart P2P SMS using carrier roaming NB IOT NTN
DatagramDispatcher.getInstance().sendSms(pendingRequest);
return;
@@ -2006,11 +2037,17 @@
sendMultipartTextInternal(pendingRequest);
}
+ private boolean isEmergencyNumber(String number) {
+ if (!mPhone.hasCalling()) return false;
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ if (tm == null) return false;
+ return tm.isEmergencyNumber(number);
+ }
+
private void sendMultipartTextInternal(PendingRequest request) {
logd("sendMultipartTextInternal: messageId=" + request.messageId);
if (isSmsDomainSelectionEnabled()) {
- TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- boolean isEmergency = tm.isEmergencyNumber(request.destAddr);
+ boolean isEmergency = isEmergencyNumber(request.destAddr);
sendSmsUsingDomainSelection(getDomainSelectionConnectionHolder(isEmergency),
request, "sendMultipartText");
return;
@@ -2021,20 +2058,20 @@
request.sentIntents, request.deliveryIntents, request.messageUri,
request.callingPackage, request.callingUser, request.persistMessage,
request.priority, false /*expectMore*/, request.validityPeriod,
- request.messageId);
+ request.messageId, request.uniqueMessageId);
} else {
if (isCdmaMo()) {
mCdmaDispatcher.sendMultipartText(request.destAddr, request.scAddr, request.texts,
request.sentIntents, request.deliveryIntents, request.messageUri,
request.callingPackage, request.callingUser, request.persistMessage,
request.priority, request.expectMore, request.validityPeriod,
- request.messageId);
+ request.messageId, request.uniqueMessageId);
} else {
mGsmDispatcher.sendMultipartText(request.destAddr, request.scAddr, request.texts,
request.sentIntents, request.deliveryIntents, request.messageUri,
request.callingPackage, request.callingUser, request.persistMessage,
request.priority, request.expectMore, request.validityPeriod,
- request.messageId);
+ request.messageId, request.uniqueMessageId);
}
}
}
@@ -2172,7 +2209,7 @@
*/
public void sendCarrierRoamingNbIotNtnText(@NonNull PendingRequest request) {
if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
- logd("onSendCarrierRoamingNbIotNtnTextError: carrier roaming nb iot ntn "
+ logd("sendCarrierRoamingNbIotNtnText: carrier roaming nb iot ntn "
+ "feature flag is disabled");
return;
}
@@ -2200,6 +2237,44 @@
sendMessage(obtainMessage(EVENT_SEND_TEXT_OVER_NTN_ERROR, pendingRequest));
}
+ /**
+ * This API should be used only by {@link DatagramDispatcher} to send MT SMS Polling message
+ * over non-terrestrial network.
+ * To enable users to receive incoming messages, the device needs to send an MO SMS to itself
+ * to trigger SMSC to send all pending SMS to the particular subscription.
+ */
+ public void sendMtSmsPollingMessage() {
+ if (!SatelliteController.getInstance().shouldSendSmsToDatagramDispatcher(mPhone)) {
+ logd("sendMtSmsPollingMessage: not in roaming nb iot ntn");
+ return;
+ }
+
+ SubscriptionManager subscriptionManager = (SubscriptionManager) mContext
+ .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ String destAddr = subscriptionManager.getPhoneNumber(mPhone.getSubId());
+ if (TextUtils.isEmpty(destAddr)) {
+ logd("sendMtSmsPollingMessage: destAddr is null or empty.");
+ return;
+ }
+
+ String mtSmsPollingText = mContext.getResources()
+ .getString(R.string.config_mt_sms_polling_text);
+ if (TextUtils.isEmpty(mtSmsPollingText)) {
+ logd("sendMtSmsPollingMessage: mtSmsPollingText is null or empty.");
+ return;
+ }
+
+ String callingPackage = mContext.getPackageName();
+ PendingRequest pendingRequest = new PendingRequest(PendingRequest.TYPE_TEXT, null,
+ callingPackage, Binder.getCallingUserHandle().getIdentifier(), destAddr,
+ getSmscAddressFromUSIMWithPhoneIdentity(callingPackage), asArrayList(null),
+ asArrayList(null), false, null, 0, asArrayList(mtSmsPollingText), null, false, 0,
+ false, 5, 0L, true, true);
+
+ if (SatelliteController.getInstance().shouldSendSmsToDatagramDispatcher(mPhone)) {
+ DatagramDispatcher.getInstance().sendSms(pendingRequest);
+ }
+ }
public interface SmsInjectionCallback {
void onSmsInjectedResult(int result);
diff --git a/src/java/com/android/internal/telephony/SmsUsageMonitor.java b/src/java/com/android/internal/telephony/SmsUsageMonitor.java
index 8e4ac60..7fb5811 100644
--- a/src/java/com/android/internal/telephony/SmsUsageMonitor.java
+++ b/src/java/com/android/internal/telephony/SmsUsageMonitor.java
@@ -35,6 +35,7 @@
import android.util.AtomicFile;
import android.util.Xml;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.util.XmlUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.telephony.Rlog;
@@ -113,6 +114,8 @@
/** Context for retrieving regexes from XML resource. */
private final Context mContext;
+ private final FeatureFlags mFeatureFlags;
+
/** Country code for the cached short code pattern matcher. */
private String mCurrentCountry;
@@ -255,8 +258,9 @@
* @param context the context to use to load resources and get TelephonyManager service
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public SmsUsageMonitor(Context context) {
+ public SmsUsageMonitor(Context context, FeatureFlags flags) {
mContext = context;
+ mFeatureFlags = flags;
ContentResolver resolver = context.getContentResolver();
mRoleManager = (RoleManager) mContext.getSystemService(Context.ROLE_SERVICE);
@@ -404,7 +408,8 @@
synchronized (mSettingsObserverHandler) {
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
// always allow emergency numbers
- if (tm.isEmergencyNumber(destAddress)) {
+ if (TelephonyCapabilities.supportsTelephonyCalling(mFeatureFlags, mContext)
+ && tm != null && tm.isEmergencyNumber(destAddress)) {
if (DBG) Rlog.d(TAG, "isEmergencyNumber");
return SmsManager.SMS_CATEGORY_NOT_SHORT_CODE;
}
diff --git a/src/java/com/android/internal/telephony/TelephonyCapabilities.java b/src/java/com/android/internal/telephony/TelephonyCapabilities.java
index 71d3b14..b650b43 100644
--- a/src/java/com/android/internal/telephony/TelephonyCapabilities.java
+++ b/src/java/com/android/internal/telephony/TelephonyCapabilities.java
@@ -18,6 +18,8 @@
import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.Build;
import android.os.SystemProperties;
@@ -209,4 +211,14 @@
return featureFlags.minimalTelephonyCdmCheck();
}
+
+ /**
+ * @return true if this device supports telephony calling, false if it does not.
+ */
+ public static boolean supportsTelephonyCalling(@NonNull FeatureFlags featureFlags,
+ Context context) {
+ if (!TelephonyCapabilities.minimalTelephonyCdmCheck(featureFlags)) return true;
+ return context.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_CALLING);
+ }
}
diff --git a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
index 10e97b6..b4a3ee6 100644
--- a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
+++ b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
@@ -301,8 +301,8 @@
return new SmsStorageMonitor(phone, flags);
}
- public SmsUsageMonitor makeSmsUsageMonitor(Context context) {
- return new SmsUsageMonitor(context);
+ public SmsUsageMonitor makeSmsUsageMonitor(Context context, FeatureFlags flags) {
+ return new SmsUsageMonitor(context, flags);
}
public ServiceStateTracker makeServiceStateTracker(GsmCdmaPhone phone, CommandsInterface ci,
diff --git a/src/java/com/android/internal/telephony/TelephonyCountryDetector.java b/src/java/com/android/internal/telephony/TelephonyCountryDetector.java
index c2d6018..1e07bc3 100644
--- a/src/java/com/android/internal/telephony/TelephonyCountryDetector.java
+++ b/src/java/com/android/internal/telephony/TelephonyCountryDetector.java
@@ -16,7 +16,6 @@
package com.android.internal.telephony;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -111,6 +110,7 @@
@GuardedBy("mLock")
private boolean mIsCountryCodesOverridden = false;
private final RegistrantList mCountryCodeChangedRegistrants = new RegistrantList();
+ private boolean mIsWifiNetworkConnected = false;
private FeatureFlags mFeatureFlags = null;
@@ -298,7 +298,7 @@
handleNetworkCountryCodeChangedEvent((NetworkCountryCodeInfo) msg.obj);
break;
case EVENT_WIFI_CONNECTIVITY_STATE_CHANGED:
- handleEventWifiConnectivityStateChanged();
+ handleEventWifiConnectivityStateChanged((boolean) msg.obj);
break;
case EVENT_LOCATION_UPDATE_REQUEST_QUOTA_RESET:
evaluateRequestingLocationUpdates();
@@ -490,11 +490,21 @@
}
}
- private void handleEventWifiConnectivityStateChanged() {
- mWifiConnectivityStateChangedRegistrantList.notifyResult(isWifiNetworkConnected());
+ private void handleEventWifiConnectivityStateChanged(boolean connected) {
+ logd("handleEventWifiConnectivityStateChanged: " + connected);
+ evaluateNotifyWifiConnectivityStateChangedEvent(connected);
evaluateRequestingLocationUpdates();
}
+ private void evaluateNotifyWifiConnectivityStateChangedEvent(boolean connected) {
+ if (connected != mIsWifiNetworkConnected) {
+ mIsWifiNetworkConnected = connected;
+ mWifiConnectivityStateChangedRegistrantList.notifyResult(mIsWifiNetworkConnected);
+ logd("evaluateNotifyWifiConnectivityStateChangedEvent: wifi connectivity state has "
+ + "changed to " + connected);
+ }
+ }
+
private void setLocationCountryCode(@NonNull Pair<String, Long> countryCodeInfo) {
logd("Set location country code to: " + countryCodeInfo.first);
if (!isValid(countryCodeInfo.first)) {
@@ -526,25 +536,23 @@
private void registerForWifiConnectivityStateChanged() {
logd("registerForWifiConnectivityStateChanged");
NetworkRequest.Builder builder = new NetworkRequest.Builder();
- builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+ builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+
ConnectivityManager.NetworkCallback networkCallback =
new ConnectivityManager.NetworkCallback() {
@Override
- public void onAvailable(Network network) {
- logd("Wifi network available: " + network);
- sendRequestAsync(EVENT_WIFI_CONNECTIVITY_STATE_CHANGED, null);
+ public void onCapabilitiesChanged(Network network,
+ NetworkCapabilities networkCapabilities) {
+ logd("onCapabilitiesChanged: " + networkCapabilities);
+ sendRequestAsync(EVENT_WIFI_CONNECTIVITY_STATE_CHANGED,
+ isInternetAvailable(networkCapabilities));
}
@Override
public void onLost(Network network) {
logd("Wifi network lost: " + network);
- sendRequestAsync(EVENT_WIFI_CONNECTIVITY_STATE_CHANGED, null);
- }
-
- @Override
- public void onUnavailable() {
- logd("Wifi network unavailable");
- sendRequestAsync(EVENT_WIFI_CONNECTIVITY_STATE_CHANGED, null);
+ sendRequestAsync(EVENT_WIFI_CONNECTIVITY_STATE_CHANGED, false);
}
};
mConnectivityManager.registerNetworkCallback(builder.build(), networkCallback);
@@ -560,15 +568,20 @@
/**
* Check whether Wi-Fi network is connected or not.
- * @return {@code true} is Wi-Fi is connected, {@code false} otherwise.
+ * @return {@code true} is Wi-Fi is connected, and internet is available, {@code false}
+ * otherwise.
*/
public boolean isWifiNetworkConnected() {
- Network activeNetwork = mConnectivityManager.getActiveNetwork();
- NetworkCapabilities networkCapabilities =
- mConnectivityManager.getNetworkCapabilities(activeNetwork);
- return networkCapabilities != null
- && networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
- && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ logd("isWifiNetworkConnected: " + mIsWifiNetworkConnected);
+ return mIsWifiNetworkConnected;
+ }
+
+ private boolean isInternetAvailable(NetworkCapabilities networkCapabilities) {
+ boolean isWifiConnected =
+ networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
+ logd("isWifiConnected: " + isWifiConnected);
+ return isWifiConnected;
}
/**
diff --git a/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameResolver.java b/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameResolver.java
index 3837790..8646981 100644
--- a/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameResolver.java
+++ b/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameResolver.java
@@ -190,7 +190,7 @@
}
/** Get the resolved carrier display name. */
- public CarrierDisplayNameData getCarrierDisplayNameData() {
+ public @NonNull CarrierDisplayNameData getCarrierDisplayNameData() {
resolveCarrierDisplayName();
return mCarrierDisplayNameData;
}
diff --git a/src/java/com/android/internal/telephony/data/AccessNetworksManager.java b/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
index 1bbc692..2691eab 100644
--- a/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
+++ b/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
@@ -333,7 +333,7 @@
log("onNetworkValidationRequested: networkCapability = ["
+ DataUtils.networkCapabilityToString(networkCapability) + "]");
- dnc.requestNetworkValidation(networkCapability, result -> post(() -> {
+ dnc.requestNetworkValidation(networkCapability, result -> {
try {
log("onNetworkValidationRequestDone:"
+ DataServiceCallback.resultCodeToString(result));
@@ -342,7 +342,7 @@
// Ignore if the remote process is no longer available to call back.
loge("onNetworkValidationRequestDone RemoteException" + e);
}
- }));
+ });
}
@Override
diff --git a/src/java/com/android/internal/telephony/data/DataUtils.java b/src/java/com/android/internal/telephony/data/DataUtils.java
index 20da97f..c88e0b3 100644
--- a/src/java/com/android/internal/telephony/data/DataUtils.java
+++ b/src/java/com/android/internal/telephony/data/DataUtils.java
@@ -287,6 +287,8 @@
case NetworkCapabilities.NET_CAPABILITY_VSIM -> ApnSetting.TYPE_VSIM;
case NetworkCapabilities.NET_CAPABILITY_BIP -> ApnSetting.TYPE_BIP;
case NetworkCapabilities.NET_CAPABILITY_RCS -> ApnSetting.TYPE_RCS;
+ case NetworkCapabilities.NET_CAPABILITY_OEM_PAID -> ApnSetting.TYPE_OEM_PAID;
+ case NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE -> ApnSetting.TYPE_OEM_PRIVATE;
default -> ApnSetting.TYPE_NONE;
};
}
@@ -315,6 +317,8 @@
case ApnSetting.TYPE_VSIM -> NetworkCapabilities.NET_CAPABILITY_VSIM;
case ApnSetting.TYPE_ENTERPRISE -> NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
case ApnSetting.TYPE_RCS -> NetworkCapabilities.NET_CAPABILITY_RCS;
+ case ApnSetting.TYPE_OEM_PAID -> NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
+ case ApnSetting.TYPE_OEM_PRIVATE -> NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE;
default -> -1;
};
}
diff --git a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
index 1005bb7..079e705 100644
--- a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
@@ -1491,14 +1491,18 @@
mPreferredDataPhoneId = mEmergencyOverride.mPhoneId;
mLastSwitchPreferredDataReason = DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN;
} else {
- int imsRegTech = mImsRegTechProvider.get(mContext, mPhoneIdInVoiceCall);
- if (isAnyVoiceCallActiveOnDevice() && imsRegTech != REGISTRATION_TECH_IWLAN) {
- if (imsRegTech != REGISTRATION_TECH_CROSS_SIM) {
- mPreferredDataPhoneId = shouldSwitchDataDueToInCall()
- ? mPhoneIdInVoiceCall : getFallbackDataPhoneIdForInternetRequests();
+ if (isAnyVoiceCallActiveOnDevice()) {
+ int imsRegTech = mImsRegTechProvider.get(mContext, mPhoneIdInVoiceCall);
+ if (imsRegTech != REGISTRATION_TECH_IWLAN) {
+ if (imsRegTech != REGISTRATION_TECH_CROSS_SIM) {
+ mPreferredDataPhoneId = shouldSwitchDataDueToInCall()
+ ? mPhoneIdInVoiceCall : getFallbackDataPhoneIdForInternetRequests();
+ } else {
+ logl("IMS call on cross-SIM, skip switching data to phone "
+ + mPhoneIdInVoiceCall);
+ }
} else {
- logl("IMS call on cross-SIM, skip switching data to phone "
- + mPhoneIdInVoiceCall);
+ mPreferredDataPhoneId = getFallbackDataPhoneIdForInternetRequests();
}
} else {
mPreferredDataPhoneId = getFallbackDataPhoneIdForInternetRequests();
@@ -1830,16 +1834,18 @@
if (phone == null) {
return false;
}
-
+ Call bgCall = phone.getBackgroundCall();
+ Call fgCall = phone.getForegroundCall();
+ if (bgCall == null || fgCall == null) {
+ return false;
+ }
// A phone in voice call might trigger data being switched to it.
// Exclude dialing to give modem time to process an EMC first before dealing with DDS switch
// Include alerting because modem RLF leads to delay in switch, so carrier required to
// switch in alerting phase.
// TODO: check ringing call for vDADA
- return (!phone.getBackgroundCall().isIdle()
- && phone.getBackgroundCall().getState() != Call.State.DIALING)
- || (!phone.getForegroundCall().isIdle()
- && phone.getForegroundCall().getState() != Call.State.DIALING);
+ return (!bgCall.isIdle() && bgCall.getState() != Call.State.DIALING)
+ || (!fgCall.isIdle() && fgCall.getState() != Call.State.DIALING);
}
private void updateHalCommandToUse() {
diff --git a/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java b/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
index 677db87..681ca12 100644
--- a/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
+++ b/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
@@ -783,6 +783,20 @@
dispose();
return;
}
+
+ if (scanType == DomainSelectionService.SCAN_TYPE_FULL_SERVICE) {
+ // Handle as unknown network.
+ EmergencyRegistrationResult result = new EmergencyRegistrationResult(
+ AccessNetworkConstants.AccessNetworkType.UNKNOWN,
+ NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN,
+ NetworkRegistrationInfo.DOMAIN_UNKNOWN, false, false, 0, 0, "", "", "");
+
+ if (mHandler != null) {
+ Message msg = mHandler.obtainMessage(EVENT_EMERGENCY_NETWORK_SCAN_RESULT,
+ new AsyncResult(null, result, null));
+ msg.sendToTarget();
+ }
+ }
}
private void onModemReset() {
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
index f983108..3c2ad0cd 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
@@ -20,6 +20,12 @@
import static android.telecom.Connection.STATE_DISCONNECTED;
import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_CALLBACK_MODE_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL;
+import static android.telephony.TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL;
+import static android.telephony.TelephonyManager.EMERGENCY_CALLBACK_MODE_SMS;
+import static android.telephony.TelephonyManager.STOP_REASON_EMERGENCY_SMS_SENT;
+import static android.telephony.TelephonyManager.STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED;
+import static android.telephony.TelephonyManager.STOP_REASON_TIMER_EXPIRED;
+import static android.telephony.TelephonyManager.STOP_REASON_UNKNOWN;
import static com.android.internal.telephony.TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED;
import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_CALLBACK;
@@ -65,6 +71,7 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.data.PhoneSwitcher;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.imsphone.ImsPhoneConnection;
import com.android.internal.telephony.satellite.SatelliteController;
import com.android.telephony.Rlog;
@@ -148,7 +155,8 @@
/** For emergency calls */
private final long mEcmExitTimeoutMs;
// A runnable which is used to automatically exit from Ecm after a period of time.
- private final Runnable mExitEcmRunnable = this::exitEmergencyCallbackMode;
+ private final Runnable mExitEcmRunnable = () -> exitEmergencyCallbackMode(
+ STOP_REASON_TIMER_EXPIRED);
// Tracks emergency calls by callId that have reached {@link Call.State#ACTIVE}.
private final Set<android.telecom.Connection> mActiveEmergencyCalls = new ArraySet<>();
private Phone mPhone;
@@ -184,6 +192,8 @@
private final CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener =
(slotIndex, subId, carrierId, specificCarrierId) -> onCarrierConfigurationChanged(
slotIndex, subId);
+ /** Feature flags */
+ private final FeatureFlags mFeatureFlags;
/**
* Listens for Emergency Callback Mode state change intents
@@ -326,12 +336,14 @@
if (!isSamePhone(mPhone, mSmsPhone)) {
completeEmergencyMode(emergencyType,
DisconnectCause.OUTGOING_EMERGENCY_CALL_PLACED);
- exitEmergencySmsCallbackMode();
+ exitEmergencySmsCallbackMode(
+ STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED);
}
} else {
completeEmergencyMode(emergencyType);
mIsEmergencyCallStartedDuringEmergencySms = false;
- exitEmergencySmsCallbackMode();
+ exitEmergencySmsCallbackMode(
+ STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED);
turnOnRadioAndSwitchDds(mPhone, EMERGENCY_TYPE_CALL,
mIsTestEmergencyNumber);
}
@@ -343,7 +355,8 @@
if (mIsEmergencyCallStartedDuringEmergencySms) {
mIsEmergencyCallStartedDuringEmergencySms = false;
- exitEmergencySmsCallbackMode();
+ exitEmergencySmsCallbackMode(
+ STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED);
turnOnRadioAndSwitchDds(mPhone, EMERGENCY_TYPE_CALL,
mIsTestEmergencyNumber);
}
@@ -409,7 +422,8 @@
// the emergency call was started, needs to exit the emergency mode first.
if (mIsEmergencyCallStartedDuringEmergencySms) {
final Phone smsPhone = mSmsPhone;
- exitEmergencySmsCallbackMode();
+ exitEmergencySmsCallbackMode(
+ STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED);
if (mPhone != null && smsPhone != null
&& !isSamePhone(mPhone, smsPhone)) {
@@ -428,7 +442,7 @@
break;
}
case MSG_EXIT_SCBM: {
- exitEmergencySmsCallbackModeAndEmergencyMode();
+ exitEmergencySmsCallbackModeAndEmergencyMode(STOP_REASON_TIMER_EXPIRED);
break;
}
case MSG_NEW_RINGING_CONNECTION: {
@@ -457,11 +471,13 @@
* @param context The context of the application.
* @param isSuplDdsSwitchRequiredForEmergencyCall Whether gnss supl requires default data for
* emergency call.
+ * @param featureFlags The telephony feature flags.
*/
- public static void make(Context context, boolean isSuplDdsSwitchRequiredForEmergencyCall) {
+ public static void make(Context context, boolean isSuplDdsSwitchRequiredForEmergencyCall,
+ @NonNull FeatureFlags featureFlags) {
if (INSTANCE == null) {
INSTANCE = new EmergencyStateTracker(context, Looper.myLooper(),
- isSuplDdsSwitchRequiredForEmergencyCall);
+ isSuplDdsSwitchRequiredForEmergencyCall, featureFlags);
}
}
@@ -481,12 +497,12 @@
* Initializes EmergencyStateTracker.
*/
private EmergencyStateTracker(Context context, Looper looper,
- boolean isSuplDdsSwitchRequiredForEmergencyCall) {
+ boolean isSuplDdsSwitchRequiredForEmergencyCall, @NonNull FeatureFlags featureFlags) {
mEcmExitTimeoutMs = DEFAULT_ECM_EXIT_TIMEOUT_MS;
mContext = context;
mHandler = new MyHandler(looper);
mIsSuplDdsSwitchRequiredForEmergencyCall = isSuplDdsSwitchRequiredForEmergencyCall;
-
+ mFeatureFlags = featureFlags;
PowerManager pm = context.getSystemService(PowerManager.class);
mWakeLock = (pm != null) ? pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"telephony:" + TAG) : null;
@@ -523,12 +539,13 @@
* @param telephonyManagerProxy The {@link TelephonyManagerProxy} to be
* injected.
* @param radioOnHelper The {@link RadioOnHelper} to be injected.
+ * @param featureFlags The {@link FeatureFlags} to be injected.
*/
@VisibleForTesting
public EmergencyStateTracker(Context context, Looper looper,
boolean isSuplDdsSwitchRequiredForEmergencyCall, PhoneFactoryProxy phoneFactoryProxy,
PhoneSwitcherProxy phoneSwitcherProxy, TelephonyManagerProxy telephonyManagerProxy,
- RadioOnHelper radioOnHelper, long ecmExitTimeoutMs) {
+ RadioOnHelper radioOnHelper, long ecmExitTimeoutMs, FeatureFlags featureFlags) {
mContext = context;
mHandler = new MyHandler(looper);
mIsSuplDdsSwitchRequiredForEmergencyCall = isSuplDdsSwitchRequiredForEmergencyCall;
@@ -537,6 +554,7 @@
mTelephonyManagerProxy = telephonyManagerProxy;
mRadioOnHelper = radioOnHelper;
mEcmExitTimeoutMs = ecmExitTimeoutMs;
+ mFeatureFlags = featureFlags;
mWakeLock = null; // Don't declare a wakelock in tests
mConfigManager = context.getSystemService(CarrierConfigManager.class);
mConfigManager.registerCarrierConfigChangeListener(mHandler::post,
@@ -574,7 +592,7 @@
// Case1) When 2nd emergency call is initiated during an active call on the same phone.
// Case2) While the device is in ECBM, an emergency call is initiated on the same phone.
if (isSamePhone(mPhone, phone) && (!mActiveEmergencyCalls.isEmpty() || isInEcm())) {
- exitEmergencySmsCallbackMode();
+ exitEmergencySmsCallbackMode(STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED);
mOngoingConnection = c;
mIsTestEmergencyNumber = isTestEmergencyNumber;
if (isInEcm()) {
@@ -622,7 +640,7 @@
mIsEmergencyCallStartedDuringEmergencySms = false;
}
- exitEmergencySmsCallbackMode();
+ exitEmergencySmsCallbackMode(STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED);
}
if (mIsEmergencyCallStartedDuringEmergencySms) {
@@ -1087,7 +1105,7 @@
* Handles the radio power off request.
*/
public void onCellularRadioPowerOffRequested() {
- exitEmergencySmsCallbackModeAndEmergencyMode();
+ exitEmergencySmsCallbackModeAndEmergencyMode(STOP_REASON_UNKNOWN);
exitEmergencyCallbackMode();
}
@@ -1159,10 +1177,14 @@
setEmergencyCallbackMode(mPhone, EMERGENCY_TYPE_CALL);
- // Post this runnable so we will automatically exit if no one invokes
- // exitEmergencyCallbackMode() directly.
long delayInMillis = TelephonyProperties.ecm_exit_timer()
.orElse(mEcmExitTimeoutMs);
+ if (mFeatureFlags.emergencyCallbackModeNotification()) {
+ mPhone.startEmergencyCallbackMode(EMERGENCY_CALLBACK_MODE_CALL, delayInMillis);
+ }
+
+ // Post this runnable so we will automatically exit if no one invokes
+ // exitEmergencyCallbackMode() directly.
mHandler.postDelayed(mExitEcmRunnable, delayInMillis);
// We don't want to go to sleep while in ECM.
@@ -1170,9 +1192,27 @@
}
/**
- * Exits emergency callback mode and notifies relevant listeners.
+ * Exits the emergency callback mode.
+ *
+ * <p>This method exits the emergency callback mode with an unknown stop reason. It removes
+ * any pending exit requests and notifies relevant listeners about the change in status.
*/
public void exitEmergencyCallbackMode() {
+ exitEmergencyCallbackMode(STOP_REASON_UNKNOWN);
+ }
+
+ /**
+ * Exits the emergency callback mode.
+ *
+ * <p>This method exits the emergency callback mode with the specified stop reason. It removes
+ * any pending exit requests and notifies relevant listeners about the change in status,
+ * providing the reason for exiting.
+ *
+ * @param reason The reason for exiting. See
+ * {@link TelephonyManager.EmergencyCallbackModeStopReason} for possible values.
+ */
+ public void exitEmergencyCallbackMode(
+ @TelephonyManager.EmergencyCallbackModeStopReason int reason) {
Rlog.d(TAG, "exit ECBM");
// Remove pending exit ECM runnable, if any.
mHandler.removeCallbacks(mExitEcmRunnable);
@@ -1191,6 +1231,10 @@
sendEmergencyCallbackModeChange();
gsmCdmaPhone.notifyEmergencyCallRegistrants(false);
+ if (mFeatureFlags.emergencyCallbackModeNotification()) {
+ gsmCdmaPhone.stopEmergencyCallbackMode(EMERGENCY_CALLBACK_MODE_CALL, reason);
+ }
+
// Exit emergency mode on modem.
exitEmergencyMode(gsmCdmaPhone, EMERGENCY_TYPE_CALL);
}
@@ -1213,11 +1257,20 @@
}
/**
- * Exits emergency callback mode and triggers runnable after exit response is received.
+ * Exits the emergency callback mode and triggers {@link Runnable} after exit response is
+ * received.
+ *
+ * <p>This method exits the emergency callback mode with the specified stop reason and then
+ * executes the provided {@link Runnable}.
+ *
+ * @param onComplete The {@link Runnable} to execute after exiting emergency callback mode.
+ * @param reason The reason for exiting. See
+ * {@link TelephonyManager.EmergencyCallbackModeStopReason} for possible values.
*/
- public void exitEmergencyCallbackMode(Runnable onComplete) {
+ public void exitEmergencyCallbackMode(Runnable onComplete,
+ @TelephonyManager.EmergencyCallbackModeStopReason int reason) {
mOnEcmExitCompleteRunnable = onComplete;
- exitEmergencyCallbackMode();
+ exitEmergencyCallbackMode(reason);
}
/**
@@ -1323,7 +1376,7 @@
// emergency SMS callback mode first.
exitScbmInOtherPhone = true;
mIsEmergencySmsStartedDuringScbm = true;
- exitEmergencySmsCallbackModeAndEmergencyMode();
+ exitEmergencySmsCallbackModeAndEmergencyMode(STOP_REASON_EMERGENCY_SMS_SENT);
} else {
Rlog.e(TAG, "Emergency SMS is in progress on the other slot.");
return CompletableFuture.completedFuture(DisconnectCause.ERROR_UNSPECIFIED);
@@ -1460,6 +1513,9 @@
*/
private void enterEmergencySmsCallbackMode() {
Rlog.d(TAG, "enter SCBM while " + (isInScbm() ? "in" : "not in") + " SCBM");
+
+ boolean shouldRestartEcm = isInScbm();
+
// Remove pending message if present.
mHandler.removeMessages(MSG_EXIT_SCBM);
@@ -1484,17 +1540,29 @@
// Post the message so we will automatically exit if no one invokes
// exitEmergencySmsCallbackModeAndEmergencyMode() directly.
mHandler.sendEmptyMessageDelayed(MSG_EXIT_SCBM, delayInMillis);
+
+ if (mFeatureFlags.emergencyCallbackModeNotification()) {
+ if (shouldRestartEcm) {
+ mSmsPhone.restartEmergencyCallbackMode(EMERGENCY_CALLBACK_MODE_SMS, delayInMillis);
+ } else {
+ mSmsPhone.startEmergencyCallbackMode(EMERGENCY_CALLBACK_MODE_SMS, delayInMillis);
+ }
+ }
}
/**
* Exits emergency SMS callback mode and emergency mode if the device is in SCBM and
* the emergency mode is in CALLBACK.
+ *
+ * @param reason The reason for exiting. See
+ * {@link TelephonyManager.EmergencyCallbackModeStopReason} for possible values.
*/
- private void exitEmergencySmsCallbackModeAndEmergencyMode() {
+ private void exitEmergencySmsCallbackModeAndEmergencyMode(
+ @TelephonyManager.EmergencyCallbackModeStopReason int reason) {
Rlog.d(TAG, "exit SCBM and emergency mode");
final Phone smsPhone = mSmsPhone;
boolean wasInScbm = isInScbm();
- exitEmergencySmsCallbackMode();
+ exitEmergencySmsCallbackMode(reason);
// The emergency mode needs to be checked to ensure that there is no ongoing emergency SMS.
if (wasInScbm && mOngoingEmergencySmsIds.isEmpty()) {
@@ -1505,13 +1573,22 @@
/**
* Exits emergency SMS callback mode.
+ *
+ * @param reason The reason for exiting. See
+ * {@link TelephonyManager.EmergencyCallbackModeStopReason} for possible values.
*/
- private void exitEmergencySmsCallbackMode() {
+ private void exitEmergencySmsCallbackMode(
+ @TelephonyManager.EmergencyCallbackModeStopReason int reason) {
// Remove pending message if present.
mHandler.removeMessages(MSG_EXIT_SCBM);
if (isInScbm()) {
Rlog.i(TAG, "exit SCBM");
+
+ if (mFeatureFlags.emergencyCallbackModeNotification()) {
+ mSmsPhone.stopEmergencyCallbackMode(EMERGENCY_CALLBACK_MODE_SMS, reason);
+ }
+
setIsInScbm(false);
}
@@ -1588,7 +1665,7 @@
final boolean isAirplaneModeOn = isAirplaneModeOn(mContext);
boolean needToTurnOnRadio = !isRadioOn() || isAirplaneModeOn;
final SatelliteController satelliteController = SatelliteController.getInstance();
- boolean needToTurnOffSatellite = satelliteController.isSatelliteEnabled();
+ boolean needToTurnOffSatellite = satelliteController.isSatelliteEnabledOrBeingEnabled();
if (isAirplaneModeOn && !isPowerOff()
&& !phone.getServiceStateTracker().getDesiredPowerState()) {
@@ -1613,8 +1690,19 @@
mRadioOnHelper.triggerRadioOnAndListen(new RadioOnStateListener.Callback() {
@Override
public void onComplete(RadioOnStateListener listener, boolean isRadioReady) {
+ // Make sure the Call has not already been canceled by the user.
+ if (expectedConnection.getState() == STATE_DISCONNECTED) {
+ Rlog.i(TAG, "Call disconnected before the outgoing call was placed."
+ + "Skipping call placement.");
+ // If call is already canceled by the user, notify modem to exit emergency
+ // call mode by sending radio on with forEmergencyCall=false.
+ for (Phone phone : mPhoneFactoryProxy.getPhones()) {
+ phone.setRadioPower(true, false, false, true);
+ }
+ return;
+ }
if (!isRadioReady) {
- if (satelliteController.isSatelliteEnabled()) {
+ if (satelliteController.isSatelliteEnabledOrBeingEnabled()) {
// Could not turn satellite off
Rlog.e(TAG, "Failed to turn off satellite modem.");
completeEmergencyMode(emergencyType, DisconnectCause.SATELLITE_ENABLED);
@@ -1647,7 +1735,7 @@
return false;
}
return phone.getServiceStateTracker().isRadioOn()
- && !satelliteController.isSatelliteEnabled();
+ && !satelliteController.isSatelliteEnabledOrBeingEnabled();
}
@Override
@@ -1659,10 +1747,9 @@
}
// onTimeout shall be called only with the Phone for emergency
return phone.getServiceStateTracker().isRadioOn()
- && !satelliteController.isSatelliteEnabled();
+ && !satelliteController.isSatelliteEnabledOrBeingEnabled();
}
- }, !isTestEmergencyNumber, phone, isTestEmergencyNumber, waitForInServiceTimeout,
- /* forNormalRoutingEmergencyCall */ false);
+ }, !isTestEmergencyNumber, phone, isTestEmergencyNumber, waitForInServiceTimeout);
} else {
switchDdsAndSetEmergencyMode(phone, emergencyType);
}
diff --git a/src/java/com/android/internal/telephony/emergency/RadioOnHelper.java b/src/java/com/android/internal/telephony/emergency/RadioOnHelper.java
index 26da1c2..e2291c9 100644
--- a/src/java/com/android/internal/telephony/emergency/RadioOnHelper.java
+++ b/src/java/com/android/internal/telephony/emergency/RadioOnHelper.java
@@ -85,7 +85,7 @@
*/
public void triggerRadioOnAndListen(RadioOnStateListener.Callback callback,
boolean forEmergencyCall, Phone phoneForEmergencyCall, boolean isTestEmergencyNumber,
- int emergencyTimeoutIntervalMillis, boolean forNormalRoutingEmergencyCall) {
+ int emergencyTimeoutIntervalMillis) {
setupListeners();
mCallback = callback;
mInProgressListeners.clear();
@@ -102,13 +102,9 @@
mListeners.get(i).waitForRadioOn(phone, this, forEmergencyCall, forEmergencyCall
&& phone == phoneForEmergencyCall, timeoutCallbackInterval);
}
- powerOnRadio(forEmergencyCall, phoneForEmergencyCall, isTestEmergencyNumber,
- forNormalRoutingEmergencyCall);
- if (SatelliteController.getInstance().isSatelliteEnabled()
- || SatelliteController.getInstance().isSatelliteBeingEnabled()) {
- // TODO: phoneForEmergencyCall is actually ignored, SatelliteController#mSatelliePhone
- // is being used instead.
- powerOffSatellite(phoneForEmergencyCall);
+ powerOnRadio(forEmergencyCall, phoneForEmergencyCall, isTestEmergencyNumber);
+ if (SatelliteController.getInstance().isSatelliteEnabledOrBeingEnabled()) {
+ powerOffSatellite();
}
}
@@ -117,25 +113,17 @@
* get an onServiceStateChanged() callback when the radio successfully comes up.
*/
private void powerOnRadio(boolean forEmergencyCall, Phone phoneForEmergencyCall,
- boolean isTestEmergencyNumber, boolean forNormalRoutingEmergencyCall) {
+ boolean isTestEmergencyNumber) {
// Always try to turn on the radio here independent of APM setting - if we got here in the
// first place, the radio is off independent of APM setting.
for (Phone phone : PhoneFactory.getPhones()) {
Rlog.d(TAG, "powerOnRadio, enabling Radio");
if (isTestEmergencyNumber) {
- phone.setRadioPowerOnForTestEmergencyCall(
- (phone == phoneForEmergencyCall) && !forNormalRoutingEmergencyCall);
+ phone.setRadioPowerOnForTestEmergencyCall(phone == phoneForEmergencyCall);
} else {
- if (forNormalRoutingEmergencyCall) {
- if (phone.getServiceStateTracker() != null) {
- // Clear all radio off reasons to ensure that the radio is turned on for
- // normal routing emergency call.
- phone.getServiceStateTracker().clearAllRadioOffReasons();
- }
- }
- phone.setRadioPower(true, forEmergencyCall && !forNormalRoutingEmergencyCall,
- (phone == phoneForEmergencyCall) && !forNormalRoutingEmergencyCall, false);
+ phone.setRadioPower(true, forEmergencyCall, phone == phoneForEmergencyCall,
+ false);
}
}
@@ -162,7 +150,7 @@
* Attempt to power off the satellite modem. We'll eventually get an
* onSatelliteModemStateChanged() callback when the satellite modem is successfully disabled.
*/
- private void powerOffSatellite(Phone phoneForEmergencyCall) {
+ private void powerOffSatellite() {
SatelliteController satelliteController = SatelliteController.getInstance();
satelliteController.requestSatelliteEnabled(
false /* enableSatellite */, false /* enableDemoMode */, false /* isEmergency */,
diff --git a/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java b/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
index 1b1922c..f44dc70 100644
--- a/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
+++ b/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
@@ -157,6 +157,11 @@
public void onRegistrationFailure(int causeCode) {
Rlog.d(TAG, "onRegistrationFailure: causeCode " + causeCode);
}
+
+ @Override
+ public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) {
+ Rlog.d(TAG, "onTerrestrialNetworkAvailableChanged: isAvailable " + isAvailable);
+ }
};
private Callback mCallback; // The callback to notify upon completion.
@@ -230,7 +235,7 @@
// Register for RADIO_OFF to handle cases where emergency call is dialed before
// we receive UNSOL_RESPONSE_RADIO_STATE_CHANGED with RADIO_OFF.
registerForRadioOff();
- if (mSatelliteController.isSatelliteEnabled()) {
+ if (mSatelliteController.isSatelliteEnabledOrBeingEnabled()) {
// Register for satellite modem state changed to notify when satellite is disabled.
registerForSatelliteEnabledChanged();
}
@@ -401,7 +406,7 @@
Rlog.d(TAG, "Trying (again) to turn the radio on and satellite modem off.");
mPhone.setRadioPower(true, mForEmergencyCall, mSelectedPhoneForEmergencyCall,
false);
- if (mSatelliteController.isSatelliteEnabled()) {
+ if (mSatelliteController.isSatelliteEnabledOrBeingEnabled()) {
mSatelliteController.requestSatelliteEnabled(
false /* enableSatellite */, false /* enableDemoMode */,
false /* isEmergency*/,
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccConnector.java b/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
index b758733..c5cc769 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
@@ -749,10 +749,12 @@
@Override
public boolean processMessage(Message message) {
if (message.what == CMD_SERVICE_DISCONNECTED) {
+ EuiccSession.get().endAllSessions();
mEuiccService = null;
transitionTo(mDisconnectedState);
return HANDLED;
} else if (message.what == CMD_LINGER_TIMEOUT) {
+ EuiccSession.get().endAllSessions();
unbind();
transitionTo(mAvailableState);
return HANDLED;
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccController.java b/src/java/com/android/internal/telephony/euicc/EuiccController.java
index 715116e..cc9d793 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccController.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccController.java
@@ -22,6 +22,7 @@
import android.Manifest.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
@@ -70,6 +71,7 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.euicc.EuiccConnector.OtaStatusChangedCallback;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.telephony.uicc.UiccController;
@@ -1089,7 +1091,7 @@
// system or the caller manage the target subscription, we let it continue. This is
// because deleting subscription won't change status of any other subscriptions.
if (!callerCanWriteEmbeddedSubscriptions
- && !mSubscriptionManager.canManageSubscription(sub, callingPackage)
+ && !canManageSubscription(sub, callingPackage)
&& !adminOwned) {
Log.e(TAG, "No permissions: " + subscriptionId + " adminOwned=" + adminOwned);
sendResult(callbackIntent, ERROR, null /* extrasIntent */);
@@ -1208,7 +1210,7 @@
if (callerCanWriteEmbeddedSubscriptions) {
passConsent = true;
} else {
- if (!mSubscriptionManager.canManageSubscription(sub, callingPackage)) {
+ if (!canManageSubscription(sub, callingPackage)) {
Log.e(TAG, "Not permitted to switch to sub: " + subscriptionId);
sendResult(callbackIntent, ERROR, null /* extrasIntent */);
return;
@@ -1287,7 +1289,7 @@
if ((cardId == TelephonyManager.UNSUPPORTED_CARD_ID || subInfo.getCardId() == cardId)
&& subInfo.isEmbedded()
&& (callerCanWriteEmbeddedSubscriptions
- || mSubscriptionManager.canManageSubscription(subInfo, callingPackage))) {
+ || canManageSubscription(subInfo, callingPackage))) {
return subInfo.getPortIndex();
}
}
@@ -1558,7 +1560,7 @@
// system or the caller can manage the target subscription, we let it continue. This is
// because updating subscription nickname won't affect any other subscriptions.
if (!callerCanWriteEmbeddedSubscriptions
- && !mSubscriptionManager.canManageSubscription(sub, callingPackage)) {
+ && !canManageSubscription(sub, callingPackage)) {
Log.e(TAG, "No permissions: " + subscriptionId);
sendResult(callbackIntent, ERROR, null /* extrasIntent */);
return;
@@ -2067,7 +2069,7 @@
if ((cardId == TelephonyManager.UNSUPPORTED_CARD_ID || subInfo.getCardId() == cardId)
&& subInfo.isEmbedded()
&& (!usePortIndex || subInfo.getPortIndex() == targetPortIndex)
- && mSubscriptionManager.canManageSubscription(subInfo, callingPackage)) {
+ && canManageSubscription(subInfo, callingPackage)) {
return true;
}
}
@@ -2136,8 +2138,7 @@
if (subInfo.isEmbedded()
&& subInfo.getCardId() == cardId
&& (!usePortIndex || subInfo.getPortIndex() == targetPortIndex)
- && mSubscriptionManager.canManageSubscription(
- subInfo, callingPackage)) {
+ && canManageSubscription(subInfo, callingPackage)) {
return true;
}
}
@@ -2156,7 +2157,7 @@
} else {
for (SubscriptionInfo subInfo : subInfoList) {
if (subInfo.isEmbedded()
- && mSubscriptionManager.canManageSubscription(subInfo, callingPackage)) {
+ && canManageSubscription(subInfo, callingPackage)) {
return true;
}
}
@@ -2391,4 +2392,13 @@
methodName + " is unsupported without " + FEATURE_TELEPHONY_EUICC);
}
}
+
+ private boolean canManageSubscription(SubscriptionInfo subInfo, String packageName) {
+ if (Flags.hsumPackageManager() && UserManager.isHeadlessSystemUserMode()) {
+ return mSubscriptionManager.canManageSubscriptionAsUser(subInfo, packageName,
+ UserHandle.of(ActivityManager.getCurrentUser()));
+ } else {
+ return mSubscriptionManager.canManageSubscription(subInfo, packageName);
+ }
+ }
}
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccSession.java b/src/java/com/android/internal/telephony/euicc/EuiccSession.java
index 99b8720..f17789f 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccSession.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccSession.java
@@ -15,6 +15,7 @@
*/
package com.android.internal.telephony.euicc;
+import android.annotation.Nullable;
import android.util.ArraySet;
import com.android.internal.annotations.GuardedBy;
@@ -85,14 +86,18 @@
/** Returns {@code true} if there is at least one session ongoing. */
public boolean hasSession() {
- boolean hasSession;
- synchronized(this) {
- hasSession = !mSessions.isEmpty();
- }
+ boolean hasSession = hasSessionInternal();
Rlog.i(TAG, "hasSession: " + hasSession);
return hasSession;
}
+ // The bare metal implementation of hasSession() without logging.
+ private boolean hasSessionInternal() {
+ synchronized(this) {
+ return !mSessions.isEmpty();
+ }
+ }
+
/**
* Notes that a logical channel may be opened by the {@code apduSender}, which will
* be used to close the channel when session ends (see {@link #endSession()}).
@@ -104,7 +109,7 @@
public void noteChannelOpen(ApduSender apduSender) {
Rlog.i(TAG, "noteChannelOpen: " + apduSender);
synchronized(this) {
- if (hasSession()) {
+ if (hasSessionInternal()) {
mApduSenders.add(apduSender);
}
}
@@ -112,19 +117,41 @@
/**
* Marks the end of a eUICC transaction session. If this ends the last ongoing session,
- * try to close the logical channel using the noted {@code apduSender}
+ * try to close the logical channel using the noted {@code apduSender}s
* (see {@link #noteChannelOpen()}).
*
* @param sessionId The session ID.
*/
public void endSession(String sessionId) {
Rlog.i(TAG, "endSession: " + sessionId);
+ endSessionInternal(sessionId);
+ }
+
+ /**
+ * Marks the end of all eUICC transaction sessions and close the logical
+ * channels using the noted {@code apduSender}s
+ * (see {@link #noteChannelOpen()}).
+ *
+ * <p>This is useful in global cleanup e.g. when EuiccService
+ * implementation app crashes and indivial {@link #endSession()} calls
+ * won't happen in {@link EuiccConnector}.
+ */
+ public void endAllSessions() {
+ Rlog.i(TAG, "endAllSessions");
+ endSessionInternal(null);
+ }
+
+ // The implementation of endSession(sessionId) or endAllSessions() when the sessionId is null,
+ // without logging.
+ private void endSessionInternal(@Nullable String sessionId) {
ApduSender[] apduSenders = new ApduSender[0];
synchronized(this) {
- boolean sessionRemoved = mSessions.remove(sessionId);
- // sessionRemoved is false if the `sessionId` was never started or there was
- // no session at all i.e. `sessions` is empty. Don't bother invoke `apduSender`.
- if (sessionRemoved && mSessions.isEmpty()) {
+ boolean sessionRemoved = removeOrClear(mSessions, sessionId);
+ // 1. sessionRemoved is false if the `sessionId` was never started or there was
+ // no session. Don't bother invoke `apduSender`.
+ // 2. If some session is removed, and as a result there is no more session, we
+ // can clsoe channels.
+ if (sessionRemoved && !hasSessionInternal()) {
// copy mApduSenders to a local variable so we don't call closeAnyOpenChannel()
// which can take time in synchronized block.
apduSenders = mApduSenders.toArray(apduSenders);
@@ -136,6 +163,21 @@
}
}
+ /**
+ * Removes the given element from the set. If the element is null, clears the set.
+ *
+ * @return true if the set changed as a result of the call
+ */
+ private static boolean removeOrClear(Set<String> collection, @Nullable String element) {
+ if (element == null) {
+ boolean collectionChanged = !collection.isEmpty();
+ collection.clear();
+ return collectionChanged;
+ } else {
+ return collection.remove(element);
+ }
+ }
+
@VisibleForTesting
public EuiccSession() {}
}
diff --git a/src/java/com/android/internal/telephony/ims/ImsResolver.java b/src/java/com/android/internal/telephony/ims/ImsResolver.java
index eb389b7..b95911f 100644
--- a/src/java/com/android/internal/telephony/ims/ImsResolver.java
+++ b/src/java/com/android/internal/telephony/ims/ImsResolver.java
@@ -19,6 +19,7 @@
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -51,6 +52,7 @@
import android.util.ArraySet;
import android.util.LocalLog;
import android.util.Log;
+import android.util.Pair;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -129,6 +131,10 @@
private static final int HANDLER_MSIM_CONFIGURATION_CHANGE = 7;
// clear any carrier ImsService test overrides.
private static final int HANDLER_CLEAR_CARRIER_IMS_SERVICE_CONFIG = 8;
+ // the user has switched
+ private static final int HANDLER_USER_SWITCHED = 9;
+ // A dynamic query has failed permanently, remove the package from being tracked
+ private static final int HANDLER_REMOVE_PACKAGE_PERM_ERROR = 10;
// Delay between dynamic ImsService queries.
private static final int DELAY_DYNAMIC_QUERY_MS = 5000;
@@ -158,14 +164,19 @@
}
private static class OverrideConfig {
+ public final String packageName;
public final int slotId;
+ public final int userId;
public final boolean isCarrierService;
- public final Map<Integer, String> featureTypeToPackageMap;
+ public final int[] featureTypes;
- OverrideConfig(int slotIndex, boolean isCarrier, Map<Integer, String> feature) {
+ OverrideConfig(String pkgName, int slotIndex, int userIndex, boolean isCarrier,
+ int[] features) {
+ packageName = pkgName;
slotId = slotIndex;
+ userId = userIndex;
isCarrierService = isCarrier;
- featureTypeToPackageMap = feature;
+ featureTypes = features;
}
}
@@ -175,7 +186,8 @@
*/
@VisibleForTesting
public static class ImsServiceInfo {
- public ComponentName name;
+ public final ComponentName name;
+ public final Set<UserHandle> users = new HashSet<>();
// Determines if features were created from metadata in the manifest or through dynamic
// query.
public boolean featureFromMetadata = true;
@@ -184,7 +196,8 @@
// Map slotId->Feature
private final HashSet<ImsFeatureConfiguration.FeatureSlotPair> mSupportedFeatures;
- public ImsServiceInfo() {
+ public ImsServiceInfo(ComponentName componentName) {
+ name = componentName;
mSupportedFeatures = new HashSet<>();
}
@@ -208,37 +221,41 @@
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
-
ImsServiceInfo that = (ImsServiceInfo) o;
-
- if (name != null ? !name.equals(that.name) : that.name != null) return false;
- if (!mSupportedFeatures.equals(that.mSupportedFeatures)) {
- return false;
- }
- return controllerFactory != null ? controllerFactory.equals(that.controllerFactory)
- : that.controllerFactory == null;
+ return Objects.equals(name, that.name) && Objects.equals(users, that.users);
}
@Override
public int hashCode() {
- // We do not include mSupportedFeatures in hashcode because the internal structure
- // changes after adding.
- int result = name != null ? name.hashCode() : 0;
- result = 31 * result + (controllerFactory != null ? controllerFactory.hashCode() : 0);
- return result;
+ return Objects.hash(name, users);
}
@Override
public String toString() {
return "[ImsServiceInfo] name="
+ name
- + ", featureFromMetadata="
+ + ", user="
+ + users
+ + ",featureFromMetadata="
+ featureFromMetadata
+ ","
+ printFeatures(mSupportedFeatures);
}
}
+ private final BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ final UserHandle handle = intent.getParcelableExtra(Intent.EXTRA_USER,
+ UserHandle.class);
+ switch (action) {
+ case Intent.ACTION_USER_SWITCHED ->
+ mHandler.obtainMessage(HANDLER_USER_SWITCHED, handle).sendToTarget();
+ }
+ }
+ };
+
// Receives broadcasts from the system involving changes to the installed applications. If
// an ImsService that we are configured to use is installed, we must bind to it.
private final BroadcastReceiver mAppChangedReceiver = new BroadcastReceiver() {
@@ -311,6 +328,17 @@
};
/**
+ * Testing interface used to mock ActivityManager in testing
+ */
+ @VisibleForTesting
+ public interface ActivityManagerProxy {
+ /**
+ * @return The current user
+ */
+ UserHandle getCurrentUser();
+ }
+
+ /**
* Testing interface used to mock SubscriptionManager in testing
*/
@VisibleForTesting
@@ -360,6 +388,13 @@
}
};
+ private ActivityManagerProxy mActivityManagerProxy = new ActivityManagerProxy() {
+ @Override
+ public UserHandle getCurrentUser() {
+ return UserHandle.of(ActivityManager.getCurrentUser());
+ }
+ };
+
/**
* Testing interface for injecting mock ImsServiceControllers.
*/
@@ -470,6 +505,11 @@
maybeRemovedImsService(packageName);
break;
}
+ case HANDLER_REMOVE_PACKAGE_PERM_ERROR: {
+ Pair<String, UserHandle> packageInfo = (Pair<String, UserHandle>) msg.obj;
+ maybeRemovedImsServiceForUser(packageInfo.first, packageInfo.second);
+ break;
+ }
case HANDLER_BOOT_COMPLETE: {
if (!mBootCompletedHandlerRan) {
mBootCompletedHandlerRan = true;
@@ -517,11 +557,15 @@
}
case HANDLER_OVERRIDE_IMS_SERVICE_CONFIG: {
OverrideConfig config = (OverrideConfig) msg.obj;
+ setPackageNameUserOverride(config.packageName, config.userId);
+ Map<Integer, String> featureConfig = new HashMap<>();
+ for (int featureType : config.featureTypes) {
+ featureConfig.put(featureType, config.packageName);
+ }
if (config.isCarrierService) {
- overrideCarrierService(config.slotId,
- config.featureTypeToPackageMap);
+ overrideCarrierService(config.slotId, featureConfig);
} else {
- overrideDeviceService(config.featureTypeToPackageMap);
+ overrideDeviceService(featureConfig);
}
break;
}
@@ -534,6 +578,11 @@
clearCarrierServiceOverrides(msg.arg1);
break;
}
+ case HANDLER_USER_SWITCHED: {
+ UserHandle handle = (UserHandle) msg.obj;
+ Log.i(TAG, "onUserSwitched=" + handle);
+ maybeAddedImsService(null);
+ }
default:
break;
}
@@ -561,11 +610,16 @@
}
@Override
- public void onPermanentError(ComponentName name) {
+ public void onPermanentError(ComponentName name, UserHandle user) {
Log.w(TAG, "onPermanentError: component=" + name);
mEventLog.log("onPermanentError - error for " + name);
- mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE,
- name.getPackageName()).sendToTarget();
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE,
+ name.getPackageName()).sendToTarget();
+ } else {
+ mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE_PERM_ERROR,
+ new Pair<>(name.getPackageName(), user)).sendToTarget();
+ }
}
};
@@ -573,6 +627,8 @@
// Array index corresponds to slot, per slot there is a feature->package name mapping.
// should only be accessed from handler
private final SparseArray<SparseArray<String>> mOverrideServices;
+ //Used during testing, restricts the ImsService to be bound on a specific user.
+ private final Map<String, UserHandle> mImsServiceTestUserRestrictions = new HashMap<>();
// Outer array index corresponds to Slot Id, Maps ImsFeature.FEATURE->bound ImsServiceController
// Locked on mBoundServicesLock
private final SparseArray<SparseArray<ImsServiceController>> mBoundImsServicesByFeature;
@@ -628,6 +684,11 @@
}
@VisibleForTesting
+ public void setActivityManagerProxy(ActivityManagerProxy proxy) {
+ mActivityManagerProxy = proxy;
+ }
+
+ @VisibleForTesting
public Handler getHandler() {
return mHandler;
}
@@ -660,6 +721,10 @@
appChangedFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
appChangedFilter.addDataScheme("package");
mReceiverContext.registerReceiver(mAppChangedReceiver, appChangedFilter);
+ if (mFeatureFlags.imsResolverUserAware()) {
+ mReceiverContext.registerReceiver(mUserReceiver, new IntentFilter(
+ Intent.ACTION_USER_SWITCHED));
+ }
mReceiverContext.registerReceiver(mConfigChangedReceiver, new IntentFilter(
CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
@@ -706,19 +771,24 @@
// carrier config changed.
private void bindCarrierServicesIfAvailable() {
boolean hasConfigChanged = false;
+ boolean pendingDynamicQuery = false;
for (int slotId = 0; slotId < mNumSlots; slotId++) {
int subId = mSubscriptionManagerProxy.getSubId(slotId);
Map<Integer, String> featureMap = getImsPackageOverrideConfig(subId);
for (int f = ImsFeature.FEATURE_EMERGENCY_MMTEL; f < ImsFeature.FEATURE_MAX; f++) {
String newPackageName = featureMap.getOrDefault(f, "");
if (!TextUtils.isEmpty(newPackageName)) {
+ Log.d(TAG, "bindCarrierServicesIfAvailable - carrier package found: "
+ + newPackageName + ", feature "
+ + ImsFeature.FEATURE_LOG_MAP.getOrDefault(f, "invalid")
+ + " on slot " + slotId);
mEventLog.log("bindCarrierServicesIfAvailable - carrier package found: "
+ newPackageName + " on slot " + slotId);
// Carrier configs are already available, so mark received.
mCarrierConfigReceived = true;
setSubId(slotId, subId);
setCarrierConfiguredPackageName(newPackageName, slotId, f);
- ImsServiceInfo info = getImsServiceInfoFromCache(newPackageName);
+ ImsServiceInfo info = getVisibleImsServiceInfoFromCache(newPackageName);
// We do not want to trigger feature configuration changes unless there is
// already a valid carrier config change.
if (info != null && info.featureFromMetadata) {
@@ -726,11 +796,18 @@
} else {
// Config will change when this query completes
scheduleQueryForFeatures(info);
+ if (info != null) pendingDynamicQuery = true;
}
}
}
}
- if (hasConfigChanged) calculateFeatureConfigurationChange();
+ // we want to make sure that we are either pending to bind to a carrier configured service
+ // or bind to the device config if we potentially missed the carrier config changed
+ // indication.
+ if (hasConfigChanged || (mFeatureFlags.imsResolverUserAware()
+ && mCarrierConfigReceived && !pendingDynamicQuery)) {
+ calculateFeatureConfigurationChange();
+ }
}
/**
@@ -833,14 +910,15 @@
}
// Used for testing only.
- public boolean overrideImsServiceConfiguration(int slotId, boolean isCarrierService,
- Map<Integer, String> featureConfig) {
+ public boolean overrideImsServiceConfiguration(String packageName, int slotId, int userId,
+ boolean isCarrierService, int[] overrideFeatureTypes) {
if (slotId < 0 || slotId >= mNumSlots) {
Log.w(TAG, "overrideImsServiceConfiguration: invalid slotId!");
return false;
}
- OverrideConfig overrideConfig = new OverrideConfig(slotId, isCarrierService, featureConfig);
+ OverrideConfig overrideConfig = new OverrideConfig(packageName, slotId, userId,
+ isCarrierService, overrideFeatureTypes);
Message.obtain(mHandler, HANDLER_OVERRIDE_IMS_SERVICE_CONFIG, overrideConfig)
.sendToTarget();
return true;
@@ -881,10 +959,14 @@
}
// not synchronized, access in handler ONLY.
- private void removeOverridePackageName(int slotId) {
+ private Set<String> removeOverridePackageName(int slotId) {
+ Set<String> removedOverrides = new HashSet<>();
for (int f = ImsFeature.FEATURE_EMERGENCY_MMTEL; f < ImsFeature.FEATURE_MAX; f++) {
- getOverridePackageName(slotId).remove(f);
+ SparseArray<String> overrides = getOverridePackageName(slotId);
+ String packageName = overrides.removeReturnOld(f);
+ if (packageName != null) removedOverrides.add(packageName);
}
+ return removedOverrides;
}
// not synchronized, access in handler ONLY.
@@ -894,6 +976,22 @@
}
// not synchronized, access in handler ONLY.
+ private void setPackageNameUserOverride(String packageName, int userId) {
+ if (packageName == null || packageName.isEmpty() || userId == UserHandle.USER_NULL) return;
+ Log.i(TAG, "setPackageNameUserOverride: set for " + packageName + ", user= " + userId);
+ mImsServiceTestUserRestrictions.put(packageName, UserHandle.of(userId));
+ }
+
+ // not synchronized, access in handler ONLY.
+ private void clearPackageNameUserOverride(String packageName) {
+ UserHandle handle = mImsServiceTestUserRestrictions.remove(packageName);
+ if (handle != null) {
+ Log.i(TAG, "clearPackageNameUserOverride: cleared for " + packageName
+ + "on user " + handle);
+ }
+ }
+
+ // not synchronized, access in handler ONLY.
private @Nullable String getOverridePackageName(int slotId,
@ImsFeature.FeatureType int featureType) {
return getOverridePackageName(slotId).get(featureType);
@@ -927,13 +1025,14 @@
/**
* Check the cached ImsServices that exist on this device to determine if there is a ImsService
- * with the same package name that matches the provided configuration.
+ * with the same package name that matches the provided configuration and is configured to run
+ * in one of the active users.
*/
// not synchronized, access in handler ONLY.
private boolean doesCachedImsServiceExist(String packageName, int slotId,
@ImsFeature.FeatureType int featureType) {
// Config exists, but the carrier ImsService also needs to support this feature
- ImsServiceInfo info = getImsServiceInfoFromCache(packageName);
+ ImsServiceInfo info = getVisibleImsServiceInfoFromCache(packageName);
return info != null && info.getSupportedFeatures().stream().anyMatch(
feature -> feature.slotId == slotId && feature.featureType == featureType);
}
@@ -1073,7 +1172,8 @@
return null;
}
- private void putImsController(int slotId, int feature, ImsServiceController controller) {
+ private void putImsController(int slotId, int subId, int feature,
+ ImsServiceController controller) {
if (slotId < 0 || slotId >= mNumSlots || feature <= ImsFeature.FEATURE_INVALID
|| feature >= ImsFeature.FEATURE_MAX) {
Log.w(TAG, "putImsController received invalid parameters - slot: " + slotId
@@ -1088,9 +1188,9 @@
}
mEventLog.log("putImsController - [" + slotId + ", "
+ ImsFeature.FEATURE_LOG_MAP.get(feature) + "] -> " + controller);
- Log.i(TAG, "ImsServiceController added on slot: " + slotId + " with feature: "
- + ImsFeature.FEATURE_LOG_MAP.get(feature) + " using package: "
- + controller.getComponentName());
+ Log.i(TAG, "ImsServiceController added on slot: " + slotId + ", subId: " + subId
+ + " with feature: " + ImsFeature.FEATURE_LOG_MAP.get(feature)
+ + " using package: " + controller.getComponentName());
services.put(feature, controller);
}
}
@@ -1134,6 +1234,10 @@
// features. Will only be one (if it exists), since it is a set.
ImsServiceInfo match = getInfoByComponentName(mInstalledServicesCache, info.name);
if (match != null) {
+ if (mFeatureFlags.imsResolverUserAware()) {
+ match.users.clear();
+ match.users.addAll(info.users);
+ }
// for dynamic query the new "info" will have no supported features yet. Don't wipe
// out the cache for the existing features or update yet. Instead start a query
// for features dynamically.
@@ -1141,9 +1245,8 @@
mEventLog.log("maybeAddedImsService - updating features for " + info.name
+ ": " + printFeatures(match.getSupportedFeatures()) + " -> "
+ printFeatures(info.getSupportedFeatures()));
- Log.i(TAG, "Updating features in cached ImsService: " + info.name);
- Log.d(TAG, "Updating features - Old features: " + match + " new features: "
- + info);
+ Log.d(TAG, "Updating features in cached ImsService: " + info.name
+ + ", old features: " + match + " new features: " + info);
// update features in the cache
match.replaceFeatures(info.getSupportedFeatures());
requiresCalculation = true;
@@ -1168,10 +1271,9 @@
if (requiresCalculation) calculateFeatureConfigurationChange();
}
- // Remove the ImsService from the cache. This may have been due to the ImsService being removed
- // from the device or was returning permanent errors when bound.
+ // Remove the ImsService from the cache due to the ImsService package being removed.
// Called from the handler ONLY
- private boolean maybeRemovedImsService(String packageName) {
+ private boolean maybeRemovedImsServiceOld(String packageName) {
ImsServiceInfo match = getInfoByPackageName(mInstalledServicesCache, packageName);
if (match != null) {
mInstalledServicesCache.remove(match.name);
@@ -1184,6 +1286,70 @@
return false;
}
+ // Remove the ImsService from the cache due to the ImsService package being removed.
+ // Called from the handler ONLY
+ private boolean maybeRemovedImsService(String packageName) {
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ return maybeRemovedImsServiceOld(packageName);
+ }
+ ImsServiceInfo match = getInfoByPackageName(mInstalledServicesCache, packageName);
+ if (match != null) {
+ List<ImsServiceInfo> imsServices = searchForImsServices(packageName,
+ match.controllerFactory);
+ ImsServiceInfo newMatch = imsServices.isEmpty() ? null : imsServices.getFirst();
+ if (newMatch == null) {
+ clearPackageNameUserOverride(match.name.getPackageName());
+ // The package doesn't exist anymore on any user, so remove
+ mInstalledServicesCache.remove(match.name);
+ mEventLog.log("maybeRemovedImsService - removing ImsService: " + match);
+ Log.i(TAG, "maybeRemovedImsService Removing ImsService for all users: "
+ + match.name);
+ unbindImsService(match);
+ } else {
+ // The Package exists on some users still, so modify the users
+ match.users.clear();
+ match.users.addAll(newMatch.users);
+ mEventLog.log("maybeRemovedImsService - modifying ImsService users: " + match);
+ Log.i(TAG, "maybeRemovedImsService - Modifying ImsService users " + match);
+ // If this package still remains on some users, then it is possible we are unbinding
+ // an active ImsService, but the assumption here is that the package is being
+ // removed on an active user. Be safe and unbind now - we will rebind below if
+ // needed.
+ unbindImsService(match);
+ }
+ calculateFeatureConfigurationChange();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Remove the cached ImsService for a specific user. If there are no more users available after
+ * removing the specified user, remove the ImsService cache entry entirely.
+ */
+ // Called from the handler ONLY
+ private boolean maybeRemovedImsServiceForUser(String packageName, UserHandle user) {
+ ImsServiceInfo match = getInfoByPackageName(mInstalledServicesCache, packageName);
+ if (match != null) {
+ mEventLog.log("maybeRemovedImsServiceForUser - removing ImsService " + match
+ + "for user " + user);
+ Log.i(TAG, "maybeRemovedImsServiceForUser: Removing ImsService "
+ + match + "for user " + user);
+ unbindImsService(match);
+ match.users.remove(user);
+ if (match.users.isEmpty()) {
+ mEventLog.log("maybeRemovedImsServiceForUser - no more users, removing "
+ + "ImsService " + match);
+ Log.i(TAG, "maybeRemovedImsServiceForUser - no more users, removing "
+ + "ImsService " + match);
+ mInstalledServicesCache.remove(match.name);
+ }
+ calculateFeatureConfigurationChange();
+ return true;
+ }
+ return false;
+ }
+
private boolean isDeviceService(ImsServiceInfo info) {
if (info == null) return false;
synchronized (mDeviceServices) {
@@ -1193,6 +1359,14 @@
private List<Integer> getSlotsForActiveCarrierService(ImsServiceInfo info) {
if (info == null) return Collections.emptyList();
+ if (mFeatureFlags.imsResolverUserAware()) {
+ UserHandle activeUser = getUserForBind(info);
+ if (activeUser == null) {
+ Log.d(TAG, "getSlotsForActiveCarrierService: ImsService " + info.name + "is not "
+ + "configured to run for any users, skipping...");
+ return Collections.emptyList();
+ }
+ }
List<Integer> slots = new ArrayList<>(mNumSlots);
for (int i = 0; i < mNumSlots; i++) {
if (!TextUtils.isEmpty(getCarrierConfiguredPackageNames(i).values().stream()
@@ -1222,7 +1396,7 @@
return searchMap.get(matchValue);
}
- private void bindImsServiceWithFeatures(ImsServiceInfo info,
+ private void bindImsServiceWithFeatures(ImsServiceInfo info, UserHandle user,
Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
// Only bind if there are features that will be created by the service.
if (shouldFeaturesCauseBind(features)) {
@@ -1230,10 +1404,21 @@
ImsServiceController controller = getControllerByServiceInfo(mActiveControllers, info);
SparseIntArray slotIdToSubIdMap = mSlotIdToSubIdMap.clone();
if (controller != null) {
- Log.i(TAG, "ImsService connection exists for " + info.name + ", updating features "
- + features);
try {
- controller.changeImsServiceFeatures(features, slotIdToSubIdMap);
+ if (!mFeatureFlags.imsResolverUserAware()
+ || Objects.equals(user, controller.getBoundUser())) {
+ Log.i(TAG, "ImsService connection exists for " + info.name
+ + ", updating features " + features);
+ controller.changeImsServiceFeatures(features, slotIdToSubIdMap);
+ } else {
+ // Changing a user is a pretty rare event, we need to unbind and rebind
+ // on the correct new user.
+ Log.i(TAG, "ImsService user changed for " + info.name
+ + ", rebinding on user " + user + ", features " + features);
+ controller.unbind();
+ controller.bind(user, features, slotIdToSubIdMap);
+ }
+
// Features have been set, there was an error adding/removing. When the
// controller recovers, it will add/remove again.
} catch (RemoteException e) {
@@ -1243,8 +1428,9 @@
controller = info.controllerFactory.create(mContext, info.name, this, mRepo,
mFeatureFlags);
Log.i(TAG, "Binding ImsService: " + controller.getComponentName()
- + " with features: " + features);
- controller.bind(features, slotIdToSubIdMap);
+ + "on user " + user + " with features: " + features + ", subIdMap: "
+ + slotIdToSubIdMap);
+ controller.bind(user, features, slotIdToSubIdMap);
mEventLog.log("bindImsServiceWithFeatures - create new controller: "
+ controller);
}
@@ -1285,7 +1471,7 @@
imsFeaturesBySlot.addAll(info.getSupportedFeatures().stream()
.filter(feature -> info.name.getPackageName().equals(
getCarrierConfiguredPackageName(feature.slotId, feature.featureType)))
- .collect(Collectors.toList()));
+ .toList());
return imsFeaturesBySlot;
}
if (isDeviceService(info)) {
@@ -1298,7 +1484,7 @@
// by the carrier ImsService.
.filter(feature -> !doesCarrierConfigurationExist(feature.slotId,
feature.featureType))
- .collect(Collectors.toList()));
+ .toList());
}
return imsFeaturesBySlot;
}
@@ -1309,8 +1495,9 @@
* adds the ImsServiceController from the mBoundImsServicesByFeature structure.
*/
@Override
- public void imsServiceFeatureCreated(int slotId, int feature, ImsServiceController controller) {
- putImsController(slotId, feature, controller);
+ public void imsServiceFeatureCreated(int slotId, int subId, int feature,
+ ImsServiceController controller) {
+ putImsController(slotId, subId, feature, controller);
}
/**
@@ -1341,13 +1528,19 @@
}
@Override
- public void imsServiceBindPermanentError(ComponentName name) {
+ public void imsServiceBindPermanentError(ComponentName name, UserHandle user) {
if (name == null) {
return;
}
- Log.w(TAG, "imsServiceBindPermanentError: component=" + name);
- mEventLog.log("imsServiceBindPermanentError - for " + name);
- mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE, name.getPackageName()).sendToTarget();
+ Log.w(TAG, "imsServiceBindPermanentError: component=" + name + ", user=" + user);
+ mEventLog.log("imsServiceBindPermanentError - for " + name + ", user " + user);
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE,
+ name.getPackageName()).sendToTarget();
+ } else {
+ mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE_PERM_ERROR,
+ new Pair<>(name.getPackageName(), user)).sendToTarget();
+ }
}
/**
@@ -1381,7 +1574,10 @@
private void clearCarrierServiceOverrides(int slotId) {
Log.i(TAG, "clearing carrier ImsService overrides");
mEventLog.log("clearing carrier ImsService overrides");
- removeOverridePackageName(slotId);
+ Set<String> removedPackages = removeOverridePackageName(slotId);
+ for (String pkg : removedPackages) {
+ clearPackageNameUserOverride(pkg);
+ }
carrierConfigChanged(slotId, getSubId(slotId));
}
@@ -1399,8 +1595,9 @@
+ oldPackageName + " -> " + overridePackageName);
mEventLog.log("overrideDeviceService - device package changed (override): "
+ oldPackageName + " -> " + overridePackageName);
+ clearPackageNameUserOverride(oldPackageName);
setDeviceConfiguration(overridePackageName, featureType);
- ImsServiceInfo info = getImsServiceInfoFromCache(overridePackageName);
+ ImsServiceInfo info = getVisibleImsServiceInfoFromCache(overridePackageName);
if (info == null || info.featureFromMetadata) {
requiresRecalc = true;
} else {
@@ -1430,7 +1627,7 @@
ArrayMap<String, ImsServiceInfo> featureDynamicImsPackages = new ArrayMap<>();
for (int f = ImsFeature.FEATURE_EMERGENCY_MMTEL; f < ImsFeature.FEATURE_MAX; f++) {
String packageName = getDeviceConfiguration(f);
- ImsServiceInfo serviceInfo = getImsServiceInfoFromCache(packageName);
+ ImsServiceInfo serviceInfo = getVisibleImsServiceInfoFromCache(packageName);
if (serviceInfo != null && !serviceInfo.featureFromMetadata
&& !featureDynamicImsPackages.containsKey(packageName)) {
featureDynamicImsPackages.put(packageName, serviceInfo);
@@ -1465,13 +1662,7 @@
setCarrierConfiguredPackageName(newPackageName, slotId, f);
// Carrier config may have not changed, but we still want to kick off a recalculation
// in case there has been a change to the supported device features.
- ImsServiceInfo info = getImsServiceInfoFromCache(newPackageName);
- Log.i(TAG, "updateBoundServices - carrier package changed: "
- + oldPackageName + " -> " + newPackageName + " on slot " + slotId
- + ", hasConfigChanged=" + hasConfigChanged);
- mEventLog.log("updateBoundServices - carrier package changed: "
- + oldPackageName + " -> " + newPackageName + " on slot " + slotId
- + ", hasConfigChanged=" + hasConfigChanged);
+ ImsServiceInfo info = getVisibleImsServiceInfoFromCache(newPackageName);
if (info == null || info.featureFromMetadata) {
hasConfigChanged = true;
} else {
@@ -1479,6 +1670,12 @@
scheduleQueryForFeatures(info);
didQuerySchedule = true;
}
+ Log.i(TAG, "updateBoundServices - carrier package changed: "
+ + oldPackageName + " -> " + newPackageName + " on slot " + slotId
+ + ", hasConfigChanged=" + hasConfigChanged);
+ mEventLog.log("updateBoundServices - carrier package changed: "
+ + oldPackageName + " -> " + newPackageName + " on slot " + slotId
+ + ", hasConfigChanged=" + hasConfigChanged);
}
if (hasConfigChanged) calculateFeatureConfigurationChange();
@@ -1530,7 +1727,7 @@
}
private void scheduleQueryForFeatures(ComponentName name, int delayMs) {
- ImsServiceInfo service = getImsServiceInfoFromCache(name.getPackageName());
+ ImsServiceInfo service = getVisibleImsServiceInfoFromCache(name.getPackageName());
if (service == null) {
Log.w(TAG, "scheduleQueryForFeatures: Couldn't find cached info for name: " + name);
return;
@@ -1614,6 +1811,12 @@
// Starts a dynamic query. Called from handler ONLY.
private void startDynamicQuery(ImsServiceInfo service) {
+ UserHandle user = getUserForBind(service);
+ if (user == null) {
+ Log.i(TAG, "scheduleQueryForFeatures: skipping query for ImsService that is not"
+ + " running: " + service);
+ return;
+ }
// if not current device/carrier service, don't perform query. If this changes, this method
// will be called again.
if (!isDeviceService(service) && getSlotsForActiveCarrierService(service).isEmpty()) {
@@ -1622,7 +1825,7 @@
return;
}
mEventLog.log("startDynamicQuery - starting query for " + service);
- boolean queryStarted = mFeatureQueryManager.startQuery(service.name,
+ boolean queryStarted = mFeatureQueryManager.startQuery(service.name, user,
service.controllerFactory.getServiceInterface());
if (!queryStarted) {
Log.w(TAG, "startDynamicQuery: service could not connect. Retrying after delay.");
@@ -1637,7 +1840,7 @@
// process complete dynamic query. Called from handler ONLY.
private void dynamicQueryComplete(ComponentName name,
Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
- ImsServiceInfo service = getImsServiceInfoFromCache(name.getPackageName());
+ ImsServiceInfo service = getVisibleImsServiceInfoFromCache(name.getPackageName());
if (service == null) {
Log.w(TAG, "dynamicQueryComplete: Couldn't find cached info for name: "
+ name);
@@ -1683,17 +1886,92 @@
// Calculate the new configuration for the bound ImsServices.
// Should ONLY be called from the handler.
- private void calculateFeatureConfigurationChange() {
+ private void calculateFeatureConfigurationChangeOld() {
for (ImsServiceInfo info : mInstalledServicesCache.values()) {
Set<ImsFeatureConfiguration.FeatureSlotPair> features = calculateFeaturesToCreate(info);
if (shouldFeaturesCauseBind(features)) {
- bindImsServiceWithFeatures(info, features);
+ bindImsServiceWithFeatures(info, mContext.getUser(), features);
} else {
unbindImsService(info);
}
}
}
+ // Should ONLY be called from the handler.
+ private void calculateFeatureConfigurationChange() {
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ calculateFeatureConfigurationChangeOld();
+ return;
+ }
+ // There is an implicit assumption here that the ImsServiceController will remove itself
+ // from caches BEFORE adding a new one. If this assumption is broken, we will remove a valid
+ // ImsServiceController from the cache accidentally. To keep this assumption valid, we will
+ // iterate through the cache twice - first to unbind, then to bind and change features of
+ // existing ImsServiceControllers. This is a little inefficient, but there should be on the
+ // order of 10 installed ImsServices at most, so running through this list twice is
+ // reasonable vs the memory cost of caching binding vs unbinding services.
+
+ // Unbind first if needed
+ for (ImsServiceInfo info : mInstalledServicesCache.values()) {
+ Set<ImsFeatureConfiguration.FeatureSlotPair> features = calculateFeaturesToCreate(info);
+ UserHandle user = getUserForBind(info);
+ if (shouldFeaturesCauseBind(features) && user != null) continue;
+ unbindImsService(info);
+ }
+ // Bind/alter features second
+ for (ImsServiceInfo info : mInstalledServicesCache.values()) {
+ Set<ImsFeatureConfiguration.FeatureSlotPair> features = calculateFeaturesToCreate(info);
+ UserHandle user = getUserForBind(info);
+ if (shouldFeaturesCauseBind(features) && user != null) {
+ bindImsServiceWithFeatures(info, user, features);
+ }
+ }
+ }
+
+ /**
+ * Returns the UserHandle that should be used to bind the ImsService.
+ *
+ * @return The UserHandle of the user that telephony is running in if the
+ * ImsService is configured to run in that user, or the current active user
+ * if not. Returns null if the ImsService is not configured to run in any
+ * active user.
+ */
+ private UserHandle getUserForBind(ImsServiceInfo info) {
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ return mContext.getUser();
+ }
+ UserHandle currentUser = mActivityManagerProxy.getCurrentUser();
+ List<UserHandle> activeUsers = getActiveUsers().stream()
+ .filter(info.users::contains).toList();
+ if (activeUsers.isEmpty()) return null;
+ // If there is a test restriction in place for this package, prioritize that restriction
+ UserHandle testRestriction = mImsServiceTestUserRestrictions.getOrDefault(
+ info.name.getPackageName(), null);
+ if (testRestriction != null && activeUsers.stream()
+ .anyMatch(u -> Objects.equals(u, testRestriction))) {
+ return testRestriction;
+ }
+ // Prioritize the User that Telephony is in, since it is always running
+ if (activeUsers.stream()
+ .anyMatch(u -> Objects.equals(u, mContext.getUser()))) {
+ return mContext.getUser();
+ }
+ if (activeUsers.stream().anyMatch(u -> Objects.equals(u, currentUser))) {
+ return currentUser;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the set of full users that are currently active.
+ */
+ private Set<UserHandle> getActiveUsers() {
+ Set<UserHandle> profiles = new HashSet<>();
+ profiles.add(mContext.getUser());
+ profiles.add(mActivityManagerProxy.getCurrentUser());
+ return profiles;
+ }
+
private static String printFeatures(Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
StringBuilder featureString = new StringBuilder();
featureString.append(" features: [");
@@ -1711,8 +1989,24 @@
}
/**
- * Returns the ImsServiceInfo that matches the provided packageName. Visible for testing
- * the ImsService caching functionality.
+ * Returns the ImsServiceInfo that matches the provided packageName if it belongs to a
+ * package that is visible as part of the set of active users.
+ */
+ public ImsServiceInfo getVisibleImsServiceInfoFromCache(String packageName) {
+ ImsServiceInfo match = getImsServiceInfoFromCache(packageName);
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ return match;
+ }
+ if (match == null) return null;
+ UserHandle targetUser = getUserForBind(match);
+ Log.d(TAG, "getVisibleImsServiceInfoFromCache: " + packageName + ", match=" + match
+ + ", targetUser=" + targetUser);
+ if (targetUser != null) return match; else return null;
+ }
+
+ /**
+ * Returns the ImsServiceInfo that matches the provided packageName. This includes
+ * ImsServiceInfos that are not currently visible for the active users.
*/
@VisibleForTesting
public ImsServiceInfo getImsServiceInfoFromCache(String packageName) {
@@ -1738,6 +2032,12 @@
return infos;
}
+ private ImsServiceInfo getInfoFromCache(List<ImsServiceInfo> infos,
+ ComponentName componentName) {
+ return infos.stream().filter(info -> Objects.equals(info.name, componentName)).findFirst()
+ .orElse(null);
+ }
+
private List<ImsServiceInfo> searchForImsServices(String packageName,
ImsServiceControllerFactory controllerFactory) {
List<ImsServiceInfo> infos = new ArrayList<>();
@@ -1745,62 +2045,84 @@
Intent serviceIntent = new Intent(controllerFactory.getServiceInterface());
serviceIntent.setPackage(packageName);
+ Set<UserHandle> profiles;
+ if (mFeatureFlags.imsResolverUserAware()) {
+ profiles = getActiveUsers();
+ } else {
+ profiles = Collections.singleton(mContext.getUser());
+ }
+ Log.v(TAG, "searchForImsServices: package=" + packageName + ", users=" + profiles);
+
PackageManager packageManager = mContext.getPackageManager();
- for (ResolveInfo entry : packageManager.queryIntentServicesAsUser(
- serviceIntent,
- PackageManager.GET_META_DATA,
- UserHandle.of(UserHandle.myUserId()))) {
- ServiceInfo serviceInfo = entry.serviceInfo;
+ for (UserHandle handle : profiles) {
+ for (ResolveInfo entry : packageManager.queryIntentServicesAsUser(serviceIntent,
+ PackageManager.GET_META_DATA, handle)) {
+ ServiceInfo serviceInfo = entry.serviceInfo;
- if (serviceInfo != null) {
- ImsServiceInfo info = new ImsServiceInfo();
- info.name = new ComponentName(serviceInfo.packageName, serviceInfo.name);
- info.controllerFactory = controllerFactory;
+ if (serviceInfo != null) {
+ ComponentName name = new ComponentName(serviceInfo.packageName,
+ serviceInfo.name);
+ ImsServiceInfo info = getInfoFromCache(infos, name);
+ if (info != null) {
+ info.users.add(handle);
+ Log.d(TAG, "service modify users:" + info);
+ continue;
+ } else {
+ info = new ImsServiceInfo(name);
+ info.users.add(handle);
+ }
+ info.controllerFactory = controllerFactory;
- // we will allow the manifest method of declaring manifest features in two cases:
- // 1) it is the device overlay "default" ImsService, where the features do not
- // change (the new method can still be used if the default does not define manifest
- // entries).
- // 2) using the "compat" ImsService, which only supports manifest query.
- if (isDeviceService(info)
- || mImsServiceControllerFactoryCompat == controllerFactory) {
- if (serviceInfo.metaData != null) {
- if (serviceInfo.metaData.getBoolean(METADATA_MMTEL_FEATURE, false)) {
- info.addFeatureForAllSlots(mNumSlots, ImsFeature.FEATURE_MMTEL);
- // only allow FEATURE_EMERGENCY_MMTEL if FEATURE_MMTEL is defined.
- if (serviceInfo.metaData.getBoolean(METADATA_EMERGENCY_MMTEL_FEATURE,
- false)) {
- info.addFeatureForAllSlots(mNumSlots,
- ImsFeature.FEATURE_EMERGENCY_MMTEL);
+ // we will allow the manifest method of declaring manifest features in two
+ // cases:
+
+ // 1) it is the device overlay "default" ImsService, where the features do not
+ // change (the new method can still be used if the default does not define
+ // manifest entries).
+ // 2) using the "compat" ImsService, which only supports manifest query.
+ if (isDeviceService(info)
+ || mImsServiceControllerFactoryCompat == controllerFactory) {
+ if (serviceInfo.metaData != null) {
+ if (serviceInfo.metaData.getBoolean(METADATA_MMTEL_FEATURE, false)) {
+ info.addFeatureForAllSlots(mNumSlots, ImsFeature.FEATURE_MMTEL);
+ // only allow FEATURE_EMERGENCY_MMTEL if FEATURE_MMTEL is defined.
+ if (serviceInfo.metaData.getBoolean(
+ METADATA_EMERGENCY_MMTEL_FEATURE,
+ false)) {
+ info.addFeatureForAllSlots(mNumSlots,
+ ImsFeature.FEATURE_EMERGENCY_MMTEL);
+ }
+ }
+ if (serviceInfo.metaData.getBoolean(METADATA_RCS_FEATURE, false)) {
+ info.addFeatureForAllSlots(mNumSlots, ImsFeature.FEATURE_RCS);
}
}
- if (serviceInfo.metaData.getBoolean(METADATA_RCS_FEATURE, false)) {
- info.addFeatureForAllSlots(mNumSlots, ImsFeature.FEATURE_RCS);
+ // Only dynamic query if we are not a compat version of ImsService and the
+ // default service.
+ if (mImsServiceControllerFactoryCompat != controllerFactory
+ && info.getSupportedFeatures().isEmpty()) {
+ // metadata empty, try dynamic query instead
+ info.featureFromMetadata = false;
}
- }
- // Only dynamic query if we are not a compat version of ImsService and the
- // default service.
- if (mImsServiceControllerFactoryCompat != controllerFactory
- && info.getSupportedFeatures().isEmpty()) {
- // metadata empty, try dynamic query instead
+ } else {
+ // We are a carrier service and not using the compat version of ImsService.
info.featureFromMetadata = false;
}
- } else {
- // We are a carrier service and not using the compat version of ImsService.
- info.featureFromMetadata = false;
- }
- Log.i(TAG, "service name: " + info.name + ", manifest query: "
- + info.featureFromMetadata);
- // Check manifest permission to be sure that the service declares the correct
- // permissions. Overridden if the METADATA_OVERRIDE_PERM_CHECK metadata is set to
- // true.
- // NOTE: METADATA_OVERRIDE_PERM_CHECK should only be set for testing.
- if (TextUtils.equals(serviceInfo.permission, Manifest.permission.BIND_IMS_SERVICE)
- || serviceInfo.metaData.getBoolean(METADATA_OVERRIDE_PERM_CHECK, false)) {
- infos.add(info);
- } else {
- Log.w(TAG, "ImsService is not protected with BIND_IMS_SERVICE permission: "
- + info.name);
+ Log.d(TAG, "service name: " + info.name + ", manifest query: "
+ + info.featureFromMetadata + ", users: " + info.users);
+ // Check manifest permission to be sure that the service declares the correct
+ // permissions. Overridden if the METADATA_OVERRIDE_PERM_CHECK metadata is set
+ // to true.
+ // NOTE: METADATA_OVERRIDE_PERM_CHECK should only be set for testing.
+ if (TextUtils.equals(serviceInfo.permission,
+ Manifest.permission.BIND_IMS_SERVICE)
+ || serviceInfo.metaData.getBoolean(METADATA_OVERRIDE_PERM_CHECK,
+ false)) {
+ infos.add(info);
+ } else {
+ Log.w(TAG, "ImsService is not protected with BIND_IMS_SERVICE permission: "
+ + info.name);
+ }
}
}
}
diff --git a/src/java/com/android/internal/telephony/ims/ImsServiceController.java b/src/java/com/android/internal/telephony/ims/ImsServiceController.java
index ea8399f..37c10eb 100644
--- a/src/java/com/android/internal/telephony/ims/ImsServiceController.java
+++ b/src/java/com/android/internal/telephony/ims/ImsServiceController.java
@@ -196,7 +196,7 @@
}
if (mCallbacks != null) {
// Will trigger an unbind.
- mCallbacks.imsServiceBindPermanentError(getComponentName());
+ mCallbacks.imsServiceBindPermanentError(getComponentName(), mBoundUser);
}
}
@@ -217,7 +217,8 @@
/**
* Called by ImsServiceController when a new MMTEL or RCS feature has been created.
*/
- void imsServiceFeatureCreated(int slotId, int feature, ImsServiceController controller);
+ void imsServiceFeatureCreated(int slotId, int subId, int feature,
+ ImsServiceController controller);
/**
* Called by ImsServiceController when a new MMTEL or RCS feature has been removed.
*/
@@ -234,7 +235,7 @@
* Called by the ImsServiceController when there has been an error binding that is
* not recoverable, such as the ImsService returning a null binder.
*/
- void imsServiceBindPermanentError(ComponentName name);
+ void imsServiceBindPermanentError(ComponentName name, UserHandle user);
}
/**
@@ -273,6 +274,7 @@
private boolean mIsBound = false;
private boolean mIsBinding = false;
+ private UserHandle mBoundUser = null;
// Set of a pair of slotId->feature
private Set<ImsFeatureConfiguration.FeatureSlotPair> mImsFeatures;
private SparseIntArray mSlotIdToSubIdMap;
@@ -337,7 +339,7 @@
if (mIsBound) {
return;
}
- bind(mImsFeatures, mSlotIdToSubIdMap);
+ bind(mBoundUser, mImsFeatures, mSlotIdToSubIdMap);
}
}
};
@@ -413,17 +415,18 @@
* @return {@link true} if the service is in the process of being bound, {@link false} if it
* has failed.
*/
- public boolean bind(Set<ImsFeatureConfiguration.FeatureSlotPair> imsFeatureSet,
- SparseIntArray slotIdToSubIdMap) {
+ public boolean bind(UserHandle user, Set<ImsFeatureConfiguration.FeatureSlotPair> imsFeatureSet,
+ SparseIntArray slotIdToSubIdMap) {
synchronized (mLock) {
if (!mIsBound && !mIsBinding) {
mIsBinding = true;
+ mBoundUser = user;
sanitizeFeatureConfig(imsFeatureSet);
mImsFeatures = imsFeatureSet;
mSlotIdToSubIdMap = slotIdToSubIdMap;
// Set the number of slots that support the feature
mImsEnablementTracker.setNumOfSlots(mSlotIdToSubIdMap.size());
- grantPermissionsToService();
+ grantPermissionsToService(user);
Intent imsServiceIntent = new Intent(getServiceInterface()).setComponent(
mComponentName);
mImsServiceConnection = new ImsServiceConnection();
@@ -432,8 +435,8 @@
mLocalLog.log("binding " + imsFeatureSet);
Log.i(LOG_TAG, "Binding ImsService:" + mComponentName);
try {
- boolean bindSucceeded = mContext.bindService(imsServiceIntent,
- mImsServiceConnection, serviceFlags);
+ boolean bindSucceeded = mContext.bindServiceAsUser(imsServiceIntent,
+ mImsServiceConnection, serviceFlags, user);
if (!bindSucceeded) {
mLocalLog.log(" binding failed, retrying in "
+ mBackoff.getCurrentDelay() + " mS");
@@ -482,6 +485,7 @@
changeImsServiceFeatures(new HashSet<>(), mSlotIdToSubIdMap);
mIsBound = false;
mIsBinding = false;
+ mBoundUser = null;
setServiceController(null);
unbindService();
}
@@ -608,6 +612,13 @@
}
/**
+ * @return The UserHandle that this controller is bound to or null if bound to no service.
+ */
+ public UserHandle getBoundUser() {
+ return mBoundUser;
+ }
+
+ /**
* Notify ImsService to enable IMS for the framework. This will trigger IMS registration and
* trigger ImsFeature status updates.
*/
@@ -766,7 +777,7 @@
// Grant runtime permissions to ImsService. PermissionManager ensures that the ImsService is
// system/signed before granting permissions.
- private void grantPermissionsToService() {
+ private void grantPermissionsToService(UserHandle user) {
mLocalLog.log("grant permissions to " + getComponentName());
Log.i(LOG_TAG, "Granting Runtime permissions to:" + getComponentName());
String[] pkgToGrant = {mComponentName.getPackageName()};
@@ -774,8 +785,7 @@
if (mPermissionManager != null) {
CountDownLatch latch = new CountDownLatch(1);
mPermissionManager.grantDefaultPermissionsToEnabledImsServices(
- pkgToGrant, UserHandle.of(UserHandle.myUserId()), Runnable::run,
- isSuccess -> {
+ pkgToGrant, user, Runnable::run, isSuccess -> {
if (isSuccess) {
latch.countDown();
} else {
@@ -807,7 +817,8 @@
Log.i(LOG_TAG, "supports emergency calling on slot " + featurePair.slotId);
}
// Signal ImsResolver to change supported ImsFeatures for this ImsServiceController
- mCallbacks.imsServiceFeatureCreated(featurePair.slotId, featurePair.featureType, this);
+ mCallbacks.imsServiceFeatureCreated(featurePair.slotId, subId, featurePair.featureType,
+ this);
}
// This method should only be called when synchronized on mLock
@@ -978,10 +989,11 @@
@Override
public String toString() {
synchronized (mLock) {
- return "[ImsServiceController: componentName=" + getComponentName() + ", features="
- + mImsFeatures + ", isBinding=" + mIsBinding + ", isBound=" + mIsBound
- + ", serviceController=" + getImsServiceController() + ", rebindDelay="
- + getRebindDelay() + "]";
+ return "[ImsServiceController: componentName=" + getComponentName() + ", boundUser="
+ + mBoundUser + ", features=" + mImsFeatures + ", isBinding=" + mIsBinding
+ + ", isBound=" + mIsBound + ", serviceController=" + getImsServiceController()
+ + ", rebindDelay=" + getRebindDelay() + ", slotToSubIdMap=" + mSlotIdToSubIdMap
+ + "]";
}
}
diff --git a/src/java/com/android/internal/telephony/ims/ImsServiceFeatureQueryManager.java b/src/java/com/android/internal/telephony/ims/ImsServiceFeatureQueryManager.java
index 564cdcc..a4b4f46 100644
--- a/src/java/com/android/internal/telephony/ims/ImsServiceFeatureQueryManager.java
+++ b/src/java/com/android/internal/telephony/ims/ImsServiceFeatureQueryManager.java
@@ -21,6 +21,7 @@
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
+import android.os.UserHandle;
import android.telephony.ims.aidl.IImsServiceController;
import android.telephony.ims.stub.ImsFeatureConfiguration;
import android.util.Log;
@@ -42,14 +43,16 @@
private static final String LOG_TAG = "ImsServiceFeatureQuery";
private final ComponentName mName;
+ private final UserHandle mUser;
private final String mIntentFilter;
// Track the status of whether or not the Service has died in case we need to permanently
// unbind (see onNullBinding below).
private boolean mIsServiceConnectionDead = false;
- ImsServiceFeatureQuery(ComponentName name, String intentFilter) {
+ ImsServiceFeatureQuery(ComponentName name, UserHandle user, String intentFilter) {
mName = name;
+ mUser = user;
mIntentFilter = intentFilter;
}
@@ -62,7 +65,8 @@
Intent imsServiceIntent = new Intent(mIntentFilter).setComponent(mName);
int serviceFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
| Context.BIND_IMPORTANT;
- boolean bindStarted = mContext.bindService(imsServiceIntent, this, serviceFlags);
+ boolean bindStarted = mContext.bindServiceAsUser(imsServiceIntent, this,
+ serviceFlags, mUser);
if (!bindStarted) {
// Docs say to unbind if this fails.
cleanup();
@@ -78,7 +82,7 @@
} else {
Log.w(LOG_TAG, "onServiceConnected: " + name + " binder null.");
cleanup();
- mListener.onPermanentError(name);
+ mListener.onPermanentError(name, mUser);
}
}
@@ -103,7 +107,7 @@
// permanently unbind and instead let the automatic rebind occur.
if (mIsServiceConnectionDead) return;
cleanup();
- mListener.onPermanentError(name);
+ mListener.onPermanentError(name, mUser);
}
private void queryImsFeatures(IImsServiceController controller) {
@@ -154,7 +158,7 @@
/**
* Called when a query has failed due to a permanent error and should not be retried.
*/
- void onPermanentError(ComponentName name);
+ void onPermanentError(ComponentName name, UserHandle user);
}
// Maps an active ImsService query (by Package Name String) its query.
@@ -171,16 +175,17 @@
/**
* Starts an ImsService feature query for the ComponentName and Intent specified.
* @param name The ComponentName of the ImsService being queried.
+ * @param user The User associated with the request.
* @param intentFilter The Intent filter that the ImsService specified.
* @return true if the query started, false if it was unable to start.
*/
- public boolean startQuery(ComponentName name, String intentFilter) {
+ public boolean startQuery(ComponentName name, UserHandle user, String intentFilter) {
synchronized (mLock) {
if (mActiveQueries.containsKey(name)) {
// We already have an active query, wait for it to return.
return true;
}
- ImsServiceFeatureQuery query = new ImsServiceFeatureQuery(name, intentFilter);
+ ImsServiceFeatureQuery query = new ImsServiceFeatureQuery(name, user, intentFilter);
mActiveQueries.put(name, query);
return query.start();
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index 26b6e18..d47f05b 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -1797,7 +1797,8 @@
dialArgs.intentExtras);
}
};
- EmergencyStateTracker.getInstance().exitEmergencyCallbackMode(onComplete);
+ EmergencyStateTracker.getInstance().exitEmergencyCallbackMode(onComplete,
+ TelephonyManager.STOP_REASON_OUTGOING_NORMAL_CALL_INITIATED);
} else {
try {
getEcbmInterface().exitEmergencyCallbackMode();
@@ -2884,7 +2885,7 @@
boolean rejectCall = false;
if (mFeatureFlags.preventHangupDuringCallMerge()) {
- if (imsCall.isCallSessionMergePending()) {
+ if (imsCall != null && imsCall.isCallSessionMergePending()) {
if (DBG) log("hangup call failed during call merge");
throw new CallStateException("can not hangup during call merge");
diff --git a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
index cf44aaf..9f74890 100644
--- a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
+++ b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
@@ -861,26 +861,24 @@
/** Adds a new {@link CarrierRoamingSatelliteControllerStats} to the storage. */
public synchronized void addCarrierRoamingSatelliteControllerStats(
CarrierRoamingSatelliteControllerStats stats) {
- // CarrierRoamingSatelliteController is a single data point
- CarrierRoamingSatelliteControllerStats[] atomArray =
- mAtoms.carrierRoamingSatelliteControllerStats;
- if (atomArray == null || atomArray.length == 0) {
- atomArray = new CarrierRoamingSatelliteControllerStats[] {new
- CarrierRoamingSatelliteControllerStats()};
+ CarrierRoamingSatelliteControllerStats existingStats = find(stats);
+ if (existingStats != null) {
+ existingStats.configDataSource = stats.configDataSource;
+ existingStats.countOfEntitlementStatusQueryRequest +=
+ stats.countOfEntitlementStatusQueryRequest;
+ existingStats.countOfSatelliteConfigUpdateRequest +=
+ stats.countOfSatelliteConfigUpdateRequest;
+ existingStats.countOfSatelliteNotificationDisplayed +=
+ stats.countOfSatelliteNotificationDisplayed;
+ existingStats.satelliteSessionGapMinSec = stats.satelliteSessionGapMinSec;
+ existingStats.satelliteSessionGapAvgSec = stats.satelliteSessionGapAvgSec;
+ existingStats.satelliteSessionGapMaxSec = stats.satelliteSessionGapMaxSec;
+ existingStats.isDeviceEntitled = stats.isDeviceEntitled;
+ } else {
+ mAtoms.carrierRoamingSatelliteControllerStats = insertAtRandomPlace(
+ mAtoms.carrierRoamingSatelliteControllerStats, stats, mMaxNumSatelliteStats);
}
- CarrierRoamingSatelliteControllerStats atom = atomArray[0];
- atom.configDataSource = stats.configDataSource;
- atom.countOfEntitlementStatusQueryRequest += stats.countOfEntitlementStatusQueryRequest;
- atom.countOfSatelliteConfigUpdateRequest += stats.countOfSatelliteConfigUpdateRequest;
- atom.countOfSatelliteNotificationDisplayed += stats.countOfSatelliteNotificationDisplayed;
- atom.satelliteSessionGapMinSec = stats.satelliteSessionGapMinSec;
- atom.satelliteSessionGapAvgSec = stats.satelliteSessionGapAvgSec;
- atom.satelliteSessionGapMaxSec = stats.satelliteSessionGapMaxSec;
- atom.carrierId = stats.carrierId;
- atom.isDeviceEntitled = stats.isDeviceEntitled;
-
- mAtoms.carrierRoamingSatelliteControllerStats = atomArray;
saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS);
}
@@ -2392,6 +2390,21 @@
}
/**
+ * Returns CarrierRoamingSatelliteControllerStats atom that has same carrier_id value or
+ * {@code null} if does not exist.
+ */
+ private @Nullable CarrierRoamingSatelliteControllerStats find(
+ CarrierRoamingSatelliteControllerStats key) {
+ for (CarrierRoamingSatelliteControllerStats stats :
+ mAtoms.carrierRoamingSatelliteControllerStats) {
+ if (stats.carrierId == key.carrierId) {
+ return stats;
+ }
+ }
+ return null;
+ }
+
+ /**
* Returns SatelliteEntitlement atom that has same values or {@code null} if it does not exist.
*/
private @Nullable SatelliteEntitlement find(SatelliteEntitlement key) {
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramController.java b/src/java/com/android/internal/telephony/satellite/DatagramController.java
index a816906..9f6edf2 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramController.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramController.java
@@ -282,7 +282,7 @@
mSendDatagramTransferState = datagramTransferState;
mSendPendingCount = sendPendingCount;
mSendErrorCode = errorCode;
- notifyDatagramTransferStateChangedToSessionController();
+ notifyDatagramTransferStateChangedToSessionController(mDatagramType);
mPointingAppController.updateSendDatagramTransferState(mSendSubId, mDatagramType,
mSendDatagramTransferState, mSendPendingCount, mSendErrorCode);
retryPollPendingDatagramsInDemoMode();
@@ -311,21 +311,23 @@
* @param receivePendingCount The number of datagrams that are currently pending to be received.
* @param errorCode If datagram transfer failed, the reason for failure.
*/
- public void updateReceiveStatus(int subId,
+ public void updateReceiveStatus(int subId, @SatelliteManager.DatagramType int datagramType,
@SatelliteManager.SatelliteDatagramTransferState int datagramTransferState,
int receivePendingCount, int errorCode) {
synchronized (mLock) {
plogd("updateReceiveStatus"
+ " subId: " + subId
+ + " datagramType: " + datagramType
+ " datagramTransferState: " + datagramTransferState
+ " receivePendingCount: " + receivePendingCount + " errorCode: " + errorCode);
mReceiveSubId = subId;
+ mDatagramType = datagramType;
mReceiveDatagramTransferState = datagramTransferState;
mReceivePendingCount = receivePendingCount;
mReceiveErrorCode = errorCode;
- notifyDatagramTransferStateChangedToSessionController();
+ notifyDatagramTransferStateChangedToSessionController(mDatagramType);
mPointingAppController.updateReceiveDatagramTransferState(mReceiveSubId,
mReceiveDatagramTransferState, mReceivePendingCount, mReceiveErrorCode);
retryPollPendingDatagramsInDemoMode();
@@ -365,6 +367,24 @@
}
/**
+ * Notify SMS received.
+ *
+ * @param subId The subId of the subscription used to receive SMS
+ */
+ public void onSmsReceived(int subId) {
+ // To keep exist notification flow, need to call with each state.
+ updateReceiveStatus(subId, SatelliteManager.DATAGRAM_TYPE_SMS,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ getReceivePendingCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ updateReceiveStatus(subId, SatelliteManager.DATAGRAM_TYPE_SMS,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS,
+ getReceivePendingCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ updateReceiveStatus(subId, SatelliteManager.DATAGRAM_TYPE_SMS,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ getReceivePendingCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ }
+
+ /**
* Set whether the device is aligned with the satellite.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@@ -565,14 +585,16 @@
return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false));
}
- private void notifyDatagramTransferStateChangedToSessionController() {
+ private void notifyDatagramTransferStateChangedToSessionController(int datagramType) {
SatelliteSessionController sessionController = SatelliteSessionController.getInstance();
if (sessionController == null) {
ploge("notifyDatagramTransferStateChangeToSessionController: SatelliteSessionController"
+ " is not initialized yet");
} else {
- sessionController.onDatagramTransferStateChanged(
- mSendDatagramTransferState, mReceiveDatagramTransferState);
+ synchronized (mLock) {
+ sessionController.onDatagramTransferStateChanged(
+ mSendDatagramTransferState, mReceiveDatagramTransferState, datagramType);
+ }
}
}
@@ -616,7 +638,7 @@
}
};
pollPendingSatelliteDatagrams(
- SatelliteController.getInstance().getHighestPrioritySubscrption(),
+ SatelliteController.getInstance().getSelectedSatelliteSubId(),
internalCallback);
}
}
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
index 682123f..07530d2 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
@@ -16,9 +16,12 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS;
import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SMS;
import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NETWORK_ERROR;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE;
@@ -75,6 +78,7 @@
private static final int EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT = 7;
private static final int CMD_SEND_SMS = 8;
private static final int EVENT_SEND_SMS_DONE = 9;
+ private static final int EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT = 10;
private static final Long TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE = TimeUnit.SECONDS.toMillis(10);
@NonNull private static DatagramDispatcher sInstance;
@NonNull private final Context mContext;
@@ -130,6 +134,15 @@
private int mLastSendRequestDatagramType = DATAGRAM_TYPE_UNKNOWN;
@Nullable private PersistentLogger mPersistentLogger = null;
+ @GuardedBy("mLock")
+ private int mModemState = SATELLITE_MODEM_STATE_UNKNOWN;
+ @GuardedBy("mLock")
+ private boolean mHasEnteredConnectedState = false;
+ @GuardedBy("mLock")
+ private boolean mShouldPollMtSms = false;
+ @GuardedBy("mLock")
+ private boolean mIsMtSmsPollingThrottled = false;
+
/**
* Create the DatagramDispatcher singleton instance.
* @param context The Context to use to create the DatagramDispatcher.
@@ -402,6 +415,16 @@
break;
}
+ case EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT: {
+ synchronized (mLock) {
+ mIsMtSmsPollingThrottled = false;
+ if (mIsAligned && mModemState == SATELLITE_MODEM_STATE_CONNECTED) {
+ sendMtSmsPollingMessage();
+ }
+ }
+ break;
+ }
+
default:
plogw("DatagramDispatcherHandler: unexpected message code: " + msg.what);
break;
@@ -491,6 +514,10 @@
mIsAligned = isAligned;
plogd("setDeviceAlignedWithSatellite: " + mIsAligned);
if (isAligned && mIsDemoMode) handleEventSatelliteAligned();
+ if (isAligned && !mIsMtSmsPollingThrottled
+ && mModemState == SATELLITE_MODEM_STATE_CONNECTED) {
+ sendMtSmsPollingMessage();
+ }
}
}
@@ -598,6 +625,13 @@
pendingDatagram.iterator().next().getValue();
if (mDatagramController.needsWaitingForSatelliteConnected(datagramArg.datagramType)) {
plogd("sendPendingDatagrams: wait for satellite connected");
+ mDatagramController.updateSendStatus(datagramArg.subId,
+ datagramArg.datagramType,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ getPendingMessagesCount(),
+ SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ startDatagramWaitForConnectedStateTimer(
+ datagramArg.datagramType);
return;
}
@@ -759,6 +793,7 @@
*/
public void onSatelliteModemStateChanged(@SatelliteManager.SatelliteModemState int state) {
synchronized (mLock) {
+ mModemState = state;
if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF
|| state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE) {
plogd("onSatelliteModemStateChanged: cleaning up resources");
@@ -767,10 +802,22 @@
sendPendingMessages();
}
- if (state == SATELLITE_MODEM_STATE_CONNECTED
- && isDatagramWaitForConnectedStateTimerStarted()) {
- stopDatagramWaitForConnectedStateTimer();
- sendPendingMessages();
+ if (state == SATELLITE_MODEM_STATE_CONNECTED) {
+ mHasEnteredConnectedState = true;
+ if (isDatagramWaitForConnectedStateTimerStarted()) {
+ stopDatagramWaitForConnectedStateTimer();
+ sendPendingMessages();
+ }
+ if (mIsAligned && !mIsMtSmsPollingThrottled) {
+ sendMtSmsPollingMessage();
+ }
+ }
+
+ if (state == SATELLITE_MODEM_STATE_NOT_CONNECTED) {
+ if (mHasEnteredConnectedState) {
+ mHasEnteredConnectedState = false;
+ mShouldPollMtSms = shouldPollMtSms();
+ }
}
}
}
@@ -781,7 +828,7 @@
mSendingInProgress = false;
mIsEmergencyCommunicationEstablished = false;
- int subId = SatelliteController.getInstance().getHighestPrioritySubscrption();
+ int subId = SatelliteController.getInstance().getSelectedSatelliteSubId();
if (getPendingMessagesCount() > 0) {
mDatagramController.updateSendStatus(subId,
mLastSendRequestDatagramType,
@@ -803,6 +850,10 @@
mSendSatelliteDatagramRequest = null;
mIsAligned = false;
mLastSendRequestDatagramType = DATAGRAM_TYPE_UNKNOWN;
+ mModemState = SATELLITE_MODEM_STATE_UNKNOWN;
+ mHasEnteredConnectedState = false;
+ mShouldPollMtSms = false;
+ stopMtSmsPollingThrottle();
}
/** @return {@code true} if already sent an emergency datagram during a session. */
@@ -867,7 +918,7 @@
@SatelliteManager.DatagramType int datagramType) {
plogw("Timed out to wait for satellite connected before sending datagrams");
synchronized (mLock) {
- int subId = SatelliteController.getInstance().getHighestPrioritySubscrption();
+ int subId = SatelliteController.getInstance().getSelectedSatelliteSubId();
// Update send status
mDatagramController.updateSendStatus(subId,
datagramType,
@@ -1051,22 +1102,17 @@
* carrier roaming nb iot ntn SMS.
*/
public void sendSms(@NonNull PendingRequest pendingSms) {
- Phone satellitePhone = SatelliteController.getInstance().getSatellitePhone();
- if (satellitePhone == null) {
- ploge("sendSms: satellitePhone is null.");
- return;
- }
-
SatelliteController.getInstance().startPointingUI();
- int subId = satellitePhone.getSubId();
- long messageId = pendingSms.messageId;
+ int subId = SatelliteController.getInstance().getSelectedSatelliteSubId();
+ long messageId = pendingSms.uniqueMessageId;
plogd("sendSms: subId=" + subId + " messageId:" + messageId);
synchronized (mLock) {
// Add SMS to pending list
mPendingSmsMap.put(messageId, pendingSms);
- int datagramType = SatelliteManager.DATAGRAM_TYPE_SMS;
+ int datagramType = pendingSms.isMtSmsPolling ?
+ DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS : DATAGRAM_TYPE_SMS;
mLastSendRequestDatagramType = datagramType;
if (mDatagramController.needsWaitingForSatelliteConnected(datagramType)) {
@@ -1098,27 +1144,30 @@
return;
}
- Phone satellitePhone = SatelliteController.getInstance().getSatellitePhone();
- if (satellitePhone == null) {
- ploge("sendPendingSms: satellitePhone is null.");
- return;
- }
- int subId = satellitePhone.getSubId();
-
+ int subId = SatelliteController.getInstance().getSelectedSatelliteSubId();
Set<Entry<Long, PendingRequest>> pendingSms = null;
if (!mSendingInProgress) {
pendingSms = mPendingSmsMap.entrySet();
}
if (pendingSms != null && pendingSms.iterator().hasNext()) {
+ PendingRequest pendingRequest = pendingSms.iterator().next().getValue();
+ int datagramType = pendingRequest.isMtSmsPolling
+ ? DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS : DATAGRAM_TYPE_SMS;
if (mDatagramController.needsWaitingForSatelliteConnected(DATAGRAM_TYPE_SMS)) {
plogd("sendPendingSms: wait for satellite connected");
+ mDatagramController.updateSendStatus(subId,
+ datagramType,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ getPendingMessagesCount(),
+ SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ startDatagramWaitForConnectedStateTimer(datagramType);
return;
}
mSendingInProgress = true;
- PendingRequest pendingRequest = pendingSms.iterator().next().getValue();
- mDatagramController.updateSendStatus(subId, DATAGRAM_TYPE_SMS,
+ mDatagramController.updateSendStatus(subId,
+ datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
getPendingMessagesCount(), SATELLITE_RESULT_SUCCESS);
sendMessage(obtainMessage(CMD_SEND_SMS, pendingRequest));
@@ -1182,8 +1231,9 @@
private void handleEventSendSmsDone(int subId, long messageId, boolean success) {
synchronized (mLock) {
mSendingInProgress = false;
- mPendingSmsMap.remove(messageId);
- int datagramType = DATAGRAM_TYPE_SMS;
+ PendingRequest pendingSms = mPendingSmsMap.remove(messageId);
+ int datagramType = pendingSms != null && pendingSms.isMtSmsPolling
+ ? DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS : DATAGRAM_TYPE_SMS;
plogd("handleEventSendSmsDone subId=" + subId + " messageId=" + messageId
+ " success=" + success);
@@ -1192,6 +1242,9 @@
mDatagramController.updateSendStatus(subId, datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS,
getPendingMessagesCount(), SATELLITE_RESULT_SUCCESS);
+ if (datagramType == DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS) {
+ startMtSmsPollingThrottle();
+ }
} else {
mDatagramController.updateSendStatus(subId, datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
@@ -1208,6 +1261,69 @@
}
}
+ private boolean isEnabledMtSmsPolling() {
+ return mContext.getResources().getBoolean(R.bool.config_enabled_mt_sms_polling);
+ }
+
+ private long getMtSmsPollingThrottleMillis() {
+ return mContext.getResources().getInteger(
+ R.integer.config_mt_sms_polling_throttle_millis);
+ }
+
+ private boolean shouldPollMtSms() {
+ SatelliteController satelliteController = SatelliteController.getInstance();
+ Phone satellitePhone = satelliteController.getSatellitePhone();
+ return isEnabledMtSmsPolling()
+ && satelliteController.shouldSendSmsToDatagramDispatcher(satellitePhone);
+ }
+
+ @GuardedBy("mLock")
+ private void sendMtSmsPollingMessage() {
+ if (!mShouldPollMtSms) {
+ return;
+ }
+
+ plogd("sendMtSmsPollingMessage");
+ mShouldPollMtSms = false;
+
+ for (Entry<Long, PendingRequest> entry : mPendingSmsMap.entrySet()) {
+ PendingRequest pendingRequest = entry.getValue();
+ if (pendingRequest.isMtSmsPolling) {
+ plogd("sendMtSmsPollingMessage: mPendingSmsMap already has the polling message.");
+ return;
+ }
+ }
+
+ Phone satellitePhone = SatelliteController.getInstance().getSatellitePhone();
+ if (satellitePhone == null) {
+ ploge("sendMtSmsPollingMessage: satellitePhone is null.");
+ return;
+ }
+
+ SmsDispatchersController smsDispatchersController =
+ satellitePhone.getSmsDispatchersController();
+ if (smsDispatchersController == null) {
+ ploge("sendMtSmsPollingMessage: smsDispatchersController is null.");
+ return;
+ }
+
+ smsDispatchersController.sendMtSmsPollingMessage();
+ }
+
+ @GuardedBy("mLock")
+ private void startMtSmsPollingThrottle() {
+ plogd("startMtSmsPollingThrottle");
+ mIsMtSmsPollingThrottled = true;
+ sendMessageDelayed(obtainMessage(EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT),
+ getMtSmsPollingThrottleMillis());
+ }
+
+ @GuardedBy("mLock")
+ private void stopMtSmsPollingThrottle() {
+ mIsMtSmsPollingThrottled = false;
+ removeMessages(EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT);
+ }
+
private static void logd(@NonNull String log) {
Rlog.d(TAG, log);
}
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
index 5a89c40..a921b89 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
@@ -352,10 +352,12 @@
if (pendingCount <= 0 && satelliteDatagram == null) {
sInstance.mDatagramController.updateReceiveStatus(mSubId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE,
pendingCount, SatelliteManager.SATELLITE_RESULT_SUCCESS);
} else if (satelliteDatagram != null) {
sInstance.mDatagramController.updateReceiveStatus(mSubId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS,
pendingCount, SatelliteManager.SATELLITE_RESULT_SUCCESS);
@@ -376,6 +378,7 @@
if (pendingCount <= 0) {
sInstance.mDatagramController.updateReceiveStatus(mSubId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
pendingCount, SatelliteManager.SATELLITE_RESULT_SUCCESS);
} else {
@@ -473,10 +476,12 @@
plogd("EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE error: " + error);
if (error != SatelliteManager.SATELLITE_RESULT_SUCCESS) {
mDatagramController.updateReceiveStatus(request.subId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED,
mDatagramController.getReceivePendingCount(), error);
mDatagramController.updateReceiveStatus(request.subId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
mDatagramController.getReceivePendingCount(),
SatelliteManager.SATELLITE_RESULT_SUCCESS);
@@ -615,6 +620,7 @@
mPendingPollSatelliteDatagramsRequest = new DatagramReceiverHandlerRequest(
callback, SatelliteServiceUtils.getPhone(), subId);
mDatagramController.updateReceiveStatus(subId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
mDatagramController.getReceivePendingCount(),
SatelliteManager.SATELLITE_RESULT_SUCCESS);
@@ -624,6 +630,7 @@
}
mDatagramController.updateReceiveStatus(subId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
mDatagramController.getReceivePendingCount(),
SatelliteManager.SATELLITE_RESULT_SUCCESS);
@@ -696,14 +703,16 @@
stopDatagramWaitForConnectedStateTimer();
}
- int subId = SatelliteController.getInstance().getHighestPrioritySubscrption();
+ int subId = SatelliteController.getInstance().getSelectedSatelliteSubId();
if (mDatagramController.isReceivingDatagrams()) {
mDatagramController.updateReceiveStatus(subId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED,
mDatagramController.getReceivePendingCount(),
SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED);
}
mDatagramController.updateReceiveStatus(subId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, 0,
SatelliteManager.SATELLITE_RESULT_SUCCESS);
cleanupDemoModeResources();
@@ -857,11 +866,13 @@
plogw("Timed out to wait for satellite connected before polling datagrams");
mDatagramController.updateReceiveStatus(mPendingPollSatelliteDatagramsRequest.subId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED,
mDatagramController.getReceivePendingCount(),
SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
mDatagramController.updateReceiveStatus(mPendingPollSatelliteDatagramsRequest.subId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
mDatagramController.getReceivePendingCount(),
SatelliteManager.SATELLITE_RESULT_SUCCESS);
diff --git a/src/java/com/android/internal/telephony/satellite/DemoSimulator.java b/src/java/com/android/internal/telephony/satellite/DemoSimulator.java
index 7b64c61..d908597 100644
--- a/src/java/com/android/internal/telephony/satellite/DemoSimulator.java
+++ b/src/java/com/android/internal/telephony/satellite/DemoSimulator.java
@@ -287,12 +287,12 @@
* and {@code false} to disable
* @param errorCallback The callback to receive the error code result of the operation.
*/
- public void enableCellularModemWhileSatelliteModeIsOn(boolean enabled,
+ public void enableTerrestrialNetworkScanWhileSatelliteModeIsOn(boolean enabled,
@NonNull IIntegerConsumer errorCallback) {
try {
errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS);
} catch (RemoteException e) {
- loge("enableCellularModemWhileSatelliteModeIsOn: RemoteException " + e);
+ loge("enableTerrestrialNetworkScanWhileSatelliteModeIsOn: RemoteException " + e);
}
}
diff --git a/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java b/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
index dfc7919..4b53178 100644
--- a/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
+++ b/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
@@ -52,7 +52,8 @@
logd("Registered to satellite PLMN " + satellitePlmn);
networkRegistrationInfo.setIsNonTerrestrialNetwork(true);
networkRegistrationInfo.setAvailableServices(
- satelliteController.getSupportedSatelliteServices(subId, satellitePlmn));
+ satelliteController.getSupportedSatelliteServicesForPlmn(
+ subId, satellitePlmn));
break;
}
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 695887e..56c7fb7 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -16,9 +16,13 @@
package com.android.internal.telephony.satellite;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY;
import static android.provider.Settings.ACTION_SATELLITE_SETTING;
+import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC;
import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL;
import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_TYPE;
+import static android.telephony.CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY;
@@ -30,12 +34,14 @@
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ESOS_SUPPORTED_BOOL;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_SUPPORTED_MSG_APPS_STRING_ARRAY;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_NIDD_APN_NAME_STRING;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE;
import static android.telephony.SubscriptionManager.SATELLITE_ATTACH_ENABLED_FOR_CARRIER;
import static android.telephony.SubscriptionManager.SATELLITE_ENTITLEMENT_STATUS;
import static android.telephony.SubscriptionManager.isValidSubscriptionId;
@@ -58,10 +64,12 @@
import android.annotation.ArrayRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.app.StatusBarManager;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -70,9 +78,13 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.hardware.devicestate.DeviceState;
+import android.hardware.devicestate.DeviceStateManager;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.nfc.NfcAdapter;
@@ -102,6 +114,7 @@
import android.provider.Telephony;
import android.telecom.TelecomManager;
import android.telephony.AccessNetworkConstants;
+import android.telephony.AnomalyReporter;
import android.telephony.CarrierConfigManager;
import android.telephony.DropBoxManagerLoggerBackend;
import android.telephony.NetworkRegistrationInfo;
@@ -111,6 +124,7 @@
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.TelephonyRegistryManager;
import android.telephony.satellite.INtnSignalStrengthCallback;
import android.telephony.satellite.ISatelliteCapabilitiesCallback;
import android.telephony.satellite.ISatelliteDatagramCallback;
@@ -126,11 +140,13 @@
import android.telephony.satellite.SatelliteSubscriberInfo;
import android.telephony.satellite.SatelliteSubscriberProvisionStatus;
import android.telephony.satellite.SatelliteSubscriptionInfo;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.uwb.UwbManager;
+import android.view.WindowManager;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -152,6 +168,7 @@
import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
+import com.android.internal.telephony.util.ArrayUtils;
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.util.FunctionalUtils;
@@ -164,6 +181,8 @@
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.TreeMap;
+import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -198,10 +217,16 @@
public static final int TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS = 2;
/** This is used by CTS to override demo pointing not aligned duration. */
public static final int TIMEOUT_TYPE_DEMO_POINTING_NOT_ALIGNED_DURATION_MILLIS = 3;
-
+ /** This is used by CTS to override evaluate esos profiles prioritization duration. */
+ public static final int TIMEOUT_TYPE_EVALUATE_ESOS_PROFILES_PRIORITIZATION_DURATION_MILLIS = 4;
/** Key used to read/write OEM-enabled satellite provision status in shared preferences. */
private static final String OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY =
"oem_enabled_satellite_provision_status_key";
+ /** Key used to read/write default messages application NTN SMS support
+ * in shared preferences. */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public static final String NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY =
+ "ntn_sms_supported_by_messages_app_key";
public static final long DEFAULT_CARRIER_EMERGENCY_CALL_WAIT_FOR_CONNECTION_TIMEOUT_MILLIS =
TimeUnit.SECONDS.toMillis(30);
@@ -210,6 +235,14 @@
private static final long WAIT_FOR_REPORT_ENTITLED_MERTICS_TIMEOUT_MILLIS =
TimeUnit.HOURS.toMillis(23);
+ /**
+ * Delay SatelliteEnable request when network selection auto. current RIL not verified to
+ * response right after network selection auto changed. Some RIL has delay for waiting in-svc
+ * with Automatic selection request.
+ */
+ private static final long DELAY_WAITING_SET_NETWORK_SELECTION_AUTO_MILLIS =
+ TimeUnit.SECONDS.toMillis(1);
+
/** Message codes used in handleMessage() */
//TODO: Move the Commands and events related to position updates to PointingAppController
private static final int CMD_START_SATELLITE_TRANSMISSION_UPDATES = 1;
@@ -262,6 +295,9 @@
EVENT_WAIT_FOR_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_RESPONSE_TIMED_OUT = 52;
private static final int EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT = 53;
protected static final int EVENT_SATELLITE_REGISTRATION_FAILURE = 54;
+ private static final int EVENT_TERRESTRIAL_NETWORK_AVAILABLE_CHANGED = 55;
+ private static final int EVENT_SET_NETWORK_SELECTION_AUTO_DONE = 56;
+ private static final int EVENT_SIGNAL_STRENGTH_CHANGED = 57;
@NonNull private static SatelliteController sInstance;
@NonNull private final Context mContext;
@@ -344,6 +380,8 @@
new AtomicBoolean(false);
private final AtomicBoolean mRegisteredForSatelliteRegistrationFailure =
new AtomicBoolean(false);
+ private final AtomicBoolean mRegisteredForTerrestrialNetworkAvailableChanged =
+ new AtomicBoolean(false);
/**
* Map key: subId, value: callback to get error code of the provision request.
*/
@@ -378,6 +416,12 @@
*/
private final ConcurrentHashMap<IBinder, ISatelliteModemStateCallback>
mSatelliteRegistrationFailureListeners = new ConcurrentHashMap<>();
+ /**
+ * Map key: binder of the callback, value: callback to receive terrestrial network
+ * available changed
+ */
+ private final ConcurrentHashMap<IBinder, ISatelliteModemStateCallback>
+ mTerrestrialNetworkAvailableChangedListeners = new ConcurrentHashMap<>();
private final Object mIsSatelliteSupportedLock = new Object();
@GuardedBy("mIsSatelliteSupportedLock")
private Boolean mIsSatelliteSupported = null;
@@ -394,11 +438,11 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected boolean mRadioOffRequested = false;
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- protected final Object mSatelliteViaOemProvisionLock = new Object();
+ protected final Object mDeviceProvisionLock = new Object();
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- @GuardedBy("mSatelliteViaOemProvisionLock")
- protected Boolean mIsSatelliteViaOemProvisioned = null;
- @GuardedBy("mSatelliteViaOemProvisionLock")
+ @GuardedBy("mDeviceProvisionLock")
+ protected Boolean mIsDeviceProvisioned = null;
+ @GuardedBy("mDeviceProvisionLock")
private Boolean mOverriddenIsSatelliteViaOemProvisioned = null;
private final Object mSatelliteCapabilitiesLock = new Object();
@GuardedBy("mSatelliteCapabilitiesLock")
@@ -479,6 +523,10 @@
@NonNull private final Map<Integer, List<Integer>>
mSatModeCapabilitiesForCarrierRoaming = new HashMap<>();
+ @GuardedBy("mSatelliteConnectedLock")
+ private SparseArray<NtnSignalStrength> mLastNotifiedCarrierRoamingNtnSignalStrength =
+ new SparseArray<>();
+
/**
* This is used for testing only. When mEnforcedEmergencyCallToSatelliteHandoverType is valid,
* Telephony will ignore the IMS registration status and cellular availability, and always send
@@ -519,7 +567,15 @@
// key : priority, low value is high, value : List<SubscriptionInfo>
@GuardedBy("mSatelliteTokenProvisionedLock")
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- protected Map<Integer, List<SubscriptionInfo>> mSubsInfoListPerPriority = new HashMap<>();
+ protected TreeMap<Integer, List<SubscriptionInfo>> mSubsInfoListPerPriority = new TreeMap<>();
+ // List of subscriber information and status at the time of last evaluation
+ @GuardedBy("mSatelliteTokenProvisionedLock")
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ private List<SatelliteSubscriberProvisionStatus> mLastEvaluatedSubscriberProvisionStatus =
+ new ArrayList<>();
+ // The ID of the satellite subscription that has highest priority and is provisioned.
+ @GuardedBy("mSatelliteTokenProvisionedLock")
+ private int mSelectedSatelliteSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
// The last ICC ID that framework configured to modem.
@GuardedBy("mSatelliteTokenProvisionedLock")
private String mLastConfiguredIccId;
@@ -528,11 +584,13 @@
private long mWaitTimeForSatelliteEnablingResponse;
private long mDemoPointingAlignedDurationMillis;
private long mDemoPointingNotAlignedDurationMillis;
+ private long mEvaluateEsosProfilesPrioritizationDurationMillis;
private final Object mLock = new Object();
@GuardedBy("mLock")
private long mLastEmergencyCallTime;
private long mSatelliteEmergencyModeDurationMillis;
private static final int DEFAULT_SATELLITE_EMERGENCY_MODE_DURATION_SECONDS = 300;
+ private AlertDialog mNetworkSelectionModeAutoDialog = null;
/** Key used to read/write satellite system notification done in shared preferences. */
private static final String SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY =
@@ -566,6 +624,18 @@
private String mConfigSatelliteGatewayServicePackage = "";
private String mConfigSatelliteCarrierRoamingEsosProvisionedClass = "";
+ private boolean mIsNotificationShowing = false;
+ private static final String OPEN_MESSAGE_BUTTON = "open_message_button";
+ private static final String HOW_IT_WORKS_BUTTON = "how_it_works_button";
+ private static final String ACTION_NOTIFICATION_CLICK = "action_notification_click";
+ private static final String ACTION_NOTIFICATION_DISMISS = "action_notification_dismiss";
+ private AtomicBoolean mOverrideNtnEligibility;
+ private String mDefaultSmsPackageName = "";
+ private String mSatelliteGatewayServicePackageName = "";
+
+ private final Object mNtnSmsSupportedByMessagesAppLock = new Object();
+ @GuardedBy("mNtnSmsSupportedByMessagesAppLock")
+ private Boolean mNtnSmsSupportedByMessagesApp = null;
private BroadcastReceiver
mDefaultSmsSubscriptionChangedBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -578,6 +648,109 @@
}
};
+ private BroadcastReceiver mPackageStateChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mDefaultSmsPackageName = Telephony.Sms.getDefaultSmsPackage(mContext);
+ mSatelliteGatewayServicePackageName = getConfigSatelliteGatewayServicePackage();
+ String schemeSpecificPart = intent.getData().getSchemeSpecificPart();
+ plogd("packageStateChanged: " + intent.getData().toString()
+ + " DefaultSmsPackageName:" + mDefaultSmsPackageName);
+
+ if (!schemeSpecificPart.equals(mSatelliteGatewayServicePackageName)
+ && !schemeSpecificPart.equals(mDefaultSmsPackageName)) {
+ plogv("Neither SMS or SatelliteGateway package");
+ return;
+ }
+ int[] activeSubIds = mSubscriptionManagerService.getActiveSubIdList(true);
+ if (activeSubIds != null) {
+ for (int activeSubId : activeSubIds) {
+ plogd("mPackageStateChangedReceiver: activeSubId= " + activeSubId);
+ handleCarrierRoamingNtnAvailableServicesChanged(activeSubId);
+ }
+ } else {
+ ploge("mPackageStateChangedReceiver: activeSubIds is null");
+ }
+ }
+ };
+
+ // List of device states returned from DeviceStateManager to determine if running on a foldable
+ // device.
+ private List<DeviceState> mDeviceStates = new ArrayList();
+
+ public static final int RESULT_RECEIVER_COUNT_ANOMALY_THRESHOLD = 100;
+ protected final Object mResultReceiverTotalCountLock = new Object();
+ @GuardedBy("mResultReceiverTotalCountLock")
+ protected int mResultReceiverTotalCount;
+ @GuardedBy("mResultReceiverTotalCountLock")
+ protected HashMap<String, Integer> mResultReceiverCountPerMethodMap = new HashMap<>();
+
+ // Satellite anomaly uuid -- ResultReceiver count threshold exceeded
+ private final UUID mAnomalyUnexpectedResultReceiverCountUUID =
+ UUID.fromString("e268f22d-9bba-4d27-b76a-1c7f5b42e241");
+
+ private UUID generateAnomalyUnexpectedResultReceiverCountUUID(int error, int errorCode) {
+ long lerror = error;
+ long lerrorCode = errorCode;
+ return new UUID(mAnomalyUnexpectedResultReceiverCountUUID.getMostSignificantBits(),
+ mAnomalyUnexpectedResultReceiverCountUUID.getLeastSignificantBits()
+ + ((lerrorCode << 32) + lerror));
+ }
+
+ /**
+ * Increments the ResultReceiver count and logs the caller information.
+ * If the count exceeds the threshold, it reports an anomaly via AnomalyReporter.
+ *
+ * @param caller The caller information that created the ResultReceiver
+ * (e.g., class name and method name)
+ */
+ public void incrementResultReceiverCount(String caller) {
+ if (mFeatureFlags.geofenceEnhancementForBetterUx()) {
+ synchronized (mResultReceiverTotalCountLock) {
+ mResultReceiverTotalCount++;
+ logd("[incrementResultReceiverCount] : " + caller
+ + " | ResultReceiver total count= " + mResultReceiverTotalCount);
+ mResultReceiverCountPerMethodMap.compute(caller, (k, v) -> v == null ? 1 : v + 1);
+
+ if (mResultReceiverTotalCount > RESULT_RECEIVER_COUNT_ANOMALY_THRESHOLD) {
+ loge("[mResultReceiverTotalCount] is exceeds limits : "
+ + mResultReceiverTotalCount);
+ loge("[incrementResultReceiverCount] mResultReceiverCountPerMethodMap is "
+ + mResultReceiverCountPerMethodMap);
+ AnomalyReporter.reportAnomaly(
+ generateAnomalyUnexpectedResultReceiverCountUUID(0, 0),
+ "Satellite ResultReceiver total count= "
+ + mResultReceiverTotalCount + " exceeds limit.");
+ }
+ }
+ } else {
+ logd("[incrementResultReceiverCount]: geofenceEnhancementForBetterUx is not enabled");
+ }
+ }
+
+ /**
+ * Decrements the ResultReceiver count and logs the caller information.
+ * Prevents the count from going below zero.
+ *
+ * @param caller The caller information that released the ResultReceiver
+ * (e.g., class name and method name)
+ */
+ public void decrementResultReceiverCount(String caller) {
+ if (mFeatureFlags.geofenceEnhancementForBetterUx()) {
+ synchronized (mResultReceiverTotalCountLock) {
+ if (mResultReceiverTotalCount > 0) {
+ mResultReceiverTotalCount--;
+ }
+ logd("[decrementResultReceiverCount] : " + caller
+ + " | ResultReceiver total count=" + mResultReceiverTotalCount);
+ mResultReceiverCountPerMethodMap.computeIfPresent(caller,
+ (k, v) -> v > 0 ? v - 1 : v);
+ }
+ } else {
+ logd("[decrementResultReceiverCount]: geofenceEnhancementForBetterUx is not enabled");
+ }
+ }
+
/**
* @return The singleton instance of SatelliteController.
*/
@@ -662,6 +835,7 @@
registerForPendingDatagramCount();
registerForSatelliteModemStateChanged();
registerForServiceStateChanged();
+ registerForSignalStrengthChanged();
mContentResolver = mContext.getContentResolver();
mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
@@ -682,6 +856,7 @@
}
mSatellitePlmnListFromOverlayConfig = readSatellitePlmnsFromOverlayConfig();
+ registerApplicationStateChanged();
updateSupportedSatelliteServicesForActiveSubscriptions();
mCarrierConfigChangeListener =
(slotIndex, subId, carrierId, specificCarrierId) ->
@@ -705,15 +880,25 @@
mDSM.registerForSignalStrengthReportDecision(this, CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING,
null);
+
loadSatelliteSharedPreferences();
+ if (mSharedPreferences != null) {
+ synchronized (mNtnSmsSupportedByMessagesAppLock) {
+ mNtnSmsSupportedByMessagesApp = mSharedPreferences.getBoolean(
+ NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY, false);
+ }
+ }
+
mWaitTimeForSatelliteEnablingResponse = getWaitForSatelliteEnablingResponseTimeoutMillis();
mDemoPointingAlignedDurationMillis = getDemoPointingAlignedDurationMillisFromResources();
mDemoPointingNotAlignedDurationMillis =
getDemoPointingNotAlignedDurationMillisFromResources();
mSatelliteEmergencyModeDurationMillis =
getSatelliteEmergencyModeDurationFromOverlayConfig(context);
+ mEvaluateEsosProfilesPrioritizationDurationMillis =
+ getEvaluateEsosProfilesPrioritizationDurationMillis();
sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
- /* delayMillis= */ TimeUnit.MINUTES.toMillis(1));
+ mEvaluateEsosProfilesPrioritizationDurationMillis);
SubscriptionManager subscriptionManager = mContext.getSystemService(
SubscriptionManager.class);
@@ -724,6 +909,9 @@
}
registerDefaultSmsSubscriptionChangedBroadcastReceiver();
updateSatelliteProvisionedStatePerSubscriberId();
+ if (android.hardware.devicestate.feature.flags.Flags.deviceStatePropertyMigration()) {
+ mDeviceStates = getSupportedDeviceStates();
+ }
}
class SatelliteSubscriptionsChangedListener
@@ -1212,8 +1400,8 @@
// If Satellite enable/disable request returned Error, no need to wait for radio
argument.callback.accept(error);
}
-
if (argument.enableSatellite) {
+ mSessionMetricsStats.resetSessionStatsShadowCounters();
mSessionMetricsStats.setInitializationResult(error)
.setSatelliteTechnology(getSupportedNtnRadioTechnology())
.setInitializationProcessingTime(
@@ -1283,8 +1471,20 @@
}
}
onCompleted = obtainMessage(EVENT_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_DONE, request);
+ SatelliteModemEnableRequestAttributes enableRequestAttributes =
+ createModemEnableRequest(argument);
+ if (enableRequestAttributes == null) {
+ plogw("UpdateEnableAttributes: enableRequestAttributes is null");
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
+ argument.callback);
+ synchronized (mSatelliteEnabledRequestLock) {
+ mSatelliteEnableAttributesUpdateRequest = null;
+ }
+ break;
+ }
mSatelliteModemInterface.requestSatelliteEnabled(
- createModemEnableRequest(argument), onCompleted);
+ enableRequestAttributes, onCompleted);
startWaitForUpdateSatelliteEnableAttributesResponseTimer(argument);
break;
}
@@ -1358,6 +1558,7 @@
updateSatelliteSupportedState(false);
}
((ResultReceiver) request.argument).send(error, bundle);
+ decrementResultReceiverCount("SC:requestIsSatelliteEnabled");
break;
}
@@ -1410,11 +1611,12 @@
synchronized (mNeedsSatellitePointingLock) {
mNeedsSatellitePointing = capabilities.isPointingRequired();
}
- if (DBG) plogd("getSatelliteCapabilities: " + capabilities);
- bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES,
- capabilities);
synchronized (mSatelliteCapabilitiesLock) {
mSatelliteCapabilities = capabilities;
+ overrideSatelliteCapabilitiesIfApplicable();
+ if (DBG) plogd("getSatelliteCapabilities: " + mSatelliteCapabilities);
+ bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES,
+ mSatelliteCapabilities);
}
}
}
@@ -1451,6 +1653,7 @@
}
}
((ResultReceiver) request.argument).send(error, bundle);
+ decrementResultReceiverCount("SC:requestTimeForNextSatelliteVisibility");
break;
}
@@ -1476,16 +1679,19 @@
if (mSatelliteModemInterface.isSatelliteServiceConnected()) {
synchronized (mIsSatelliteSupportedLock) {
if (mIsSatelliteSupported == null || !mIsSatelliteSupported) {
+ final String caller = "SC:CMD_IS_SATELLITE_SUPPORTED";
ResultReceiver receiver = new ResultReceiver(this) {
@Override
protected void onReceiveResult(
int resultCode, Bundle resultData) {
+ decrementResultReceiverCount(caller);
plogd("onRadioStateChanged.requestIsSatelliteSupported: "
+ "resultCode=" + resultCode
+ ", resultData=" + resultData);
}
};
sendRequestAsync(CMD_IS_SATELLITE_SUPPORTED, receiver, null);
+ incrementResultReceiverCount(caller);
}
}
}
@@ -1524,6 +1730,7 @@
ploge("EVENT_SATELLITE_MODEM_STATE_CHANGED: result is null");
} else {
handleEventSatelliteModemStateChanged((int) ar.result);
+ updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(getSatellitePhone());
}
break;
@@ -1603,6 +1810,7 @@
}
result.send(errorCode, null);
}
+ decrementResultReceiverCount("SC:requestNtnSignalStrength");
break;
}
@@ -1612,6 +1820,7 @@
ploge("EVENT_NTN_SIGNAL_STRENGTH_CHANGED: result is null");
} else {
handleEventNtnSignalStrengthChanged((NtnSignalStrength) ar.result);
+ updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(getSatellitePhone());
}
break;
}
@@ -1690,12 +1899,13 @@
case EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT: {
synchronized (mSatellitePhoneLock) {
mNtnEligibilityHysteresisTimedOut = true;
- boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone);
- plogd("EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT:"
- + " isCarrierRoamingNtnEligible=" + eligible);
- if (eligible) {
- requestIsSatelliteAllowedForCurrentLocation();
- }
+ }
+
+ boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone);
+ plogd("EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT:"
+ + " isCarrierRoamingNtnEligible=" + eligible);
+ if (eligible) {
+ requestIsSatelliteAllowedForCurrentLocation();
}
break;
}
@@ -1710,35 +1920,38 @@
RequestProvisionSatelliteArgument argument =
(RequestProvisionSatelliteArgument) request.argument;
onCompleted = obtainMessage(EVENT_UPDATE_PROVISION_SATELLITE_TOKEN_DONE, request);
- // only pass to index 0.
- // TODO: Select the subscription with highest priority and set it to mSatelliteSubId
- int subId = -1;
- synchronized (mSatelliteTokenProvisionedLock) {
- subId = mSubscriberIdPerSub.getOrDefault(
- argument.mSatelliteSubscriberInfoList.get(0).getSubscriberId(), -1);
- }
- setSatellitePhone(subId);
- String iccId = mSubscriptionManagerService.getSubscriptionInfo(subId).getIccId();
- argument.setIccId(iccId);
- boolean sendResponse = false;
- synchronized (mSatelliteTokenProvisionedLock) {
- if (!iccId.equals(mLastConfiguredIccId)) {
- logd("updateSatelliteSubscription subId=" + subId + ", iccId=" + iccId
- + " to modem");
- mSatelliteModemInterface.updateSatelliteSubscription(iccId, onCompleted);
- } else {
- sendResponse = true;
+ boolean provisionChanged = updateSatelliteSubscriptionProvisionState(
+ argument.mSatelliteSubscriberInfoList, argument.mProvisioned);
+ selectBindingSatelliteSubscription(false);
+ int subId = getSelectedSatelliteSubId();
+ SubscriptionInfo subscriptionInfo =
+ mSubscriptionManagerService.getSubscriptionInfo(subId);
+ if (subscriptionInfo == null) {
+ logw("updateSatelliteToken subId=" + subId + " is not found");
+ } else {
+ String iccId = subscriptionInfo.getIccId();
+ argument.setIccId(iccId);
+ synchronized (mSatelliteTokenProvisionedLock) {
+ if (!iccId.equals(mLastConfiguredIccId)) {
+ logd("updateSatelliteSubscription subId=" + subId
+ + ", iccId=" + iccId + " to modem");
+ mSatelliteModemInterface.updateSatelliteSubscription(
+ iccId, onCompleted);
+ }
}
}
- handleEventSatelliteSubscriptionProvisionStateChanged(
- argument.mSatelliteSubscriberInfoList, true);
- if (sendResponse) {
- // The response is sent immediately because the ICCID has already been
- // delivered to the modem.
- Bundle bundle = new Bundle();
- bundle.putBoolean(SatelliteManager.KEY_PROVISION_SATELLITE_TOKENS, true);
- argument.mResult.send(SATELLITE_RESULT_SUCCESS, bundle);
+ if (provisionChanged) {
+ handleEventSatelliteSubscriptionProvisionStateChanged();
}
+
+ // The response is sent immediately because the ICCID has already been
+ // delivered to the modem.
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(
+ argument.mProvisioned ? SatelliteManager.KEY_PROVISION_SATELLITE_TOKENS
+ : SatelliteManager.KEY_DEPROVISION_SATELLITE_TOKENS, true);
+ argument.mResult.send(SATELLITE_RESULT_SUCCESS, bundle);
+ decrementResultReceiverCount("SC:provisionSatellite");
break;
}
@@ -1755,10 +1968,6 @@
}
}
logd("updateSatelliteSubscription result=" + error);
- Bundle bundle = new Bundle();
- bundle.putBoolean(SatelliteManager.KEY_PROVISION_SATELLITE_TOKENS,
- error == SATELLITE_RESULT_SUCCESS);
- argument.mResult.send(error, bundle);
break;
}
@@ -1768,8 +1977,8 @@
mIsWifiConnected = (boolean) ar.result;
plogd("EVENT_WIFI_CONNECTIVITY_STATE_CHANGED: mIsWifiConnected="
+ mIsWifiConnected);
- handleStateChangedForCarrierRoamingNtnEligibility();
}
+ evaluateCarrierRoamingNtnEligibilityChange();
break;
}
case EVENT_SATELLITE_ACCESS_RESTRICTION_CHECKING_RESULT: {
@@ -1808,6 +2017,30 @@
}
break;
+ case EVENT_TERRESTRIAL_NETWORK_AVAILABLE_CHANGED:
+ ar = (AsyncResult) msg.obj;
+ if (ar.result == null) {
+ loge("EVENT_TERRESTRIAL_NETWORK_AVAILABLE_CHANGED: result is null");
+ } else {
+ handleEventTerrestrialNetworkAvailableChanged((boolean) ar.result);
+ }
+ break;
+
+ case EVENT_SET_NETWORK_SELECTION_AUTO_DONE: {
+ logd("EVENT_SET_NETWORK_SELECTION_AUTO_DONE");
+ RequestSatelliteEnabledArgument argument =
+ (RequestSatelliteEnabledArgument) msg.obj;
+ sendRequestAsync(CMD_SET_SATELLITE_ENABLED, argument, null);
+ break;
+ }
+
+ case EVENT_SIGNAL_STRENGTH_CHANGED: {
+ ar = (AsyncResult) msg.obj;
+ int phoneId = (int) ar.userObj;
+ updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(
+ PhoneFactory.getPhone(phoneId));
+ }
+
default:
Log.w(TAG, "SatelliteControllerHandler: unexpected message code: " +
msg.what);
@@ -1821,11 +2054,13 @@
public ResultReceiver mResult;
public long mRequestId;
public String mIccId;
+ public boolean mProvisioned;
RequestProvisionSatelliteArgument(List<SatelliteSubscriberInfo> satelliteSubscriberInfoList,
- ResultReceiver result) {
+ ResultReceiver result, boolean provisioned) {
this.mSatelliteSubscriberInfoList = satelliteSubscriberInfoList;
this.mResult = result;
+ this.mProvisioned = provisioned;
this.mRequestId = sNextSatelliteEnableRequestId.getAndUpdate(
n -> ((n + 1) % Long.MAX_VALUE));
}
@@ -1921,6 +2156,21 @@
* 4. ongoing request = enable, current request = disable: send request to modem
*/
synchronized (mSatelliteEnabledRequestLock) {
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ if (mSatelliteEnabledRequest != null && mNetworkSelectionModeAutoDialog != null
+ && mNetworkSelectionModeAutoDialog.isShowing()
+ && request.isEmergency && request.enableSatellite) {
+ synchronized (mSatellitePhoneLock) {
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_ILLEGAL_STATE,
+ FunctionalUtils.ignoreRemoteException(
+ mSatelliteEnabledRequest.callback::accept));
+ }
+ mSatelliteEnabledRequest = null;
+ mNetworkSelectionModeAutoDialog.dismiss();
+ mNetworkSelectionModeAutoDialog = null;
+ }
+ }
if (!isSatelliteEnabledRequestInProgress()) {
synchronized (mIsSatelliteEnabledLock) {
if (mIsSatelliteEnabled != null && mIsSatelliteEnabled == enableSatellite) {
@@ -1983,7 +2233,87 @@
}
}
}
- sendRequestAsync(CMD_SET_SATELLITE_ENABLED, request, null);
+
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ Phone satellitePhone = getSatellitePhone();
+ if (enableSatellite && satellitePhone != null
+ && satellitePhone.getServiceStateTracker() != null
+ && satellitePhone.getServiceStateTracker().getServiceState()
+ .getIsManualSelection()) {
+ checkNetworkSelectionModeAuto(request);
+ } else {
+ sendRequestAsync(CMD_SET_SATELLITE_ENABLED, request, null);
+ }
+ } else {
+ sendRequestAsync(CMD_SET_SATELLITE_ENABLED, request, null);
+ }
+ }
+
+ private void checkNetworkSelectionModeAuto(RequestSatelliteEnabledArgument argument) {
+ plogd("checkNetworkSelectionModeAuto");
+ if (argument.isEmergency) {
+ // ESOS
+ getSatellitePhone().setNetworkSelectionModeAutomatic(null);
+ sendMessageDelayed(obtainMessage(EVENT_SET_NETWORK_SELECTION_AUTO_DONE, argument),
+ DELAY_WAITING_SET_NETWORK_SELECTION_AUTO_MILLIS);
+ } else {
+ // P2P
+ if (mNetworkSelectionModeAutoDialog != null
+ && mNetworkSelectionModeAutoDialog.isShowing()) {
+ logd("requestSatelliteEnabled: already auto network selection mode popup showing");
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS,
+ FunctionalUtils.ignoreRemoteException(argument.callback::accept));
+ return;
+ }
+ logd("requestSatelliteEnabled: auto network selection mode popup");
+ Configuration configuration = Resources.getSystem().getConfiguration();
+ boolean nightMode = (configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK)
+ == Configuration.UI_MODE_NIGHT_YES;
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(mContext, nightMode
+ ? AlertDialog.THEME_DEVICE_DEFAULT_DARK
+ : AlertDialog.THEME_DEVICE_DEFAULT_LIGHT);
+
+ String title = mContext.getResources().getString(
+ R.string.satellite_manual_selection_state_popup_title);
+ String message = mContext.getResources().getString(
+ R.string.satellite_manual_selection_state_popup_message);
+ String ok = mContext.getResources().getString(
+ R.string.satellite_manual_selection_state_popup_ok);
+ String cancel = mContext.getResources().getString(
+ R.string.satellite_manual_selection_state_popup_cancel);
+
+ builder.setTitle(title).setMessage(message)
+ .setPositiveButton(ok, (dialog, which) -> {
+ logd("checkNetworkSelectionModeAuto: setPositiveButton");
+ getSatellitePhone().setNetworkSelectionModeAutomatic(null);
+ sendMessageDelayed(obtainMessage(EVENT_SET_NETWORK_SELECTION_AUTO_DONE,
+ argument), DELAY_WAITING_SET_NETWORK_SELECTION_AUTO_MILLIS);
+ })
+ .setNegativeButton(cancel, (dialog, which) -> {
+ logd("checkNetworkSelectionModeAuto: setNegativeButton");
+ synchronized (mSatelliteEnabledRequestLock) {
+ mSatelliteEnabledRequest = null;
+ }
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_ILLEGAL_STATE,
+ FunctionalUtils.ignoreRemoteException(argument.callback::accept));
+ })
+ .setOnCancelListener(dialog -> {
+ logd("checkNetworkSelectionModeAuto: setOnCancelListener");
+ synchronized (mSatelliteEnabledRequestLock) {
+ mSatelliteEnabledRequest = null;
+ }
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_ILLEGAL_STATE,
+ FunctionalUtils.ignoreRemoteException(argument.callback::accept));
+ });
+ mNetworkSelectionModeAutoDialog = builder.create();
+ mNetworkSelectionModeAutoDialog.getWindow()
+ .setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ mNetworkSelectionModeAutoDialog.show();
+ }
}
/**
@@ -2079,6 +2409,7 @@
}
sendRequestAsync(CMD_IS_SATELLITE_ENABLED, result, null);
+ incrementResultReceiverCount("SC:requestIsSatelliteEnabled");
}
/**
@@ -2087,13 +2418,15 @@
*
* @return {@code true} if the satellite modem is enabled and {@code false} otherwise.
*/
- public boolean isSatelliteEnabled() {
+ private boolean isSatelliteEnabled() {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
plogd("isSatelliteEnabled: oemEnabledSatelliteFlag is disabled");
return false;
}
- if (mIsSatelliteEnabled == null) return false;
- return mIsSatelliteEnabled;
+ synchronized (mIsSatelliteEnabledLock) {
+ if (mIsSatelliteEnabled == null) return false;
+ return mIsSatelliteEnabled;
+ }
}
/**
@@ -2101,16 +2434,31 @@
*
* @return {@code true} if the satellite modem is being enabled and {@code false} otherwise.
*/
- public boolean isSatelliteBeingEnabled() {
+ private boolean isSatelliteBeingEnabled() {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
plogd("isSatelliteBeingEnabled: oemEnabledSatelliteFlag is disabled");
return false;
}
- if (mSatelliteSessionController != null) {
- return mSatelliteSessionController.isInEnablingState();
+ if (mSatelliteSessionController != null
+ && mSatelliteSessionController.isInEnablingState()) {
+ return true;
}
- return false;
+
+ synchronized (mSatelliteEnabledRequestLock) {
+ return (mSatelliteEnabledRequest != null);
+ }
+ }
+
+ /**
+ * Get whether the satellite modem is enabled or being enabled.
+ * This will return the cached value instead of querying the satellite modem.
+ *
+ * @return {@code true} if the satellite modem is enabled or being enabled, {@code false}
+ * otherwise.
+ */
+ public boolean isSatelliteEnabledOrBeingEnabled() {
+ return isSatelliteEnabled() || isSatelliteBeingEnabled();
}
/**
@@ -2119,10 +2467,14 @@
* @return {@code true} if the satellite modem is being disabled and {@code false} otherwise.
*/
public boolean isSatelliteBeingDisabled() {
- if (mSatelliteSessionController != null) {
- return mSatelliteSessionController.isInDisablingState();
+ if (mSatelliteSessionController != null
+ && mSatelliteSessionController.isInDisablingState()) {
+ return true;
}
- return false;
+
+ synchronized (mSatelliteEnabledRequestLock) {
+ return (mSatelliteDisabledRequest != null);
+ }
}
/**
@@ -2194,7 +2546,7 @@
/* We have already successfully queried the satellite modem. */
Bundle bundle = new Bundle();
bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, mIsSatelliteSupported);
- bundle.putInt(SATELLITE_SUBSCRIPTION_ID, getHighestPrioritySubscrption());
+ bundle.putInt(SATELLITE_SUBSCRIPTION_ID, getSelectedSatelliteSubId());
result.send(SATELLITE_RESULT_SUCCESS, bundle);
return;
}
@@ -2219,6 +2571,7 @@
synchronized (mSatelliteCapabilitiesLock) {
if (mSatelliteCapabilities != null) {
Bundle bundle = new Bundle();
+ overrideSatelliteCapabilitiesIfApplicable();
bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES,
mSatelliteCapabilities);
result.send(SATELLITE_RESULT_SUCCESS, bundle);
@@ -2247,7 +2600,7 @@
return;
}
- final int validSubId = getHighestPrioritySubscrption();
+ final int validSubId = getSelectedSatelliteSubId();
mPointingAppController.registerForSatelliteTransmissionUpdates(validSubId, callback);
sendRequestAsync(CMD_START_SATELLITE_TRANSMISSION_UPDATES,
new SatelliteTransmissionUpdateArgument(result, callback, validSubId), null);
@@ -2265,7 +2618,7 @@
@NonNull ISatelliteTransmissionUpdateCallback callback) {
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(errorCallback::accept);
mPointingAppController.unregisterForSatelliteTransmissionUpdates(
- getHighestPrioritySubscrption(), result, callback);
+ getSelectedSatelliteSubId(), result, callback);
// Even if handler is null - which means there are no listeners, the modem command to stop
// satellite transmission updates might have failed. The callers might want to retry
@@ -2289,36 +2642,60 @@
@NonNull String token, @NonNull byte[] provisionData,
@NonNull IIntegerConsumer callback) {
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
- int error = evaluateOemSatelliteRequestAllowed(false);
- if (error != SATELLITE_RESULT_SUCCESS) {
- result.accept(error);
- return null;
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ List<SatelliteSubscriberInfo> subscriberInfoList =
+ getNtnOnlySatelliteSubscriberInfoList(result);
+ if (subscriberInfoList == null) {
+ return null;
+ }
+ ResultReceiver internalReceiver = new ResultReceiver(this) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ plogd("provisionSatelliteService: resultCode=" + resultCode
+ + ", resultData=" + resultData);
+ result.accept(resultCode);
+ }
+ };
+ provisionSatellite(subscriberInfoList, internalReceiver);
+
+ ICancellationSignal cancelTransport = CancellationSignal.createTransport();
+ CancellationSignal.fromTransport(cancelTransport).setOnCancelListener(() -> {
+ deprovisionSatellite(subscriberInfoList, internalReceiver);
+ mProvisionMetricsStats.setIsCanceled(true);
+ });
+ return cancelTransport;
+ } else {
+ int error = evaluateOemSatelliteRequestAllowed(false);
+ if (error != SATELLITE_RESULT_SUCCESS) {
+ result.accept(error);
+ return null;
+ }
+
+ final int validSubId = getSelectedSatelliteSubId();
+ if (mSatelliteProvisionCallbacks.containsKey(validSubId)) {
+ result.accept(SatelliteManager.SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS);
+ return null;
+ }
+
+ Boolean satelliteProvisioned = isDeviceProvisioned();
+ if (satelliteProvisioned != null && satelliteProvisioned) {
+ result.accept(SATELLITE_RESULT_SUCCESS);
+ return null;
+ }
+
+ sendRequestAsync(CMD_PROVISION_SATELLITE_SERVICE,
+ new ProvisionSatelliteServiceArgument(token, provisionData, result, validSubId),
+ null);
+
+ ICancellationSignal cancelTransport = CancellationSignal.createTransport();
+ CancellationSignal.fromTransport(cancelTransport).setOnCancelListener(() -> {
+ sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE,
+ new ProvisionSatelliteServiceArgument(token, provisionData, null,
+ validSubId), null);
+ mProvisionMetricsStats.setIsCanceled(true);
+ });
+ return cancelTransport;
}
-
- final int validSubId = getHighestPrioritySubscrption();
- if (mSatelliteProvisionCallbacks.containsKey(validSubId)) {
- result.accept(SatelliteManager.SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS);
- return null;
- }
-
- Boolean satelliteProvisioned = isSatelliteViaOemProvisioned();
- if (satelliteProvisioned != null && satelliteProvisioned) {
- result.accept(SATELLITE_RESULT_SUCCESS);
- return null;
- }
-
- sendRequestAsync(CMD_PROVISION_SATELLITE_SERVICE,
- new ProvisionSatelliteServiceArgument(token, provisionData, result, validSubId),
- null);
-
- ICancellationSignal cancelTransport = CancellationSignal.createTransport();
- CancellationSignal.fromTransport(cancelTransport).setOnCancelListener(() -> {
- sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE,
- new ProvisionSatelliteServiceArgument(token, provisionData, null,
- validSubId), null);
- mProvisionMetricsStats.setIsCanceled(true);
- });
- return cancelTransport;
}
/**
@@ -2334,21 +2711,38 @@
public void deprovisionSatelliteService(
@NonNull String token, @NonNull IIntegerConsumer callback) {
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
- int error = evaluateOemSatelliteRequestAllowed(false);
- if (error != SATELLITE_RESULT_SUCCESS) {
- result.accept(error);
- return;
- }
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ List<SatelliteSubscriberInfo> subscriberInfoList =
+ getNtnOnlySatelliteSubscriberInfoList(result);
+ if (subscriberInfoList == null) {
+ return;
+ }
+ ResultReceiver internalReceiver = new ResultReceiver(this) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ plogd("deprovisionSatelliteService: resultCode=" + resultCode
+ + ", resultData=" + resultData);
+ result.accept(resultCode);
+ }
+ };
+ deprovisionSatellite(subscriberInfoList, internalReceiver);
+ } else {
+ int error = evaluateOemSatelliteRequestAllowed(false);
+ if (error != SATELLITE_RESULT_SUCCESS) {
+ result.accept(error);
+ return;
+ }
- if (Boolean.FALSE.equals(isSatelliteViaOemProvisioned())) {
- result.accept(SATELLITE_RESULT_SUCCESS);
- return;
- }
+ if (Boolean.FALSE.equals(isDeviceProvisioned())) {
+ result.accept(SATELLITE_RESULT_SUCCESS);
+ return;
+ }
- sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE,
+ sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE,
new ProvisionSatelliteServiceArgument(token, null,
- result, getHighestPrioritySubscrption()),
+ result, getSelectedSatelliteSubId()),
null);
+ }
}
/**
@@ -2367,13 +2761,13 @@
mSatelliteProvisionStateChangedListeners.put(callback.asBinder(), callback);
- boolean isProvisioned = Boolean.TRUE.equals(isSatelliteViaOemProvisioned());
+ boolean isProvisioned = Boolean.TRUE.equals(isDeviceProvisioned());
try {
callback.onSatelliteProvisionStateChanged(isProvisioned);
} catch (RemoteException ex) {
loge("registerForSatelliteProvisionStateChanged: " + ex);
}
- synchronized (mSatelliteViaOemProvisionLock) {
+ synchronized (mDeviceProvisionLock) {
plogd("registerForSatelliteProvisionStateChanged: report current provisioned "
+ "state, state=" + isProvisioned);
}
@@ -2412,17 +2806,18 @@
return;
}
- synchronized (mSatelliteViaOemProvisionLock) {
- if (mIsSatelliteViaOemProvisioned != null) {
+ synchronized (mDeviceProvisionLock) {
+ if (mIsDeviceProvisioned != null) {
Bundle bundle = new Bundle();
bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED,
- mIsSatelliteViaOemProvisioned);
+ mIsDeviceProvisioned);
result.send(SATELLITE_RESULT_SUCCESS, bundle);
return;
}
}
sendRequestAsync(CMD_IS_SATELLITE_PROVISIONED, result, null);
+ incrementResultReceiverCount("SC:requestIsSatelliteProvisioned");
}
/**
@@ -2439,8 +2834,9 @@
return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
}
if (mFeatureFlags.carrierRoamingNbIotNtn()) {
- plogd("registerForSatelliteModemStateChanged: add RegistrationFailure Listeners");
+ plogd("registerForSatelliteModemStateChanged: add Listeners for ModemState");
mSatelliteRegistrationFailureListeners.put(callback.asBinder(), callback);
+ mTerrestrialNetworkAvailableChangedListeners.put(callback.asBinder(), callback);
}
if (mSatelliteSessionController != null) {
mSatelliteSessionController.registerForSatelliteModemStateChanged(callback);
@@ -2472,8 +2868,9 @@
+ " is not initialized yet");
}
if (mFeatureFlags.carrierRoamingNbIotNtn()) {
- plogd("unregisterForModemStateChanged: remove RegistrationFailure Listeners");
+ plogd("unregisterForModemStateChanged: remove Listeners for ModemState");
mSatelliteRegistrationFailureListeners.remove(callback.asBinder());
+ mTerrestrialNetworkAvailableChangedListeners.remove(callback.asBinder());
}
}
@@ -2495,7 +2892,7 @@
}
plogd("registerForIncomingDatagram: callback=" + callback);
return mDatagramController.registerForSatelliteDatagram(
- getHighestPrioritySubscrption(), callback);
+ getSelectedSatelliteSubId(), callback);
}
/**
@@ -2516,7 +2913,7 @@
}
plogd("unregisterForIncomingDatagram: callback=" + callback);
mDatagramController.unregisterForSatelliteDatagram(
- getHighestPrioritySubscrption(), callback);
+ getSelectedSatelliteSubId(), callback);
}
/**
@@ -2538,7 +2935,7 @@
}
mDatagramController.pollPendingSatelliteDatagrams(
- getHighestPrioritySubscrption(), result);
+ getSelectedSatelliteSubId(), result);
}
/**
@@ -2578,7 +2975,7 @@
mIsEmergency);
}
- mDatagramController.sendSatelliteDatagram(getHighestPrioritySubscrption(), datagramType,
+ mDatagramController.sendSatelliteDatagram(getSelectedSatelliteSubId(), datagramType,
datagram, needFullScreenPointingUI, result);
}
@@ -2596,10 +2993,11 @@
}
sendRequestAsync(CMD_GET_TIME_SATELLITE_NEXT_VISIBLE, result, null);
+ incrementResultReceiverCount("SC:requestTimeForNextSatelliteVisibility");
}
/**
- * Inform whether the device is aligned with satellite for demo mode.
+ * Inform whether the device is aligned with the satellite in both real and demo mode.
*
* @param isAligned {@true} means device is aligned with the satellite, otherwise {@false}.
*/
@@ -2748,6 +3146,7 @@
Phone phone = SatelliteServiceUtils.getPhone();
sendRequestAsync(CMD_REQUEST_NTN_SIGNAL_STRENGTH, result, phone);
+ incrementResultReceiverCount("SC:requestNtnSignalStrength");
}
/**
@@ -2886,8 +3285,8 @@
synchronized (mIsSatelliteSupportedLock) {
mIsSatelliteSupported = null;
}
- synchronized (mSatelliteViaOemProvisionLock) {
- mIsSatelliteViaOemProvisioned = Optional.ofNullable(provisioned)
+ synchronized (mDeviceProvisionLock) {
+ mIsDeviceProvisioned = Optional.ofNullable(provisioned)
.filter(s -> s.equalsIgnoreCase("true") || s.equalsIgnoreCase("false"))
.map(s -> s.equalsIgnoreCase("true"))
.orElse(null);
@@ -2923,6 +3322,21 @@
}
/**
+ * This API can be used by only CTS to control ingoring cellular service state event.
+ *
+ * @param enabled Whether to enable boolean config.
+ * @return {@code true} if the value is set successfully, {@code false} otherwise.
+ */
+ public boolean setSatelliteIgnoreCellularServiceState(boolean enabled) {
+ plogd("setSatelliteIgnoreCellularServiceState - " + enabled);
+ if (mSatelliteSessionController == null) {
+ ploge("setSatelliteIgnoreCellularServiceState is not initialized yet");
+ return false;
+ }
+ return mSatelliteSessionController.setSatelliteIgnoreCellularServiceState(enabled);
+ }
+
+ /**
* This API can be used by only CTS to override timeout durations used by DatagramController
* module.
*
@@ -3001,6 +3415,14 @@
} else {
mDemoPointingNotAlignedDurationMillis = timeoutMillis;
}
+ } else if (timeoutType
+ == TIMEOUT_TYPE_EVALUATE_ESOS_PROFILES_PRIORITIZATION_DURATION_MILLIS) {
+ if (reset) {
+ mEvaluateEsosProfilesPrioritizationDurationMillis =
+ getEvaluateEsosProfilesPrioritizationDurationMillis();
+ } else {
+ mEvaluateEsosProfilesPrioritizationDurationMillis = timeoutMillis;
+ }
} else {
plogw("Invalid timeoutType=" + timeoutType);
return false;
@@ -3087,7 +3509,7 @@
ploge("setOemEnabledSatelliteProvisionStatus: mock modem not allowed");
return false;
}
- synchronized (mSatelliteViaOemProvisionLock) {
+ synchronized (mDeviceProvisionLock) {
if (reset) {
mOverriddenIsSatelliteViaOemProvisioned = null;
} else {
@@ -3137,15 +3559,18 @@
plogd("onSatelliteServiceConnected");
// Vendor service might have just come back from a crash
moveSatelliteToOffStateAndCleanUpResources(SATELLITE_RESULT_MODEM_ERROR);
+ final String caller = "SC:onSatelliteServiceConnected";
ResultReceiver receiver = new ResultReceiver(this) {
@Override
protected void onReceiveResult(
int resultCode, Bundle resultData) {
+ decrementResultReceiverCount(caller);
plogd("onSatelliteServiceConnected.requestIsSatelliteSupported:"
+ " resultCode=" + resultCode);
}
};
requestIsSatelliteSupported(receiver);
+ incrementResultReceiverCount(caller);
} else {
plogd("onSatelliteServiceConnected: Satellite vendor service is not supported."
+ " Ignored the event");
@@ -3201,6 +3626,36 @@
}
/**
+ * Notify SMS received.
+ *
+ * @param subId The subId of the subscription used to receive SMS
+ */
+ public void onSmsReceived(int subId) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ logd("onSmsReceived: carrierRoamingNbIotNtn is disabled");
+ return;
+ }
+
+ if (!isSatelliteEnabled()) {
+ logd("onSmsReceived: satellite is not enabled");
+ return;
+ }
+
+ int satelliteSubId = getSelectedSatelliteSubId();
+ if (subId != satelliteSubId) {
+ logd("onSmsReceived: SMS received " + subId
+ + ", but not satellite subscription " + satelliteSubId);
+ return;
+ }
+
+ if (mDatagramController != null) {
+ mDatagramController.onSmsReceived(subId);
+ } else {
+ logd("onSmsReceived: DatagramController is not initialized");
+ }
+ }
+
+ /**
* @return {@code true} if satellite is supported via OEM on the device,
* {@code false} otherwise.
*/
@@ -3241,7 +3696,7 @@
* the satellite network {@code plmn}.
*/
@NonNull
- public List<Integer> getSupportedSatelliteServices(int subId, String plmn) {
+ public List<Integer> getSupportedSatelliteServicesForPlmn(int subId, String plmn) {
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
logd("getSupportedSatelliteServices: carrierEnabledSatelliteFlag is disabled");
return new ArrayList<>();
@@ -3409,6 +3864,11 @@
}
int subId = phone.getSubId();
+ int carrierRoamingNtnConnectType = getCarrierRoamingNtnConnectType(subId);
+ if (carrierRoamingNtnConnectType == CARRIER_ROAMING_NTN_CONNECT_MANUAL) {
+ return isInCarrierRoamingNbIotNtn(phone);
+ }
+
if (!isSatelliteSupportedViaCarrier(subId)) {
return false;
}
@@ -3474,6 +3934,14 @@
* else {@return false}
*/
public boolean isInCarrierRoamingNbIotNtn() {
+ return isInCarrierRoamingNbIotNtn(getSatellitePhone());
+ }
+
+ /**
+ * @return {@code true} if phone is in carrier roaming nb iot ntn mode,
+ * else {@return false}
+ */
+ private boolean isInCarrierRoamingNbIotNtn(@Nullable Phone phone) {
if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
plogd("isInCarrierRoamingNbIotNtn: carrier roaming nb iot ntn "
+ "feature flag is disabled");
@@ -3485,12 +3953,33 @@
return false;
}
- Phone satellitePhone = getSatellitePhone();
- if (!isCarrierRoamingNtnEligible(satellitePhone)) {
- plogd("isInCarrierRoamingNbIotNtn: not carrier roaming ntn eligible.");
+ if (phone == null) {
+ plogd("isInCarrierRoamingNbIotNtn: phone is null");
return false;
}
+ int subId = phone.getSubId();
+ if (!isSatelliteSupportedViaCarrier(subId)) {
+ plogd("isInCarrierRoamingNbIotNtn[phoneId=" + phone.getPhoneId()
+ + "]: satellite is not supported via carrier");
+ return false;
+ }
+
+ int carrierRoamingNtnConnectType = getCarrierRoamingNtnConnectType(subId);
+ if (carrierRoamingNtnConnectType != CARRIER_ROAMING_NTN_CONNECT_MANUAL) {
+ plogd("isInCarrierRoamingNbIotNtn[phoneId=" + phone.getPhoneId() + "]: not manual "
+ + "connect. carrierRoamingNtnConnectType = " + carrierRoamingNtnConnectType);
+ return false;
+ }
+
+ if (subId != getSelectedSatelliteSubId()) {
+ plogd("isInCarrierRoamingNbIotNtn: subId=" + subId
+ + " does not match satellite subId=" + getSelectedSatelliteSubId());
+ return false;
+ }
+
+ plogd("isInCarrierRoamingNbIotNtn: carrier roaming ntn eligible for phone"
+ + " associated with subId " + phone.getSubId());
return true;
}
@@ -3704,10 +4193,13 @@
new ResultReceiver(this) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
+ decrementResultReceiverCount(
+ "SC:isSatelliteSupportedViaOemInternal");
plogd("isSatelliteSupportedViaOemInternal.requestIsSatelliteSupported:"
+ " resultCode=" + resultCode);
}
});
+ incrementResultReceiverCount("SC:isSatelliteSupportedViaOemInternal");
return null;
}
@@ -3733,8 +4225,8 @@
if (result == SATELLITE_RESULT_SUCCESS
|| result == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) {
persistOemEnabledSatelliteProvisionStatus(true);
- synchronized (mSatelliteViaOemProvisionLock) {
- mIsSatelliteViaOemProvisioned = true;
+ synchronized (mDeviceProvisionLock) {
+ mIsDeviceProvisioned = true;
}
callback.accept(SATELLITE_RESULT_SUCCESS);
handleEventSatelliteProvisionStateChanged(true);
@@ -3761,8 +4253,8 @@
if (result == SATELLITE_RESULT_SUCCESS
|| result == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) {
persistOemEnabledSatelliteProvisionStatus(false);
- synchronized (mSatelliteViaOemProvisionLock) {
- mIsSatelliteViaOemProvisioned = false;
+ synchronized (mDeviceProvisionLock) {
+ mIsDeviceProvisioned = false;
}
if (arg.callback != null) {
arg.callback.accept(SATELLITE_RESULT_SUCCESS);
@@ -3812,21 +4304,21 @@
}
/**
- * Check if satellite is provisioned for a subscription on the device.
- * @return true if satellite is provisioned on the given subscription else return false.
+ * Check if satellite is provisioned for the device.
+ * @return {@code true} if device is provisioned for satellite else return {@code false}.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@Nullable
- protected Boolean isSatelliteViaOemProvisioned() {
- synchronized (mSatelliteViaOemProvisionLock) {
+ protected Boolean isDeviceProvisioned() {
+ synchronized (mDeviceProvisionLock) {
if (mOverriddenIsSatelliteViaOemProvisioned != null) {
return mOverriddenIsSatelliteViaOemProvisioned;
}
- if (mIsSatelliteViaOemProvisioned == null) {
- mIsSatelliteViaOemProvisioned = getPersistedOemEnabledSatelliteProvisionStatus();
+ if (mIsDeviceProvisioned == null) {
+ mIsDeviceProvisioned = getPersistedDeviceProvisionStatus();
}
- return mIsSatelliteViaOemProvisioned;
+ return mIsDeviceProvisioned;
}
}
@@ -3834,6 +4326,23 @@
RequestSatelliteEnabledArgument argument =
(RequestSatelliteEnabledArgument) request.argument;
handlePersistentLoggingOnSessionStart(argument);
+ selectBindingSatelliteSubscription(argument.enableSatellite);
+ SatelliteModemEnableRequestAttributes enableRequestAttributes =
+ createModemEnableRequest(argument);
+ if (enableRequestAttributes == null) {
+ plogw("handleSatelliteEnabled: enableRequestAttributes is null");
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE, argument.callback);
+ synchronized (mSatelliteEnabledRequestLock) {
+ if (argument.enableSatellite) {
+ mSatelliteEnabledRequest = null;
+ } else {
+ mSatelliteDisabledRequest = null;
+ }
+ }
+ return;
+ }
+
if (mSatelliteSessionController != null) {
mSatelliteSessionController.onSatelliteEnablementStarted(argument.enableSatellite);
} else {
@@ -3853,8 +4362,7 @@
Message onCompleted = obtainMessage(EVENT_SET_SATELLITE_ENABLED_DONE, request);
mSatelliteModemInterface.requestSatelliteEnabled(
- createModemEnableRequest(argument),
- onCompleted);
+ enableRequestAttributes, onCompleted);
startWaitForSatelliteEnablingResponseTimer(argument);
// Logs satellite session timestamps for session metrics
if (argument.enableSatellite) {
@@ -3864,11 +4372,15 @@
}
/** Get the request attributes that modem needs to enable/disable satellite */
- private SatelliteModemEnableRequestAttributes createModemEnableRequest(
+ @Nullable private SatelliteModemEnableRequestAttributes createModemEnableRequest(
@NonNull RequestSatelliteEnabledArgument arg) {
- int subId = getHighestPrioritySubscrption();
+ int subId = getSelectedSatelliteSubId();
SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(subId);
- String iccid = subInfo != null ? subInfo.getIccId() : "";
+ if (subInfo == null) {
+ loge("createModemEnableRequest: no SubscriptionInfo found for subId=" + subId);
+ return null;
+ }
+ String iccid = subInfo.getIccId();
String apn = getConfigForSubId(subId).getString(KEY_SATELLITE_NIDD_APN_NAME_STRING, "");
return new SatelliteModemEnableRequestAttributes(
arg.enableSatellite, arg.enableDemoMode, arg.isEmergency,
@@ -3905,6 +4417,7 @@
registerForNtnSignalStrengthChanged();
registerForCapabilitiesChanged();
registerForSatelliteRegistrationFailure();
+ registerForTerrestrialNetworkAvailableChanged();
requestIsSatelliteProvisioned(
new ResultReceiver(this) {
@@ -3912,6 +4425,7 @@
protected void onReceiveResult(int resultCode, Bundle resultData) {
plogd("updateSatelliteSupportedState.requestIsSatelliteProvisioned: "
+ "resultCode=" + resultCode + ", resultData=" + resultData);
+ decrementResultReceiverCount("SC:requestIsSatelliteProvisioned");
requestSatelliteEnabled(false, false, false,
new IIntegerConsumer.Stub() {
@Override
@@ -3922,16 +4436,21 @@
});
}
});
+ incrementResultReceiverCount("SC:requestIsSatelliteProvisioned");
+
requestSatelliteCapabilities(
new ResultReceiver(this) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
plogd("updateSatelliteSupportedState.requestSatelliteCapabilities: "
+ "resultCode=" + resultCode + ", resultData=" + resultData);
+ decrementResultReceiverCount("SC:requestSatelliteCapabilities");
}
});
+ incrementResultReceiverCount("SC:requestSatelliteCapabilities");
}
registerForSatelliteSupportedStateChanged();
+ selectBindingSatelliteSubscription(false);
}
private void updateSatelliteEnabledState(boolean enabled, String caller) {
@@ -3947,6 +4466,9 @@
if (!enabled) {
mIsModemEnabledReportingNtnSignalStrength.set(false);
}
+ if (mFeatureFlags.satelliteStateChangeListener()) {
+ notifyEnabledStateChanged(enabled);
+ }
}
private void registerForPendingDatagramCount() {
@@ -4019,14 +4541,27 @@
}
}
+ private void registerForTerrestrialNetworkAvailableChanged() {
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ if (!mRegisteredForTerrestrialNetworkAvailableChanged.get()) {
+ mSatelliteModemInterface.registerForTerrestrialNetworkAvailableChanged(this,
+ EVENT_TERRESTRIAL_NETWORK_AVAILABLE_CHANGED, null);
+ mRegisteredForTerrestrialNetworkAvailableChanged.set(true);
+ }
+ }
+ }
+
private void handleEventSatelliteProvisionStateChanged(boolean provisioned) {
plogd("handleSatelliteProvisionStateChangedEvent: provisioned=" + provisioned);
- synchronized (mSatelliteViaOemProvisionLock) {
+ synchronized (mDeviceProvisionLock) {
persistOemEnabledSatelliteProvisionStatus(provisioned);
- mIsSatelliteViaOemProvisioned = provisioned;
+ mIsDeviceProvisioned = provisioned;
}
+ notifyDeviceProvisionStateChanged(provisioned);
+ }
+ private void notifyDeviceProvisionStateChanged(boolean provisioned) {
List<ISatelliteProvisionStateCallback> deadCallersList = new ArrayList<>();
mSatelliteProvisionStateChangedListeners.values().forEach(listener -> {
try {
@@ -4041,48 +4576,60 @@
});
}
- private void handleEventSatelliteSubscriptionProvisionStateChanged(
- List<SatelliteSubscriberInfo> newList, boolean provisioned) {
- logd("handleEventSatelliteSubscriptionProvisionStateChanged: newList=" + newList
- + " , provisioned=" + provisioned);
+ private boolean updateSatelliteSubscriptionProvisionState(List<SatelliteSubscriberInfo> newList,
+ boolean provisioned) {
+ logd("updateSatelliteSubscriptionProvisionState: List=" + newList + " , provisioned="
+ + provisioned);
boolean provisionChanged = false;
synchronized (mSatelliteTokenProvisionedLock) {
for (SatelliteSubscriberInfo subscriberInfo : newList) {
- if (mProvisionedSubscriberId.getOrDefault(subscriberInfo.getSubscriberId(), false)
- == provisioned) {
+ Boolean currentProvisioned =
+ mProvisionedSubscriberId.get(subscriberInfo.getSubscriberId());
+ if (currentProvisioned != null && currentProvisioned == provisioned) {
continue;
}
provisionChanged = true;
mProvisionedSubscriberId.put(subscriberInfo.getSubscriberId(), provisioned);
- int subId = mSubscriberIdPerSub.getOrDefault(subscriberInfo.getSubscriberId(),
- SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ int subId = subscriberInfo.getSubId();
try {
mSubscriptionManagerService.setIsSatelliteProvisionedForNonIpDatagram(subId,
provisioned);
- plogd("handleEventSatelliteSubscriptionProvisionStateChanged: set Provision "
- + "state to db subId=" + subId);
+ plogd("updateSatelliteSubscriptionProvisionState: set Provision state to db "
+ + "subId=" + subId);
} catch (IllegalArgumentException | SecurityException ex) {
ploge("setIsSatelliteProvisionedForNonIpDatagram: subId=" + subId + ", ex="
+ ex);
}
}
}
- if (!provisionChanged) {
- logd("handleEventSatelliteSubscriptionProvisionStateChanged: provision state nothing "
- + "changed.");
- return;
- }
+ return provisionChanged;
+ }
+
+ private void handleEventSatelliteSubscriptionProvisionStateChanged() {
List<SatelliteSubscriberProvisionStatus> informList =
getPrioritizedSatelliteSubscriberProvisionStatusList();
plogd("handleEventSatelliteSubscriptionProvisionStateChanged: " + informList);
notifySatelliteSubscriptionProvisionStateChanged(informList);
- // Report updated provisioned status
+ updateDeviceProvisionStatus();
+ // Report updated provisioned status to metrics.
synchronized (mSatelliteTokenProvisionedLock) {
boolean isProvisioned = !mProvisionedSubscriberId.isEmpty()
&& mProvisionedSubscriberId.containsValue(Boolean.TRUE);
mControllerMetricsStats.setIsProvisioned(isProvisioned);
}
- handleStateChangedForCarrierRoamingNtnEligibility();
+ selectBindingSatelliteSubscription(false);
+ evaluateCarrierRoamingNtnEligibilityChange();
+ }
+
+ private void updateDeviceProvisionStatus() {
+ boolean isProvisioned = getPersistedDeviceProvisionStatus();
+ plogd("updateDeviceProvisionStatus: isProvisioned=" + isProvisioned);
+ synchronized (mDeviceProvisionLock) {
+ if (mIsDeviceProvisioned == null || mIsDeviceProvisioned != isProvisioned) {
+ mIsDeviceProvisioned = isProvisioned;
+ notifyDeviceProvisionStateChanged(isProvisioned);
+ }
+ }
}
private void notifySatelliteSubscriptionProvisionStateChanged(
@@ -4117,7 +4664,7 @@
mWaitingForSatelliteModemOff = false;
}
} else {
- if (isSatelliteEnabled() || isSatelliteBeingEnabled() || isSatelliteBeingDisabled()) {
+ if (isSatelliteEnabledOrBeingEnabled() || isSatelliteBeingDisabled()) {
notifyModemStateChangedToSessionController(state);
} else {
// Telephony framework and modem are out of sync. We need to disable modem
@@ -4180,12 +4727,13 @@
synchronized (mSatelliteCapabilitiesLock) {
mSatelliteCapabilities = capabilities;
+ overrideSatelliteCapabilitiesIfApplicable();
}
List<ISatelliteCapabilitiesCallback> deadCallersList = new ArrayList<>();
mSatelliteCapabilitiesChangedListeners.values().forEach(listener -> {
try {
- listener.onSatelliteCapabilitiesChanged(capabilities);
+ listener.onSatelliteCapabilitiesChanged(this.mSatelliteCapabilities);
} catch (RemoteException e) {
plogd("handleEventSatelliteCapabilitiesChanged RemoteException: " + e);
deadCallersList.add(listener);
@@ -4267,7 +4815,8 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected void setSettingsKeyToAllowDeviceRotation(int val) {
// Only allows on a foldable device type.
- if (!isFoldable(mContext)) {
+ if (!isFoldable(mContext, mDeviceStates)) {
+ logd("setSettingsKeyToAllowDeviceRotation(" + val + "), device was not a foldable");
return;
}
@@ -4308,10 +4857,19 @@
* If the device type is foldable.
*
* @param context context
+ * @param deviceStates list of {@link DeviceState}s provided from {@link DeviceStateManager}
* @return {@code true} if device type is foldable. {@code false} for otherwise.
*/
- private boolean isFoldable(Context context) {
- return context.getResources().getIntArray(R.array.config_foldedDeviceStates).length > 0;
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public boolean isFoldable(Context context, List<DeviceState> deviceStates) {
+ if (android.hardware.devicestate.feature.flags.Flags.deviceStatePropertyMigration()) {
+ return deviceStates.stream().anyMatch(deviceState -> deviceState.hasProperty(
+ PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY)
+ || deviceState.hasProperty(
+ PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY));
+ } else {
+ return context.getResources().getIntArray(R.array.config_foldedDeviceStates).length > 0;
+ }
}
/**
@@ -4398,6 +4956,9 @@
sendRequestAsync(CMD_UPDATE_SATELLITE_ENABLE_ATTRIBUTES,
mSatelliteEnableAttributesUpdateRequest, null);
}
+ synchronized (mSatellitePhoneLock) {
+ updateLastNotifiedNtnModeAndNotify(mSatellitePhone);
+ }
}
}
}
@@ -4444,6 +5005,10 @@
updateSatelliteEnabledState(
false, "moveSatelliteToOffStateAndCleanUpResources");
}
+ selectBindingSatelliteSubscription(false);
+ synchronized (mSatellitePhoneLock) {
+ updateLastNotifiedNtnModeAndNotify(mSatellitePhone);
+ }
}
private void setDemoModeEnabled(boolean enabled) {
@@ -4506,6 +5071,7 @@
if (activeSubIds != null) {
for (int subId : activeSubIds) {
updateSupportedSatelliteServices(subId);
+ handleCarrierRoamingNtnAvailableServicesChanged(subId);
}
} else {
loge("updateSupportedSatelliteServicesForActiveSubscriptions: "
@@ -4621,25 +5187,31 @@
@NonNull private PersistableBundle getConfigForSubId(int subId) {
PersistableBundle config = null;
if (mCarrierConfigManager != null) {
- config = mCarrierConfigManager.getConfigForSubId(subId,
- KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
- KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
- KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL,
- KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT,
- KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL,
- KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY,
- KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL,
- KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT,
- KEY_SATELLITE_ESOS_SUPPORTED_BOOL,
- KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL,
- KEY_SATELLITE_NIDD_APN_NAME_STRING,
- KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
- KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT,
- KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT,
- KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT,
- KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
- KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT
- );
+ try {
+ config = mCarrierConfigManager.getConfigForSubId(subId,
+ KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+ KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL,
+ KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT,
+ KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL,
+ KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY,
+ KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL,
+ KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT,
+ KEY_SATELLITE_ESOS_SUPPORTED_BOOL,
+ KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL,
+ KEY_SATELLITE_NIDD_APN_NAME_STRING,
+ KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
+ KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT,
+ KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT,
+ KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT,
+ KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
+ KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
+ KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE,
+ KEY_SATELLITE_SUPPORTED_MSG_APPS_STRING_ARRAY
+ );
+ } catch (Exception e) {
+ logw("getConfigForSubId: " + e);
+ }
}
if (config == null || config.isEmpty()) {
config = CarrierConfigManager.getDefaultConfig();
@@ -4663,15 +5235,15 @@
updateSupportedSatelliteServicesForActiveSubscriptions();
processNewCarrierConfigData(subId);
resetCarrierRoamingSatelliteModeParams(subId);
- handleStateChangedForCarrierRoamingNtnEligibility();
+ evaluateCarrierRoamingNtnEligibilityChange();
sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
- TimeUnit.MINUTES.toMillis(1));
+ mEvaluateEsosProfilesPrioritizationDurationMillis);
}
// imsi, msisdn, default sms subId change
private void handleSubscriptionsChanged() {
sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
- TimeUnit.MINUTES.toMillis(1));
+ mEvaluateEsosProfilesPrioritizationDurationMillis);
}
private void processNewCarrierConfigData(int subId) {
@@ -4777,6 +5349,8 @@
}
}
}
+ // Need to update the provision status of the device
+ updateDeviceProvisionStatus();
}
@NonNull
@@ -4818,6 +5392,17 @@
return getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ESOS_SUPPORTED_BOOL);
}
+ /**
+ * Return whether the device allows to turn off satellite session for emergency call.
+ *
+ * @param subId Associated subscription ID
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public boolean turnOffSatelliteSessionForEmergencyCall(int subId) {
+ return getConfigForSubId(subId).getBoolean(
+ KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL);
+ }
+
private int getCarrierRoamingNtnConnectType(int subId) {
return getConfigForSubId(subId).getInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT);
}
@@ -5079,7 +5664,7 @@
}
if (isProvisionRequired) {
- Boolean satelliteProvisioned = isSatelliteViaOemProvisioned();
+ Boolean satelliteProvisioned = isDeviceProvisioned();
if (satelliteProvisioned == null) {
plogd("evaluateOemSatelliteRequestAllowed: satelliteProvisioned is null");
return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
@@ -5108,6 +5693,17 @@
}
}
+ /**
+ * Returns a list of messaging apps that support satellite.
+ */
+ @NonNull public List<String> getSatelliteSupportedMsgApps(int subId) {
+ String[] satelliteSupportedMsgApps = getConfigForSubId(subId)
+ .getStringArray(KEY_SATELLITE_SUPPORTED_MSG_APPS_STRING_ARRAY);
+
+ return satelliteSupportedMsgApps != null
+ ? List.of(satelliteSupportedMsgApps) : Collections.emptyList();
+ }
+
private void sendErrorAndReportSessionMetrics(@SatelliteManager.SatelliteResult int error,
Consumer<Integer> result) {
result.accept(error);
@@ -5129,8 +5725,15 @@
}
}
+ private void registerForSignalStrengthChanged() {
+ for (Phone phone : PhoneFactory.getPhones()) {
+ phone.getSignalStrengthController().registerForSignalStrengthChanged(this,
+ EVENT_SIGNAL_STRENGTH_CHANGED, phone.getPhoneId());
+ }
+ }
+
private void handleEventServiceStateChanged() {
- handleStateChangedForCarrierRoamingNtnEligibility();
+ evaluateCarrierRoamingNtnEligibilityChange();
handleServiceStateForSatelliteConnectionViaCarrier();
}
@@ -5138,14 +5741,18 @@
for (Phone phone : PhoneFactory.getPhones()) {
int subId = phone.getSubId();
ServiceState serviceState = phone.getServiceState();
- if (serviceState == null) {
+ if (serviceState == null || subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
continue;
}
synchronized (mSatelliteConnectedLock) {
CarrierRoamingSatelliteSessionStats sessionStats =
mCarrierRoamingSatelliteSessionStatsMap.get(subId);
-
+ if (DEBUG) {
+ plogd("handleServiceStateForSatelliteConnectionViaCarrier : SubId = " + subId
+ + " isUsingNonTerrestrialNetwork = "
+ + serviceState.isUsingNonTerrestrialNetwork());
+ }
if (serviceState.isUsingNonTerrestrialNetwork()) {
if (sessionStats != null) {
sessionStats.onSignalStrength(phone);
@@ -5190,6 +5797,7 @@
mWasSatelliteConnectedViaCarrier.put(subId, false);
}
updateLastNotifiedNtnModeAndNotify(phone);
+ updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(phone);
}
}
determineAutoConnectSystemNotification();
@@ -5197,7 +5805,6 @@
private void updateLastNotifiedNtnModeAndNotify(@Nullable Phone phone) {
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) return;
-
if (phone == null) {
return;
}
@@ -5211,7 +5818,11 @@
if (!initialized) mInitialized.put(subId, true);
mLastNotifiedNtnMode.put(subId, currNtnMode);
phone.notifyCarrierRoamingNtnModeChanged(currNtnMode);
+ updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(phone);
logCarrierRoamingSatelliteSessionStats(phone, lastNotifiedNtnMode, currNtnMode);
+ if(mIsNotificationShowing && !currNtnMode) {
+ dismissSatelliteNotification();
+ }
}
}
}
@@ -5236,18 +5847,18 @@
}
}
- private void handleStateChangedForCarrierRoamingNtnEligibility() {
+ private void evaluateCarrierRoamingNtnEligibilityChange() {
if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
- plogd("handleStateChangedForCarrierRoamingNtnEligibility: "
+ plogd("evaluateCarrierRoamingNtnEligibilityChange: "
+ "carrierRoamingNbIotNtn flag is disabled");
return;
}
- synchronized (mSatellitePhoneLock) {
- boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone);
- plogd("handleStateChangedForCarrierRoamingNtnEligibility: "
- + "isCarrierRoamingNtnEligible=" + eligible);
+ boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone);
+ plogd("evaluateCarrierRoamingNtnEligibilityChange: "
+ + "isCarrierRoamingNtnEligible=" + eligible);
+ synchronized (mSatellitePhoneLock) {
if (eligible) {
if (shouldStartNtnEligibilityHysteresisTimer(eligible)) {
startNtnEligibilityHysteresisTimer();
@@ -5286,7 +5897,7 @@
return;
}
- int subId = getHighestPrioritySubscrption();
+ int subId = getSelectedSatelliteSubId();
long timeout = getCarrierSupportedSatelliteNotificationHysteresisTimeMillis(subId);
mNtnEligibilityHysteresisTimedOut = false;
plogd("startNtnEligibilityHysteresisTimer: sendMessageDelayed subId=" + subId
@@ -5308,6 +5919,11 @@
return;
}
+ if (mOverrideNtnEligibility != null) {
+ mSatellitePhone.notifyCarrierRoamingNtnEligibleStateChanged(currentNtnEligibility);
+ return;
+ }
+
synchronized (mSatellitePhoneLock) {
if (mSatellitePhone == null) {
ploge("notifyNtnEligibility: mSatellitePhone is null");
@@ -5320,7 +5936,7 @@
|| mLastNotifiedNtnEligibility != currentNtnEligibility) {
mLastNotifiedNtnEligibility = currentNtnEligibility;
mSatellitePhone.notifyCarrierRoamingNtnEligibleStateChanged(currentNtnEligibility);
- updateSatelliteSystemNotification(getHighestPrioritySubscrption(),
+ updateSatelliteSystemNotification(getSelectedSatelliteSubId(),
CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL,
currentNtnEligibility);
}
@@ -5340,10 +5956,10 @@
}
private void persistOemEnabledSatelliteProvisionStatus(boolean isProvisioned) {
- synchronized (mSatelliteViaOemProvisionLock) {
+ synchronized (mDeviceProvisionLock) {
plogd("persistOemEnabledSatelliteProvisionStatus: isProvisioned=" + isProvisioned);
if (mFeatureFlags.carrierRoamingNbIotNtn()) {
- int subId = SatelliteServiceUtils.getNtnOnlySubscriptionId(mContext);
+ int subId = getNtnOnlySubscriptionId();
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
try {
mSubscriptionManagerService.setIsSatelliteProvisionedForNonIpDatagram(subId,
@@ -5370,24 +5986,34 @@
}
@Nullable
- private Boolean getPersistedOemEnabledSatelliteProvisionStatus() {
- plogd("getPersistedOemEnabledSatelliteProvisionStatus:");
- synchronized (mSatelliteViaOemProvisionLock) {
+ private boolean getPersistedDeviceProvisionStatus() {
+ plogd("getPersistedDeviceProvisionStatus");
+ synchronized (mDeviceProvisionLock) {
if (mFeatureFlags.carrierRoamingNbIotNtn()) {
- int subId = SatelliteServiceUtils.getNtnOnlySubscriptionId(mContext);
+ int subId = getNtnOnlySubscriptionId();
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- return mSubscriptionManagerService.isSatelliteProvisionedForNonIpDatagram(
- subId);
- } else {
- plogd("getPersistedOemEnabledSatelliteProvisionStatus: "
- + "subId=INVALID_SUBSCRIPTION_ID, return null");
- return null;
+ if (mSubscriptionManagerService.isSatelliteProvisionedForNonIpDatagram(subId)) {
+ return true;
+ }
}
+
+ List<SubscriptionInfo> activeSubscriptionInfoList =
+ mSubscriptionManagerService.getActiveSubscriptionInfoList(
+ mContext.getOpPackageName(), mContext.getAttributionTag(), true);
+ for (SubscriptionInfo info : activeSubscriptionInfoList) {
+ if (info.isSatelliteESOSSupported()) {
+ if (mSubscriptionManagerService.isSatelliteProvisionedForNonIpDatagram(
+ info.getSubscriptionId())) {
+ return true;
+ }
+ }
+ }
+ return false;
} else {
if (!loadSatelliteSharedPreferences()) return false;
if (mSharedPreferences == null) {
- ploge("getPersistedOemEnabledSatelliteProvisionStatus: mSharedPreferences is "
+ ploge("getPersistedDeviceProvisionStatus: mSharedPreferences is "
+ "null");
return false;
} else {
@@ -5419,8 +6045,9 @@
Bundle bundle = new Bundle();
bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED,
- Boolean.TRUE.equals(isSatelliteViaOemProvisioned()));
+ Boolean.TRUE.equals(isDeviceProvisioned()));
((ResultReceiver) request.argument).send(SATELLITE_RESULT_SUCCESS, bundle);
+ decrementResultReceiverCount("SC:requestIsSatelliteProvisioned");
}
private long getWaitForSatelliteEnablingResponseTimeoutMillis() {
@@ -5590,7 +6217,7 @@
return;
}
- if (!isSatelliteEnabled()) {
+ if (!isSatelliteEnabledOrBeingEnabled()) {
plogd("handleCmdUpdateNtnSignalStrengthReporting: ignore request, satellite is "
+ "disabled");
return;
@@ -5659,29 +6286,32 @@
}
Pair<Boolean, Integer> isNtn = isUsingNonTerrestrialNetworkViaCarrier();
+ boolean notificationKeyStatus = mSharedPreferences.getBoolean(
+ SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false);
+ if (DEBUG) {
+ logd("determineAutoConnectSystemNotification: isNtn.first = " + isNtn.first
+ + " IsNotiToShow = " + !notificationKeyStatus + " mIsNotificationShowing = "
+ + mIsNotificationShowing);
+ }
if (isNtn.first) {
- if (mSharedPreferences == null) {
- try {
- mSharedPreferences = mContext.getSharedPreferences(SATELLITE_SHARED_PREF,
- Context.MODE_PRIVATE);
- } catch (Exception e) {
- loge("Cannot get default shared preferences: " + e);
- }
- }
- if (mSharedPreferences == null) {
- loge("determineSystemNotification: Cannot get default shared preferences");
- return;
- }
- if (!mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false)) {
+ if (!notificationKeyStatus && getCarrierRoamingNtnConnectType(isNtn.second)
+ == CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC) {
updateSatelliteSystemNotification(isNtn.second,
CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC,
/*visible*/ true);
- mSharedPreferences.edit().putBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY,
- true).apply();
}
+ } else if (mIsNotificationShowing
+ && !isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
+ // Dismiss the notification if it is still displaying.
+ dismissSatelliteNotification();
}
}
+ private void dismissSatelliteNotification() {
+ mIsNotificationShowing = false;
+ updateSatelliteSystemNotification(-1, -1,/*visible*/ false);
+ }
+
/**
* Update the system notification to reflect the current satellite status, that's either already
* connected OR needs to be manually enabled. The device should only display one notification
@@ -5695,15 +6325,13 @@
*/
private void updateSatelliteSystemNotification(int subId,
@CARRIER_ROAMING_NTN_CONNECT_TYPE int carrierRoamingNtnConnectType, boolean visible) {
- plogd("updateSatelliteSystemNotification subId=" + subId
- + ", carrierRoamingNtnConnectType=" + SatelliteServiceUtils
- .carrierRoamingNtnConnectTypeToString(carrierRoamingNtnConnectType)
- + ", visible=" + visible);
+ plogd("updateSatelliteSystemNotification subId=" + subId + ", carrierRoamingNtnConnectType="
+ + SatelliteServiceUtils.carrierRoamingNtnConnectTypeToString(
+ carrierRoamingNtnConnectType) + ", visible=" + visible);
final NotificationChannel notificationChannel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL,
- NotificationManager.IMPORTANCE_DEFAULT
- );
+ NotificationManager.IMPORTANCE_DEFAULT);
notificationChannel.setSound(null, null);
NotificationManager notificationManager = mContext.getSystemService(
NotificationManager.class);
@@ -5736,54 +6364,130 @@
com.android.internal.R.color.system_notification_accent_color))
.setVisibility(Notification.VISIBILITY_PUBLIC);
- // Add action to invoke message application.
- // getDefaultSmsPackage and getLaunchIntentForPackage are nullable.
- Optional<Intent> nullableIntent = Optional.ofNullable(
- Telephony.Sms.getDefaultSmsPackage(mContext))
- .flatMap(packageName -> {
- PackageManager pm = mContext.getPackageManager();
- return Optional.ofNullable(pm.getLaunchIntentForPackage(packageName));
- });
- // If nullableIntent is null, create new Intent for most common way to invoke message app.
- Intent finalIntent = nullableIntent.map(intent -> {
- // Invoke the home screen of default message application.
- intent.setAction(Intent.ACTION_MAIN);
- intent.addCategory(Intent.CATEGORY_HOME);
- return intent;
- }).orElseGet(() -> {
- ploge("showSatelliteSystemNotification: no default sms package name, Invoke "
- + "default sms compose window instead");
- Intent newIntent = new Intent(Intent.ACTION_VIEW);
- newIntent.setData(Uri.parse("sms:"));
- return newIntent;
- });
-
- PendingIntent pendingIntentOpenMessage = PendingIntent.getActivity(mContext, 0,
- finalIntent, PendingIntent.FLAG_IMMUTABLE);
+ // Intent for `Open Messages` [Button 1]
+ Intent openMessageIntent = new Intent();
+ openMessageIntent.setAction(OPEN_MESSAGE_BUTTON);
+ PendingIntent openMessagePendingIntent = PendingIntent.getBroadcast(mContext, 0,
+ openMessageIntent, PendingIntent.FLAG_IMMUTABLE);
Notification.Action actionOpenMessage = new Notification.Action.Builder(0,
mContext.getResources().getString(R.string.satellite_notification_open_message),
- pendingIntentOpenMessage).build();
- notificationBuilder.addAction(actionOpenMessage);
+ openMessagePendingIntent).build();
+ notificationBuilder.addAction(actionOpenMessage); // Handle `Open Messages` button
- // Add action to invoke Satellite setting activity in Settings.
- Intent intentSatelliteSetting = new Intent(ACTION_SATELLITE_SETTING);
- intentSatelliteSetting.putExtra("sub_id", subId);
- PendingIntent pendingIntentSatelliteSetting = PendingIntent.getActivity(mContext, 0,
- intentSatelliteSetting, PendingIntent.FLAG_IMMUTABLE);
-
- Notification.Action actionOpenSatelliteSetting = new Notification.Action.Builder(null,
+ // Button for `How it works` [Button 2]
+ Intent howItWorksIntent = new Intent();
+ howItWorksIntent.setAction(HOW_IT_WORKS_BUTTON);
+ howItWorksIntent.putExtra("SUBID", subId);
+ PendingIntent howItWorksPendingIntent = PendingIntent.getBroadcast(mContext, 0,
+ howItWorksIntent, PendingIntent.FLAG_IMMUTABLE);
+ Notification.Action actionHowItWorks = new Notification.Action.Builder(0,
mContext.getResources().getString(R.string.satellite_notification_how_it_works),
- pendingIntentSatelliteSetting).build();
- notificationBuilder.addAction(actionOpenSatelliteSetting);
+ howItWorksPendingIntent).build();
+ notificationBuilder.addAction(actionHowItWorks); // Handle `How it works` button
+
+ // Intent for clicking the main notification body
+ Intent notificationClickIntent = new Intent(ACTION_NOTIFICATION_CLICK);
+ PendingIntent notificationClickPendingIntent = PendingIntent.getBroadcast(mContext, 0,
+ notificationClickIntent, PendingIntent.FLAG_IMMUTABLE);
+ notificationBuilder.setContentIntent(
+ notificationClickPendingIntent); // Handle notification body click
+
+ // Intent for dismissing/swiping the notification
+ Intent deleteIntent = new Intent(ACTION_NOTIFICATION_DISMISS);
+ PendingIntent deletePendingIntent = PendingIntent.getBroadcast(mContext, 0, deleteIntent,
+ PendingIntent.FLAG_IMMUTABLE);
+ notificationBuilder.setDeleteIntent(
+ deletePendingIntent); // Handle notification swipe/dismiss
notificationManager.notifyAsUser(NOTIFICATION_TAG, NOTIFICATION_ID,
notificationBuilder.build(), UserHandle.ALL);
+ // The Intent filter is to receive the above four events.
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(OPEN_MESSAGE_BUTTON);
+ filter.addAction(HOW_IT_WORKS_BUTTON);
+ filter.addAction(ACTION_NOTIFICATION_CLICK);
+ filter.addAction(ACTION_NOTIFICATION_DISMISS);
+ mContext.registerReceiver(mNotificationInteractionBroadcastReceiver, filter,
+ Context.RECEIVER_EXPORTED);
+
+ mIsNotificationShowing = true;
mCarrierRoamingSatelliteControllerStats.reportCountOfSatelliteNotificationDisplayed();
mCarrierRoamingSatelliteControllerStats.reportCarrierId(getSatelliteCarrierId());
mSessionMetricsStats.addCountOfSatelliteNotificationDisplayed();
}
+ private final BroadcastReceiver mNotificationInteractionBroadcastReceiver =
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent receivedIntent) {
+ String intentAction = receivedIntent.getAction();
+ if (TextUtils.isEmpty(intentAction)) {
+ loge("Received empty action from the notification");
+ return;
+ }
+ if (DBG) {
+ plogd("Notification Broadcast recvd action = "
+ + receivedIntent.getAction());
+ }
+ boolean closeStatusBar = true;
+ switch (intentAction) {
+ case OPEN_MESSAGE_BUTTON -> {
+ // Add action to invoke message application.
+ // getDefaultSmsPackage and getLaunchIntentForPackage are nullable.
+ Optional<Intent> nullableIntent = Optional.ofNullable(
+ Telephony.Sms.getDefaultSmsPackage(context)).flatMap(
+ packageName -> {
+ PackageManager pm = context.getPackageManager();
+ return Optional.ofNullable(
+ pm.getLaunchIntentForPackage(packageName));
+ });
+ // If nullableIntent is null, create new Intent for most common way to
+ // invoke
+ // message app.
+ Intent finalIntent = nullableIntent.map(intent -> {
+ // Invoke the home screen of default message application.
+ intent.setAction(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_HOME);
+ return intent;
+ }).orElseGet(() -> {
+ ploge("showSatelliteSystemNotification: no default sms package "
+ + "name, Invoke default sms compose window instead");
+ Intent newIntent = new Intent(Intent.ACTION_VIEW);
+ newIntent.setData(Uri.parse("sms:"));
+ return newIntent;
+ });
+ context.startActivity(finalIntent);
+ }
+ case HOW_IT_WORKS_BUTTON -> {
+ int subId = receivedIntent.getIntExtra("SUBID", -1);
+ Intent intentSatelliteSetting = new Intent(ACTION_SATELLITE_SETTING);
+ intentSatelliteSetting.putExtra("sub_id", subId);
+ intentSatelliteSetting.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intentSatelliteSetting);
+
+ }
+ case ACTION_NOTIFICATION_DISMISS -> closeStatusBar = false;
+ }
+ // Note : ACTION_NOTIFICATION_DISMISS is not required to handled
+ dismissNotificationAndUpdatePref(closeStatusBar);
+ }
+ };
+
+ private void dismissNotificationAndUpdatePref(boolean closeStatusBar) {
+ dismissSatelliteNotification();
+ if (closeStatusBar) {
+ // Collapse the status bar once user interact with notification.
+ StatusBarManager statusBarManager = mContext.getSystemService(StatusBarManager.class);
+ if (statusBarManager != null) {
+ statusBarManager.collapsePanels();
+ }
+ }
+ // update the sharedpref only when user interacted with the notification.
+ mSharedPreferences.edit().putBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, true).apply();
+ mContext.unregisterReceiver(mNotificationInteractionBroadcastReceiver);
+ }
+
private void resetCarrierRoamingSatelliteModeParams() {
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) return;
@@ -5926,7 +6630,7 @@
AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
for (NetworkRegistrationInfo nri : nriList) {
- if (nri.isInService() || nri.isEmergencyEnabled()) {
+ if (nri.isInService()) {
logv("getWwanIsInService: return true");
return true;
}
@@ -5986,6 +6690,13 @@
}
}
+ private void plogv(@NonNull String log) {
+ Rlog.v(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.debug(TAG, log);
+ }
+ }
+
private void handlePersistentLoggingOnSessionStart(RequestSatelliteEnabledArgument argument) {
if (mPersistentLogger == null) {
return;
@@ -6046,6 +6757,10 @@
return TimeUnit.SECONDS.toMillis(duration);
}
+ private long getEvaluateEsosProfilesPrioritizationDurationMillis() {
+ return TimeUnit.MINUTES.toMillis(1);
+ }
+
/**
* Calculate priority
* 1. Active eSOS profiles are higher priority than inactive eSOS profiles.
@@ -6063,7 +6778,8 @@
List<SubscriptionInfo> allSubInfos = mSubscriptionManagerService.getAllSubInfoList(
mContext.getOpPackageName(), mContext.getAttributionTag());
// Key : priority - lower value has higher priority; Value : List<SubscriptionInfo>
- Map<Integer, List<SubscriptionInfo>> newSubsInfoListPerPriority = new HashMap<>();
+ TreeMap<Integer, List<SubscriptionInfo>> newSubsInfoListPerPriority = new TreeMap<>();
+ plogd("evaluateESOSProfilesPrioritization: allSubInfos.size()=" + allSubInfos.size());
synchronized (mSatelliteTokenProvisionedLock) {
for (SubscriptionInfo info : allSubInfos) {
int subId = info.getSubscriptionId();
@@ -6075,6 +6791,14 @@
if (!isNtnOnly && !isESOSSupported) {
continue;
}
+ if (!isActive && !isNtnOnly) {
+ continue;
+ }
+ if (!isNtnOnly && !isCarrierConfigLoaded(subId)) {
+ // Skip to add priority list if the carrier config is not loaded properly
+ // for the given carrier subscription.
+ continue;
+ }
int keyPriority = (isESOSSupported && isActive && isDefaultSmsSubId) ? 0
: (isESOSSupported && isActive) ? 1
@@ -6100,8 +6824,13 @@
logd("Old phone number is removed: id = " + subId);
isChanged = true;
}
+ if (!newSubscriberId.isEmpty()) {
+ mSubscriberIdPerSub.put(newSubscriberId, subId);
+ }
}
}
+ plogd("evaluateESOSProfilesPrioritization: newSubsInfoListPerPriority.size()="
+ + newSubsInfoListPerPriority.size());
if (!mHasSentBroadcast && newSubsInfoListPerPriority.size() == 0) {
logd("evaluateESOSProfilesPrioritization: no satellite subscription available");
@@ -6110,27 +6839,45 @@
// If priority has changed, send broadcast for provisioned ESOS subs IDs
synchronized (mSatelliteTokenProvisionedLock) {
+ List<SatelliteSubscriberProvisionStatus> newEvaluatedSubscriberProvisionStatus =
+ getPrioritizedSatelliteSubscriberProvisionStatusList(
+ newSubsInfoListPerPriority);
if (isPriorityChanged(mSubsInfoListPerPriority, newSubsInfoListPerPriority)
+ || isSubscriberContentChanged(mLastEvaluatedSubscriberProvisionStatus,
+ newEvaluatedSubscriberProvisionStatus)
|| isChanged) {
mSubsInfoListPerPriority = newSubsInfoListPerPriority;
+ mLastEvaluatedSubscriberProvisionStatus = newEvaluatedSubscriberProvisionStatus;
sendBroadCastForProvisionedESOSSubs();
mHasSentBroadcast = true;
+ selectBindingSatelliteSubscription(false);
}
}
}
+ // to check if the contents of carrier config is loaded properly
+ private Boolean isCarrierConfigLoaded(int subId) {
+ PersistableBundle carrierConfig = mCarrierConfigManager
+ .getConfigForSubId(subId, KEY_CARRIER_CONFIG_APPLIED_BOOL);
+ return carrierConfig != null ? carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL) : false;
+ }
+
// The subscriberId for ntnOnly SIMs is the Iccid, whereas for ESOS supported SIMs, the
// subscriberId is the Imsi prefix 6 digit + phone number.
- private Pair<String, Integer> getSubscriberIdAndType(SubscriptionInfo info) {
+ private Pair<String, Integer> getSubscriberIdAndType(@Nullable SubscriptionInfo info) {
String subscriberId = "";
@SatelliteSubscriberInfo.SubscriberIdType int subscriberIdType =
SatelliteSubscriberInfo.ICCID;
- if (info.isSatelliteESOSSupported()) {
- subscriberId = getPhoneNumberBasedCarrier(info.getSubscriptionId());
- subscriberIdType = SatelliteSubscriberInfo.IMSI_MSISDN;
+ if (info == null) {
+ logd("getSubscriberIdAndType: subscription info is null");
+ return new Pair<>(subscriberId, subscriberIdType);
}
if (info.isOnlyNonTerrestrialNetwork()) {
subscriberId = info.getIccId();
+ } else if (info.isSatelliteESOSSupported()) {
+ subscriberId = getPhoneNumberBasedCarrier(info.getSubscriptionId());
+ subscriberIdType = SatelliteSubscriberInfo.IMSI_MSISDN;
}
logd("getSubscriberIdAndType: subscriberId=" + subscriberId + ", subscriberIdType="
+ subscriberIdType);
@@ -6178,6 +6925,24 @@
return false;
}
+ // Checks if there are any changes between subscriberInfos. return false if the same.
+ // Note that, Use lists with the same priority so we can compare contents properly.
+ private boolean isSubscriberContentChanged(List<SatelliteSubscriberProvisionStatus> currentList,
+ List<SatelliteSubscriberProvisionStatus> newList) {
+ if (currentList.size() != newList.size()) {
+ return true;
+ }
+ for (int i = 0; i < currentList.size(); i++) {
+ SatelliteSubscriberProvisionStatus curSub = currentList.get(i);
+ SatelliteSubscriberProvisionStatus newSub = newList.get(i);
+ if (!curSub.getSatelliteSubscriberInfo().equals(newSub.getSatelliteSubscriberInfo())) {
+ logd("isSubscriberContentChanged: cur=" + curSub + " , new=" + newSub);
+ return true;
+ }
+ }
+ return false;
+ }
+
private void sendBroadCastForProvisionedESOSSubs() {
String packageName = getConfigSatelliteGatewayServicePackage();
String className = getConfigSatelliteCarrierRoamingEsosProvisionedClass();
@@ -6231,10 +6996,18 @@
private List<SatelliteSubscriberProvisionStatus>
getPrioritizedSatelliteSubscriberProvisionStatusList() {
+ synchronized (mSatelliteTokenProvisionedLock) {
+ return getPrioritizedSatelliteSubscriberProvisionStatusList(mSubsInfoListPerPriority);
+ }
+ }
+
+ private List<SatelliteSubscriberProvisionStatus>
+ getPrioritizedSatelliteSubscriberProvisionStatusList(
+ Map<Integer, List<SubscriptionInfo>> subsInfoListPerPriority) {
List<SatelliteSubscriberProvisionStatus> list = new ArrayList<>();
synchronized (mSatelliteTokenProvisionedLock) {
- for (int priority : mSubsInfoListPerPriority.keySet()) {
- List<SubscriptionInfo> infoList = mSubsInfoListPerPriority.get(priority);
+ for (int priority : subsInfoListPerPriority.keySet()) {
+ List<SubscriptionInfo> infoList = subsInfoListPerPriority.get(priority);
if (infoList == null) {
logd("getPrioritySatelliteSubscriberProvisionStatusList: no exist this "
+ "priority " + priority);
@@ -6274,6 +7047,60 @@
return list;
}
+ public int getSelectedSatelliteSubId() {
+ synchronized (mSatelliteTokenProvisionedLock) {
+ return mSelectedSatelliteSubId;
+ }
+ }
+
+ private void selectBindingSatelliteSubscription(boolean shouldIgnoreEnabledState) {
+ if ((isSatelliteEnabled() || isSatelliteBeingEnabled()) && !shouldIgnoreEnabledState) {
+ plogd("selectBindingSatelliteSubscription: satellite subscription will be selected "
+ + "once the satellite session ends");
+ return;
+ }
+
+ int selectedSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ List<SatelliteSubscriberProvisionStatus> satelliteSubscribers =
+ getPrioritizedSatelliteSubscriberProvisionStatusList();
+ for (SatelliteSubscriberProvisionStatus status : satelliteSubscribers) {
+ // TODO: need to check if satellite is allowed at current location for the subscription
+ int subId = getSubIdFromSubscriberId(
+ status.getSatelliteSubscriberInfo().getSubscriberId());
+ if (status.getProvisionStatus() && isActiveSubId(subId)) {
+ selectedSubId = subId;
+ break;
+ }
+ }
+
+ synchronized (mSatelliteTokenProvisionedLock) {
+ if (selectedSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ && isSatelliteSupportedViaOem()) {
+ selectedSubId = getNtnOnlySubscriptionId();
+ }
+ mSelectedSatelliteSubId = selectedSubId;
+ setSatellitePhone(selectedSubId);
+ }
+ plogd("selectBindingSatelliteSubscription: SelectedSatelliteSubId="
+ + mSelectedSatelliteSubId);
+ }
+
+ private int getSubIdFromSubscriberId(String subscriberId) {
+ synchronized (mSatelliteTokenProvisionedLock) {
+ return mSubscriberIdPerSub.getOrDefault(subscriberId,
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ }
+ }
+
+ private boolean isActiveSubId(int subId) {
+ SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(subId);
+ if (subInfo == null) {
+ logd("isActiveSubId: subscription associated with subId=" + subId + " not found");
+ return false;
+ }
+ return subInfo.isActive();
+ }
+
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected boolean isSubscriptionProvisioned(int subId) {
plogd("isSubscriptionProvisioned: subId=" + subId);
@@ -6304,19 +7131,102 @@
@NonNull ResultReceiver result) {
if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
+ logd("provisionSatellite: carrierRoamingNbIotNtn not support");
return;
}
- if (list.size() == 0) {
+ if (list.isEmpty()) {
result.send(SATELLITE_RESULT_INVALID_ARGUMENTS, null);
+ logd("provisionSatellite: SatelliteSubscriberInfo list is empty");
return;
}
logd("provisionSatellite:" + list);
RequestProvisionSatelliteArgument request = new RequestProvisionSatelliteArgument(list,
- result);
+ result, true);
sendRequestAsync(CMD_UPDATE_PROVISION_SATELLITE_TOKEN, request, null);
+ incrementResultReceiverCount("SC:provisionSatellite");
}
+ /**
+ * Deliver the list of deprovisioned satellite subscriber ids.
+ *
+ * @param list List of deprovisioned satellite subscriber ids.
+ * @param result The result receiver that returns whether deliver success or fail.
+ */
+ public void deprovisionSatellite(@NonNull List<SatelliteSubscriberInfo> list,
+ @NonNull ResultReceiver result) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
+ logd("deprovisionSatellite: carrierRoamingNbIotNtn not support");
+ return;
+ }
+ if (list.isEmpty()) {
+ result.send(SATELLITE_RESULT_INVALID_ARGUMENTS, null);
+ logd("deprovisionSatellite: SatelliteSubscriberInfo list is empty");
+ return;
+ }
+
+ logd("deprovisionSatellite:" + list);
+ RequestProvisionSatelliteArgument request = new RequestProvisionSatelliteArgument(list,
+ result, false);
+ sendRequestAsync(CMD_UPDATE_PROVISION_SATELLITE_TOKEN, request, null);
+ incrementResultReceiverCount("SC:provisionSatellite");
+ }
+
+ /**
+ * Inform whether application supports NTN SMS in satellite mode.
+ *
+ * This method is used by default messaging application to inform framework whether it supports
+ * NTN SMS or not.
+ *
+ * @param ntnSmsSupported {@code true} If application supports NTN SMS, else {@code false}.
+ */
+ public void setNtnSmsSupportedByMessagesApp(boolean ntnSmsSupported) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ return;
+ }
+ persistNtnSmsSupportedByMessagesApp(ntnSmsSupported);
+ handleCarrierRoamingNtnAvailableServicesChanged(getSelectedSatelliteSubId());
+ }
+
+ private void persistNtnSmsSupportedByMessagesApp(boolean ntnSmsSupported) {
+ plogd("persistNtnSmsSupportedByMessagesApp: ntnSmsSupported=" + ntnSmsSupported);
+ if (!loadSatelliteSharedPreferences()) return;
+
+ if (mSharedPreferences == null) {
+ ploge("persistNtnSmsSupportedByMessagesApp: mSharedPreferences is null");
+ } else {
+ mSharedPreferences.edit().putBoolean(
+ NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY, ntnSmsSupported).apply();
+ synchronized (mNtnSmsSupportedByMessagesAppLock) {
+ mNtnSmsSupportedByMessagesApp = ntnSmsSupported;
+ }
+ }
+ }
+
+ private boolean isNtnSmsSupportedByMessagesApp() {
+ synchronized (mNtnSmsSupportedByMessagesAppLock) {
+ if (mNtnSmsSupportedByMessagesApp != null) {
+ plogd("isNtnSmsSupportedByMessagesApp:" + mNtnSmsSupportedByMessagesApp);
+ return mNtnSmsSupportedByMessagesApp;
+ }
+ }
+
+ if (!loadSatelliteSharedPreferences()) return false;
+
+ if (mSharedPreferences == null) {
+ ploge("isNtnSmsSupportedByMessagesApp: mSharedPreferences is null");
+ return false;
+ } else {
+ boolean ntnSmsSupported = mSharedPreferences.getBoolean(
+ NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY, false);
+ synchronized (mNtnSmsSupportedByMessagesAppLock) {
+ mNtnSmsSupportedByMessagesApp = ntnSmsSupported;
+ plogd("isNtnSmsSupportedByMessagesApp:" + mNtnSmsSupportedByMessagesApp);
+ }
+ return ntnSmsSupported;
+ }
+ }
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected void setSatellitePhone(int subId) {
@@ -6325,7 +7235,8 @@
if (mSatellitePhone == null) {
mSatellitePhone = SatelliteServiceUtils.getPhone();
}
- plogd("mSatellitePhone:" + (mSatellitePhone != null) + ", subId=" + subId);
+ plogd("mSatellitePhone: phoneId=" + (mSatellitePhone != null
+ ? mSatellitePhone.getPhoneId() : "null") + ", subId=" + subId);
int carrierId = mSatellitePhone.getCarrierId();
if (carrierId != UNKNOWN_CARRIER_ID) {
mControllerMetricsStats.setCarrierId(carrierId);
@@ -6338,13 +7249,14 @@
/** Return the carrier ID of the binding satellite subscription. */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public int getSatelliteCarrierId() {
- synchronized (mSatellitePhoneLock) {
- if (mSatellitePhone != null) {
- return mSatellitePhone.getCarrierId();
- } else {
+ synchronized (mSatelliteTokenProvisionedLock) {
+ SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(
+ mSelectedSatelliteSubId);
+ if (subInfo == null) {
logd("getSatelliteCarrierId: returns UNKNOWN_CARRIER_ID");
return UNKNOWN_CARRIER_ID;
}
+ return subInfo.getCarrierId();
}
}
@@ -6369,12 +7281,22 @@
return false;
}
+ if (!mIsRadioOn) {
+ plogd("isCarrierRoamingNtnEligible: radio is off");
+ return false;
+ }
+
if (phone == null) {
plogd("isCarrierRoamingNtnEligible: phone is null");
return false;
}
int subId = phone.getSubId();
+ if (!isSatelliteRoamingP2pSmSSupported(subId)) {
+ plogd("isCarrierRoamingNtnEligible: doesn't support P2P SMS");
+ return false;
+ }
+
if (!isSatelliteSupportedViaCarrier(subId)) {
plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId()
+ "]: satellite is not supported via carrier");
@@ -6387,8 +7309,9 @@
return false;
}
- if (!isSatelliteServiceSupportedByCarrier(subId,
- NetworkRegistrationInfo.SERVICE_TYPE_SMS)) {
+
+ int[] services = getSupportedServicesOnCarrierRoamingNtn(subId);
+ if (!ArrayUtils.contains(services, NetworkRegistrationInfo.SERVICE_TYPE_SMS)) {
plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId()
+ "]: SMS is not supported by carrier");
return false;
@@ -6401,6 +7324,11 @@
return false;
}
+ if (mOverrideNtnEligibility != null) {
+ // TODO need to send the value from `mOverrideNtnEligibility` or simply true ?
+ return true;
+ }
+
if (SatelliteServiceUtils.isCellularAvailable()) {
plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId()
+ "]: cellular is available");
@@ -6418,11 +7346,19 @@
return true;
}
- private boolean isSatelliteServiceSupportedByCarrier(int subId,
+
+ /**
+ * Checks if the satellite service is supported by the carrier for the specified
+ * subscription ID and servicetype.
+ *
+ * @param subId The subscription id.
+ * @param serviceType The type of service to check
+ */
+ public boolean isSatelliteServiceSupportedByCarrier(int subId,
@NetworkRegistrationInfo.ServiceType int serviceType) {
List<String> satellitePlmnList = getSatellitePlmnsForCarrier(subId);
for (String satellitePlmn : satellitePlmnList) {
- if (getSupportedSatelliteServices(subId, satellitePlmn).contains(serviceType)) {
+ if (getSupportedSatelliteServicesForPlmn(subId, satellitePlmn).contains(serviceType)) {
return true;
}
}
@@ -6437,15 +7373,6 @@
}
}
- /**
- * Return the highest priority satellite subscirption ID.
- */
- public int getHighestPrioritySubscrption() {
- synchronized (mSatellitePhoneLock) {
- return mSatellitePhone.getSubId();
- }
- }
-
/** Start PointingUI if it is required. */
public void startPointingUI() {
synchronized (mNeedsSatellitePointingLock) {
@@ -6534,6 +7461,42 @@
});
}
+ private void handleEventTerrestrialNetworkAvailableChanged(boolean isAvailable) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("handleEventTerrestrialNetworkAvailableChanged: "
+ + "carrierRoamingNbIotNtn flag is disabled");
+ return;
+ }
+
+ plogd("handleEventTerrestrialNetworkAvailableChanged: " + isAvailable);
+
+ List<ISatelliteModemStateCallback> deadCallersList = new ArrayList<>();
+ mTerrestrialNetworkAvailableChangedListeners.values().forEach(listener -> {
+ try {
+ listener.onTerrestrialNetworkAvailableChanged(isAvailable);
+ } catch (RemoteException e) {
+ logd("handleEventTerrestrialNetworkAvailableChanged RemoteException: " + e);
+ deadCallersList.add(listener);
+ }
+ });
+ deadCallersList.forEach(listener -> {
+ mTerrestrialNetworkAvailableChangedListeners.remove(listener.asBinder());
+ });
+
+ if (isAvailable && !mIsEmergency) {
+ requestSatelliteEnabled(
+ false /* enableSatellite */, false /* enableDemoMode */,
+ false /* isEmergency */,
+ new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ plogd("handleEventTerrestrialNetworkAvailableChanged:"
+ + " requestSatelliteEnabled result=" + result);
+ }
+ });
+ }
+ }
+
/**
* This API can be used by only CTS to override the cached value for the device overlay config
* value :
@@ -6583,7 +7546,8 @@
return result;
}
- private String getConfigSatelliteGatewayServicePackage() {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected String getConfigSatelliteGatewayServicePackage() {
if (!mChangeIntentComponent) {
return getStringFromOverlayConfig(
R.string.config_satellite_gateway_service_package);
@@ -6613,6 +7577,11 @@
mContext.registerReceiver(mDefaultSmsSubscriptionChangedBroadcastReceiver, intentFilter);
}
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected List<DeviceState> getSupportedDeviceStates() {
+ return mContext.getSystemService(DeviceStateManager.class).getSupportedDeviceStates();
+ }
+
FeatureFlags getFeatureFlags() {
return mFeatureFlags;
}
@@ -6630,4 +7599,303 @@
return !mWaitingForSatelliteModemOff;
}
}
+
+ /**
+ * Method to override the Carrier roaming Non-terrestrial network eligibility check
+ *
+ * @param state flag to enable or disable the Ntn eligibility check.
+ * @param resetRequired reset overriding the check with adb command.
+ */
+ public boolean overrideCarrierRoamingNtnEligibilityChanged(boolean state,
+ boolean resetRequired) {
+ Log.d(TAG, "overrideCarrierRoamingNtnEligibilityChanged state = " + state
+ + " resetRequired = " + resetRequired);
+ if (resetRequired) {
+ mOverrideNtnEligibility = null;
+ } else {
+ if (mOverrideNtnEligibility == null) {
+ mOverrideNtnEligibility = new AtomicBoolean(state);
+ } else {
+ mOverrideNtnEligibility.set(state);
+ }
+ synchronized (mSatellitePhoneLock) {
+ if (this.mSatellitePhone != null) {
+ updateLastNotifiedNtnEligibilityAndNotify(state);
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * This method check for the key KEY_SATELLITE_MAX_DATAGRAM_SIZE in carrier config. If
+ * available it fetches the value and override the same in SatelliteCapabilities. Otherwise it
+ * uses the value in the existed mSatelliteCapabilities.
+ */
+ private void overrideSatelliteCapabilitiesIfApplicable() {
+ synchronized (this.mSatellitePhoneLock) {
+ if (this.mSatellitePhone == null) {
+ return;
+ }
+ }
+ int subId = getSelectedSatelliteSubId();
+ PersistableBundle config = getPersistableBundle(subId);
+ if (config.containsKey(KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE)) {
+ int datagramSize = config.getInt(KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE);
+ SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(subId);
+ if (!(subInfo == null || subInfo.isOnlyNonTerrestrialNetwork())) {
+ this.mSatelliteCapabilities.setMaxBytesPerOutgoingDatagram(datagramSize);
+ }
+ }
+ }
+
+ private int getNtnOnlySubscriptionId() {
+ List<SubscriptionInfo> infoList = mSubscriptionManagerService.getAllSubInfoList(
+ mContext.getOpPackageName(), mContext.getAttributionTag());
+ int subId = infoList.stream()
+ .filter(info -> info.isOnlyNonTerrestrialNetwork())
+ .mapToInt(SubscriptionInfo::getSubscriptionId)
+ .findFirst()
+ .orElse(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ logd("getNtnOnlySubscriptionId: subId=" + subId);
+ return subId;
+ }
+
+ @Nullable
+ private List<SatelliteSubscriberInfo> getNtnOnlySatelliteSubscriberInfoList(
+ Consumer<Integer> result) {
+ SatelliteSubscriberInfo satelliteSubscriberInfo = getNtnOnlySatelliteSubscriberInfo();
+ if (satelliteSubscriberInfo == null) {
+ result.accept(SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
+ return null;
+ }
+ List<SatelliteSubscriberInfo> satelliteSubscriberInfoList = new ArrayList<>();
+ satelliteSubscriberInfoList.add(satelliteSubscriberInfo);
+
+ return satelliteSubscriberInfoList;
+ }
+
+ @Nullable private SatelliteSubscriberInfo getNtnOnlySatelliteSubscriberInfo() {
+ int ntnOnlySubId = getNtnOnlySubscriptionId();
+ if (ntnOnlySubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ logw("getNtnOnlySatelliteSubscriberInfo: no ntn only subscription found");
+ return null;
+ }
+ SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(ntnOnlySubId);
+ if (subInfo == null) {
+ logw("getNtnOnlySatelliteSubscriberInfo: no subscription info found for subId="
+ + ntnOnlySubId);
+ return null;
+ }
+ return getSatelliteSubscriberInfo(subInfo);
+ }
+
+ @Nullable private SatelliteSubscriberInfo getSatelliteSubscriberInfo(
+ @NonNull SubscriptionInfo subInfo) {
+ Pair<String, Integer> subscriberIdPair = getSubscriberIdAndType(subInfo);
+ String subscriberId = subscriberIdPair.first;
+ int carrierId = subInfo.getCarrierId();
+ String apn = getConfigForSubId(subInfo.getSubscriptionId())
+ .getString(KEY_SATELLITE_NIDD_APN_NAME_STRING, "");
+ logd("getSatelliteSubscriberInfo: subInfo: " + subInfo + ", subscriberId:"
+ + subscriberId + " , carrierId=" + carrierId + " , apn=" + apn);
+ if (subscriberId.isEmpty()) {
+ logw("getSatelliteSubscriberInfo: not a satellite subscription.");
+ return null;
+ }
+ return new SatelliteSubscriberInfo.Builder().setSubscriberId(subscriberId)
+ .setCarrierId(carrierId).setNiddApn(apn)
+ .setSubId(subInfo.getSubscriptionId())
+ .setSubscriberIdType(subscriberIdPair.second)
+ .build();
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected void handleCarrierRoamingNtnAvailableServicesChanged(int subId) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("handleCarrierRoamingNtnAvailableServicesChanged: "
+ + "carrierRoamingNbIotNtn flag is disabled");
+ return;
+ }
+ updateLastNotifiedNtnAvailableServicesAndNotify(subId);
+ evaluateCarrierRoamingNtnEligibilityChange();
+ }
+
+ private void updateLastNotifiedNtnAvailableServicesAndNotify(int subId) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("notifyNtnAvailableServices: carrierRoamingNbIotNtn flag is disabled");
+ return;
+ }
+ Phone phone = SatelliteServiceUtils.getPhone(subId);
+ if (phone == null) {
+ plogd("notifyNtnAvailableServices: phone is null.");
+ return;
+ }
+ plogd("updateLastNotifiedNtnAvailableServicesAndNotify: phoneId= " + phone.getPhoneId());
+ int[] services = getSupportedServicesOnCarrierRoamingNtn(subId);
+ phone.notifyCarrierRoamingNtnAvailableServicesChanged(services);
+ }
+
+ /** Return services that are supported on carrier roaming non-terrestrial network. */
+ public int[] getSupportedServicesOnCarrierRoamingNtn(int subId) {
+ if (isSatelliteSupportedViaCarrier(subId)) {
+ // TODO: b/377367448 Cleanup get supported satellite services to align with starlink.
+ int[] services = getSupportedSatelliteServicesForCarrier(subId);
+ if (isP2PSmsDisallowedOnCarrierRoamingNtn(subId)) {
+ services = Arrays.stream(services).filter(
+ value -> value != NetworkRegistrationInfo.SERVICE_TYPE_SMS).toArray();
+ }
+ return services;
+ }
+ return new int[0];
+ }
+
+ /**
+ * Whether the P2P SMS over carrier roaming satellite is disallowed or not.
+ *
+ * @param subId Associated subscription ID
+ * return {@code true} when the phone does not support P2P SMS over carrier roaming satellite
+ * {@code false} otherwise
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public boolean isP2PSmsDisallowedOnCarrierRoamingNtn(int subId) {
+ int carrierRoamingNtnConnectType = getCarrierRoamingNtnConnectType(subId);
+ if (carrierRoamingNtnConnectType == CARRIER_ROAMING_NTN_CONNECT_MANUAL) {
+ // Manual Connected
+ plogd("isP2PSmsDisallowedOnCarrierRoamingNtn: manual connect");
+ if (!isNtnSmsSupportedByMessagesApp()
+ || !isApplicationSupportsP2P(mSatelliteGatewayServicePackageName)) {
+ plogd("isP2PSmsDisallowedOnCarrierRoamingNtn: APKs do not supports P2P");
+ return true;
+ }
+ }
+ plogd("isP2PSmsDisallowedOnCarrierRoamingNtn: P2P is supported");
+ return false;
+ }
+
+ @NonNull
+ private int[] getSupportedSatelliteServicesForCarrier(int subId) {
+ PersistableBundle config = getPersistableBundle(subId);
+ int[] availableServices = config.getIntArray(
+ KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY);
+ if (availableServices == null) {
+ logd("getSupportedSatelliteServicesForCarrier: defaultCapabilities is null");
+ return new int[0];
+ }
+ logd("getSupportedSatelliteServicesForCarrier: subId=" + subId
+ + ", return default values " + Arrays.toString(availableServices));
+ return availableServices;
+ }
+
+ /**
+ * Whether application supports the P2P SMS to connect to carrier roaming non-terrestrial
+ * network.
+ *
+ * @param packageName application's default package name
+ * return {@code true} when the application supports P2P SMS over the roaming satellite
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public boolean isApplicationSupportsP2P(String packageName) {
+ PackageManager pm = mContext.getPackageManager();
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ try {
+ applicationInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
+ } catch (PackageManager.NameNotFoundException e) {
+ logd("isApplicationSupportsP2P pkgName: " + packageName + " is not installed.");
+ return false;
+ }
+ if (applicationInfo == null || applicationInfo.metaData == null) {
+ logd("isApplicationSupportsP2P pkgName: " + packageName + " meta-data info is empty.");
+ return false;
+ }
+ return applicationInfo.metaData.getBoolean(
+ SatelliteManager.METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT);
+ }
+
+ /**
+ * Registers for the applications state changed.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public void registerApplicationStateChanged() {
+ mDefaultSmsPackageName = Telephony.Sms.getDefaultSmsPackage(mContext);
+ mSatelliteGatewayServicePackageName = getConfigSatelliteGatewayServicePackage();
+
+ IntentFilter packageFilter = new IntentFilter();
+ packageFilter.addAction(Telephony.Sms.Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED);
+ packageFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+ packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ packageFilter.addDataScheme("package");
+ mContext.registerReceiver(mPackageStateChangedReceiver, packageFilter,
+ mContext.RECEIVER_EXPORTED);
+ }
+
+
+ private void notifyEnabledStateChanged(boolean isEnabled) {
+ TelephonyRegistryManager trm = mContext.getSystemService(TelephonyRegistryManager.class);
+ if (trm == null) {
+ loge("Telephony registry service is down!");
+ return;
+ }
+
+ trm.notifySatelliteStateChanged(isEnabled);
+ logd("notifyEnabledStateChanged to " + isEnabled);
+ }
+
+ private NtnSignalStrength getCarrierRoamingNtnSignalStrength(@NonNull Phone phone) {
+ NtnSignalStrength carrierRoamingNtnSignalStrength = new NtnSignalStrength(
+ NTN_SIGNAL_STRENGTH_NONE);
+
+ if (isInCarrierRoamingNbIotNtn(phone)) {
+ if (mSatelliteSessionController.isInConnectedState()) {
+ synchronized (mNtnSignalsStrengthLock) {
+ carrierRoamingNtnSignalStrength = mNtnSignalStrength;
+ }
+ plogd("getCarrierRoamingNtnSignalStrength[phoneId=" + phone.getPhoneId()
+ + "]: in carrier roaming nb iot ntn mode.");
+ }
+ } else if (isInSatelliteModeForCarrierRoaming(phone)) {
+ ServiceState serviceState = phone.getServiceState();
+ if (serviceState.getState() != ServiceState.STATE_OUT_OF_SERVICE) {
+ carrierRoamingNtnSignalStrength = new NtnSignalStrength(
+ phone.getSignalStrength().getLevel());
+ plogd("getCarrierRoamingNtnSignalStrength[phoneId=" + phone.getPhoneId()
+ + "]: is in satellite mode for carrier roaming.");
+ }
+ }
+
+ return carrierRoamingNtnSignalStrength;
+ }
+
+ private void updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(@Nullable Phone phone) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) return;
+ if (phone == null) {
+ return;
+ }
+
+ NtnSignalStrength currSignalStrength = getCarrierRoamingNtnSignalStrength(phone);
+ int subId = phone.getSubId();
+ synchronized (mSatelliteConnectedLock) {
+ NtnSignalStrength lastNotifiedSignalStrength =
+ mLastNotifiedCarrierRoamingNtnSignalStrength.get(subId);
+ if (lastNotifiedSignalStrength == null
+ || lastNotifiedSignalStrength.getLevel() != currSignalStrength.getLevel()) {
+ mLastNotifiedCarrierRoamingNtnSignalStrength.put(subId, currSignalStrength);
+ phone.notifyCarrierRoamingNtnSignalStrengthChanged(currSignalStrength);
+ }
+ }
+ }
+
+ /** Returns whether to send SMS to DatagramDispatcher or not. */
+ public boolean shouldSendSmsToDatagramDispatcher(@Nullable Phone phone) {
+ if (!isInCarrierRoamingNbIotNtn(phone)) {
+ return false;
+ }
+
+ if (isDemoModeEnabled()) {
+ return false;
+ }
+
+ int[] services = getSupportedServicesOnCarrierRoamingNtn(phone.getSubId());
+ return ArrayUtils.contains(services, NetworkRegistrationInfo.SERVICE_TYPE_SMS);
+ }
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
index a19f802..5fa85db 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
@@ -104,6 +104,8 @@
new RegistrantList();
@NonNull private final RegistrantList mSatelliteRegistrationFailureRegistrants =
new RegistrantList();
+ @NonNull private final RegistrantList mTerrestrialNetworkAvailableChangedRegistrants =
+ new RegistrantList();
private class SatelliteListener extends ISatelliteListener.Stub {
@@ -192,6 +194,11 @@
mSatelliteRegistrationFailureRegistrants.notifyResult(causeCode);
}
+ @Override
+ public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) {
+ mTerrestrialNetworkAvailableChangedRegistrants.notifyResult(isAvailable);
+ }
+
private boolean notifyResultIfExpectedListener() {
// Demo listener should notify results only during demo mode
// Vendor listener should notify result only during real mode
@@ -587,6 +594,27 @@
}
/**
+ * Registers for the terrestrial network available changed.
+ *
+ * @param h Handler for notification message.
+ * @param what User-defined message code.
+ * @param obj User object.
+ */
+ public void registerForTerrestrialNetworkAvailableChanged(
+ @NonNull Handler h, int what, @Nullable Object obj) {
+ mTerrestrialNetworkAvailableChangedRegistrants.add(h, what, obj);
+ }
+
+ /**
+ * Unregisters for the terrestrial network available changed.
+ *
+ * @param h Handler to be removed from the registrant list.
+ */
+ public void unregisterForTerrestrialNetworkAvailableChanged(@NonNull Handler h) {
+ mTerrestrialNetworkAvailableChangedRegistrants.remove(h);
+ }
+
+ /**
* Request to enable or disable the satellite service listening mode.
* Listening mode allows the satellite service to listen for incoming pages.
*
@@ -652,14 +680,14 @@
};
if (mSatelliteController.isDemoModeEnabled()) {
- mDemoSimulator.enableCellularModemWhileSatelliteModeIsOn(
+ mDemoSimulator.enableTerrestrialNetworkScanWhileSatelliteModeIsOn(
enabled, errorCallback);
} else {
- mSatelliteService.enableCellularModemWhileSatelliteModeIsOn(
+ mSatelliteService.enableTerrestrialNetworkScanWhileSatelliteModeIsOn(
enabled, errorCallback);
}
} catch (RemoteException e) {
- ploge("enableCellularModemWhileSatelliteModeIsOn: RemoteException " + e);
+ ploge("enableTerrestrialNetworkScanWhileSatelliteModeIsOn: RemoteException " + e);
if (message != null) {
sendMessageWithResult(
message, null, SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
index 0bf8184..182f667 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
@@ -124,6 +124,8 @@
@Nullable private PersistentLogger mPersistentLogger = null;
+ private boolean mIsTestEmergencyNumber = false;
+
/**
* Create an instance of SatelliteSOSMessageRecommender.
*
@@ -213,11 +215,13 @@
* @param connection The connection created by TelephonyConnectionService for the emergency
* call.
*/
- public void onEmergencyCallStarted(@NonNull Connection connection) {
+ public void onEmergencyCallStarted(@NonNull Connection connection,
+ boolean isTestEmergencyNumber) {
if (!isSatelliteSupported()) {
plogd("onEmergencyCallStarted: satellite is not supported");
return;
}
+ mIsTestEmergencyNumber = isTestEmergencyNumber;
if (hasMessages(EVENT_EMERGENCY_CALL_STARTED)) {
logd("onEmergencyCallStarted: Ignoring due to ongoing event:");
@@ -281,7 +285,7 @@
private void handleSatelliteProvisionStateChangedEvent(boolean provisioned) {
if (!provisioned) {
- cleanUpResources();
+ cleanUpResources(false);
}
}
@@ -317,11 +321,12 @@
boolean isCellularAvailable = SatelliteServiceUtils.isCellularAvailable();
if (!isCellularAvailable
&& isSatelliteAllowed()
- && (isSatelliteViaOemAvailable()
+ && (isDeviceProvisioned()
|| isSatelliteConnectedViaCarrierWithinHysteresisTime())
&& shouldTrackCall(mEmergencyConnection.getState())) {
plogd("handleTimeoutEvent: Sent EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer");
- Bundle extras = createExtraBundleForEventDisplayEmergencyMessage();
+ Bundle extras = createExtraBundleForEventDisplayEmergencyMessage(
+ mIsTestEmergencyNumber);
mEmergencyConnection.sendConnectionEvent(
TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE, extras);
isDialerNotified = true;
@@ -331,8 +336,7 @@
+ ", isCellularAvailable=" + isCellularAvailable
+ ", isSatelliteAllowed=" + isSatelliteAllowed()
+ ", shouldTrackCall=" + shouldTrackCall(mEmergencyConnection.getState()));
- reportESosRecommenderDecision(isDialerNotified);
- cleanUpResources();
+ cleanUpResources(isDialerNotified);
}
}
@@ -355,8 +359,8 @@
* @return {@code true} if satellite is provisioned via OEM else return {@code false}
*/
@VisibleForTesting
- public boolean isSatelliteViaOemAvailable() {
- Boolean satelliteProvisioned = mSatelliteController.isSatelliteViaOemProvisioned();
+ public boolean isDeviceProvisioned() {
+ Boolean satelliteProvisioned = mSatelliteController.isDeviceProvisioned();
return satelliteProvisioned != null ? satelliteProvisioned : false;
}
@@ -383,13 +387,12 @@
* we're not tracking. There must be some unexpected things happened in
* TelephonyConnectionService. Thus, we need to clean up the resources.
*/
- cleanUpResources();
+ cleanUpResources(false);
return;
}
if (!shouldTrackCall(state)) {
- reportESosRecommenderDecision(false);
- cleanUpResources();
+ cleanUpResources(false);
} else {
// Location service will enter emergency mode only when connection state changes to
// STATE_DIALING
@@ -400,7 +403,8 @@
}
}
- private void reportESosRecommenderDecision(boolean isDialerNotified) {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected void reportESosRecommenderDecision(boolean isDialerNotified) {
SatelliteStats.getInstance().onSatelliteSosMessageRecommender(
new SatelliteStats.SatelliteSosMessageRecommenderParams.Builder()
.setDisplaySosMessageSent(isDialerNotified)
@@ -411,11 +415,12 @@
.setRecommendingHandoverType(getEmergencyCallToSatelliteHandoverType())
.setIsSatelliteAllowedInCurrentLocation(isSatelliteAllowed())
.setIsWifiConnected(mCountryDetector.isWifiNetworkConnected())
- .setCarrierId(getAvailableNtnCarrierID()).build());
+ .setCarrierId(mSatelliteController.getSatelliteCarrierId()).build());
}
- private void cleanUpResources() {
+ private void cleanUpResources(boolean isDialerNotified) {
plogd("cleanUpResources");
+ reportESosRecommenderDecision(isDialerNotified);
synchronized (mLock) {
stopTimer();
if (mEmergencyConnection != null) {
@@ -426,6 +431,7 @@
mIsTimerTimedOut = false;
mCheckingAccessRestrictionInProgress = false;
mIsSatelliteAllowedForCurrentLocation = false;
+ mIsTestEmergencyNumber = false;
}
}
@@ -585,11 +591,13 @@
@Nullable
private static String getSatelliteEmergencyHandoverIntentActionFromOverlayConfig(
- @NonNull Context context) {
+ @NonNull Context context, boolean isTestEmergencyNumber) {
String action;
try {
- action = context.getResources().getString(
- R.string.config_satellite_emergency_handover_intent_action);
+ int actionIntent = isTestEmergencyNumber
+ ? R.string.config_satellite_test_with_esp_replies_intent_action
+ : R.string.config_satellite_emergency_handover_intent_action;
+ action = context.getResources().getString(actionIntent);
} catch (Resources.NotFoundException ex) {
loge("getSatelliteEmergencyHandoverIntentFilterActionFromOverlayConfig: ex=" + ex);
action = null;
@@ -635,13 +643,15 @@
return callback;
}
- @NonNull private Bundle createExtraBundleForEventDisplayEmergencyMessage() {
+ @NonNull private Bundle createExtraBundleForEventDisplayEmergencyMessage(
+ boolean isTestEmergencyNumber) {
int handoverType = EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS;
Pair<String, String> oemSatelliteMessagingApp =
getOemEnabledSatelliteHandoverAppFromOverlayConfig(mContext);
String packageName = oemSatelliteMessagingApp.first;
String className = oemSatelliteMessagingApp.second;
- String action = getSatelliteEmergencyHandoverIntentActionFromOverlayConfig(mContext);
+ String action = getSatelliteEmergencyHandoverIntentActionFromOverlayConfig(mContext,
+ isTestEmergencyNumber);
if (isSatelliteConnectedViaCarrierWithinHysteresisTime()
|| isEmergencyCallToSatelliteHandoverTypeT911Enforced()) {
@@ -710,7 +720,8 @@
@NonNull Connection connection) {
plogd("Sent EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer forcefully.");
mEmergencyConnection = connection;
- Bundle extras = createExtraBundleForEventDisplayEmergencyMessage();
+ Bundle extras = createExtraBundleForEventDisplayEmergencyMessage(
+ /* isTestEmergencyNumber= */ true);
connection.sendConnectionEvent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE, extras);
mEmergencyConnection = null;
}
@@ -726,14 +737,9 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
public int getEmergencyCallToSatelliteHandoverType() {
- if (Flags.carrierRoamingNbIotNtn() && isSatelliteViaOemAvailable()
+ if (Flags.carrierRoamingNbIotNtn() && isDeviceProvisioned()
&& isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
- Phone satellitePhone = mSatelliteController.getSatellitePhone();
- if (satellitePhone == null) {
- ploge("getEmergencyCallToSatelliteHandoverType: satellitePhone is null");
- return EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911;
- }
- int satelliteSubId = satellitePhone.getSubId();
+ int satelliteSubId = mSatelliteController.getSelectedSatelliteSubId();
return mSatelliteController.getCarrierRoamingNtnEmergencyCallToSatelliteHandoverType(
satelliteSubId);
} else if (isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
@@ -793,7 +799,7 @@
}
private boolean isSatelliteViaOemProvisioned() {
- Boolean provisioned = mSatelliteController.isSatelliteViaOemProvisioned();
+ Boolean provisioned = mSatelliteController.isDeviceProvisioned();
return (provisioned != null) && provisioned;
}
@@ -822,23 +828,6 @@
}
}
- /** Returns the carrier ID of NTN subscription */
- private int getAvailableNtnCarrierID() {
- Pair<Boolean, Integer> ntnSubInfo =
- mSatelliteController.isUsingNonTerrestrialNetworkViaCarrier();
- if (ntnSubInfo.first) {
- TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- return tm.createForSubscriptionId(ntnSubInfo.second).getSimCarrierId();
- }
-
- Phone satellitePhone = mSatelliteController.getSatellitePhone();
- if (satellitePhone != null) {
- return satellitePhone.getCarrierId();
- }
-
- return TelephonyManager.UNKNOWN_CARRIER_ID;
- }
-
private void plogd(@NonNull String log) {
Rlog.d(TAG, log);
if (mPersistentLogger != null) {
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
index f4208f7..3f181bf 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
@@ -19,6 +19,8 @@
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SMS;
+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_RECEIVE_FAILED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE;
@@ -38,20 +40,26 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AlarmManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.AsyncResult;
import android.os.Build;
+import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.WorkSource;
import android.telephony.DropBoxManagerLoggerBackend;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.PersistentLogger;
+import android.telephony.ServiceState;
import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.stub.ISatelliteGateway;
@@ -66,8 +74,10 @@
import com.android.internal.telephony.ExponentialBackoff;
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
+import com.android.internal.telephony.util.ArrayUtils;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.telephony.Rlog;
@@ -123,7 +133,10 @@
private static final int EVENT_SATELLITE_ENABLEMENT_FAILED = 8;
private static final int EVENT_SCREEN_STATE_CHANGED = 9;
protected static final int EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT = 10;
- protected static final int EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT = 11;
+ protected static final int EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT = 11;
+ private static final int EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE = 12;
+ private static final int EVENT_SERVICE_STATE_CHANGED = 13;
+ protected static final int EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT = 14;
private static final long REBIND_INITIAL_DELAY = 2 * 1000; // 2 seconds
private static final long REBIND_MAXIMUM_DELAY = 64 * 1000; // 1 minute
@@ -160,6 +173,7 @@
private long mSatelliteStayAtListeningFromSendingMillis;
private long mSatelliteStayAtListeningFromReceivingMillis;
private long mSatelliteNbIotInactivityTimeoutMillis;
+ private boolean mIgnoreCellularServiceState = false;
private final ConcurrentHashMap<IBinder, ISatelliteModemStateCallback> mListeners;
@SatelliteManager.SatelliteModemState private int mCurrentState;
@SatelliteManager.SatelliteModemState private int mPreviousState;
@@ -169,15 +183,20 @@
boolean mIsScreenOn = true;
private boolean mIsDeviceAlignedWithSatellite = false;
- @GuardedBy("mLock")
- @NonNull private boolean mIsDisableCellularModemInProgress = false;
@NonNull private final SatelliteController mSatelliteController;
@NonNull private final DatagramController mDatagramController;
@Nullable private PersistentLogger mPersistentLogger = null;
@Nullable private DeviceStateMonitor mDeviceStateMonitor;
@NonNull private SessionMetricsStats mSessionMetricsStats;
-
@NonNull private FeatureFlags mFeatureFlags;
+ @NonNull private AlarmManager mAlarmManager;
+ private final AlarmManager.OnAlarmListener mAlarmListener = new AlarmManager.OnAlarmListener() {
+ @Override
+ public void onAlarm() {
+ plogd("onAlarm: screen off timer expired");
+ sendMessage(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT);
+ }
+ };
/**
* @return The singleton instance of SatelliteSessionController.
@@ -205,8 +224,10 @@
boolean isSatelliteSupported) {
if (sInstance == null || isSatelliteSupported != sInstance.mIsSatelliteSupported) {
ConcurrentHashMap<IBinder, ISatelliteModemStateCallback> existingListeners = null;
+ boolean existIgnoreCellularServiceState = false;
if (sInstance != null) {
existingListeners = sInstance.mListeners;
+ existIgnoreCellularServiceState = sInstance.mIgnoreCellularServiceState;
sInstance.cleanUpResource();
}
@@ -220,6 +241,10 @@
Log.d(TAG, "make() existingListeners: " + existingListeners.size());
sInstance.mListeners.putAll(existingListeners);
}
+ if (existIgnoreCellularServiceState) {
+ Log.d(TAG, "make() existIgnoreCellularServiceState is true");
+ sInstance.mIgnoreCellularServiceState = true;
+ }
}
return sInstance;
}
@@ -277,12 +302,13 @@
bindService();
});
- Phone phone = mSatelliteController.getSatellitePhone();
- if (phone == null) {
- phone = SatelliteServiceUtils.getPhone();
+ Phone satellitePhone = mSatelliteController.getSatellitePhone();
+ if (satellitePhone == null) {
+ satellitePhone = SatelliteServiceUtils.getPhone();
}
- mDeviceStateMonitor = phone.getDeviceStateMonitor();
+ mDeviceStateMonitor = satellitePhone.getDeviceStateMonitor();
mSessionMetricsStats = SessionMetricsStats.getInstance();
+ mAlarmManager = mContext.getSystemService(AlarmManager.class);
addState(mUnavailableState);
addState(mPowerOffState);
@@ -307,9 +333,10 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public void onDatagramTransferStateChanged(
@SatelliteManager.SatelliteDatagramTransferState int sendState,
- @SatelliteManager.SatelliteDatagramTransferState int receiveState) {
+ @SatelliteManager.SatelliteDatagramTransferState int receiveState,
+ @SatelliteManager.DatagramType int datagramType) {
sendMessage(EVENT_DATAGRAM_TRANSFER_STATE_CHANGED,
- new DatagramTransferState(sendState, receiveState));
+ new DatagramTransferState(sendState, receiveState, datagramType));
if (sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING) {
mIsSendingTriggeredDuringTransferringState.set(true);
}
@@ -450,6 +477,23 @@
}
/**
+ * This API can be used by only CTS to control ingoring cellular service state event.
+ *
+ * @param enabled Whether to enable boolean config.
+ * @return {@code true} if the value is set successfully, {@code false} otherwise.
+ */
+ public boolean setSatelliteIgnoreCellularServiceState(boolean enabled) {
+ plogd("setSatelliteIgnoreCellularServiceState : "
+ + "old = " + mIgnoreCellularServiceState + " new : " + enabled);
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ return false;
+ }
+
+ mIgnoreCellularServiceState = enabled;
+ return true;
+ }
+
+ /**
* This API can be used by only CTS to update satellite gateway service package name.
*
* @param servicePackageName The package name of the satellite gateway service.
@@ -511,10 +555,12 @@
mIsDeviceAlignedWithSatellite = isAligned;
if (mIsDeviceAlignedWithSatellite) {
- stopCarrierRoamingNbIotInactivityTimer();
+ stopEsosInactivityTimer();
+ stopP2pSmsInactivityTimer();
} else {
if (mCurrentState == SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED) {
- evaluateStartingCarrierRoamingNbIotInactivityTimer();
+ evaluateStartingEsosInactivityTimer();
+ evaluateStartingP2pSmsInactivityTimer();
}
}
}
@@ -540,6 +586,17 @@
}
/**
+ * Get whether state machine is in connected state.
+ *
+ * @return {@code true} if state machine is in connected state and {@code false} otherwise.
+ */
+ public boolean isInConnectedState() {
+ if (DBG) plogd("isInConnectedState: getCurrentState=" + getCurrentState());
+ return getCurrentState() == mConnectedState;
+ }
+
+
+ /**
* Release all resource.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
@@ -547,9 +604,46 @@
plogd("cleanUpResource");
mIsDeviceAlignedWithSatellite = false;
unregisterForScreenStateChanged();
+ if (mAlarmManager != null) {
+ mAlarmManager.cancel(mAlarmListener);
+ }
+
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ // Register to received Cellular service state
+ for (Phone phone : PhoneFactory.getPhones()) {
+ if (phone == null) continue;
+
+ phone.unregisterForServiceStateChanged(getHandler());
+ if (DBG) {
+ plogd("cleanUpResource: unregisterForServiceStateChanged phoneId "
+ + phone.getPhoneId());
+ }
+ }
+ }
+
quitNow();
}
+ /**
+ * Uses this function to notify that cellular service state has changed
+ *
+ * @param serviceState The state of the cellular service.
+ */
+ @VisibleForTesting
+ public void onCellularServiceStateChanged(ServiceState serviceState) {
+ sendMessage(EVENT_SERVICE_STATE_CHANGED, new AsyncResult(null, serviceState, null));
+ }
+
+ /**
+ * Uses this function to set AlarmManager object for testing.
+ *
+ * @param alarmManager The instance of AlarmManager.
+ */
+ @VisibleForTesting
+ public void setAlarmManager(AlarmManager alarmManager) {
+ mAlarmManager = alarmManager;
+ }
+
private boolean isDemoMode() {
return mIsDemoMode;
}
@@ -557,11 +651,14 @@
private static class DatagramTransferState {
@SatelliteManager.SatelliteDatagramTransferState public int sendState;
@SatelliteManager.SatelliteDatagramTransferState public int receiveState;
+ @SatelliteManager.DatagramType public int datagramType;
DatagramTransferState(@SatelliteManager.SatelliteDatagramTransferState int sendState,
- @SatelliteManager.SatelliteDatagramTransferState int receiveState) {
+ @SatelliteManager.SatelliteDatagramTransferState int receiveState,
+ @SatelliteManager.DatagramType int datagramType) {
this.sendState = sendState;
this.receiveState = receiveState;
+ this.datagramType = datagramType;
}
}
@@ -591,9 +688,6 @@
mPreviousState = mCurrentState;
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_OFF;
mIsSendingTriggeredDuringTransferringState.set(false);
- synchronized (mLock) {
- mIsDisableCellularModemInProgress = false;
- }
unbindService();
stopNbIotInactivityTimer();
DemoSimulator.getInstance().onSatelliteModeOff();
@@ -790,9 +884,16 @@
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_IDLE;
mIsSendingTriggeredDuringTransferringState.set(false);
stopNbIotInactivityTimer();
+
//Enable Cellular Modem scanning
- mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(true, null);
- notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ Message onCompleted =
+ obtainMessage(EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE);
+ mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(true, onCompleted);
+ if (isConcurrentTnScanningSupported()) {
+ plogd("IDLE state is hidden from clients");
+ } else {
+ notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ }
}
@Override
@@ -807,7 +908,7 @@
break;
case EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE:
handleEventDisableCellularModemWhileSatelliteModeIsOnDone(
- (AsyncResult) msg.obj);
+ (AsyncResult) msg.obj);
break;
case EVENT_SATELLITE_ENABLEMENT_STARTED:
handleSatelliteEnablementStarted((boolean) msg.obj);
@@ -821,6 +922,22 @@
case EVENT_SATELLITE_MODEM_STATE_CHANGED:
handleSatelliteModemStateChanged(msg);
break;
+ case EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE:
+ plogd("EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE");
+ break;
+ case EVENT_SERVICE_STATE_CHANGED:
+ if (!mIgnoreCellularServiceState) {
+ AsyncResult ar = (msg.obj != null) ? (AsyncResult) msg.obj : null;
+ if (ar == null || ar.result == null) {
+ plogd("IdleState: processing: can't access ServiceState");
+ } else {
+ ServiceState newServiceState = (ServiceState) ar.result;
+ handleEventServiceStateChanged(newServiceState);
+ }
+ } else {
+ plogd("IdleState: processing: ignore EVENT_SERVICE_STATE_CHANGED");
+ }
+ break;
}
// Ignore all unexpected events.
return HANDLED;
@@ -831,68 +948,86 @@
if ((datagramTransferState.sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING)
|| (datagramTransferState.receiveState
== SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING)) {
- if (mSatelliteController.isSatelliteAttachRequired()) {
- ploge("Unexpected transferring state received for NB-IOT NTN");
- } else {
- transitionTo(mTransferringState);
- }
+ transitionTo(mTransferringState);
} else if ((datagramTransferState.sendState
== SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT)
|| (datagramTransferState.receiveState
== SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT)) {
if (mSatelliteController.isSatelliteAttachRequired()) {
- disableCellularModemWhileSatelliteModeIsOn();
+ transitionTo(mNotConnectedState);
} else {
ploge("Unexpected transferring state received for non-NB-IOT NTN");
}
}
}
- private void handleEventDisableCellularModemWhileSatelliteModeIsOnDone(
- @NonNull AsyncResult result) {
- synchronized (mLock) {
- if (mIsDisableCellularModemInProgress) {
- int error = SatelliteServiceUtils.getSatelliteError(
- result, "DisableCellularModemWhileSatelliteModeIsOnDone");
- if (error == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
- transitionTo(mNotConnectedState);
- }
- mIsDisableCellularModemInProgress = false;
- } else {
- ploge("DisableCellularModemWhileSatelliteModeIsOn is not in progress");
+ private void handleEventServiceStateChanged(ServiceState serviceState) {
+ boolean isInServiceOrEmergency =
+ serviceState.getVoiceRegState() == ServiceState.STATE_IN_SERVICE
+ || serviceState.getDataRegState() == ServiceState.STATE_IN_SERVICE
+ || serviceState.isEmergencyOnly();
+ if (!isInServiceOrEmergency) {
+ plogd("handleEventServiceStateChanged: is not IN_SERVICE or EMERGENCY_ONLY");
+ return;
+ }
+
+ // In emergency
+ boolean isEmergency = mSatelliteController.getRequestIsEmergency();
+ if (isEmergency) {
+ boolean isEmergencyCommunicationEstablished = (mDatagramController == null)
+ ? false : mDatagramController.isEmergencyCommunicationEstablished();
+ boolean isTurnOffAllowed =
+ mSatelliteController.turnOffSatelliteSessionForEmergencyCall(getSubId());
+ if (isEmergencyCommunicationEstablished || !isTurnOffAllowed) {
+ logd("handleEventServiceStateChanged: "
+ + "can't disable emergency satellite session");
+ return;
}
}
+
+ mSatelliteController.requestSatelliteEnabled(
+ false /*enableSatellite*/,
+ false /*enableDemoMode*/,
+ isEmergency /*isEmergency*/,
+ new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ plogd("requestSatelliteEnabled result=" + result);
+ if (result == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
+ mSessionMetricsStats.addCountOfAutoExitDueToTnNetwork();
+ }
+ }
+ });
+ }
+
+ private void handleEventDisableCellularModemWhileSatelliteModeIsOnDone(
+ @NonNull AsyncResult result) {
+ int error = SatelliteServiceUtils.getSatelliteError(
+ result, "DisableCellularModemWhileSatelliteModeIsOnDone");
+ plogd("Disable TN scanning done with result: " + error);
}
private void handleSatelliteModemStateChanged(@NonNull Message msg) {
int state = msg.arg1;
if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) {
transitionTo(mPowerOffState);
- }
- }
-
- private void disableCellularModemWhileSatelliteModeIsOn() {
- synchronized (mLock) {
- if (mIsDisableCellularModemInProgress) {
- plogd("Cellular scanning is already being disabled");
- return;
+ } else if (state == SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED
+ || state == SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED) {
+ if (isConcurrentTnScanningSupported()) {
+ plogd("Notifying the new state " + state + " to clients but still"
+ + " stay at IDLE state internally");
+ notifyStateChangedEvent(state);
+ } else {
+ plogd("Ignoring the modem state " + state);
}
-
- mIsDisableCellularModemInProgress = true;
- Message onCompleted =
- obtainMessage(EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE);
- mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(false,
- onCompleted);
}
}
@Override
public void exit() {
if (DBG) plogd("Exiting IdleState");
- if (!mSatelliteController.isSatelliteAttachRequired()) {
- // Disable cellular modem scanning
- mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(false, null);
- }
+ // Disable cellular modem scanning
+ mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(false, null);
}
}
@@ -1053,14 +1188,16 @@
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED;
notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
startNbIotInactivityTimer();
- evaluateStartingCarrierRoamingNbIotInactivityTimer();
+ evaluateStartingEsosInactivityTimer();
+ evaluateStartingP2pSmsInactivityTimer();
}
@Override
public void exit() {
if (DBG) plogd("Exiting NotConnectedState");
- stopCarrierRoamingNbIotInactivityTimer();
+ stopEsosInactivityTimer();
+ stopP2pSmsInactivityTimer();
}
@Override
@@ -1074,8 +1211,22 @@
case EVENT_SATELLITE_MODEM_STATE_CHANGED:
handleEventSatelliteModemStateChanged(msg.arg1);
break;
- case EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT:
- // fall through
+ case EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT:
+ if (isP2pSmsInActivityTimerStarted()) {
+ plogd("NotConnectedState: processing: P2P_SMS inactivity timer running "
+ + "can not move to IDLE");
+ } else {
+ transitionTo(mIdleState);
+ }
+ break;
+ case EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT:
+ if (isEsosInActivityTimerStarted()) {
+ plogd("NotConnectedState: processing: ESOS inactivity timer running "
+ + "can not move to IDLE");
+ } else {
+ transitionTo(mIdleState);
+ }
+ break;
case EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT:
transitionTo(mIdleState);
break;
@@ -1112,17 +1263,29 @@
|| datagramTransferState.receiveState
== SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT) {
stopNbIotInactivityTimer();
- stopCarrierRoamingNbIotInactivityTimer();
+
+ if (mSatelliteController.getRequestIsEmergency()) {
+ stopEsosInactivityTimer();
+ }
+ stopP2pSmsInactivityTimer();
} else if (datagramTransferState.sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE
&& datagramTransferState.receiveState
== SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE) {
startNbIotInactivityTimer();
- evaluateStartingCarrierRoamingNbIotInactivityTimer();
+ evaluateStartingEsosInactivityTimer();
+ evaluateStartingP2pSmsInactivityTimer();
} else if (isSending(datagramTransferState.sendState)
|| isReceiving(datagramTransferState.receiveState)) {
- restartNbIotInactivityTimer();
- stopCarrierRoamingNbIotInactivityTimer();
- evaluateStartingCarrierRoamingNbIotInactivityTimer();
+ stopNbIotInactivityTimer();
+
+ int datagramType = datagramTransferState.datagramType;
+ if (datagramType == DATAGRAM_TYPE_SOS_MESSAGE) {
+ stopEsosInactivityTimer();
+ } else if (datagramType == DATAGRAM_TYPE_SMS) {
+ stopP2pSmsInactivityTimer();
+ } else {
+ plogd("datagram type is not SOS_Message and SMS " + datagramType);
+ }
}
}
}
@@ -1136,11 +1299,16 @@
mCurrentState = SATELLITE_MODEM_STATE_CONNECTED;
notifyStateChangedEvent(SATELLITE_MODEM_STATE_CONNECTED);
startNbIotInactivityTimer();
+ evaluateStartingEsosInactivityTimer();
+ evaluateStartingP2pSmsInactivityTimer();
}
@Override
public void exit() {
if (DBG) plogd("Exiting ConnectedState");
+
+ stopEsosInactivityTimer();
+ stopP2pSmsInactivityTimer();
}
@Override
@@ -1169,6 +1337,22 @@
case EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT:
handleEventScreenOffInactivityTimerTimedOut();
break;
+ case EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT:
+ if (isP2pSmsInActivityTimerStarted()) {
+ plogd("ConnectedState: processing: P2P_SMS inactivity timer running "
+ + "can not move to IDLE");
+ } else {
+ transitionTo(mIdleState);
+ }
+ break;
+ case EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT:
+ if (isEsosInActivityTimerStarted()) {
+ plogd("ConnectedState: processing: ESOS inactivity timer running "
+ + "can not move to IDLE");
+ } else {
+ transitionTo(mIdleState);
+ }
+ break;
}
// Ignore all unexpected events.
return HANDLED;
@@ -1229,8 +1413,17 @@
case EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT:
whatString = "EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT";
break;
- case EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT:
- whatString = "EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT";
+ case EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT:
+ whatString = "EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT";
+ break;
+ case EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT:
+ whatString = "EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT";
+ break;
+ case EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE:
+ whatString = "EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE";
+ break;
+ case EVENT_SERVICE_STATE_CHANGED:
+ whatString = "EVENT_SERVICE_STATE_CHANGED";
break;
default:
whatString = "UNKNOWN EVENT " + what;
@@ -1247,12 +1440,7 @@
}
private int getSubId() {
- Phone phone = mSatelliteController.getSatellitePhone();
- if (phone == null) {
- return SatelliteServiceUtils.getPhone().getSubId();
- }
-
- return phone.getSubId();
+ return mSatelliteController.getSelectedSatelliteSubId();
}
private void notifyStateChangedEvent(@SatelliteManager.SatelliteModemState int state) {
@@ -1407,8 +1595,13 @@
return;
}
+ if (!mSatelliteController.isInCarrierRoamingNbIotNtn()) {
+ logd("registerScreenOnOffChanged: device is not in CarrierRoamingNbIotNtn");
+ return;
+ }
+
if (mSatelliteController.getRequestIsEmergency()) {
- if (DBG) logd("registerScreenOnOffChanged: Emergency mode");
+ logd("registerScreenOnOffChanged: not register, device is in Emergency mode");
// screen on/off timer is available in not emergency mode
return;
}
@@ -1458,16 +1651,42 @@
}
mIsScreenOn = screenOn;
+ if (mSatelliteController.getRequestIsEmergency()) {
+ if (DBG) logd("handleEventScreenStateChanged: Emergency mode");
+ // This is for coexistence
+ // emergency mode can be set after registerForScreenStateChanged() called for P2P-sms
+ return;
+ }
+
+ int subId = getSubId();
+ if (!isP2pSmsSupportedOnCarrierRoamingNtn(subId)) {
+ if (DBG) plogd("handleEventScreenStateChanged: P2P_SMS is not supported");
+ return;
+ }
+
if (!screenOn) {
// Screen off, start timer
int timeoutMillis = getScreenOffInactivityTimeoutDurationSec() * 1000;
- sendMessageDelayed(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT, timeoutMillis);
+ if (mAlarmManager == null) {
+ plogd("handleEventScreenStateChanged: can not access AlarmManager to start timer");
+ return;
+ }
+
+ mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + timeoutMillis,
+ TAG, new HandlerExecutor(getHandler()), new WorkSource(), mAlarmListener);
plogd("handleEventScreenStateChanged: start timer " + timeoutMillis);
} else {
// Screen on, stop timer
removeMessages(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT);
+ if (mAlarmManager == null) {
+ plogd("handleEventScreenStateChanged: can not access AlarmManager to stop timer");
+ return;
+ }
+
+ mAlarmManager.cancel(mAlarmListener);
plogd("handleEventScreenStateChanged: stop timer");
}
}
@@ -1479,13 +1698,6 @@
DEFAULT_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC);
}
- private int getP2pSmsInactivityTimeoutDurationSec() {
- PersistableBundle config = mSatelliteController.getPersistableBundle(getSubId());
-
- return config.getInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
- DEFAULT_P2P_SMS_INACTIVITY_TIMEOUT_SEC);
- }
-
private int getEsosInactivityTimeoutDurationSec() {
PersistableBundle config = mSatelliteController.getPersistableBundle(getSubId());
@@ -1493,62 +1705,128 @@
DEFAULT_ESOS_INACTIVITY_TIMEOUT_SEC);
}
- private void evaluateStartingCarrierRoamingNbIotInactivityTimer() {
+ private void evaluateStartingEsosInactivityTimer() {
if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
- plogd("evaluateStartingCarrierRoamingNbIotInactivityTimer: "
+ plogd("evaluateStartingEsosInactivityTimer: "
+ "carrierRoamingNbIotNtn is disabled");
return;
}
+ if (isEsosInActivityTimerStarted()) {
+ plogd("isEsosInActivityTimerStarted: "
+ + "ESOS inactivity timer already started");
+ return;
+ }
+
int subId = getSubId();
- if (!mSatelliteController.isSatelliteRoamingP2pSmSSupported(subId)
- && !mSatelliteController.isSatelliteEsosSupported(subId)) {
- plogd("evaluateStartingCarrierRoamingNbIotInactivityTimer: "
- + "device does not support P2P SMS and ESOS are disabled");
+ if (!mSatelliteController.isSatelliteEsosSupported(subId)) {
+ plogd("evaluateStartingEsosInactivityTimer: ESOS is not supported");
+ return;
+ }
+
+ if (!mSatelliteController.getRequestIsEmergency()) {
+ plogd("evaluateStartingEsosInactivityTimer: request is not emergency");
return;
}
if (mIsDeviceAlignedWithSatellite) {
- plogd("evaluateStartingCarrierRoamingNbIotInactivityTimer: "
- + "can't start inactivity timer due to device aligned satellite");
+ plogd("evaluateStartingEsosInactivityTimer: "
+ + "can't start ESOS inactivity timer due to device aligned satellite");
return;
}
- if (hasMessages(EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT)) {
- plogd("evaluateStartingCarrierRoamingNbIotInactivityTimer: already started");
- return;
- }
-
- int timeOutMillis;
- if (mSatelliteController.getRequestIsEmergency()) {
- timeOutMillis = getEsosInactivityTimeoutDurationSec() * 1000;
- } else if (mSatelliteController.isInCarrierRoamingNbIotNtn()) {
- timeOutMillis = getP2pSmsInactivityTimeoutDurationSec() * 1000;
- } else {
- plogd("evaluateStartingCarrierRoamingNbIotInactivityTimer: "
- + "can't start inactivity timer device is in not P2P SMS and ESOS mode");
- return;
- }
-
+ int timeOutMillis = getEsosInactivityTimeoutDurationSec() * 1000;
DatagramController datagramController = DatagramController.getInstance();
if (datagramController.isSendingInIdleState()
&& datagramController.isPollingInIdleState()) {
- sendMessageDelayed(EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT,
- timeOutMillis);
- plogd("evaluateStartingCarrierRoamingNbIotInactivityTimer: start inactivity timer "
+ sendMessageDelayed(EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT, timeOutMillis);
+ plogd("evaluateStartingEsosInactivityTimer: start ESOS inactivity timer "
+ timeOutMillis);
} else {
- plogd("evaluateStartingCarrierRoamingNbIotInactivityTimer: "
- + "can't start inactivity timer");
+ plogd("evaluateStartingEsosInactivityTimer: "
+ + "can't start ESOS inactivity timer");
}
}
- private void stopCarrierRoamingNbIotInactivityTimer() {
- removeMessages(EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT);
- plogd("stopCarrierRoamingNbIotInactivityTimer:");
+ private void stopEsosInactivityTimer() {
+ if (isEsosInActivityTimerStarted()) {
+ removeMessages(EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT);
+ plogd("stopEsosInactivityTimer: ESOS inactivity timer stopped");
+ }
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public boolean isEsosInActivityTimerStarted() {
+ return hasMessages(EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT);
+ }
+
+ private int getP2pSmsInactivityTimeoutDurationSec() {
+ PersistableBundle config = mSatelliteController.getPersistableBundle(getSubId());
+
+ return config.getInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
+ DEFAULT_P2P_SMS_INACTIVITY_TIMEOUT_SEC);
+ }
+
+ private void evaluateStartingP2pSmsInactivityTimer() {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("evaluateStartingP2pSmsInactivityTimer: "
+ + "carrierRoamingNbIotNtn is disabled");
+ return;
+ }
+
+ if (isP2pSmsInActivityTimerStarted()) {
+ plogd("isP2pSmsInActivityTimerStarted: "
+ + "P2P_SMS inactivity timer already started");
+ return;
+ }
+
+ int subId = getSubId();
+ if (!isP2pSmsSupportedOnCarrierRoamingNtn(subId)) {
+ if (DBG) plogd("evaluateStartingP2pSmsInactivityTimer: P2P_SMS is not supported");
+ return;
+ }
+
+ if (mIsDeviceAlignedWithSatellite) {
+ plogd("evaluateStartingP2pSmsInactivityTimer: "
+ + "can't start P2P_SMS inactivity timer due to device aligned satellite");
+ return;
+ }
+
+ int timeOutMillis = getP2pSmsInactivityTimeoutDurationSec() * 1000;
+ DatagramController datagramController = DatagramController.getInstance();
+ if (datagramController.isSendingInIdleState()
+ && datagramController.isPollingInIdleState()) {
+ sendMessageDelayed(EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT, timeOutMillis);
+ plogd("evaluateStartingP2pSmsInactivityTimer: start P2P_SMS inactivity timer "
+ + timeOutMillis);
+ } else {
+ plogd("evaluateStartingP2pSmsInactivityTimer: "
+ + "can't start P2P_SMS inactivity timer");
+ }
+ }
+
+ private void stopP2pSmsInactivityTimer() {
+ if (isP2pSmsInActivityTimerStarted()) {
+ removeMessages(EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT);
+ plogd("stopP2pSmsInactivityTimer: P2P_SMS inactivity timer stopped");
+ }
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public boolean isP2pSmsInActivityTimerStarted() {
+ return hasMessages(EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT);
}
private void handleEventScreenOffInactivityTimerTimedOut() {
+ if (mSatelliteController.getRequestIsEmergency()) {
+ loge("handleEventScreenOffInactivityTimerTimedOut: Emergency mode");
+ /* This is for coexistence
+ * mIsEmergency can be set after
+ * EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT timer started
+ */
+ return;
+ }
+
plogd("handleEventScreenOffInactivityTimerTimedOut: request disable satellite");
mSatelliteController.requestSatelliteEnabled(
@@ -1562,7 +1840,6 @@
if (result == SATELLITE_RESULT_SUCCESS) {
mSessionMetricsStats.addCountOfAutoExitDueToScreenOff();
}
- // TODO(b/364738085): Add CountOfAutoExitDueToTnNetwork
}
});
}
@@ -1645,6 +1922,25 @@
return true;
}
+ private boolean isP2pSmsSupportedOnCarrierRoamingNtn(int subId) {
+ if (!mSatelliteController.isSatelliteRoamingP2pSmSSupported(subId)) {
+ if (DBG) plogd("isP2pSmsSupportedOnCarrierRoamingNtn: P2P_SMS is not supported");
+ return false;
+ }
+
+ int[] services = mSatelliteController.getSupportedServicesOnCarrierRoamingNtn(subId);
+ if (!ArrayUtils.contains(services, NetworkRegistrationInfo.SERVICE_TYPE_SMS)) {
+ if (DBG) {
+ plogd("isP2pSmsSupportedOnCarrierRoamingNtn: P2P_SMS service is not supported "
+ + "on carrier roaming ntn.");
+ }
+ return false;
+ }
+
+ if (DBG) plogd("isP2pSmsSupportedOnCarrierRoamingNtn: P2_SMS is supported");
+ return true;
+ }
+
private boolean isSatellitePersistentLoggingEnabled(
@NonNull Context context, @NonNull FeatureFlags featureFlags) {
if (featureFlags.satellitePersistentLogging()) {
@@ -1658,6 +1954,16 @@
}
}
+ private boolean isConcurrentTnScanningSupported() {
+ try {
+ return mContext.getResources().getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning);
+ } catch (RuntimeException e) {
+ plogd("isConcurrentTnScanningSupported: ex=" + e);
+ return false;
+ }
+ }
+
private void plogd(@NonNull String log) {
logd(log);
if (mPersistentLogger != null) {
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java
index 771432e..3138b16 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java
@@ -325,13 +325,18 @@
return;
}
String simCountry = MccTable.countryCodeForMcc(subscriptionInfoInternal.getMcc());
- String satelliteRegisteredCountry = MccTable.countryCodeForMcc(
- satelliteRegisteredPlmn.substring(0, 3));
- if (simCountry.equalsIgnoreCase(satelliteRegisteredCountry)) {
- mIsNtnRoamingInHomeCountry = false;
- } else {
- // If device is connected to roaming non-terrestrial network, update to true.
- mIsNtnRoamingInHomeCountry = true;
+ mIsNtnRoamingInHomeCountry = true;
+ if (satelliteRegisteredPlmn != null
+ && satelliteRegisteredPlmn.length() >= 3) {
+ String satelliteRegisteredCountry = MccTable.countryCodeForMcc(
+ satelliteRegisteredPlmn.substring(0, 3));
+ if (simCountry.equalsIgnoreCase(satelliteRegisteredCountry)) {
+ mIsNtnRoamingInHomeCountry = true;
+ } else {
+ // If device is connected to roaming non-terrestrial network, then marking as
+ // roaming in external country
+ mIsNtnRoamingInHomeCountry = false;
+ }
}
logd("updateNtnRoamingInHomeCountry: mIsNtnRoamingInHomeCountry="
+ mIsNtnRoamingInHomeCountry);
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java
index ec135da..56c3431 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java
@@ -141,14 +141,13 @@
builder.setCountOfDemoModeOutgoingDatagramSuccess(ADD_COUNT);
} else {
builder.setCountOfOutgoingDatagramSuccess(ADD_COUNT);
- }
-
- if (SatelliteServiceUtils.isSosMessage(datagramType)) {
- builder.setCountOfDatagramTypeSosSmsSuccess(ADD_COUNT);
- } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING) {
- builder.setCountOfDatagramTypeLocationSharingSuccess(ADD_COUNT);
- } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
- builder.setCountOfDatagramTypeKeepAliveSuccess(ADD_COUNT).build();
+ if (SatelliteServiceUtils.isSosMessage(datagramType)) {
+ builder.setCountOfDatagramTypeSosSmsSuccess(ADD_COUNT);
+ } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING) {
+ builder.setCountOfDatagramTypeLocationSharingSuccess(ADD_COUNT);
+ } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
+ builder.setCountOfDatagramTypeKeepAliveSuccess(ADD_COUNT).build();
+ }
}
SatelliteStats.SatelliteControllerParams controllerParam = builder.build();
@@ -166,14 +165,13 @@
builder.setCountOfDemoModeOutgoingDatagramFail(ADD_COUNT);
} else {
builder.setCountOfOutgoingDatagramFail(ADD_COUNT);
- }
-
- if (SatelliteServiceUtils.isSosMessage(datagramType)) {
- builder.setCountOfDatagramTypeSosSmsFail(ADD_COUNT);
- } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING) {
- builder.setCountOfDatagramTypeLocationSharingFail(ADD_COUNT);
- } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
- builder.setCountOfDatagramTypeKeepAliveFail(ADD_COUNT);
+ if (SatelliteServiceUtils.isSosMessage(datagramType)) {
+ builder.setCountOfDatagramTypeSosSmsFail(ADD_COUNT);
+ } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING) {
+ builder.setCountOfDatagramTypeLocationSharingFail(ADD_COUNT);
+ } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
+ builder.setCountOfDatagramTypeKeepAliveFail(ADD_COUNT);
+ }
}
SatelliteStats.SatelliteControllerParams controllerParam = builder.build();
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java
index a234378..2ae8f9d 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java
@@ -46,9 +46,13 @@
private long mTerminationProcessingTimeMillis;
private int mSessionDurationSec;
private int mCountOfSuccessfulOutgoingDatagram;
+ private int mShadowCountOfSuccessfulOutgoingDatagram;
private int mCountOfFailedOutgoingDatagram;
+ private int mShadowCountOfFailedOutgoingDatagram;
private int mCountOfTimedOutUserMessagesWaitingForConnection;
+ private int mShadowCountOfTimedOutUserMessagesWaitingForConnection;
private int mCountOfTimedOutUserMessagesWaitingForAck;
+ private int mShadowCountOfTimedOutUserMessagesWaitingForAck;
private int mCountOfSuccessfulIncomingDatagram;
private int mCountOfIncomingDatagramFailed;
private boolean mIsDemoMode;
@@ -131,6 +135,7 @@
}
mCountOfSuccessfulOutgoingDatagram++;
+ mShadowCountOfSuccessfulOutgoingDatagram++;
logd("addCountOfSuccessfulOutgoingDatagram: current count="
+ mCountOfSuccessfulOutgoingDatagram);
return this;
@@ -146,6 +151,7 @@
}
mCountOfFailedOutgoingDatagram++;
+ mShadowCountOfFailedOutgoingDatagram++;
logd("addCountOfFailedOutgoingDatagram: current count=" + mCountOfFailedOutgoingDatagram);
if (resultCode == SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE) {
@@ -166,6 +172,7 @@
}
mCountOfTimedOutUserMessagesWaitingForConnection++;
+ mShadowCountOfTimedOutUserMessagesWaitingForConnection++;
logd("addCountOfTimedOutUserMessagesWaitingForConnection: current count="
+ mCountOfTimedOutUserMessagesWaitingForConnection);
return this;
@@ -180,6 +187,7 @@
}
mCountOfTimedOutUserMessagesWaitingForAck++;
+ mShadowCountOfTimedOutUserMessagesWaitingForAck++;
logd("addCountOfTimedOutUserMessagesWaitingForAck: current count="
+ mCountOfTimedOutUserMessagesWaitingForAck);
return this;
@@ -278,12 +286,12 @@
public void requestSatelliteSessionStats(int subId, @NonNull ResultReceiver result) {
Bundle bundle = new Bundle();
SatelliteSessionStats sessionStats = new SatelliteSessionStats.Builder()
- .setCountOfSuccessfulUserMessages(mCountOfSuccessfulOutgoingDatagram)
- .setCountOfUnsuccessfulUserMessages(mCountOfFailedOutgoingDatagram)
+ .setCountOfSuccessfulUserMessages(mShadowCountOfSuccessfulOutgoingDatagram)
+ .setCountOfUnsuccessfulUserMessages(mShadowCountOfFailedOutgoingDatagram)
.setCountOfTimedOutUserMessagesWaitingForConnection(
- mCountOfTimedOutUserMessagesWaitingForConnection)
+ mShadowCountOfTimedOutUserMessagesWaitingForConnection)
.setCountOfTimedOutUserMessagesWaitingForAck(
- mCountOfTimedOutUserMessagesWaitingForAck)
+ mShadowCountOfTimedOutUserMessagesWaitingForAck)
.setCountOfUserMessagesInQueueToBeSent(
DatagramDispatcher.getInstance().getPendingUserMessagesCount())
.build();
@@ -322,6 +330,14 @@
mCountOfAutoExitDueToTnNetwork = 0;
}
+ public void resetSessionStatsShadowCounters() {
+ logd("resetTheStatsCounters");
+ mShadowCountOfSuccessfulOutgoingDatagram = 0;
+ mShadowCountOfFailedOutgoingDatagram = 0;
+ mShadowCountOfTimedOutUserMessagesWaitingForConnection = 0;
+ mShadowCountOfTimedOutUserMessagesWaitingForAck = 0;
+ }
+
private static void logd(@NonNull String log) {
if (DBG) {
Log.d(TAG, log);
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
index d835f2d..9d62972 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
@@ -2121,9 +2121,6 @@
* @param capabilities Service capabilities bitmasks
*/
public void setServiceCapabilities(int subId, int capabilities) {
- if (!mFeatureFlags.dataOnlyCellularService()) {
- return;
- }
writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_SERVICE_CAPABILITIES,
capabilities, SubscriptionInfoInternal.Builder::setServiceCapabilities);
}
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
index 353493b..a0a050c 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
@@ -27,6 +27,7 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.app.compat.CompatChanges;
@@ -720,7 +721,7 @@
return false;
}
} else {
- if (!mSubscriptionManager.canManageSubscription(subInfo.toSubscriptionInfo(),
+ if (!canManageSubscription(subInfo.toSubscriptionInfo(),
callingPackage)) {
loge("checkCarrierPrivilegeOnSubList: cannot manage sub " + subId);
return false;
@@ -1450,8 +1451,8 @@
SatelliteController satelliteController = SatelliteController.getInstance();
boolean isSatelliteEnabledOrBeingEnabled = false;
if (satelliteController != null) {
- isSatelliteEnabledOrBeingEnabled = satelliteController.isSatelliteEnabled()
- || satelliteController.isSatelliteBeingEnabled();
+ isSatelliteEnabledOrBeingEnabled =
+ satelliteController.isSatelliteEnabledOrBeingEnabled();
}
if (!isSatelliteEnabledOrBeingEnabled) {
@@ -1838,37 +1839,35 @@
+ " newSetting=" + SubscriptionManager.usageSettingToString(newUsageSetting));
}
- if (mFeatureFlags.dataOnlyCellularService()) {
- final int[] servicesFromCarrierConfig =
- config.getIntArray(
- CarrierConfigManager.KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY);
- int serviceBitmasks = 0;
- boolean allServicesAreValid = true;
- // Check if all services from carrier config are valid before setting to db
- if (servicesFromCarrierConfig == null) {
- allServicesAreValid = false;
- } else {
- for (int service : servicesFromCarrierConfig) {
- if (service < SubscriptionManager.SERVICE_CAPABILITY_VOICE
- || service > SubscriptionManager.SERVICE_CAPABILITY_MAX) {
- allServicesAreValid = false;
- break;
- } else {
- serviceBitmasks |= SubscriptionManager.serviceCapabilityToBitmask(service);
- }
+ final int[] servicesFromCarrierConfig =
+ config.getIntArray(
+ CarrierConfigManager.KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY);
+ int serviceBitmasks = 0;
+ boolean allServicesAreValid = true;
+ // Check if all services from carrier config are valid before setting to db
+ if (servicesFromCarrierConfig == null) {
+ allServicesAreValid = false;
+ } else {
+ for (int service : servicesFromCarrierConfig) {
+ if (service < SubscriptionManager.SERVICE_CAPABILITY_VOICE
+ || service > SubscriptionManager.SERVICE_CAPABILITY_MAX) {
+ allServicesAreValid = false;
+ break;
+ } else {
+ serviceBitmasks |= SubscriptionManager.serviceCapabilityToBitmask(service);
}
}
- // In case we get invalid service override, fall back to default value.
- // DO NOT throw exception which will crash phone process.
- if (!allServicesAreValid) {
- serviceBitmasks = SubscriptionManager.getAllServiceCapabilityBitmasks();
- }
+ }
+ // In case we get invalid service override, fall back to default value.
+ // DO NOT throw exception which will crash phone process.
+ if (!allServicesAreValid) {
+ serviceBitmasks = SubscriptionManager.getAllServiceCapabilityBitmasks();
+ }
- if (serviceBitmasks != subInfo.getServiceCapabilities()) {
- log("updateSubscriptionByCarrierConfig: serviceCapabilities updated from "
- + subInfo.getServiceCapabilities() + " to " + serviceBitmasks);
- mSubscriptionDatabaseManager.setServiceCapabilities(subId, serviceBitmasks);
- }
+ if (serviceBitmasks != subInfo.getServiceCapabilities()) {
+ log("updateSubscriptionByCarrierConfig: serviceCapabilities updated from "
+ + subInfo.getServiceCapabilities() + " to " + serviceBitmasks);
+ mSubscriptionDatabaseManager.setServiceCapabilities(subId, serviceBitmasks);
}
}
@@ -2268,7 +2267,7 @@
return getSubscriptionInfoStreamAsUser(BINDER_WRAPPER.getCallingUserHandle())
.map(SubscriptionInfoInternal::toSubscriptionInfo)
.filter(subInfo -> subInfo.isEmbedded()
- && mSubscriptionManager.canManageSubscription(subInfo, callingPackage))
+ && canManageSubscription(subInfo, callingPackage))
.sorted(Comparator.comparing(SubscriptionInfo::getSimSlotIndex)
.thenComparing(SubscriptionInfo::getSubscriptionId))
.collect(Collectors.toList());
@@ -2994,7 +2993,7 @@
return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
.map(SubscriptionInfoInternal::toSubscriptionInfo)
.filter(info -> groupUuid.equals(info.getGroupUuid())
- && (mSubscriptionManager.canManageSubscription(info, callingPackage)
+ && (canManageSubscription(info, callingPackage)
|| TelephonyPermissions.checkCallingOrSelfReadPhoneStateNoThrow(
mContext, info.getSubscriptionId(), callingPackage,
callingFeatureId, "getSubscriptionsInGroup")))
@@ -4903,6 +4902,15 @@
return cardNumber;
}
+ private boolean canManageSubscription(SubscriptionInfo subInfo, String packageName) {
+ if (Flags.hsumPackageManager() && UserManager.isHeadlessSystemUserMode()) {
+ return mSubscriptionManager.canManageSubscriptionAsUser(subInfo, packageName,
+ UserHandle.of(ActivityManager.getCurrentUser()));
+ } else {
+ return mSubscriptionManager.canManageSubscription(subInfo, packageName);
+ }
+ }
+
/**
* Log debug messages.
*
diff --git a/src/java/com/android/internal/telephony/uicc/IccRecords.java b/src/java/com/android/internal/telephony/uicc/IccRecords.java
index 57ea9b9..cccbf19 100644
--- a/src/java/com/android/internal/telephony/uicc/IccRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/IccRecords.java
@@ -36,6 +36,7 @@
import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.MccTable;
import com.android.internal.telephony.gsm.SimTlv;
@@ -1300,10 +1301,18 @@
return null;
}
+ if (rsp.exception instanceof CommandException commandException) {
+ switch (commandException.getCommandError()) {
+ case REQUEST_NOT_SUPPORTED:
+ throw new UnsupportedOperationException(commandException);
+ default:
+ // handle other exceptions in the rsp.exception conditional below
+ }
+ }
if (rsp.exception != null) {
loge("getIccSimChallengeResponse exception: " + rsp.exception);
//TODO: propagate better exceptions up to the user now that we have them available
- //in the call stack.
+ //in the call stack (see CommandException switch above).
return null;
}
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index dd71c44..9db25b6 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -80,6 +80,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -162,8 +163,7 @@
// this needs to be here, because on bootup we dont know which index maps to which UiccSlot
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private CommandsInterface[] mCis;
- @VisibleForTesting
- public UiccSlot[] mUiccSlots;
+ private UiccSlot[] mUiccSlots;
private int[] mPhoneIdToSlotId;
private boolean mIsSlotStatusSupported = true;
@@ -491,6 +491,27 @@
}
/**
+ * Set UiccSlot object for a specific physical slot index on the device.
+ *
+ * This is only supposed to be used internally and by unit tests.
+ *
+ * @param slotId Slot index
+ * @param slot Slot object
+ */
+ @VisibleForTesting
+ public void setUiccSlot(int slotId, @NonNull UiccSlot slot) {
+ synchronized (mLock) {
+ if (!isValidSlotIndex(slotId)) {
+ throw new ArrayIndexOutOfBoundsException("Invalid slot index: " + slotId);
+ }
+ if (mUiccSlots[slotId] != null) {
+ mUiccSlots[slotId].dispose();
+ }
+ mUiccSlots[slotId] = Objects.requireNonNull(slot);
+ }
+ }
+
+ /**
* API to get UiccSlot object for a given phone id
* @return UiccSlot object for the given phone id
*/
@@ -1076,7 +1097,7 @@
log("Creating mUiccSlots[" + slotId + "]; mUiccSlots.length = "
+ mUiccSlots.length);
}
- mUiccSlots[slotId] = new UiccSlot(mContext, true);
+ setUiccSlot(slotId, new UiccSlot(mContext, true));
}
mUiccSlots[slotId].update(mCis[index], status, index, slotId);
@@ -1353,7 +1374,7 @@
if (VDBG) {
log("Creating mUiccSlot[" + i + "]; mUiccSlots.length = " + mUiccSlots.length);
}
- mUiccSlots[i] = new UiccSlot(mContext, isActive);
+ setUiccSlot(i, new UiccSlot(mContext, isActive));
}
if (isActive) { // check isActive flag so that we don't have to iterate through all
@@ -1803,6 +1824,17 @@
return mCardStrings;
}
+ /**
+ * Release resources. Must be called each time this class is used.
+ */
+ @VisibleForTesting
+ public void dispose() {
+ for (var slot : mUiccSlots) {
+ slot.dispose();
+ }
+ mUiccSlots = null;
+ }
+
public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " ");
pw.println("mIsCdmaSupported=" + isCdmaSupported(mContext));
diff --git a/src/java/com/android/internal/telephony/uicc/UiccPort.java b/src/java/com/android/internal/telephony/uicc/UiccPort.java
index 905db70..8118a12 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccPort.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccPort.java
@@ -33,6 +33,8 @@
import com.android.internal.telephony.flags.FeatureFlagsImpl;
import com.android.telephony.Rlog;
+import dalvik.system.CloseGuard;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -46,6 +48,7 @@
// The lock object is created by UiccSlot that owns this UiccCard - this is to share the lock
// between UiccSlot, UiccCard, EuiccCard, UiccPort, EuiccPort and UiccProfile for now.
protected final Object mLock;
+ private final CloseGuard mCloseGuard = CloseGuard.get();
private String mIccid;
protected String mCardId;
@@ -68,6 +71,7 @@
if (DBG) log("Creating");
mPhoneId = phoneId;
mLock = lock;
+ mCloseGuard.open("cleanup");
update(c, ci, ics, uiccCard);
}
@@ -97,6 +101,7 @@
public void dispose() {
synchronized (mLock) {
if (DBG) log("Disposing Port");
+ mCloseGuard.close();
if (mUiccProfile != null) {
mUiccProfile.dispose();
}
@@ -106,9 +111,14 @@
}
@Override
- protected void finalize() {
+ protected void finalize() throws Throwable {
if (DBG) log("UiccPort finalized");
- cleanupOpenLogicalChannelRecordsIfNeeded();
+ try {
+ if (mCloseGuard != null) mCloseGuard.warnIfOpen();
+ cleanupOpenLogicalChannelRecordsIfNeeded();
+ } finally {
+ super.finalize();
+ }
}
/**
@@ -440,7 +450,13 @@
* removal or modem reset. The obsoleted records may trigger a redundant release of logical
* channel that may have been assigned to other client.
*/
+ @SuppressWarnings("GuardedBy")
private void cleanupOpenLogicalChannelRecordsIfNeeded() {
+ // This check may raise GuardedBy warning, but we need it as long as this method is called
+ // from finalize(). We can remove it from there once UiccPort is fully protected against
+ // resource leak (e.g. with CloseGuard) and all (direct and indirect) users are fixed.
+ if (mOpenChannelRecords == null) return;
+
synchronized (mOpenChannelRecords) {
for (OpenLogicalChannelRecord record : mOpenChannelRecords) {
if (DBG) log("Clean up " + record);
diff --git a/src/java/com/android/internal/telephony/uicc/UiccSlot.java b/src/java/com/android/internal/telephony/uicc/UiccSlot.java
index db10271..d986c93 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccSlot.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccSlot.java
@@ -391,6 +391,13 @@
}
}
+ /**
+ * Release resources. Must be called each time this class is used.
+ */
+ public void dispose() {
+ nullifyUiccCard(false);
+ }
+
public boolean isStateUnknown() {
// CardState is not specific to any port index, use default port.
CardState cardState = mCardState.get(TelephonyManager.DEFAULT_PORT_INDEX);
diff --git a/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java b/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
index b17a0fd..1d9dc68 100644
--- a/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
+++ b/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
@@ -119,9 +119,7 @@
mChannelKey = CHANNEL_ID_PRE + "_" + phoneId;
mChannelResponseKey = CHANNEL_RESPONSE_ID_PRE + "_" + phoneId;
mHandler = new Handler();
-
mChannelInUse = false;
- closeAnyOpenChannel();
}
/**
diff --git a/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java b/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java
index 4889187..c690ab4 100644
--- a/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java
+++ b/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.telephony.ims;
+package android.telephony.ims;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -36,6 +36,7 @@
import com.android.internal.telephony.FakeTelephonyProvider;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -176,6 +177,11 @@
createFakeSimInfo();
}
+ @After
+ public void tearDown() {
+ mFakeTelephonyProvider.close();
+ }
+
@Test
@SmallTest
public void testLoadAndUpdateConfigForSub() {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java
index a860dff..1c58ef2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java
@@ -220,8 +220,9 @@
// Capture CarrierConfigChangeListener to emulate the carrier config change notification
ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
- CarrierPrivilegesTracker cpt = new CarrierPrivilegesTracker(mTestableLooper.getLooper(),
- mPhone, mContext, mFeatureFlags);
+ CarrierPrivilegesTracker cpt =
+ new CarrierPrivilegesTracker(
+ mTestableLooper.getLooper(), mPhone, mContext, mFeatureFlags);
verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
listenerArgumentCaptor.capture());
mCarrierConfigChangeListener = listenerArgumentCaptor.getAllValues().get(0);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
index 70e3dee..9788320 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
@@ -241,6 +241,14 @@
}
@Override
+ public boolean bindServiceAsUser(
+ Intent serviceIntent,
+ ServiceConnection connection,
+ int flags, UserHandle user) {
+ return bindService(serviceIntent, connection, flags);
+ }
+
+ @Override
public void unbindService(
ServiceConnection connection) {
IInterface service = mServiceByServiceConnection.remove(connection);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
index 8dad3ec..8720171 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
@@ -378,6 +378,51 @@
@Test
@SmallTest
+ public void testNotifyCallbackModeStarted() {
+ doReturn(true).when(mFeatureFlags).emergencyCallbackModeNotification();
+ int phoneId = mPhone.getPhoneId();
+ int subId = mPhone.getSubId();
+ int type = 1;
+ long durationMillis = 1000;
+
+ mDefaultPhoneNotifierUT.notifyCallbackModeStarted(mPhone, type, durationMillis);
+
+ verify(mTelephonyRegistryManager).notifyCallbackModeStarted(eq(phoneId), eq(subId),
+ eq(type), eq(durationMillis));
+ }
+
+ @Test
+ @SmallTest
+ public void testNotifyCallbackModeRestarted() {
+ doReturn(true).when(mFeatureFlags).emergencyCallbackModeNotification();
+ int phoneId = mPhone.getPhoneId();
+ int subId = mPhone.getSubId();
+ int type = 1;
+ long durationMillis = 1000;
+
+ mDefaultPhoneNotifierUT.notifyCallbackModeRestarted(mPhone, type, durationMillis);
+
+ verify(mTelephonyRegistryManager).notifyCallbackModeRestarted(eq(phoneId), eq(subId),
+ eq(type), eq(durationMillis));
+ }
+
+ @Test
+ @SmallTest
+ public void testNotifyCallbackModeStopped() {
+ doReturn(true).when(mFeatureFlags).emergencyCallbackModeNotification();
+ int phoneId = mPhone.getPhoneId();
+ int subId = mPhone.getSubId();
+ int type = 1;
+ int reason = 0;
+
+ mDefaultPhoneNotifierUT.notifyCallbackModeStopped(mPhone, type, reason);
+
+ verify(mTelephonyRegistryManager).notifyCallbackModeStopped(eq(phoneId), eq(subId),
+ eq(type), eq(reason));
+ }
+
+ @Test
+ @SmallTest
public void testCarrierRoamingNtnModeChanged() {
int subId = mPhone.getSubId();
mDefaultPhoneNotifierUT.notifyCarrierRoamingNtnModeChanged(mPhone, true);
@@ -393,4 +438,15 @@
verify(mTelephonyRegistryManager).notifyCarrierRoamingNtnEligibleStateChanged(
eq(subId), eq(true));
}
+
+ @Test
+ @SmallTest
+ public void testCarrierRoamingNtnAvailableServicesChanged() {
+ int subId = mPhone.getSubId();
+ int[] testServices = {3, 6};
+ mDefaultPhoneNotifierUT.notifyCarrierRoamingNtnAvailableServicesChanged(
+ mPhone, testServices);
+ verify(mTelephonyRegistryManager).notifyCarrierRoamingNtnAvailableServicesChanged(
+ eq(subId), eq(testServices));
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java b/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
index c923f69..101c668 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
@@ -196,4 +196,11 @@
selectionArgs);
return count;
}
+
+ /**
+ * Release resources. Must be called each time this class is used.
+ */
+ public void close() {
+ mDbHelper.close();
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GbaManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/GbaManagerTest.java
index bad32e9..8898a0f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GbaManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GbaManagerTest.java
@@ -41,6 +41,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.telephony.IBootstrapAuthenticationCallback;
import android.telephony.TelephonyManager;
import android.telephony.gba.GbaAuthRequest;
@@ -51,8 +52,6 @@
import android.testing.TestableLooper;
import android.util.Log;
-import androidx.test.filters.SmallTest;
-
import com.android.internal.telephony.metrics.RcsStats;
import org.junit.After;
@@ -66,7 +65,7 @@
*/
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public final class GbaManagerTest {
+public final class GbaManagerTest extends TelephonyTest {
private static final String LOG_TAG = "GbaManagerTest";
private static final ComponentName TEST_DEFAULT_SERVICE_NAME = new ComponentName(
@@ -91,6 +90,7 @@
@Before
public void setUp() throws Exception {
+ super.setUp(getClass().getSimpleName());
log("setUp");
mMockContext = mock(Context.class);
mMockBinder = mock(IBinder.class);
@@ -100,7 +100,8 @@
if (Looper.myLooper() == null) {
Looper.prepare();
}
- when(mMockContext.bindService(any(), any(), anyInt())).thenReturn(true);
+ when(mMockContext.bindServiceAsUser(any(), any(), anyInt(), any(UserHandle.class)))
+ .thenReturn(true);
when(mMockGbaServiceBinder.asBinder()).thenReturn(mMockBinder);
mTestGbaManager = new GbaManager(mMockContext, TEST_SUB_ID, null, 0, mMockRcsStats);
mHandler = mTestGbaManager.getHandler();
@@ -109,137 +110,129 @@
} catch (Exception e) {
fail("Unable to create looper from handler.");
}
+ monitorTestableLooper(mLooper);
}
@After
public void tearDown() throws Exception {
log("tearDown");
mTestGbaManager.destroy();
- mTestGbaManager = null;
- mHandler = null;
- mLooper.destroy();
- mLooper = null;
+ super.tearDown();
}
@Test
- @SmallTest
public void testFailOnRequest() throws Exception {
GbaAuthRequest request = createDefaultRequest();
mTestGbaManager.bootstrapAuthenticationRequest(request);
- mLooper.processAllMessages();
+ processAllMessages();
- verify(mMockContext, never()).bindService(any(), any(), anyInt());
+ verify(mMockContext, never()).bindServiceAsUser(any(), any(), anyInt(),
+ any(UserHandle.class));
verify(mMockCallback).onAuthenticationFailure(anyInt(), anyInt());
assertTrue(!mTestGbaManager.isServiceConnected());
}
@Test
- @SmallTest
public void testBindServiceOnRequest() throws Exception {
- mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName());
+ mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName(), 123);
GbaAuthRequest request = createDefaultRequest();
mTestGbaManager.bootstrapAuthenticationRequest(request);
- mLooper.processAllMessages();
+ processAllMessages();
bindAndConnectService(TEST_DEFAULT_SERVICE_NAME);
- mLooper.processAllMessages();
+ processAllMessages();
verify(mMockGbaServiceBinder).authenticationRequest(any());
assertTrue(mTestGbaManager.isServiceConnected());
}
@Test
- @SmallTest
public void testFailAndRetryOnRequest() throws RemoteException {
- when(mMockContext.bindService(any(), any(), anyInt())).thenReturn(false);
- mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName());
+ when(mMockContext.bindServiceAsUser(any(), any(), anyInt(), any(UserHandle.class)))
+ .thenReturn(false);
+ mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName(), 123);
GbaAuthRequest request = createDefaultRequest();
mTestGbaManager.bootstrapAuthenticationRequest(request);
for (int i = 0; i < GbaManager.MAX_RETRY; i++) {
- mLooper.processAllMessages();
- verify(mMockContext, times(i + 1)).bindService(any(), any(), anyInt());
- try {
- Thread.sleep(GbaManager.RETRY_TIME_MS + 500);
- } catch (InterruptedException e) {
- }
+ processAllMessages();
+ verify(mMockContext, times(i + 1)).bindServiceAsUser(any(), any(), anyInt(),
+ any(UserHandle.class));
+ moveTimeForward(GbaManager.REQUEST_TIMEOUT_MS);
}
assertTrue(!mTestGbaManager.isServiceConnected());
- mLooper.processAllMessages();
+ processAllMessages();
verify(mMockCallback).onAuthenticationFailure(anyInt(), anyInt());
}
@Test
- @SmallTest
public void testBindServiceWhenPackageNameChanged() {
- mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName());
+ mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName(), 123);
mTestGbaManager.overrideReleaseTime(RELEASE_TIME_60S);
GbaAuthRequest request = createDefaultRequest();
mTestGbaManager.bootstrapAuthenticationRequest(request);
- mLooper.processAllMessages();
+ processAllMessages();
ServiceConnection conn = bindAndConnectService(TEST_DEFAULT_SERVICE_NAME);
- mTestGbaManager.overrideServicePackage(TEST_SERVICE2_NAME.getPackageName());
+ mTestGbaManager.overrideServicePackage(TEST_SERVICE2_NAME.getPackageName(), 123);
assertEquals(TEST_SERVICE2_NAME.getPackageName(), mTestGbaManager.getServicePackage());
- mLooper.processAllMessages();
+ processAllMessages();
unbindService(conn);
bindAndConnectService(TEST_SERVICE2_NAME);
assertTrue(mTestGbaManager.isServiceConnected());
}
@Test
- @SmallTest
public void testBindServiceWhenReleaseTimeChanged() {
- mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName());
+ mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName(), 123);
mTestGbaManager.overrideReleaseTime(RELEASE_NEVER);
assertEquals(RELEASE_NEVER, mTestGbaManager.getReleaseTime());
- mLooper.processAllMessages();
+ processAllMessages();
bindAndConnectService(TEST_DEFAULT_SERVICE_NAME);
assertTrue(mTestGbaManager.isServiceConnected());
}
@Test
- @SmallTest
public void testDontBindServiceWhenPackageNameChanged() {
- mTestGbaManager.overrideServicePackage(TEST_SERVICE2_NAME.getPackageName());
+ mTestGbaManager.overrideServicePackage(TEST_SERVICE2_NAME.getPackageName(), 123);
- mLooper.processAllMessages();
+ processAllMessages();
- verify(mMockContext, never()).bindService(any(), any(), anyInt());
+ verify(mMockContext, never()).bindServiceAsUser(any(), any(), anyInt(),
+ any(UserHandle.class));
assertTrue(!mTestGbaManager.isServiceConnected());
}
@Test
- @SmallTest
public void testDontBindServiceWhenReleaseTimeChanged() {
- mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName());
+ mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName(), 123);
mTestGbaManager.overrideReleaseTime(RELEASE_TIME_60S);
- mLooper.processAllMessages();
+ processAllMessages();
- verify(mMockContext, never()).bindService(any(), any(), anyInt());
+ verify(mMockContext, never()).bindServiceAsUser(any(), any(), anyInt(),
+ any(UserHandle.class));
assertTrue(!mTestGbaManager.isServiceConnected());
}
@Test
- @SmallTest
public void testMetricsGbaEvent() throws Exception {
- mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName());
+ mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName(), 123);
mTestGbaManager.overrideReleaseTime(RELEASE_NEVER);
- mLooper.processAllMessages();
+ processAllMessages();
bindAndConnectService(TEST_DEFAULT_SERVICE_NAME);
GbaAuthRequest request = createDefaultRequest();
// Failure case
mTestGbaManager.bootstrapAuthenticationRequest(request);
- mLooper.processAllMessages();
+ processAllMessages();
ArgumentCaptor<GbaAuthRequest> captor = ArgumentCaptor.forClass(GbaAuthRequest.class);
verify(mMockGbaServiceBinder, times(1)).authenticationRequest(captor.capture());
@@ -254,7 +247,7 @@
// Success case
mTestGbaManager.bootstrapAuthenticationRequest(request);
- mLooper.processAllMessages();
+ processAllMessages();
ArgumentCaptor<GbaAuthRequest> captor2 = ArgumentCaptor.forClass(GbaAuthRequest.class);
verify(mMockGbaServiceBinder, times(2)).authenticationRequest(captor2.capture());
@@ -280,9 +273,10 @@
ArgumentCaptor.forClass(Intent.class);
ArgumentCaptor<ServiceConnection> serviceCaptor =
ArgumentCaptor.forClass(ServiceConnection.class);
- verify(mMockContext, atLeastOnce()).bindService(intentCaptor.capture(),
+ verify(mMockContext, atLeastOnce()).bindServiceAsUser(intentCaptor.capture(),
serviceCaptor.capture(), eq(
- Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE));
+ Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+ any(UserHandle.class));
Intent testIntent = intentCaptor.getValue();
assertEquals(GbaService.SERVICE_INTERFACE, testIntent.getAction());
assertEquals(component.getPackageName(), testIntent.getPackage());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
index d8005e8..28d0318 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
@@ -1270,8 +1270,7 @@
doReturn(mIsimUiccRecords).when(mPhone).getIsimRecords();
doReturn(refImpuArray).when(mIsimUiccRecords).getIsimImpu();
- List<Uri> impuList = mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG,
- FEATURE_ID);
+ List<Uri> impuList = mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG);
assertNotNull(impuList);
assertEquals(refImpuArray.length, impuList.size());
@@ -1288,8 +1287,7 @@
refImpuArray[2] = "tel:+91987754324";
doReturn(mIsimUiccRecords).when(mPhone).getIsimRecords();
doReturn(refImpuArray).when(mIsimUiccRecords).getIsimImpu();
- List<Uri> impuList = mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG,
- FEATURE_ID);
+ List<Uri> impuList = mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG);
assertNotNull(impuList);
// Null or Empty string cannot be converted to URI
assertEquals(refImpuArray.length - 2, impuList.size());
@@ -1300,7 +1298,7 @@
doReturn(null).when(mPhone).getIsimRecords();
try {
- mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG, FEATURE_ID);
+ mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG);
fail();
} catch (Exception ex) {
assertTrue(ex instanceof IllegalStateException);
@@ -1311,32 +1309,121 @@
@Test
public void getImsPublicUserIdentities_InValidSubIdCheck() {
try {
- mPhoneSubInfoControllerUT.getImsPublicUserIdentities(-1, TAG, FEATURE_ID);
+ mPhoneSubInfoControllerUT.getImsPublicUserIdentities(-1, TAG);
fail();
} catch (Exception ex) {
assertTrue(ex instanceof IllegalArgumentException);
- assertTrue(ex.getMessage().contains("Invalid SubscriptionID"));
+ assertTrue(ex.getMessage().contains("Invalid subscription"));
}
}
@Test
public void getImsPublicUserIdentities_NoReadPrivilegedPermission() {
mContextFixture.removeCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL);
- String[] refImpuArray = new String[3];
- refImpuArray[0] = "012345678";
- refImpuArray[1] = "sip:test@verify.com";
- refImpuArray[2] = "tel:+91987754324";
- doReturn(mIsimUiccRecords).when(mPhone).getIsimRecords();
- doReturn(refImpuArray).when(mIsimUiccRecords).getIsimImpu();
- List<Uri> impuList = mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG,
- FEATURE_ID);
+ try {
+ mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG);
+ fail();
+ } catch (Exception ex) {
+ assertTrue(ex instanceof SecurityException);
+ assertTrue(ex.getMessage().contains("getImsPublicUserIdentities"));
+ }
- assertNotNull(impuList);
- assertEquals(refImpuArray.length, impuList.size());
- assertEquals(impuList.get(0).toString(), refImpuArray[0]);
- assertEquals(impuList.get(1).toString(), refImpuArray[1]);
- assertEquals(impuList.get(2).toString(), refImpuArray[2]);
mContextFixture.addCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE);
}
+
+ @Test
+ public void getImsPcscfAddresses() {
+ String[] preDefinedPcscfs = new String[3];
+ preDefinedPcscfs[0] = "127.0.0.1";
+ preDefinedPcscfs[1] = "192.168.0.1";
+ preDefinedPcscfs[2] = "::1";
+ doReturn(true).when(mFeatureFlags).supportIsimRecord();
+ doReturn(mIsimUiccRecords).when(mPhone).getIsimRecords();
+ doReturn(preDefinedPcscfs).when(mIsimUiccRecords).getIsimPcscf();
+
+ List<String> pcscfAddresses = mPhoneSubInfoControllerUT.getImsPcscfAddresses(0, TAG);
+
+ assertNotNull(pcscfAddresses);
+ assertEquals(preDefinedPcscfs.length, pcscfAddresses.size());
+ assertEquals(preDefinedPcscfs[0], pcscfAddresses.get(0).toString());
+ assertEquals(preDefinedPcscfs[1], pcscfAddresses.get(1).toString());
+ assertEquals(preDefinedPcscfs[2], pcscfAddresses.get(2).toString());
+ }
+
+ @Test
+ public void getImsPcscfAddresses_InvalidPcscf() {
+ String[] preDefinedPcscfs = new String[3];
+ preDefinedPcscfs[0] = null;
+ preDefinedPcscfs[2] = "";
+ preDefinedPcscfs[2] = "::1";
+ doReturn(true).when(mFeatureFlags).supportIsimRecord();
+ doReturn(mIsimUiccRecords).when(mPhone).getIsimRecords();
+ doReturn(preDefinedPcscfs).when(mIsimUiccRecords).getIsimPcscf();
+
+ List<String> pcscfAddresses = mPhoneSubInfoControllerUT.getImsPcscfAddresses(0, TAG);
+
+ assertNotNull(pcscfAddresses);
+ // Null or Empty string is not added to pcscf list
+ assertEquals(preDefinedPcscfs.length - 2, pcscfAddresses.size());
+ }
+
+ @Test
+ public void getImsPcscfAddresses_IsimNotLoadedError() {
+ doReturn(true).when(mFeatureFlags).supportIsimRecord();
+ doReturn(null).when(mPhone).getIsimRecords();
+
+ try {
+ mPhoneSubInfoControllerUT.getImsPcscfAddresses(0, TAG);
+ fail();
+ } catch (Exception ex) {
+ assertTrue(ex instanceof IllegalStateException);
+ assertTrue(ex.getMessage().contains("ISIM is not loaded"));
+ }
+ }
+
+ @Test
+ public void getImsPcscfAddresses_InValidSubIdCheck() {
+ doReturn(true).when(mFeatureFlags).supportIsimRecord();
+
+ try {
+ mPhoneSubInfoControllerUT.getImsPcscfAddresses(-1, TAG);
+ fail();
+ } catch (Exception ex) {
+ assertTrue(ex instanceof IllegalArgumentException);
+ assertTrue(ex.getMessage().contains("Invalid subscription"));
+ }
+ }
+
+ @Test
+ public void getImsPcscfAddresses_NoReadPrivilegedPermission() {
+ mContextFixture.removeCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL);
+ doReturn(true).when(mFeatureFlags).supportIsimRecord();
+
+ try {
+ mPhoneSubInfoControllerUT.getImsPcscfAddresses(0, TAG);
+ fail();
+ } catch (Exception ex) {
+ assertTrue(ex instanceof SecurityException);
+ assertTrue(ex.getMessage().contains("getImsPcscfAddresses"));
+ }
+
+ mContextFixture.addCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE);
+ }
+
+ @Test
+ public void getImsPcscfAddresses_FlagDisabled() {
+ String[] preDefinedPcscfs = new String[3];
+ preDefinedPcscfs[0] = "127.0.0.1";
+ preDefinedPcscfs[1] = "192.168.0.1";
+ preDefinedPcscfs[2] = "::1";
+ doReturn(false).when(mFeatureFlags).supportIsimRecord();
+ doReturn(mIsimUiccRecords).when(mPhone).getIsimRecords();
+ doReturn(preDefinedPcscfs).when(mIsimUiccRecords).getIsimPcscf();
+
+ List<String> pcscfAddresses = mPhoneSubInfoControllerUT.getImsPcscfAddresses(0, TAG);
+
+ assertNotNull(pcscfAddresses);
+ assertEquals(0, pcscfAddresses.size());
+ }
}
\ No newline at end of file
diff --git a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
index 88c5389..48c9f9c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
@@ -175,6 +175,7 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.SparseArray;
+import android.view.Display;
import androidx.test.filters.FlakyTest;
@@ -312,6 +313,7 @@
} catch (RuntimeException e) {
}
Context context = new ContextFixture().getTestDouble();
+ doReturn(Display.DEFAULT_DISPLAY).when(context).getDisplayId();
doReturn(true).when(mConnectionManager).isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
doReturn(mConnectionManager).when(context)
.getSystemService(Context.CONNECTIVITY_SERVICE);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index 1465176..70bdcba 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
@@ -2983,7 +2983,7 @@
doReturn(ServiceState.STATE_IN_SERVICE).when(mSST).getCombinedRegState(ss);
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Plmn should be shown, and the string is "Emergency call only"
Bundle b = getExtrasFromLastSpnUpdateIntent();
@@ -3005,7 +3005,7 @@
sst.mSS = ss;
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Plmn should be shown, and the string is "No service"
Bundle b = getExtrasFromLastSpnUpdateIntent();
@@ -3026,7 +3026,7 @@
sst.mSS = ss;
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Plmn should be shown, and the string is null
Bundle b = getExtrasFromLastSpnUpdateIntent();
@@ -3049,7 +3049,7 @@
doReturn(false).when(mPhone).isWifiCallingEnabled();
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Show both spn & plmn
String spn = mBundle.getString(CarrierConfigManager.KEY_CARRIER_NAME_STRING);
@@ -3091,7 +3091,7 @@
doReturn(formats).when(r).getStringArray(anyInt());
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Only spn should be shown
String spn = mBundle.getString(CarrierConfigManager.KEY_CARRIER_NAME_STRING);
@@ -3128,7 +3128,7 @@
doReturn(true).when(mPhone).isImsRegistered();
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Only spn should be shown
String spn = mBundle.getString(CarrierConfigManager.KEY_CARRIER_NAME_STRING);
@@ -3161,7 +3161,7 @@
doReturn(true).when(mPhone).isImsRegistered();
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Only plmn should be shown
String plmn = mBundle.getStringArray(CarrierConfigManager.KEY_PNN_OVERRIDE_STRING_ARRAY)[0];
@@ -3187,7 +3187,7 @@
doReturn(false).when(mPhone).isWifiCallingEnabled();
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Show both spn & plmn
String spn = mBundle.getString(CarrierConfigManager.KEY_CARRIER_NAME_STRING);
@@ -3240,7 +3240,7 @@
doReturn(false).when(mPhone).isWifiCallingEnabled();
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Plmn should be shown, and the string is "No service"
Bundle b = getExtrasFromLastSpnUpdateIntent();
@@ -3271,7 +3271,7 @@
doReturn(true).when(mPhone).isWifiCallingEnabled();
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Plmn should be shown, and the string is "No service"
Bundle b = getExtrasFromLastSpnUpdateIntent();
@@ -3303,7 +3303,7 @@
doReturn(true).when(mPhone).isWifiCallingEnabled();
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Plmn should be shown, and the string is "No service"
Bundle b = getExtrasFromLastSpnUpdateIntent();
@@ -3503,7 +3503,7 @@
doReturn(Arrays.asList("10123")).when(mSatelliteController).getSatellitePlmnsForCarrier(
anyInt());
doReturn(satelliteSupportedServiceList).when(mSatelliteController)
- .getSupportedSatelliteServices(sst.mSubId, "10123");
+ .getSupportedSatelliteServicesForPlmn(sst.mSubId, "10123");
assertFalse(sst.mSS.isUsingNonTerrestrialNetwork());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimultaneousCallingTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SimultaneousCallingTrackerTest.java
index 054df07..6fd45ea 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SimultaneousCallingTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimultaneousCallingTrackerTest.java
@@ -134,7 +134,6 @@
.getSubscriptionInfo(any(Integer.class));
doReturn(RIL.RADIO_HAL_VERSION_2_2).when(mMockRadioConfigProxy).getVersion();
doReturn(true).when(mFeatureFlags).simultaneousCallingIndications();
- doReturn(true).when(mFeatureFlags).dataOnlyCellularService();
mMockRegistryManager = mContext.getSystemService(TelephonyRegistryManager.class);
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
index acf793e..b8316cb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
@@ -25,6 +25,7 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.isNull;
@@ -116,17 +117,23 @@
public void testNotifySmsSentToEmergencyStateTracker(String destAddr, long messageId,
boolean isOverIms, boolean isLastSmsPart) {
- notifySmsSent(destAddr, messageId, isOverIms, isLastSmsPart, true/*success*/);
+ notifySmsSent(getSmsTracker(destAddr, messageId), isOverIms,
+ isLastSmsPart, true/*success*/);
}
public void testNotifySmsSentFailedToEmergencyStateTracker(String destAddr,
long messageId, boolean isOverIms) {
- notifySmsSent(destAddr, messageId, isOverIms, true/*isLastSmsPart*/, false/*success*/);
+ notifySmsSent(getSmsTracker(destAddr, messageId), isOverIms,
+ true/*isLastSmsPart*/, false/*success*/);
}
public void testNotifySmsReceivedViaImsToEmergencyStateTracker(String origAddr) {
notifySmsReceivedViaImsToEmergencyStateTracker(origAddr);
}
+
+ private SMSDispatcher.SmsTracker getSmsTracker(String destAddr, long messageId) {
+ return new SMSDispatcher.SmsTracker(destAddr, messageId);
+ }
}
/**
@@ -140,9 +147,9 @@
@Override
public void sendData(String callingPackage, int callingUser, String destAddr,
String scAddr, int destPort, byte[] data, PendingIntent sentIntent,
- PendingIntent deliveryIntent, boolean isForVvm) {
+ PendingIntent deliveryIntent, boolean isForVvm, long uniqueMessageId) {
super.sendData(callingPackage, callingUser, destAddr, scAddr, destPort,
- data, sentIntent, deliveryIntent, isForVvm);
+ data, sentIntent, deliveryIntent, isForVvm, uniqueMessageId);
}
@Override
@@ -167,9 +174,9 @@
@Override
public void sendData(String callingPackage, int callingUser, String destAddr, String scAddr,
int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent,
- boolean isForVvm) {
+ boolean isForVvm, long uniqueMessageId) {
super.sendData(callingPackage, callingUser, destAddr, scAddr, destPort,
- data, sentIntent, deliveryIntent, isForVvm);
+ data, sentIntent, deliveryIntent, isForVvm, uniqueMessageId);
}
@Override
@@ -491,7 +498,7 @@
verify(mEmergencySmsDsc).finishSelection();
verify(mImsSmsDispatcher).sendText(eq("911"), eq("2222"), eq("text"), eq(mSentIntent),
any(), any(), eq("test-app"), eq(mCallingUserId), eq(false),
- eq(0), eq(false), eq(10), eq(false), eq(1L), eq(false));
+ eq(0), eq(false), eq(10), eq(false), eq(1L), eq(false), anyLong());
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
assertEquals(0, holder.getPendingRequests().size());
@@ -542,7 +549,7 @@
verify(mImsSmsDispatcher).sendMultipartText(eq("911"), eq("2222"), eq(parts),
eq(sentIntents), eq(deliveryIntents), any(), eq("test-app"),
eq(mCallingUserId), eq(false), eq(0), eq(false),
- eq(10), eq(1L));
+ eq(10), eq(1L), anyLong());
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
assertEquals(0, holder.getPendingRequests().size());
@@ -741,7 +748,7 @@
verify(mImsSmsDispatcher).sendText(eq("1111"), eq("2222"), eq("text"), eq(mSentIntent),
any(), any(), eq("test-app"), eq(mCallingUserId),
- eq(false), eq(0), eq(false), eq(10), eq(false), eq(1L), eq(false));
+ eq(false), eq(0), eq(false), eq(10), eq(false), eq(1L), eq(false), anyLong());
}
@Test
@@ -782,7 +789,7 @@
verify(mImsSmsDispatcher).sendText(eq("911"), eq("2222"), eq("text"), eq(mSentIntent),
any(), any(), eq("test-app"), eq(0), eq(false), eq(0), eq(false), eq(10),
- eq(false), eq(1L), eq(false));
+ eq(false), eq(1L), eq(false), anyLong());
}
@Test
@@ -818,7 +825,7 @@
verify(mImsSmsDispatcher, times(2)).sendText(eq("1111"), eq("2222"),
eq("text"), eq(mSentIntent), any(), any(), eq("test-app"), eq(mCallingUserId),
eq(false), eq(0), eq(false), eq(10), eq(false), eq(1L),
- eq(false));
+ eq(false), anyLong());
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
assertEquals(0, holder.getPendingRequests().size());
@@ -839,7 +846,7 @@
// ImsSmsDispatcher handles this text directly.
verify(mImsSmsDispatcher).sendText(eq("1111"), eq("2222"), eq("text"),
eq(mSentIntent), any(), any(), eq("test-app"), eq(mCallingUserId), eq(false), eq(0),
- eq(false), eq(10), eq(false), eq(1L), eq(false));
+ eq(false), eq(10), eq(false), eq(1L), eq(false), anyLong());
}
@Test
@@ -903,7 +910,7 @@
verify(newSmsDsc).finishSelection();
verify(mImsSmsDispatcher, times(2)).sendText(eq("1111"), eq("2222"), eq("text"),
eq(mSentIntent), any(), any(), eq("test-app"), eq(mCallingUserId), eq(false), eq(0),
- eq(false), eq(10), eq(false), eq(1L), eq(false));
+ eq(false), eq(10), eq(false), eq(1L), eq(false), anyLong());
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
assertEquals(0, holder.getPendingRequests().size());
@@ -974,7 +981,7 @@
verify(newEmergencySmsDsc).finishSelection();
verify(mImsSmsDispatcher, times(2)).sendText(eq("911"), eq("2222"), eq("text"),
eq(mSentIntent), any(), any(), eq("test-app"), eq(0), eq(false), eq(0), eq(false),
- eq(10), eq(false), eq(1L), eq(false));
+ eq(10), eq(false), eq(1L), eq(false), anyLong());
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
assertEquals(0, holder.getPendingRequests().size());
@@ -1017,7 +1024,7 @@
verify(mImsSmsDispatcher).sendText(eq("1111"), eq("2222"), eq("text"), eq(mSentIntent),
any(), any(), eq("test-app"), eq(mCallingUserId), eq(false), eq(0),
- eq(false), eq(10), eq(false), eq(1L), eq(false));
+ eq(false), eq(10), eq(false), eq(1L), eq(false), anyLong());
}
@Test
@@ -1060,7 +1067,7 @@
verify(mImsSmsDispatcher).sendText(eq("911"), eq("2222"), eq("text"), eq(mSentIntent),
any(), any(), eq("test-app"), eq(mCallingUserId), eq(false), eq(0), eq(false),
- eq(10), eq(false), eq(1L), eq(false));
+ eq(10), eq(false), eq(1L), eq(false), anyLong());
}
private void switchImsSmsFormat(int phoneType) {
@@ -1079,7 +1086,8 @@
@Test
public void testSendSmsToDatagramDispatcher() {
- when(mSatelliteController.isInCarrierRoamingNbIotNtn()).thenReturn(true);
+ when(mSatelliteController.shouldSendSmsToDatagramDispatcher(any(Phone.class)))
+ .thenReturn(true);
mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
"test-app", mCallingUserId, false, 0, false, 10, false, 1L, false);
processAllMessages();
@@ -1219,13 +1227,13 @@
verify(mSmsDsc).finishSelection();
if (domain == NetworkRegistrationInfo.DOMAIN_PS) {
verify(mImsSmsDispatcher).sendData(eq("test-app"), eq(0), eq("1111"), eq("2222"),
- eq(8080), eq(data), eq(mSentIntent), any(), eq(false));
+ eq(8080), eq(data), eq(mSentIntent), any(), eq(false), anyLong());
} else if (isCdmaMo) {
verify(mCdmaSmsDispatcher).sendData(eq("test-app"), eq(0), eq("1111"), eq("2222"),
- eq(8080), eq(data), eq(mSentIntent), any(), eq(false));
+ eq(8080), eq(data), eq(mSentIntent), any(), eq(false), anyLong());
} else {
verify(mGsmSmsDispatcher).sendData(eq("test-app"), eq(0), eq("1111"), eq("2222"),
- eq(8080), eq(data), eq(mSentIntent), any(), eq(false));
+ eq(8080), eq(data), eq(mSentIntent), any(), eq(false), anyLong());
}
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
@@ -1256,15 +1264,15 @@
if (domain == NetworkRegistrationInfo.DOMAIN_PS) {
verify(mImsSmsDispatcher).sendText(eq("1111"), eq("2222"), eq("text"), eq(mSentIntent),
any(), any(), eq("test-app"), eq(0), eq(false), eq(0), eq(false), eq(10),
- eq(false), eq(1L), eq(false));
+ eq(false), eq(1L), eq(false), anyLong());
} else if (isCdmaMo) {
verify(mCdmaSmsDispatcher).sendText(eq("1111"), eq("2222"), eq("text"), eq(mSentIntent),
any(), any(), eq("test-app"), eq(0), eq(false), eq(0), eq(false), eq(10),
- eq(false), eq(1L), eq(false));
+ eq(false), eq(1L), eq(false), anyLong());
} else {
verify(mGsmSmsDispatcher).sendText(eq("1111"), eq("2222"), eq("text"), eq(mSentIntent),
any(), any(), eq("test-app"), eq(0), eq(false), eq(0), eq(false), eq(10),
- eq(false), eq(1L), eq(false));
+ eq(false), eq(1L), eq(false), anyLong());
}
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
@@ -1298,16 +1306,16 @@
if (domain == NetworkRegistrationInfo.DOMAIN_PS) {
verify(mImsSmsDispatcher).sendMultipartText(eq("1111"), eq("2222"), eq(parts),
eq(sentIntents), eq(deliveryIntents), any(), eq("test-app"), eq(mCallingUserId),
- eq(false), eq(0), eq(false), eq(10), eq(1L));
+ eq(false), eq(0), eq(false), eq(10), eq(1L), anyLong());
} else if (isCdmaMo) {
verify(mCdmaSmsDispatcher).sendMultipartText(eq("1111"), eq("2222"), eq(parts),
eq(sentIntents), eq(deliveryIntents), any(), eq("test-app"), eq(mCallingUserId),
eq(false), eq(0),
- eq(false), eq(10), eq(1L));
+ eq(false), eq(10), eq(1L), anyLong());
} else {
verify(mGsmSmsDispatcher).sendMultipartText(eq("1111"), eq("2222"), eq(parts),
eq(sentIntents), eq(deliveryIntents), any(), eq("test-app"), eq(mCallingUserId),
- eq(false), eq(0), eq(false), eq(10), eq(1L));
+ eq(false), eq(0), eq(false), eq(10), eq(1L), anyLong());
}
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
@@ -1384,6 +1392,6 @@
SmsDispatchersController.PendingRequest.TYPE_TEXT, null, "test-app",
mCallingUserId, "1111", "2222", asArrayList(mSentIntent), asArrayList(null),
false, null, 0, asArrayList("text"), null,
- false, 0, false, 10, 100L, false);
+ false, 0, false, 10, 100L, false, false);
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java
index dc1ee63..1846bae 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java
@@ -16,13 +16,17 @@
package com.android.internal.telephony;
-import android.telephony.TelephonyManager;
-import android.test.AndroidTestCase;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
-import androidx.test.filters.SmallTest;
+import android.telephony.TelephonyManager;
import com.android.telephony.Rlog;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
/**
* Test cases to verify selection of the optimal 7 bit encoding tables
* (for all combinations of enabled national language tables) for messages
@@ -33,7 +37,7 @@
* Tests both encoding variations: unsupported characters mapped to space,
* and unsupported characters force entire message to UCS-2.
*/
-public class SmsMessageBodyTest extends AndroidTestCase {
+public class SmsMessageBodyTest extends TelephonyTest {
private static final String TAG = "SmsMessageBodyTest";
// ASCII chars in the GSM 7 bit default alphabet
@@ -250,7 +254,12 @@
*/
private static final int UDH_SEPTET_COST_CONCATENATED_MESSAGE = 6;
- @SmallTest
+ @Before
+ public void setUp() {
+ TelephonyManager.setupISmsForTest(Mockito.mock(ISms.class));
+ }
+
+ @Test
public void testCalcLengthAscii() throws Exception {
StringBuilder sb = new StringBuilder(320);
int[] values = {0, 0, 0, SmsConstants.ENCODING_7BIT, 0, 0};
@@ -282,7 +291,7 @@
}
}
- @SmallTest
+ @Test
public void testCalcLengthUnicode() throws Exception {
StringBuilder sb = new StringBuilder(160);
int[] values = {0, 0, 0, SmsConstants.ENCODING_16BIT, 0, 0};
@@ -482,7 +491,7 @@
}
}
- //@LargeTest
+ //@Test
/*public void testCalcLengthMixed7bit() throws Exception {
StringBuilder sb = new StringBuilder(320);
CounterHelper ch = new CounterHelper();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsUsageMonitorShortCodeTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsUsageMonitorShortCodeTest.java
index 3b637c9..1e1e43f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsUsageMonitorShortCodeTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsUsageMonitorShortCodeTest.java
@@ -26,6 +26,8 @@
import android.os.Looper;
+import com.android.internal.telephony.flags.FeatureFlagsImpl;
+
import org.junit.Ignore;
/**
@@ -465,7 +467,8 @@
if (Looper.myLooper() == null) {
Looper.prepare();
}
- SmsUsageMonitor monitor = new SmsUsageMonitor(TestApplication.getAppContext());
+ SmsUsageMonitor monitor = new SmsUsageMonitor(TestApplication.getAppContext(),
+ new FeatureFlagsImpl());
for (ShortCodeTest test : sShortCodeTests) {
assertEquals("country: " + test.countryIso + " number: " + test.address,
test.category, monitor.checkDestination(test.address, test.countryIso));
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java
index 1e2b8ce..99ece85 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java
@@ -48,7 +48,6 @@
@Before
public void setUp() throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE);
mSetFlagsRule.enableFlags(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG);
mSubscriptionInfoUT = new SubscriptionInfo.Builder()
.setId(1)
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyCountryDetectorTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyCountryDetectorTest.java
index 9b3777b..5db1206 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyCountryDetectorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyCountryDetectorTest.java
@@ -112,26 +112,27 @@
when(mSST2.getLocaleTracker()).thenReturn(mMockLocaleTracker2);
when(mMockLocaleTracker2.getCurrentCountry()).thenReturn("");
- when(mConnectivityManager.getActiveNetwork()).thenReturn(mMockNetwork);
mNetworkCapabilities = new NetworkCapabilities();
mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, true);
- when(mConnectivityManager.getNetworkCapabilities(any(Network.class)))
- .thenReturn(mNetworkCapabilities);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED, true);
when(mLocationManager.getProviders(true)).thenReturn(Arrays.asList("TEST_PROVIDER"));
when(mMockFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
mCountryDetectorUT = new TestTelephonyCountryDetector(
mLooper, mContext, mLocationManager, mConnectivityManager, mMockFeatureFlags);
+ verify(mConnectivityManager).registerNetworkCallback(
+ any(NetworkRequest.class), mNetworkCallbackCaptor.capture());
+ mNetworkCallbackCaptor.getValue().onAvailable(mMockNetwork);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, mNetworkCapabilities);
+ mTestableLooper.processAllMessages();
if (isGeoCoderImplemented()) {
verify(mLocationManager).requestLocationUpdates(anyString(), anyLong(), anyFloat(),
mLocationListenerCaptor.capture());
verify(mLocationManager).getProviders(true);
verify(mLocationManager).getLastKnownLocation(anyString());
}
- verify(mConnectivityManager).registerNetworkCallback(
- any(NetworkRequest.class), mNetworkCallbackCaptor.capture());
}
@After
@@ -285,7 +286,7 @@
// Wi-fi is not available
clearInvocations(mLocationManager);
- mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, false);
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
mTestableLooper.processAllMessages();
verify(mLocationManager, never()).removeUpdates(any(LocationListener.class));
@@ -294,6 +295,9 @@
clearInvocations(mLocationManager);
mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
mNetworkCallbackCaptor.getValue().onAvailable(mMockNetwork);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED, true);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, mNetworkCapabilities);
mTestableLooper.processAllMessages();
// Location updates were already requested
verify(mLocationManager, never()).requestLocationUpdates(anyString(), anyLong(), anyFloat(),
@@ -301,7 +305,10 @@
// Make Wi-fi not available and reset the quota
clearInvocations(mLocationManager);
- mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, false);
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED, false);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, mNetworkCapabilities);
mTestableLooper.moveTimeForward(
TestTelephonyCountryDetector.getLocationUpdateRequestQuotaResetTimeoutMillis());
mTestableLooper.processAllMessages();
@@ -311,6 +318,9 @@
clearInvocations(mLocationManager);
mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
mNetworkCallbackCaptor.getValue().onAvailable(mMockNetwork);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED, true);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, mNetworkCapabilities);
mTestableLooper.processAllMessages();
verify(mLocationManager).requestLocationUpdates(anyString(), anyLong(), anyFloat(),
any(LocationListener.class));
@@ -324,16 +334,20 @@
verify(mLocationManager, never()).requestLocationUpdates(anyString(), anyLong(), anyFloat(),
any(LocationListener.class));
- // Wi-fi becomes not available
+ // Wi-fi lost
clearInvocations(mLocationManager);
- mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, false);
- mNetworkCallbackCaptor.getValue().onUnavailable();
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
mTestableLooper.processAllMessages();
verify(mLocationManager).removeUpdates(any(LocationListener.class));
}
@Test
public void testRegisterUnregisterForWifiConnectivityStateChanged() {
+ // Set Wi-Fi unavailable.
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
+ mTestableLooper.processAllMessages();
+
WifiConnectivityStateChangedListener listener = new WifiConnectivityStateChangedListener(
mLooper);
@@ -344,19 +358,63 @@
clearInvocations(mLocationManager);
mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
mNetworkCallbackCaptor.getValue().onAvailable(mMockNetwork);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED, true);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, mNetworkCapabilities);
mTestableLooper.processAllMessages();
assertTrue(listener.getIsWifiConnected());
- // Wi-fi becomes not available
+ // Wi-fi lost
clearInvocations(mLocationManager);
- mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, false);
- mNetworkCallbackCaptor.getValue().onUnavailable();
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
mTestableLooper.processAllMessages();
assertFalse(listener.getIsWifiConnected());
mCountryDetectorUT.unregisterForWifiConnectivityStateChanged(listener);
}
+ @Test
+ public void testReflectWifiConnectedStatusChanged() {
+ // 1. Wi-Fi is turned off, network capability is not available.
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
+ mNetworkCapabilities = new NetworkCapabilities();
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, false);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED, false);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, mNetworkCapabilities);
+ mTestableLooper.processAllMessages();
+ assertFalse(mCountryDetectorUT.isWifiNetworkConnected());
+
+ // 2. Wi-Fi is turned on, but network capability has not been updated.
+ mNetworkCallbackCaptor.getValue().onAvailable(mMockNetwork);
+ mTestableLooper.processAllMessages();
+ assertFalse(mCountryDetectorUT.isWifiNetworkConnected());
+
+ // 3. Network capability has been updated, not some of them still false.
+ mNetworkCapabilities = new NetworkCapabilities();
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED, false);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, mNetworkCapabilities);
+ mTestableLooper.processAllMessages();
+ assertFalse(mCountryDetectorUT.isWifiNetworkConnected());
+
+ // 4. Network capability has been updated to validated.
+ mNetworkCapabilities = new NetworkCapabilities();
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED, true);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, mNetworkCapabilities);
+ mTestableLooper.processAllMessages();
+ assertTrue(mCountryDetectorUT.isWifiNetworkConnected());
+
+ // 5. Wi-Fi is turned off.
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
+ mTestableLooper.processAllMessages();
+ assertFalse(mCountryDetectorUT.isWifiNetworkConnected());
+ }
+
private static boolean isGeoCoderImplemented() {
return Geocoder.isPresent();
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
index a645439..2ff38b2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
@@ -42,6 +42,7 @@
import android.content.pm.UserInfo;
import android.net.LinkProperties;
import android.os.Build;
+import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -68,6 +69,7 @@
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
+import android.telephony.satellite.NtnSignalStrength;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.text.TextUtils;
@@ -86,6 +88,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -103,6 +106,7 @@
// Mocked classes
private SubscriptionInfo mMockSubInfo;
private TelephonyRegistry.ConfigurationProvider mMockConfigurationProvider;
+ private IBinder mMockIBinder;
private TelephonyCallbackWrapper mTelephonyCallback;
private List<LinkCapacityEstimate> mLinkCapacityEstimateList;
@@ -123,8 +127,13 @@
private CellIdentity mCellIdentityForRegiFail;
private int mRegistrationFailReason;
private Set<Integer> mSimultaneousCallingSubscriptions;
+ private int mCallbackModeStopReason = TelephonyManager.STOP_REASON_UNKNOWN;
+ private long mCallbackModeDurationMillis;
private boolean mCarrierRoamingNtnMode;
private boolean mCarrierRoamingNtnEligible;
+ private List<Integer> mCarrierRoamingNtnAvailableServices;
+ private NtnSignalStrength mCarrierRoamingNtnSignalStrength;
+ private boolean mIsSatelliteEnabled;
// All events contribute to TelephonyRegistry#isPhoneStatePermissionRequired
private static final Set<Integer> READ_PHONE_STATE_EVENTS;
@@ -201,6 +210,7 @@
TelephonyCallback.RegistrationFailedListener,
TelephonyCallback.DataActivityListener,
TelephonyCallback.SimultaneousCellularCallingSupportListener,
+ TelephonyCallback.EmergencyCallbackModeListener,
TelephonyCallback.CarrierRoamingNtnModeListener {
// This class isn't mockable to get invocation counts because the IBinder is null and
// crashes the TelephonyRegistry. Make a cheesy verify(times()) alternative.
@@ -298,6 +308,27 @@
}
@Override
+ public void onCallbackModeStarted(@TelephonyManager.EmergencyCallbackModeType int type,
+ @NonNull Duration timerDuration, int subId) {
+ invocationCount.incrementAndGet();
+ mCallbackModeDurationMillis = timerDuration.toMillis();
+ }
+
+ @Override
+ public void onCallbackModeRestarted(@TelephonyManager.EmergencyCallbackModeType int type,
+ @NonNull Duration timerDuration, int subId) {
+ invocationCount.incrementAndGet();
+ mCallbackModeDurationMillis = timerDuration.toMillis();
+ }
+
+ @Override
+ public void onCallbackModeStopped(@TelephonyManager.EmergencyCallbackModeType int type,
+ @TelephonyManager.EmergencyCallbackModeStopReason int reason, int subId) {
+ invocationCount.incrementAndGet();
+ mCallbackModeStopReason = reason;
+ }
+
+ @Override
public void onCarrierRoamingNtnModeChanged(boolean active) {
invocationCount.incrementAndGet();
mCarrierRoamingNtnMode = active;
@@ -308,6 +339,30 @@
invocationCount.incrementAndGet();
mCarrierRoamingNtnEligible = eligible;
}
+
+ @Override
+ public void onCarrierRoamingNtnAvailableServicesChanged(List<Integer> services) {
+ invocationCount.incrementAndGet();
+ mCarrierRoamingNtnAvailableServices = services;
+ }
+
+ @Override
+ public void onCarrierRoamingNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength) {
+ invocationCount.incrementAndGet();
+ mCarrierRoamingNtnSignalStrength = ntnSignalStrength;
+ }
+ }
+
+ public class MySatelliteStateChangeListener implements ISatelliteStateChangeListener {
+ @Override
+ public void onSatelliteEnabledStateChanged(boolean isEnabled) throws RemoteException {
+ mIsSatelliteEnabled = isEnabled;
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return mMockIBinder;
+ }
}
private void addTelephonyRegistryService() {
@@ -322,6 +377,7 @@
super.setUp(getClass().getSimpleName());
mMockSubInfo = mock(SubscriptionInfo.class);
mMockConfigurationProvider = mock(TelephonyRegistry.ConfigurationProvider.class);
+ mMockIBinder = mock(IBinder.class);
when(mMockConfigurationProvider.getRegistrationLimit()).thenReturn(-1);
when(mMockConfigurationProvider.isRegistrationLimitEnabledInPlatformCompat(anyInt()))
.thenReturn(false);
@@ -349,6 +405,7 @@
processAllMessages();
assertEquals(mTelephonyRegistry.asBinder(),
ServiceManager.getService("telephony.registry"));
+ doReturn(new int[]{1}).when(mSubscriptionManager).getActiveSubscriptionIdList();
}
@After
@@ -981,6 +1038,8 @@
mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.TIRAMISU;
doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfo(anyString(), anyInt());
+ doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfoAsUser(
+ anyString(), anyInt(), any(UserHandle.class));
mContextFixture.addCallingOrSelfPermission("");
mContextFixture.addCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE);
mContextFixture.addCallingOrSelfPermission(
@@ -1077,6 +1136,8 @@
mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.TIRAMISU;
doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfo(anyString(), anyInt());
+ doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfoAsUser(
+ anyString(), anyInt(), any(UserHandle.class));
mContextFixture.addCallingOrSelfPermission("");
mContextFixture.addCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE);
mContextFixture.addCallingOrSelfPermission(
@@ -1589,6 +1650,57 @@
}
@Test
+ @EnableFlags(Flags.FLAG_EMERGENCY_CALLBACK_MODE_NOTIFICATION)
+ public void testNotifyCallbackModeStarted() {
+ final long durationMillis = 1000;
+ int[] events = {TelephonyCallback.EVENT_EMERGENCY_CALLBACK_MODE_CHANGED};
+
+ mTelephonyRegistry.listenWithEventList(false, false, 1/*subId*/,
+ mContext.getOpPackageName(), mContext.getAttributionTag(),
+ mTelephonyCallback.callback, events, true);
+ mTelephonyRegistry.notifyCallbackModeStarted(0/*phoneId*/, 1/*subId*/,
+ TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL, durationMillis);
+ processAllMessages();
+
+ assertEquals(1, mTelephonyCallback.invocationCount.get());
+ assertEquals(durationMillis, mCallbackModeDurationMillis);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_EMERGENCY_CALLBACK_MODE_NOTIFICATION)
+ public void testNotifyCallbackModeReStarted() {
+ final long durationMillis = 1000;
+ int[] events = {TelephonyCallback.EVENT_EMERGENCY_CALLBACK_MODE_CHANGED};
+
+ mTelephonyRegistry.listenWithEventList(false, false, 1/*subId*/,
+ mContext.getOpPackageName(), mContext.getAttributionTag(),
+ mTelephonyCallback.callback, events, true);
+ mTelephonyRegistry.notifyCallbackModeRestarted(0/*phoneId*/, 1/*subId*/,
+ TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL, durationMillis);
+ processAllMessages();
+
+ assertEquals(1, mTelephonyCallback.invocationCount.get());
+ assertEquals(durationMillis, mCallbackModeDurationMillis);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_EMERGENCY_CALLBACK_MODE_NOTIFICATION)
+ public void testNotifyCallbackModeStopped() {
+ final int reason = TelephonyManager.STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED;
+ int[] events = {TelephonyCallback.EVENT_EMERGENCY_CALLBACK_MODE_CHANGED};
+
+ mTelephonyRegistry.listenWithEventList(false, false, 1/*subId*/,
+ mContext.getOpPackageName(), mContext.getAttributionTag(),
+ mTelephonyCallback.callback, events, true);
+ mTelephonyRegistry.notifyCallbackModeStopped(0/*phoneId*/, 1/*subId*/,
+ TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL, reason);
+ processAllMessages();
+
+ assertEquals(1, mTelephonyCallback.invocationCount.get());
+ assertEquals(reason, mCallbackModeStopReason);
+ }
+
+ @Test
public void testNotifyCarrierRoamingNtnModeChanged() {
int subId = INVALID_SUBSCRIPTION_ID;
doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
@@ -1618,4 +1730,112 @@
processAllMessages();
assertTrue(mCarrierRoamingNtnEligible);
}
+
+ @Test
+ @EnableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ public void testNotifyCarrierRoamingNtnAvailableServicesChanged() {
+ int subId = INVALID_SUBSCRIPTION_ID;
+ doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
+ doReturn(0/*slotIndex*/).when(mMockSubInfo).getSimSlotIndex();
+ int[] events = {TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_AVAILABLE_SERVICES_CHANGED};
+
+ mTelephonyRegistry.listenWithEventList(false, false, subId, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), mTelephonyCallback.callback, events, true);
+
+ int[] services = {3, 6};
+ mTelephonyRegistry.notifyCarrierRoamingNtnAvailableServicesChanged(subId, services);
+ processAllMessages();
+ int[] carrierServices = mCarrierRoamingNtnAvailableServices.stream()
+ .mapToInt(Integer::intValue).toArray();
+ assertTrue(Arrays.equals(carrierServices, services));
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ public void testNotifyCarrierRoamingNtnSignalStrengthChanged() {
+ int subId = INVALID_SUBSCRIPTION_ID;
+ doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
+ doReturn(0/*slotIndex*/).when(mMockSubInfo).getSimSlotIndex();
+ int[] events = {TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_SIGNAL_STRENGTH_CHANGED};
+
+ mTelephonyRegistry.listenWithEventList(false, false, subId, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), mTelephonyCallback.callback, events, true);
+
+ mTelephonyRegistry.notifyCarrierRoamingNtnSignalStrengthChanged(subId,
+ new NtnSignalStrength(NtnSignalStrength.NTN_SIGNAL_STRENGTH_GOOD));
+ processAllMessages();
+ assertEquals(mCarrierRoamingNtnSignalStrength.getLevel(),
+ NtnSignalStrength.NTN_SIGNAL_STRENGTH_GOOD);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_SATELLITE_STATE_CHANGE_LISTENER)
+ public void testNotifySatelliteStateChanged_onRegistration_getNotified() {
+ MySatelliteStateChangeListener listener = new MySatelliteStateChangeListener();
+ // Set initial satellite enabled state to true
+ mTelephonyRegistry.notifySatelliteStateChanged(true);
+
+ try {
+ // Start monitoring
+ mTelephonyRegistry.addSatelliteStateChangeListener(listener,
+ mContext.getOpPackageName(), mContext.getAttributionTag());
+ processAllMessages();
+
+ // verify latest state is immediately available on registration
+ assertTrue(mIsSatelliteEnabled);
+ } finally {
+ // Clean up
+ mTelephonyRegistry.removeSatelliteStateChangeListener(listener,
+ mContext.getOpPackageName());
+ }
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_SATELLITE_STATE_CHANGE_LISTENER)
+ public void testNotifySatelliteStateChanged_duringRegistration_getNotified() {
+ MySatelliteStateChangeListener listener = new MySatelliteStateChangeListener();
+ // Set initial satellite enabled state to true
+ mTelephonyRegistry.notifySatelliteStateChanged(true);
+
+ try {
+ // Start monitoring
+ mTelephonyRegistry.addSatelliteStateChangeListener(listener,
+ mContext.getOpPackageName(), mContext.getAttributionTag());
+
+ // Satellite enabled state changed
+ mTelephonyRegistry.notifySatelliteStateChanged(false);
+ processAllMessages();
+ // We can receive the new state
+ assertFalse(mIsSatelliteEnabled);
+ } finally {
+ // Clean up
+ mTelephonyRegistry.removeSatelliteStateChangeListener(listener,
+ mContext.getOpPackageName());
+ }
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_SATELLITE_STATE_CHANGE_LISTENER)
+ public void testNotifySatelliteStateChanged_removeRegistration_notNotified() {
+ MySatelliteStateChangeListener listener = new MySatelliteStateChangeListener();
+ // Set initial satellite enabled state to true
+ mTelephonyRegistry.notifySatelliteStateChanged(true);
+
+ try {
+ // Start monitoring
+ mTelephonyRegistry.addSatelliteStateChangeListener(listener,
+ mContext.getOpPackageName(), mContext.getAttributionTag());
+ mTelephonyRegistry.notifySatelliteStateChanged(false);
+ } finally {
+ // Stop monitoring from now on
+ mTelephonyRegistry.removeSatelliteStateChangeListener(listener,
+ mContext.getOpPackageName());
+ }
+
+ // Satellite enabled state changed again
+ mTelephonyRegistry.notifySatelliteStateChanged(true);
+ processAllMessages();
+ // We should not receive the new state change after monitoring end
+ assertFalse(mIsSatelliteEnabled);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index d80c9a2..88eea32 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -747,6 +747,8 @@
doReturn(mDataRetryManager).when(mDataNetworkController).getDataRetryManager();
doReturn(mCarrierPrivilegesTracker).when(mPhone).getCarrierPrivilegesTracker();
doReturn(0).when(mPhone).getPhoneId();
+ doReturn(true).when(mPhone).hasCalling();
+ doReturn(true).when(mPhone2).hasCalling();
//mUiccController
doReturn(mUiccCardApplication3gpp).when(mUiccController).getUiccCardApplication(anyInt(),
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 2f3fabf..ec7ad3c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony.domainselection;
import static android.telephony.AccessNetworkConstants.AccessNetworkType.EUTRAN;
+import static android.telephony.AccessNetworkConstants.AccessNetworkType.UNKNOWN;
import static android.telephony.AccessNetworkConstants.AccessNetworkType.UTRAN;
import static android.telephony.DomainSelectionService.SCAN_TYPE_FULL_SERVICE;
import static android.telephony.DomainSelectionService.SCAN_TYPE_NO_PREFERENCE;
@@ -516,6 +517,131 @@
@Test
@SmallTest
+ public void testWwanSelectorCallbackOnRequestEmergencyNetworkScanAndErrorForScanTypeFull()
+ throws Exception {
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDomainSelectionController);
+
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+
+ assertNotNull(transportCallback);
+
+ DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
+ mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
+ false, 0, TELECOM_CALL_ID1, null, null, null);
+
+ mDsc.selectDomain(attr);
+
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
+ transportCallback.onCreated(domainSelector);
+
+ IWwanSelectorCallback wwanCallback = onWwanSelected(transportCallback);
+
+ assertNotNull(wwanCallback);
+
+ int[] preferredNetworks = new int[] { EUTRAN, UTRAN };
+ int scanType = SCAN_TYPE_FULL_SERVICE;
+ IWwanSelectorResultCallback resultCallback =
+ Mockito.mock(IWwanSelectorResultCallback.class);
+
+ wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType,
+ false, resultCallback);
+ processAllMessages();
+
+ ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
+ ArgumentCaptor<Message> msgCaptor = ArgumentCaptor.forClass(Message.class);
+
+ verify(mPhone).registerForEmergencyNetworkScan(handlerCaptor.capture(), anyInt(), any());
+ verify(mCi).registerForModemReset(any(), anyInt(), any());
+ processAllMessages();
+
+ int[] expectedPreferredNetworks = new int[] { EUTRAN, UTRAN };
+
+ verify(mPhone).triggerEmergencyNetworkScan(eq(expectedPreferredNetworks),
+ eq(scanType), msgCaptor.capture());
+
+ Handler handler = handlerCaptor.getValue();
+ Message msg = msgCaptor.getValue();
+
+ assertNotNull(handler);
+ assertNotNull(msg);
+
+ CommandException commandException =
+ new CommandException(CommandException.Error.INTERNAL_ERR);
+ handler.sendMessage(handler.obtainMessage(msg.what,
+ new AsyncResult((Integer) scanType, null, commandException)));
+ processAllMessages();
+
+ EmergencyRegistrationResult regResult = new EmergencyRegistrationResult(UNKNOWN,
+ NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN,
+ NetworkRegistrationInfo.DOMAIN_UNKNOWN, false, false, 0, 0, "", "", "");
+ verify(resultCallback).onComplete(eq(regResult));
+ verify(mPhone, times(0)).cancelEmergencyNetworkScan(anyBoolean(), any());
+ }
+
+ @Test
+ @SmallTest
+ public void testWwanSelectorCallbackOnRequestEmergencyNetworkScanAndErrorForScanTypeNoPref()
+ throws Exception {
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDomainSelectionController);
+
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+
+ assertNotNull(transportCallback);
+
+ DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
+ mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
+ false, 0, TELECOM_CALL_ID1, null, null, null);
+
+ mDsc.selectDomain(attr);
+
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
+ transportCallback.onCreated(domainSelector);
+
+ IWwanSelectorCallback wwanCallback = onWwanSelected(transportCallback);
+
+ assertNotNull(wwanCallback);
+
+ int[] preferredNetworks = new int[] { EUTRAN, UTRAN };
+ int scanType = SCAN_TYPE_NO_PREFERENCE;
+ IWwanSelectorResultCallback resultCallback =
+ Mockito.mock(IWwanSelectorResultCallback.class);
+
+ wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType,
+ false, resultCallback);
+ processAllMessages();
+
+ ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
+ ArgumentCaptor<Message> msgCaptor = ArgumentCaptor.forClass(Message.class);
+
+ verify(mPhone).registerForEmergencyNetworkScan(handlerCaptor.capture(), anyInt(), any());
+ verify(mCi).registerForModemReset(any(), anyInt(), any());
+ processAllMessages();
+
+ int[] expectedPreferredNetworks = new int[] { EUTRAN, UTRAN };
+
+ verify(mPhone).triggerEmergencyNetworkScan(eq(expectedPreferredNetworks),
+ eq(scanType), msgCaptor.capture());
+
+ Handler handler = handlerCaptor.getValue();
+ Message msg = msgCaptor.getValue();
+
+ assertNotNull(handler);
+ assertNotNull(msg);
+
+ CommandException commandException =
+ new CommandException(CommandException.Error.INTERNAL_ERR);
+ handler.sendMessage(handler.obtainMessage(msg.what,
+ new AsyncResult((Integer) scanType, null, commandException)));
+ processAllMessages();
+
+ verify(resultCallback, times(0)).onComplete(any());
+ verify(mPhone, times(0)).cancelEmergencyNetworkScan(anyBoolean(), any());
+ }
+
+ @Test
+ @SmallTest
public void testModemResetOnRequestEmergencyNetworkDuringNetworkScan()
throws Exception {
mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
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 25e9715..32cca3c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
@@ -21,6 +21,8 @@
import static android.telephony.NetworkRegistrationInfo.DOMAIN_CS_PS;
import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_HOME;
+import static android.telephony.TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL;
+import static android.telephony.TelephonyManager.EMERGENCY_CALLBACK_MODE_SMS;
import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_CALLBACK;
import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_WLAN;
@@ -36,6 +38,7 @@
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.anyVararg;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
@@ -121,6 +124,7 @@
doReturn(TelephonyManager.SIM_STATE_READY)
.when(mTelephonyManagerProxy).getSimState(anyInt());
+ doReturn(true).when(mFeatureFlags).emergencyCallbackModeNotification();
}
@After
@@ -135,7 +139,7 @@
EmergencyStateTracker.getInstance();
});
- EmergencyStateTracker.make(mContext, true);
+ EmergencyStateTracker.make(mContext, true, mFeatureFlags);
assertNotNull(EmergencyStateTracker.getInstance());
}
@@ -143,7 +147,7 @@
@Test
@SmallTest
public void getInstance_returnsSameInstance() {
- EmergencyStateTracker.make(mContext, true);
+ EmergencyStateTracker.make(mContext, true, mFeatureFlags);
EmergencyStateTracker instance1 = EmergencyStateTracker.getInstance();
EmergencyStateTracker instance2 = EmergencyStateTracker.getInstance();
@@ -180,7 +184,7 @@
ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor
.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone),
- eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS), eq(false));
+ eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS));
// isOkToCall() should return true when IN_SERVICE state
assertFalse(callback.getValue()
.isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
@@ -239,7 +243,7 @@
ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor
.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone),
- eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS), eq(false));
+ eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS));
// onTimeout should return true when radion on
assertFalse(callback.getValue()
.isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
@@ -266,6 +270,7 @@
@Test
@SmallTest
public void startEmergencyCall_radioOff_turnOnRadioHangupCallTurnOffRadio() {
+ android.telecom.Connection testConnection = new android.telecom.Connection() {};
EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
true /* isSuplDdsSwitchRequiredForEmergencyCall */);
// Create test Phones and set radio off
@@ -281,16 +286,17 @@
.build();
doReturn(nri).when(ss).getNetworkRegistrationInfo(anyInt(), anyInt());
CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(testPhone,
- mTestConnection1, false);
+ testConnection, false);
// startEmergencyCall should trigger radio on
ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor
.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone),
- eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS), eq(false));
+ eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS));
// Hangup the call
- emergencyStateTracker.endCall(mTestConnection1);
+ testConnection.setDisconnected(null);
+ emergencyStateTracker.endCall(testConnection);
// onTimeout and isOkToCall should return true even in case radion is off
assertTrue(callback.getValue()
@@ -301,6 +307,7 @@
callback.getValue().onComplete(null, true);
assertFalse(future.isDone());
+ verify(testPhone).setRadioPower(true, false, false, true);
}
/**
@@ -323,7 +330,7 @@
ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor
.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone),
- eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS), eq(false));
+ eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS));
// Verify future completes with DisconnectCause.POWER_OFF if radio not ready
CompletableFuture<Void> unused = future.thenAccept((result) -> {
assertEquals((Integer) result, (Integer) DisconnectCause.POWER_OFF);
@@ -346,7 +353,7 @@
true /* isRadioOn */);
when(mSST.isRadioOn()).thenReturn(true);
// Satellite enabled
- when(mSatelliteController.isSatelliteEnabled()).thenReturn(true);
+ when(mSatelliteController.isSatelliteEnabledOrBeingEnabled()).thenReturn(true);
setConfigForDdsSwitch(testPhone, null,
CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY, "150");
@@ -359,11 +366,11 @@
ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor
.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone),
- eq(false), eq(0), eq(false));
+ eq(false), eq(0));
// isOkToCall() should return true once satellite modem is off
assertFalse(callback.getValue()
.isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, false));
- when(mSatelliteController.isSatelliteEnabled()).thenReturn(false);
+ when(mSatelliteController.isSatelliteEnabledOrBeingEnabled()).thenReturn(false);
assertTrue(callback.getValue()
.isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, false));
// Once radio on is complete, trigger delay dial
@@ -391,7 +398,7 @@
Phone testPhone = setupTestPhoneForEmergencyCall(false /* isRoaming */,
true /* isRadioOn */);
// Satellite enabled
- when(mSatelliteController.isSatelliteEnabled()).thenReturn(true);
+ when(mSatelliteController.isSatelliteEnabledOrBeingEnabled()).thenReturn(true);
CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(testPhone,
mTestConnection1, false);
@@ -400,7 +407,7 @@
ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor
.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone),
- eq(false), eq(0), eq(false));
+ eq(false), eq(0));
// Verify future completes with DisconnectCause.POWER_OFF if radio not ready
CompletableFuture<Void> unused = future.thenAccept((result) -> {
assertEquals((Integer) result, (Integer) DisconnectCause.SATELLITE_ENABLED);
@@ -428,7 +435,7 @@
// Radio already on so shouldn't trigger this
verify(mRadioOnHelper, never()).triggerRadioOnAndListen(any(), anyBoolean(), any(),
- anyBoolean(), eq(0), eq(false));
+ anyBoolean(), eq(0));
// Carrier supports control-plane fallback, so no DDS switch
verify(mPhoneSwitcher, never()).overrideDefaultDataForEmergency(anyInt(), anyInt(), any());
}
@@ -761,6 +768,8 @@
.getBooleanExtra(TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, true));
// Verify emergency callback mode set on modem
verify(testPhone).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any());
+ // Verify emergency callback mode started with the correct emergency type
+ verify(testPhone).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_CALL), anyLong());
}
/**
@@ -819,6 +828,9 @@
processAllFutureMessages();
+ // Verify emergency callback mode stopped with the correct emergency type and reason.
+ verify(testPhone).stopEmergencyCallbackMode(eq(EmergencyStateTracker.EMERGENCY_TYPE_CALL),
+ eq(TelephonyManager.STOP_REASON_TIMER_EXPIRED));
// Verify exitEmergencyMode() is called after timeout
verify(testPhone).exitEmergencyMode(any(Message.class));
assertFalse(emergencyStateTracker.isInEmergencyMode());
@@ -854,6 +866,9 @@
emergencyStateTracker.onCellularRadioPowerOffRequested();
+ // Verify emergency callback mode stopped with the correct emergency type and reason.
+ verify(testPhone).stopEmergencyCallbackMode(eq(EmergencyStateTracker.EMERGENCY_TYPE_CALL),
+ eq(TelephonyManager.STOP_REASON_UNKNOWN));
// Verify exitEmergencyMode() is called.
verify(testPhone).exitEmergencyMode(any(Message.class));
assertFalse(emergencyStateTracker.isInEcm());
@@ -1005,7 +1020,8 @@
assertTrue(emergencyStateTracker.isInEcm());
verify(phone0, times(1)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
verify(phone0, times(1)).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
-
+ verify(phone0, times(1)).startEmergencyCallbackMode(
+ eq(EMERGENCY_CALLBACK_MODE_CALL), anyLong());
// Second emergency call started.
CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(phone0,
mTestConnection2, false);
@@ -1013,6 +1029,8 @@
assertFalse(future.isDone());
verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
verify(phone0, times(1)).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
+ verify(phone0, times(1)).startEmergencyCallbackMode(
+ eq(EMERGENCY_CALLBACK_MODE_CALL), anyLong());
}
@Test
@@ -1087,6 +1105,10 @@
verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WLAN), any(Message.class));
verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
verify(phone0, never()).exitEmergencyMode(any(Message.class));
+ verify(phone0, times(2)).startEmergencyCallbackMode(
+ eq(EMERGENCY_CALLBACK_MODE_CALL), anyLong());
+ verify(phone0, never()).stopEmergencyCallbackMode(
+ eq(EMERGENCY_CALLBACK_MODE_CALL), anyInt());
}
@Test
@@ -1224,6 +1246,7 @@
verify(mCarrierConfigManager).getConfigForSubId(anyInt(),
eq(CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT));
verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
+ verify(phone0).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_SMS), anyLong());
assertTrue(emergencyStateTracker.isInEmergencyMode());
assertTrue(emergencyStateTracker.isInScbm());
}
@@ -1256,6 +1279,7 @@
verify(mCarrierConfigManager).getConfigForSubId(anyInt(),
eq(CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT));
verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
+ verify(phone0).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_SMS), anyLong());
assertTrue(emergencyStateTracker.isInEmergencyMode());
assertTrue(emergencyStateTracker.isInScbm());
}
@@ -1288,6 +1312,8 @@
verify(mCarrierConfigManager, times(2)).getConfigForSubId(anyInt(),
eq(CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT));
verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
+ verify(phone0).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_SMS), anyLong());
+ verify(phone0).restartEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_SMS), anyLong());
assertTrue(emergencyStateTracker.isInEmergencyMode());
assertTrue(emergencyStateTracker.isInScbm());
}
@@ -1413,6 +1439,7 @@
processAllMessages();
verify(phone0, times(2)).setEmergencyMode(anyInt(), any(Message.class));
+ verify(phone0).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_CALL), anyLong());
// Expect: DisconnectCause#NOT_DISCONNECTED.
assertEquals(future.getNow(DisconnectCause.ERROR_UNSPECIFIED),
Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
@@ -1473,6 +1500,8 @@
CompletableFuture<Integer> future = emergencyStateTracker.startEmergencySms(phone1,
TEST_SMS_ID_2, false);
+ verify(phone0).stopEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_SMS),
+ eq(TelephonyManager.STOP_REASON_EMERGENCY_SMS_SENT));
verify(phone0).exitEmergencyMode(any(Message.class));
// Waits for exiting emergency mode on other phone.
assertFalse(future.isDone());
@@ -1726,6 +1755,7 @@
assertFalse(emergencyStateTracker.isInEmergencyCall());
assertTrue(emergencyStateTracker.isInScbm());
verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
+ verify(phone0).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_SMS), anyLong());
}
@Test
@@ -2156,6 +2186,7 @@
processAllMessages();
verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
+ verify(phone0).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_CALL), anyLong());
assertTrue(emergencyStateTracker.isInEmergencyMode());
assertTrue(emergencyStateTracker.isInEcm());
assertFalse(emergencyStateTracker.isInEmergencyCall());
@@ -2212,6 +2243,8 @@
// Enter emergency callback mode and emergency mode changed by SMS end.
verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
+ verify(phone0).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_CALL), anyLong());
+ verify(phone0).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_SMS), anyLong());
assertTrue(emergencyStateTracker.isInEmergencyMode());
assertTrue(emergencyStateTracker.isInEcm());
assertFalse(emergencyStateTracker.isInEmergencyCall());
@@ -3168,7 +3201,7 @@
// Wait for the radio off for all phones
verify(mSST, times(2)).registerForVoiceRegStateOrRatChanged(any(), anyInt(), any());
verify(mRadioOnHelper, never()).triggerRadioOnAndListen(any(), anyBoolean(), any(),
- anyBoolean(), eq(0), eq(false));
+ anyBoolean(), eq(0));
}
/**
@@ -3379,7 +3412,7 @@
anyInt(), anyInt(), any());
return new EmergencyStateTracker(mContext, mTestableLooper.getLooper(),
isSuplDdsSwitchRequiredForEmergencyCall, mPhoneFactoryProxy, mPhoneSwitcherProxy,
- mTelephonyManagerProxy, mRadioOnHelper, TEST_ECM_EXIT_TIMEOUT_MS);
+ mTelephonyManagerProxy, mRadioOnHelper, TEST_ECM_EXIT_TIMEOUT_MS, mFeatureFlags);
}
private Phone setupTestPhoneForEmergencyCall(boolean isRoaming, boolean isRadioOn) {
@@ -3483,6 +3516,7 @@
eq(CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT));
if (!emergencyStateTracker.isInEcm() && !emergencyStateTracker.isInEmergencyCall()) {
verify(phone).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
+ verify(phone).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_SMS), anyLong());
}
assertTrue(emergencyStateTracker.isInEmergencyMode());
assertTrue(emergencyStateTracker.isInScbm());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/emergency/RadioOnStateListenerTest.java b/tests/telephonytests/src/com/android/internal/telephony/emergency/RadioOnStateListenerTest.java
index bb349a7..e9bff91 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/RadioOnStateListenerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/RadioOnStateListenerTest.java
@@ -104,7 +104,7 @@
*/
@Test
public void testRegisterForSatelliteCallback() {
- doReturn(true).when(mSatelliteController).isSatelliteEnabled();
+ doReturn(true).when(mSatelliteController).isSatelliteEnabledOrBeingEnabled();
mListener.waitForRadioOn(mMockPhone, mCallback, false, false, 0);
waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
@@ -229,7 +229,7 @@
@Test
public void testTimeout_RetryFailure_WithSatellite() {
- doReturn(true).when(mSatelliteController).isSatelliteEnabled();
+ doReturn(true).when(mSatelliteController).isSatelliteEnabledOrBeingEnabled();
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_POWER_OFF);
when(mMockPhone.getState()).thenReturn(PhoneConstants.State.IDLE);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
index 879118f..569785b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
@@ -1906,6 +1906,8 @@
when(mSubscriptionManager.canManageSubscription(subInfo, PACKAGE_NAME)).thenReturn(
hasPrivileges);
+ when(mSubscriptionManager.canManageSubscriptionAsUser(eq(subInfo), eq(PACKAGE_NAME), any()))
+ .thenReturn(hasPrivileges);
when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(
Collections.singletonList(subInfo));
}
@@ -1943,8 +1945,12 @@
.build();
when(mSubscriptionManager.canManageSubscription(subInfo1, PACKAGE_NAME)).thenReturn(
hasPrivileges);
+ when(mSubscriptionManager.canManageSubscriptionAsUser(eq(subInfo1), eq(PACKAGE_NAME),
+ any())).thenReturn(hasPrivileges);
when(mSubscriptionManager.canManageSubscription(subInfo2, PACKAGE_NAME)).thenReturn(
hasPrivileges);
+ when(mSubscriptionManager.canManageSubscriptionAsUser(eq(subInfo2), eq(PACKAGE_NAME),
+ any())).thenReturn(hasPrivileges);
ArrayList<SubscriptionInfo> subInfos = new ArrayList<>(Arrays.asList(subInfo1, subInfo2));
when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(subInfos);
}
@@ -1963,8 +1969,12 @@
.build();
when(mSubscriptionManager.canManageSubscription(subInfo1, PACKAGE_NAME)).thenReturn(
false);
+ when(mSubscriptionManager.canManageSubscriptionAsUser(eq(subInfo1), eq(PACKAGE_NAME),
+ any())).thenReturn(false);
when(mSubscriptionManager.canManageSubscription(subInfo2, PACKAGE_NAME)).thenReturn(
true);
+ when(mSubscriptionManager.canManageSubscriptionAsUser(eq(subInfo2), eq(PACKAGE_NAME),
+ any())).thenReturn(true);
ArrayList<SubscriptionInfo> subInfos = new ArrayList<>(Arrays.asList(subInfo1, subInfo2));
when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(subInfos);
}
@@ -1979,6 +1989,8 @@
.build();
when(mSubscriptionManager.canManageSubscription(subInfo, PACKAGE_NAME)).thenReturn(
hasPrivileges);
+ when(mSubscriptionManager.canManageSubscriptionAsUser(eq(subInfo), eq(PACKAGE_NAME), any()))
+ .thenReturn(hasPrivileges);
when(mSubscriptionManager.getAvailableSubscriptionInfoList()).thenReturn(
Collections.singletonList(subInfo));
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccSessionTest.java b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccSessionTest.java
index f91088c..6e0d383 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccSessionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccSessionTest.java
@@ -103,6 +103,7 @@
private EuiccSession mEuiccSession;
@Mock private ApduSender mApduSender;
+ @Mock private ApduSender mApduSender2;
@Before
public void setUp() throws Exception {
@@ -114,6 +115,7 @@
public void startOneSession_featureDisabled_noop() throws Exception {
mEuiccSession.startSession(SESSION_ID_1);
mEuiccSession.noteChannelOpen(mApduSender);
+ mEuiccSession.noteChannelOpen(mApduSender2);
assertThat(mEuiccSession.hasSession()).isFalse();
@@ -121,6 +123,7 @@
assertThat(mEuiccSession.hasSession()).isFalse();
verify(mApduSender, never()).closeAnyOpenChannel();
+ verify(mApduSender2, never()).closeAnyOpenChannel();
}
@Test
@@ -128,6 +131,7 @@
public void startOneSession_endSession_hasSession() throws Exception {
mEuiccSession.startSession(SESSION_ID_1);
mEuiccSession.noteChannelOpen(mApduSender);
+ mEuiccSession.noteChannelOpen(mApduSender2);
assertThat(mEuiccSession.hasSession()).isTrue();
@@ -140,6 +144,7 @@
assertThat(mEuiccSession.hasSession()).isFalse();
verify(mApduSender).closeAnyOpenChannel();
+ verify(mApduSender2).closeAnyOpenChannel();
}
@Test
@@ -164,7 +169,24 @@
@Test
@EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
- public void noteChannelOpen_noSession_noop() throws Exception {
+ public void startTwoSessions_endAllSessions_hasSession() throws Exception {
+ mEuiccSession.startSession(SESSION_ID_1);
+ mEuiccSession.noteChannelOpen(mApduSender);
+ mEuiccSession.startSession(SESSION_ID_2);
+ mEuiccSession.noteChannelOpen(mApduSender2);
+
+ assertThat(mEuiccSession.hasSession()).isTrue();
+
+ mEuiccSession.endAllSessions();
+
+ assertThat(mEuiccSession.hasSession()).isFalse();
+ verify(mApduSender).closeAnyOpenChannel();
+ verify(mApduSender2).closeAnyOpenChannel();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
+ public void noteChannelOpen_noSession_endSession_noop() throws Exception {
// noteChannelOpen called without a session started
mEuiccSession.noteChannelOpen(mApduSender);
@@ -175,4 +197,18 @@
assertThat(mEuiccSession.hasSession()).isFalse();
verify(mApduSender, never()).closeAnyOpenChannel();
}
+
+ @Test
+ @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
+ public void endAllSessions_noSession_endAllSessions_noOp() throws Exception {
+ // noteChannelOpen called without a session started
+ mEuiccSession.noteChannelOpen(mApduSender);
+
+ assertThat(mEuiccSession.hasSession()).isFalse();
+
+ mEuiccSession.endAllSessions();
+
+ assertThat(mEuiccSession.hasSession()).isFalse();
+ verify(mApduSender, never()).closeAnyOpenChannel();
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
index 8a10fde..639a2a3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
@@ -313,7 +313,7 @@
// send SMS and check sentIntent
mReceivedTestIntent = false;
mGsmSmsDispatcher.sendMultipartText("+123" /*destAddr*/, "222" /*scAddr*/, parts,
- sentIntents, null, null, null, mCallingUserId, false, -1, false, -1, 0L);
+ sentIntents, null, null, null, mCallingUserId, false, -1, false, -1, 0L, 0L);
waitForMs(500);
synchronized (mLock) {
@@ -456,7 +456,7 @@
mGsmSmsDispatcher.sendMultipartText("6501002000" /*destAddr*/, "222" /*scAddr*/, parts,
withSentIntents ? sentIntents : null, null, null, null, mCallingUserId,
- false, -1, false, -1, 0L);
+ false, -1, false, -1, 0L, 0L);
}
@Test
@@ -549,7 +549,7 @@
messageRef += parts.size();
}
mGsmSmsDispatcher.sendMultipartText("6501002000" /*destAddr*/, "222" /*scAddr*/, parts,
- null, null, null, null, mCallingUserId, false, -1, false, -1, 0L);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, 0L, 0L);
waitForMs(150);
ArgumentCaptor<String> pduCaptor = ArgumentCaptor.forClass(String.class);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
index 4abf33f..130fba8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
@@ -27,6 +27,7 @@
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -46,6 +47,7 @@
import android.os.Looper;
import android.os.PersistableBundle;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.os.UserManager;
import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyManager;
@@ -69,8 +71,10 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.stubbing.Answer;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -95,13 +99,14 @@
"TestCarrier2Pkg", "Carrier2ImsService");
private static final int NUM_MAX_SLOTS = 2;
- private static final String TAG = ImsResolverTest.class.getSimpleName();
+ private static final UserHandle TEST_USER_HANDLE = UserHandle.of(Integer.MAX_VALUE);
// Mocked classes
Context mMockContext;
PackageManager mMockPM;
ImsResolver.SubscriptionManagerProxy mTestSubscriptionManagerProxy;
ImsResolver.TelephonyManagerProxy mTestTelephonyManagerProxy;
+ ImsResolver.ActivityManagerProxy mTestActivityManagerProxy;
CarrierConfigManager mMockCarrierConfigManager;
UserManager mMockUserManager;
ImsResolver.ImsDynamicQueryManagerFactory mMockQueryManagerFactory;
@@ -112,6 +117,7 @@
private BroadcastReceiver mTestPackageBroadcastReceiver;
private BroadcastReceiver mTestCarrierConfigReceiver;
private BroadcastReceiver mTestBootCompleteReceiver;
+ private BroadcastReceiver mTestUserChangedReceiver;
private ImsServiceFeatureQueryManager.Listener mDynamicQueryListener;
private PersistableBundle[] mCarrierConfigs;
private FeatureFlags mFeatureFlags;
@@ -124,12 +130,14 @@
mMockPM = mock(PackageManager.class);
mTestSubscriptionManagerProxy = mock(ImsResolver.SubscriptionManagerProxy.class);
mTestTelephonyManagerProxy = mock(ImsResolver.TelephonyManagerProxy.class);
+ mTestActivityManagerProxy = mock(ImsResolver.ActivityManagerProxy.class);
mMockCarrierConfigManager = mock(CarrierConfigManager.class);
mMockUserManager = mock(UserManager.class);
mMockQueryManagerFactory = mock(ImsResolver.ImsDynamicQueryManagerFactory.class);
mMockQueryManager = mock(ImsServiceFeatureQueryManager.class);
mMockRepo = mock(ImsFeatureBinderRepository.class);
mFeatureFlags = mock(FeatureFlags.class);
+ when(mFeatureFlags.imsResolverUserAware()).thenReturn(true);
}
@After
@@ -411,7 +419,7 @@
ArgumentCaptor<SparseIntArray> arrayCaptor =
ArgumentCaptor.forClass(SparseIntArray.class);
- verify(controller).bind(eq(features), arrayCaptor.capture());
+ verify(controller).bind(eq(mContext.getUser()), eq(features), arrayCaptor.capture());
SparseIntArray slotIdToSubIdMap = arrayCaptor.getValue();
SparseIntArray compareMap = new SparseIntArray();
compareMap.put(0, 0);
@@ -469,11 +477,14 @@
when(mMockQueryManager.isQueryInProgress()).thenReturn(false);
setupDynamicQueryFeatures(TEST_CARRIER_2_DEFAULT_NAME, featuresAll, 1);
- verify(deviceController).bind(eq(featuresDevice), any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()), eq(featuresDevice),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
- verify(carrierController1).bind(eq(featuresMmTel), any(SparseIntArray.class));
+ verify(carrierController1).bind(eq(mContext.getUser()), eq(featuresMmTel),
+ any(SparseIntArray.class));
verify(carrierController1, never()).unbind();
- verify(carrierController2).bind(eq(featuresRcs), any(SparseIntArray.class));
+ verify(carrierController2).bind(eq(mContext.getUser()), eq(featuresRcs),
+ any(SparseIntArray.class));
verify(carrierController2, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController1.getComponentName());
assertEquals(TEST_CARRIER_2_DEFAULT_NAME, carrierController2.getComponentName());
@@ -521,11 +532,14 @@
when(mMockQueryManager.isQueryInProgress()).thenReturn(false);
setupDynamicQueryFeatures(TEST_CARRIER_2_DEFAULT_NAME, allFeatures, 1);
- verify(deviceController, never()).bind(any(), any(SparseIntArray.class));
+ verify(deviceController, never()).bind(eq(mContext.getUser()), any(),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
- verify(carrierController1).bind(eq(featuresMmTel), any(SparseIntArray.class));
+ verify(carrierController1).bind(eq(mContext.getUser()), eq(featuresMmTel),
+ any(SparseIntArray.class));
verify(carrierController1, never()).unbind();
- verify(carrierController2).bind(eq(featuresRcs), any(SparseIntArray.class));
+ verify(carrierController2).bind(eq(mContext.getUser()), eq(featuresRcs),
+ any(SparseIntArray.class));
verify(carrierController2, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController1.getComponentName());
assertEquals(TEST_CARRIER_2_DEFAULT_NAME, carrierController2.getComponentName());
@@ -553,7 +567,7 @@
startBindCarrierConfigAlreadySet();
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, features, 1);
- verify(controller).bind(eq(features), any(SparseIntArray.class));
+ verify(controller).bind(eq(mContext.getUser()), eq(features), any(SparseIntArray.class));
verify(controller, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, controller.getComponentName());
}
@@ -582,7 +596,7 @@
// We will not bind with FEATURE_EMERGENCY_MMTEL
features.remove(new ImsFeatureConfiguration.FeatureSlotPair(0,
ImsFeature.FEATURE_EMERGENCY_MMTEL));
- verify(controller).bind(eq(features), any(SparseIntArray.class));
+ verify(controller).bind(eq(mContext.getUser()), eq(features), any(SparseIntArray.class));
verify(controller, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, controller.getComponentName());
}
@@ -606,20 +620,23 @@
setupPackageQuery(info);
ImsServiceController deviceController1 = mock(ImsServiceController.class);
ImsServiceController deviceController2 = mock(ImsServiceController.class);
- setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
+ setImsServiceControllerDDCFactory(deviceController1, deviceController2, null);
// Bind using default features
startBindNoCarrierConfig(1);
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet1 =
convertToHashSet(featuresController1, 0);
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet2 =
convertToHashSet(featuresController2, 0);
- verify(deviceController1).bind(eq(featureSet1), any(SparseIntArray.class));
- verify(deviceController2).bind(eq(featureSet2), any(SparseIntArray.class));
+ verify(deviceController1).bind(eq(mContext.getUser()), eq(featureSet1),
+ any(SparseIntArray.class));
+ verify(deviceController2).bind(eq(mContext.getUser()), eq(featureSet2),
+ any(SparseIntArray.class));
// simulate ImsServiceController binding and setup
- mTestImsResolver.imsServiceFeatureCreated(0, ImsFeature.FEATURE_EMERGENCY_MMTEL,
+ mTestImsResolver.imsServiceFeatureCreated(0, 0, ImsFeature.FEATURE_EMERGENCY_MMTEL,
deviceController1);
- mTestImsResolver.imsServiceFeatureCreated(0, ImsFeature.FEATURE_MMTEL, deviceController1);
- mTestImsResolver.imsServiceFeatureCreated(0, ImsFeature.FEATURE_RCS, deviceController2);
+ mTestImsResolver.imsServiceFeatureCreated(0, 0, ImsFeature.FEATURE_MMTEL,
+ deviceController1);
+ mTestImsResolver.imsServiceFeatureCreated(0, 0, ImsFeature.FEATURE_RCS, deviceController2);
mTestImsResolver.enableIms(0 /*slotId*/);
// Verify enableIms is only called once per controller.
@@ -651,7 +668,7 @@
// Bind without emergency calling
startBindCarrierConfigAlreadySet();
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, features, 1);
- verify(controller).bind(eq(features), any(SparseIntArray.class));
+ verify(controller).bind(eq(mContext.getUser()), eq(features), any(SparseIntArray.class));
verify(controller, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, controller.getComponentName());
@@ -686,8 +703,8 @@
startBindCarrierConfigAlreadySet();
processAllMessages();
- verify(mMockQueryManager, never()).startQuery(any(), any());
- verify(controller, never()).bind(any(), any(SparseIntArray.class));
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
+ verify(controller, never()).bind(any(), any(), any(SparseIntArray.class));
verify(controller, never()).unbind();
}
@@ -719,7 +736,7 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet = convertToHashSet(features, 0);
ArgumentCaptor<SparseIntArray> arrayCaptor =
ArgumentCaptor.forClass(SparseIntArray.class);
- verify(controller).bind(eq(featureSet), arrayCaptor.capture());
+ verify(controller).bind(eq(mContext.getUser()), eq(featureSet), arrayCaptor.capture());
SparseIntArray slotIdToSubIdMap = arrayCaptor.getValue();
SparseIntArray compareMap = new SparseIntArray();
compareMap.put(0, 0);
@@ -729,7 +746,7 @@
}
verify(controller, never()).unbind();
- verify(mMockQueryManager, never()).startQuery(any(), any());
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
assertEquals(TEST_DEVICE_DEFAULT_NAME, controller.getComponentName());
}
@@ -763,7 +780,7 @@
featureSet.addAll(convertToHashSet(features, 1));
ArgumentCaptor<SparseIntArray> arrayCaptor =
ArgumentCaptor.forClass(SparseIntArray.class);
- verify(controller).bind(eq(featureSet), arrayCaptor.capture());
+ verify(controller).bind(eq(mContext.getUser()), eq(featureSet), arrayCaptor.capture());
SparseIntArray slotIdToSubIdMap = arrayCaptor.getValue();
assertEquals(slotIdToSubIdMap.size(), 2);
SparseIntArray compareMap = new SparseIntArray();
@@ -774,7 +791,7 @@
assertEquals(slotIdToSubIdMap.get(i), compareMap.get(i));
}
verify(controller, never()).unbind();
- verify(mMockQueryManager, never()).startQuery(any(), any());
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
assertEquals(TEST_DEVICE_DEFAULT_NAME, controller.getComponentName());
// Change number of SIMs and verify the features in the ImsServiceController are changed
@@ -823,7 +840,7 @@
ArgumentCaptor<SparseIntArray> arrayCaptor =
ArgumentCaptor.forClass(SparseIntArray.class);
- verify(controller).bind(eq(featureSet), arrayCaptor.capture());
+ verify(controller).bind(eq(mContext.getUser()), eq(featureSet), arrayCaptor.capture());
SparseIntArray slotIdToSubIdMap = arrayCaptor.getValue();
assertEquals(slotIdToSubIdMap.size(), 1);
SparseIntArray compareMap = new SparseIntArray();
@@ -833,7 +850,7 @@
assertEquals(slotIdToSubIdMap.get(i), compareMap.get(i));
}
verify(controller, never()).unbind();
- verify(mMockQueryManager, never()).startQuery(any(), any());
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
assertEquals(TEST_DEVICE_DEFAULT_NAME, controller.getComponentName());
// Change number of SIMs and verify the features in the ImsServiceController are changed
@@ -895,17 +912,19 @@
processAllMessages();
// ensure that startQuery was called
verify(mMockQueryManager, times(1)).startQuery(eq(TEST_DEVICE_DEFAULT_NAME),
- any(String.class));
+ any(UserHandle.class), any(String.class));
verify(mMockQueryManager, times(1)).startQuery(eq(TEST_DEVICE2_DEFAULT_NAME),
- any(String.class));
+ any(UserHandle.class), any(String.class));
mDynamicQueryListener.onComplete(TEST_DEVICE_DEFAULT_NAME, deviceFeatures1);
mDynamicQueryListener.onComplete(TEST_DEVICE2_DEFAULT_NAME, deviceFeatures2);
processAllMessages();
- verify(deviceController, times(2)).bind(eq(deviceFeatures1), any(SparseIntArray.class));
- verify(deviceController2, times(1)).bind(eq(deviceFeatures2), any(SparseIntArray.class));
+ verify(deviceController, times(2)).bind(eq(mContext.getUser()), eq(deviceFeatures1),
+ any(SparseIntArray.class));
+ verify(deviceController2, times(1)).bind(eq(mContext.getUser()), eq(deviceFeatures2),
+ any(SparseIntArray.class));
}
/**
@@ -942,7 +961,8 @@
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that all features that have been defined for the carrier override are bound
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
verify(carrierController, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
// Verify that all features that are not defined in the carrier override are bound in the
@@ -950,7 +970,8 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
convertToHashSet(deviceFeatures, 0);
deviceFeatureSet.removeAll(carrierFeatures);
- verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
@@ -1006,7 +1027,8 @@
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that all features that have been defined for the carrier override are bound
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
verify(carrierController, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
// Verify that all features that are not defined in the carrier override are bound in the
@@ -1015,7 +1037,8 @@
convertToHashSet(deviceFeatures, 0);
deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 1));
deviceFeatureSet.removeAll(carrierFeatures);
- verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
@@ -1062,9 +1085,9 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet = convertToHashSet(features, 0);
// There is no carrier override set, so make sure that the ImsServiceController binds
// to all SIMs.
- verify(controller).bind(eq(featureSet), any(SparseIntArray.class));
+ verify(controller).bind(eq(mContext.getUser()), eq(featureSet), any(SparseIntArray.class));
verify(controller, never()).unbind();
- verify(mMockQueryManager, never()).startQuery(any(), any());
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
assertEquals(TEST_DEVICE_DEFAULT_NAME, controller.getComponentName());
}
@@ -1100,7 +1123,8 @@
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that all features that have been defined for the carrier override are bound
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
verify(carrierController, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
// Verify that all features that are not defined in the carrier override are bound in the
@@ -1108,7 +1132,8 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
convertToHashSet(deviceFeatures, 0);
deviceFeatureSet.removeAll(carrierFeatures);
- verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
}
@@ -1127,11 +1152,11 @@
// Callback from mock ImsServiceControllers
// All features on slot 1 should be the device default
- mTestImsResolver.imsServiceFeatureCreated(1, ImsFeature.FEATURE_MMTEL, deviceController);
- mTestImsResolver.imsServiceFeatureCreated(1, ImsFeature.FEATURE_RCS, deviceController);
- mTestImsResolver.imsServiceFeatureCreated(0, ImsFeature.FEATURE_MMTEL, deviceController);
+ mTestImsResolver.imsServiceFeatureCreated(1, 1, ImsFeature.FEATURE_MMTEL, deviceController);
+ mTestImsResolver.imsServiceFeatureCreated(1, 1, ImsFeature.FEATURE_RCS, deviceController);
+ mTestImsResolver.imsServiceFeatureCreated(0, 0, ImsFeature.FEATURE_MMTEL, deviceController);
// The carrier override contains this feature
- mTestImsResolver.imsServiceFeatureCreated(0, ImsFeature.FEATURE_RCS, carrierController);
+ mTestImsResolver.imsServiceFeatureCreated(0, 0, ImsFeature.FEATURE_RCS, carrierController);
}
/**
@@ -1155,7 +1180,7 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet =
convertToHashSet(features, 0);
featureSet.addAll(convertToHashSet(features, 1));
- verify(controller).bind(eq(featureSet), any(SparseIntArray.class));
+ verify(controller).bind(eq(mContext.getUser()), eq(featureSet), any(SparseIntArray.class));
// add RCS to features list
Set<String> newFeatures = new HashSet<>(features);
@@ -1191,7 +1216,7 @@
setupPackageQuery(info);
ImsServiceController deviceController1 = mock(ImsServiceController.class);
ImsServiceController deviceController2 = mock(ImsServiceController.class);
- setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
+ setImsServiceControllerDDCFactory(deviceController1, deviceController2, null);
// Bind using default features
startBindNoCarrierConfig(2);
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet1 =
@@ -1200,8 +1225,10 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet2 =
convertToHashSet(featuresController2, 0);
featureSet2.addAll(convertToHashSet(featuresController2, 1));
- verify(deviceController1).bind(eq(featureSet1), any(SparseIntArray.class));
- verify(deviceController2).bind(eq(featureSet2), any(SparseIntArray.class));
+ verify(deviceController1).bind(eq(mContext.getUser()), eq(featureSet1),
+ any(SparseIntArray.class));
+ verify(deviceController2).bind(eq(mContext.getUser()), eq(featureSet2),
+ any(SparseIntArray.class));
// add RCS to features list for device 1
Set<String> newFeatures1 = new HashSet<>(featuresController1);
@@ -1239,7 +1266,7 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet =
convertToHashSet(features, 0);
featureSet.addAll(convertToHashSet(features, 1));
- verify(controller).bind(eq(featureSet), any(SparseIntArray.class));
+ verify(controller).bind(eq(mContext.getUser()), eq(featureSet), any(SparseIntArray.class));
// add RCS to features list
Set<String> newFeatures = new HashSet<>(features);
@@ -1288,7 +1315,8 @@
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that all features that have been defined for the carrier override are bound
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
verify(carrierController, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
// Verify that all features that are not defined in the carrier override are bound in the
@@ -1297,7 +1325,8 @@
convertToHashSet(deviceFeatures, 1);
deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 0));
deviceFeatureSet.removeAll(carrierFeatures);
- verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
@@ -1356,13 +1385,13 @@
ImsServiceController deviceController1 = mock(ImsServiceController.class);
ImsServiceController deviceController2 = mock(ImsServiceController.class);
ImsServiceController carrierController = mock(ImsServiceController.class);
- setImsServiceControllerFactory(deviceController1, deviceController2, carrierController,
- null);
+ setImsServiceControllerDDCFactory(deviceController1, deviceController2, carrierController);
startBindCarrierConfigAlreadySet();
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that all features that have been defined for the carrier override are bound
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
verify(carrierController, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
// Verify that all features that are not defined in the carrier override are bound in the
@@ -1370,13 +1399,16 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet1 =
convertToHashSet(deviceFeatures1, 1);
deviceFeatureSet1.removeAll(carrierFeatures);
- verify(deviceController1).bind(eq(deviceFeatureSet1), any(SparseIntArray.class));
+ verify(deviceController1).bind(eq(mContext.getUser()), eq(deviceFeatureSet1),
+ any(SparseIntArray.class));
verify(deviceController1, never()).unbind();
HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet2 =
convertToHashSet(deviceFeatures2, 0);
deviceFeatureSet2.addAll(convertToHashSet(deviceFeatures2, 1));
+ deviceFeatureSet2.addAll(convertToHashSet(deviceFeatures2, 1));
deviceFeatureSet2.removeAll(carrierFeatures);
- verify(deviceController2).bind(eq(deviceFeatureSet2), any(SparseIntArray.class));
+ verify(deviceController2).bind(eq(mContext.getUser()), eq(deviceFeatureSet2),
+ any(SparseIntArray.class));
verify(deviceController2, never()).unbind();
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController1.getComponentName());
assertEquals(TEST_DEVICE2_DEFAULT_NAME, deviceController2.getComponentName());
@@ -1392,7 +1424,7 @@
verify(carrierController).changeImsServiceFeatures(eq(carrierFeatures),
any(SparseIntArray.class));
deviceFeatureSet1.removeAll(carrierFeatures);
- verify(deviceController1, times(2)).changeImsServiceFeatures(eq(deviceFeatureSet1),
+ verify(deviceController1).changeImsServiceFeatures(eq(deviceFeatureSet1),
any(SparseIntArray.class));
deviceFeatureSet2.removeAll(carrierFeatures);
verify(deviceController2).changeImsServiceFeatures(eq(deviceFeatureSet2),
@@ -1429,7 +1461,8 @@
startBindCarrierConfigAlreadySet();
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that all features that have been defined for the carrier override are bound
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
verify(carrierController, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
// Verify that all features that are not defined in the carrier override are bound in the
@@ -1438,7 +1471,8 @@
convertToHashSet(deviceFeatures, 1);
deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 0));
deviceFeatureSet.removeAll(carrierFeatures);
- verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
@@ -1497,14 +1531,20 @@
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that all features that have been defined for the carrier override are bound
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
// device features change
HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
convertToHashSet(deviceFeatures, 1);
deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 0));
deviceFeatureSet.removeAll(carrierFeatures);
- verify(deviceController).changeImsServiceFeatures(eq(deviceFeatureSet),
- any(SparseIntArray.class));
+ if (mFeatureFlags.imsResolverUserAware()) {
+ verify(deviceController).changeImsServiceFeatures(eq(deviceFeatureSet),
+ any(SparseIntArray.class));
+ } else {
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
+ }
}
/**
@@ -1644,7 +1684,8 @@
assertNotNull(mTestImsResolver.getImsServiceInfoFromCache(
TEST_CARRIER_DEFAULT_NAME.getPackageName()));
// Verify that carrier 2 is bound
- verify(carrierController2).bind(eq(carrierFeatures2), any(SparseIntArray.class));
+ verify(carrierController2).bind(eq(mContext.getUser()), eq(carrierFeatures2),
+ any(SparseIntArray.class));
assertNotNull(mTestImsResolver.getImsServiceInfoFromCache(
TEST_CARRIER_2_DEFAULT_NAME.getPackageName()));
// device features change to accommodate for the features carrier 2 lacks
@@ -1692,7 +1733,8 @@
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that all features that have been defined for the carrier override are bound
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
// device features change
HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
convertToHashSet(deviceFeatures, 1);
@@ -1733,13 +1775,15 @@
setupDynamicQueryFeaturesFailure(TEST_CARRIER_DEFAULT_NAME, 1);
// Verify that a bind never occurs for the carrier controller.
- verify(carrierController, never()).bind(any(), any(SparseIntArray.class));
+ verify(carrierController, never()).bind(eq(mContext.getUser()), any(),
+ any(SparseIntArray.class));
verify(carrierController, never()).unbind();
// Verify that all features are used to bind to the device ImsService since the carrier
// ImsService failed to bind properly.
HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
convertToHashSet(deviceFeatures, 0);
- verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
}
@@ -1774,18 +1818,21 @@
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that a bind never occurs for the carrier controller.
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
verify(carrierController, never()).unbind();
// Verify that all features that are not defined in the carrier override are bound in the
// device controller (including emergency voice for slot 0)
HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
convertToHashSet(deviceFeatures, 0);
deviceFeatureSet.removeAll(carrierFeatures);
- verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
- mTestImsResolver.imsServiceBindPermanentError(TEST_CARRIER_DEFAULT_NAME);
+ mTestImsResolver.imsServiceBindPermanentError(TEST_CARRIER_DEFAULT_NAME,
+ mContext.getUser());
processAllMessages();
verify(carrierController).unbind();
// Verify that the device ImsService features are changed to include the ones previously
@@ -1815,7 +1862,7 @@
setupPackageQuery(info);
ImsServiceController deviceController1 = mock(ImsServiceController.class);
ImsServiceController deviceController2 = mock(ImsServiceController.class);
- setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
+ setImsServiceControllerDDCFactory(deviceController1, deviceController2, null);
startBindNoCarrierConfig(1);
processAllMessages();
@@ -1825,11 +1872,12 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureResultSet =
convertToHashSet(featureResult, 0);
featureResultSet.addAll(convertToHashSet(featureResult, 1));
- verify(deviceController1).bind(eq(featureResultSet), any(SparseIntArray.class));
+ verify(deviceController1).bind(eq(mContext.getUser()), eq(featureResultSet),
+ any(SparseIntArray.class));
verify(deviceController1, never()).unbind();
- verify(deviceController2, never()).bind(any(), any(SparseIntArray.class));
+ verify(deviceController2, never()).bind(any(), any(), any(SparseIntArray.class));
verify(deviceController2, never()).unbind();
- verify(mMockQueryManager, never()).startQuery(any(), any());
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController1.getComponentName());
}
@@ -1852,7 +1900,7 @@
setupPackageQuery(info);
ImsServiceController deviceController1 = mock(ImsServiceController.class);
ImsServiceController deviceController2 = mock(ImsServiceController.class);
- setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
+ setImsServiceControllerDDCFactory(deviceController1, deviceController2, null);
startBindNoCarrierConfig(1);
processAllMessages();
@@ -1862,11 +1910,12 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureResultSet =
convertToHashSet(featureResult, 0);
featureResultSet.addAll(convertToHashSet(featureResult, 1));
- verify(deviceController1).bind(eq(featureResultSet), any(SparseIntArray.class));
+ verify(deviceController1).bind(eq(mContext.getUser()), eq(featureResultSet),
+ any(SparseIntArray.class));
verify(deviceController1, never()).unbind();
- verify(deviceController2, never()).bind(any(), any(SparseIntArray.class));
+ verify(deviceController2, never()).bind(any(), any(), any(SparseIntArray.class));
verify(deviceController2, never()).unbind();
- verify(mMockQueryManager, never()).startQuery(any(), any());
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController1.getComponentName());
}
@@ -1893,7 +1942,7 @@
setupPackageQuery(info);
ImsServiceController deviceController1 = mock(ImsServiceController.class);
ImsServiceController deviceController2 = mock(ImsServiceController.class);
- setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
+ setImsServiceControllerDDCFactory(deviceController1, deviceController2, null);
startBindNoCarrierConfig(1);
processAllMessages();
@@ -1904,11 +1953,13 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet2 =
convertToHashSet(features2, 0);
featureSet2.addAll(convertToHashSet(features2, 1));
- verify(deviceController1).bind(eq(featureSet1), any(SparseIntArray.class));
+ verify(deviceController1).bind(eq(mContext.getUser()), eq(featureSet1),
+ any(SparseIntArray.class));
verify(deviceController1, never()).unbind();
- verify(deviceController2).bind(eq(featureSet2), any(SparseIntArray.class));
+ verify(deviceController2).bind(eq(mContext.getUser()), eq(featureSet2),
+ any(SparseIntArray.class));
verify(deviceController2, never()).unbind();
- verify(mMockQueryManager, never()).startQuery(any(), any());
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController1.getComponentName());
assertEquals(TEST_DEVICE2_DEFAULT_NAME, deviceController2.getComponentName());
}
@@ -1934,16 +1985,134 @@
setupPackageQuery(info);
ImsServiceController deviceController1 = mock(ImsServiceController.class);
ImsServiceController deviceController2 = mock(ImsServiceController.class);
- setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
+ setImsServiceControllerDDCFactory(deviceController1, deviceController2, null);
startBindNoCarrierConfig(1);
processAllMessages();
- verify(deviceController1, never()).bind(any(), any(SparseIntArray.class));
+ verify(deviceController1, never()).bind(any(), any(), any(SparseIntArray.class));
verify(deviceController1, never()).unbind();
- verify(deviceController2, never()).bind(any(), any(SparseIntArray.class));
+ verify(deviceController2, never()).bind(any(), any(), any(SparseIntArray.class));
verify(deviceController2, never()).unbind();
- verify(mMockQueryManager, never()).startQuery(any(), any());
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
+ }
+
+ /**
+ * Change the current active user while having ImsServices in system user. The ImsService config
+ * should not change.
+ */
+ @Test
+ @SmallTest
+ public void testChangeCurrentUserServicesInSystem() throws RemoteException {
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ return;
+ }
+ setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
+ TEST_DEVICE_DEFAULT_NAME.getPackageName());
+ List<ResolveInfo> info = new ArrayList<>();
+ Set<String> deviceFeatures = new HashSet<>();
+ deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
+ deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
+ // Set the carrier override package for slot 0
+ setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
+ HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
+ // Carrier service doesn't support the voice feature.
+ carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
+ info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true));
+ info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
+ // Use device default package, which will load the ImsService that the device provides
+ setupPackageQuery(info);
+
+ ImsServiceController deviceController = mock(ImsServiceController.class);
+ ImsServiceController carrierController = mock(ImsServiceController.class);
+ setImsServiceControllerFactory(deviceController, carrierController);
+
+ startBindCarrierConfigAlreadySet();
+ setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
+
+ // Perform a user switch
+ userChanged(TEST_USER_HANDLE);
+ setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 2);
+
+
+ // Verify that all features that have been defined for the device/carrier override are bound
+ // and are not changed when the user changes.
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
+ verify(carrierController, atLeastOnce()).changeImsServiceFeatures(eq(carrierFeatures),
+ any(SparseIntArray.class));
+ verify(carrierController, never()).unbind();
+ HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
+ convertToHashSet(deviceFeatures, 0);
+ deviceFeatureSet.removeAll(carrierFeatures);
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
+ verify(deviceController, atLeastOnce()).changeImsServiceFeatures(eq(deviceFeatureSet),
+ any(SparseIntArray.class));
+ verify(deviceController, never()).unbind();
+ }
+
+ /**
+ * Change the current active user while having a carrier ImsService installed for second user.
+ * The features should change when the current user changes to the second user and back.
+ */
+ @Test
+ @SmallTest
+ public void testChangeCurrentUserCarrierInSecondUser() throws RemoteException {
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ return;
+ }
+ setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
+ TEST_DEVICE_DEFAULT_NAME.getPackageName());
+ Set<String> deviceFeatures = new HashSet<>();
+ deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
+ deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
+ // Set the carrier override package for slot 0
+ setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
+ HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
+ // Carrier service doesn't support the voice feature.
+ carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
+ // Use device default package, which will load the ImsService that the device provides
+ setupPackageQuery(Collections.singletonList(
+ getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true)));
+ setupPackageQueryForUser(Collections.singletonList(
+ getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true)),
+ TEST_USER_HANDLE);
+
+ ImsServiceController deviceController = mock(ImsServiceController.class);
+ ImsServiceController carrierController = mock(ImsServiceController.class);
+ setImsServiceControllerFactory(deviceController, carrierController);
+
+ startBindCarrierConfigAlreadySet();
+
+ verify(carrierController, never()).bind(eq(mContext.getUser()), any(),
+ any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()),
+ eq(convertToHashSet(deviceFeatures, 0)), any(SparseIntArray.class));
+
+ // Perform a user switch
+ setBoundImsServiceControllerUser(carrierController, TEST_USER_HANDLE);
+ userChanged(TEST_USER_HANDLE);
+ setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
+
+
+ // Verify the carrier controller was bound only when the user changed
+ verify(carrierController).bind(eq(TEST_USER_HANDLE), eq(carrierFeatures),
+ any(SparseIntArray.class));
+ verify(carrierController, never()).changeImsServiceFeatures(eq(carrierFeatures),
+ any(SparseIntArray.class));
+ verify(carrierController, never()).unbind();
+
+ HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
+ convertToHashSet(deviceFeatures, 0);
+ deviceFeatureSet.removeAll(carrierFeatures);
+ verify(deviceController).changeImsServiceFeatures(eq(deviceFeatureSet),
+ any(SparseIntArray.class));
+ verify(deviceController, never()).unbind();
+ }
+
+ private void setCurrentUser(UserHandle handle) {
+ when(mTestActivityManagerProxy.getCurrentUser()).thenReturn(handle);
}
private void setupResolver(int numSlots, String deviceMmTelPkgName,
@@ -1970,12 +2139,15 @@
when(mTestTelephonyManagerProxy.getSimState(any(Context.class), eq(i))).thenReturn(
TelephonyManager.SIM_STATE_READY);
}
+ when(mMockContext.getUser()).thenReturn(mContext.getUser());
+ when(mTestActivityManagerProxy.getCurrentUser()).thenReturn(mContext.getUser());
mTestImsResolver = new ImsResolver(mMockContext, deviceMmTelPkgName, deviceRcsPkgName,
numSlots, mMockRepo, Looper.myLooper(), mFeatureFlags);
mTestImsResolver.setSubscriptionManagerProxy(mTestSubscriptionManagerProxy);
mTestImsResolver.setTelephonyManagerProxy(mTestTelephonyManagerProxy);
+ mTestImsResolver.setActivityManagerProxy(mTestActivityManagerProxy);
when(mMockQueryManagerFactory.create(any(Context.class),
any(ImsServiceFeatureQueryManager.Listener.class))).thenReturn(mMockQueryManager);
mTestImsResolver.setImsDynamicQueryManagerFactory(mMockQueryManagerFactory);
@@ -1983,24 +2155,55 @@
}
private void setupPackageQuery(List<ResolveInfo> infos) {
- // Only return info if not using the compat argument
- when(mMockPM.queryIntentServicesAsUser(
+ doAnswer((Answer<List<ResolveInfo>>) invocation -> {
+ Intent intent = (Intent) invocation.getArguments()[0];
+ String pkg = intent.getPackage();
+ if (pkg == null) {
+ return infos;
+ } else {
+ for (ResolveInfo info : infos) {
+ if (pkg.equals(info.serviceInfo.packageName)) {
+ return Collections.singletonList(info);
+ }
+ }
+ }
+ return Collections.emptyList();
+ }).when(mMockPM).queryIntentServicesAsUser(
+ // Only return info if not using the compat argument
argThat(argument -> ImsService.SERVICE_INTERFACE.equals(argument.getAction())),
- anyInt(), any())).thenReturn(infos);
+ anyInt(), any());
+ }
+
+ private void setupPackageQueryForUser(List<ResolveInfo> infos, UserHandle user) {
+ doAnswer((Answer<List<ResolveInfo>>) invocation -> {
+ Intent intent = (Intent) invocation.getArguments()[0];
+ String pkg = intent.getPackage();
+ if (pkg == null) {
+ return infos;
+ } else {
+ for (ResolveInfo info : infos) {
+ if (pkg.equals(info.serviceInfo.packageName)) {
+ return Collections.singletonList(info);
+ }
+ }
+ }
+ return Collections.emptyList();
+ }).when(mMockPM).queryIntentServicesAsUser(
+ // Only return info if not using the compat argument
+ argThat(argument -> ImsService.SERVICE_INTERFACE.equals(argument.getAction())),
+ anyInt(), eq(user));
}
private void setupPackageQuery(ComponentName name, Set<String> features,
boolean isPermissionGranted) {
List<ResolveInfo> info = new ArrayList<>();
info.add(getResolveInfo(name, features, isPermissionGranted));
- // Only return info if not using the compat argument
- when(mMockPM.queryIntentServicesAsUser(
- argThat(argument -> ImsService.SERVICE_INTERFACE.equals(argument.getAction())),
- anyInt(), any())).thenReturn(info);
+ setupPackageQuery(info);
}
private ImsServiceController setupController() {
ImsServiceController controller = mock(ImsServiceController.class);
+ when(controller.getBoundUser()).thenReturn(mContext.getUser());
mTestImsResolver.setImsServiceControllerFactory(
new ImsResolver.ImsServiceControllerFactory() {
@Override
@@ -2028,15 +2231,25 @@
processAllMessages();
ArgumentCaptor<BroadcastReceiver> receiversCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mMockContext, times(3)).registerReceiver(receiversCaptor.capture(), any());
- mTestPackageBroadcastReceiver = receiversCaptor.getAllValues().get(0);
- mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(1);
- mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(2);
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ verify(mMockContext, times(3)).registerReceiver(receiversCaptor.capture(), any());
+ mTestPackageBroadcastReceiver = receiversCaptor.getAllValues().get(0);
+ mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(1);
+ mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(2);
+ } else {
+ verify(mMockContext, times(4)).registerReceiver(receiversCaptor.capture(), any());
+ mTestPackageBroadcastReceiver = receiversCaptor.getAllValues().get(0);
+ mTestUserChangedReceiver = receiversCaptor.getAllValues().get(1);
+ mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(2);
+ mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(3);
+
+ }
ArgumentCaptor<ImsServiceFeatureQueryManager.Listener> queryManagerCaptor =
ArgumentCaptor.forClass(ImsServiceFeatureQueryManager.Listener.class);
verify(mMockQueryManagerFactory).create(any(Context.class), queryManagerCaptor.capture());
mDynamicQueryListener = queryManagerCaptor.getValue();
- when(mMockQueryManager.startQuery(any(ComponentName.class), any(String.class)))
+ when(mMockQueryManager.startQuery(any(ComponentName.class), any(UserHandle.class),
+ any(String.class)))
.thenReturn(true);
processAllMessages();
}
@@ -2050,10 +2263,18 @@
processAllMessages();
ArgumentCaptor<BroadcastReceiver> receiversCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mMockContext, times(3)).registerReceiver(receiversCaptor.capture(), any());
- mTestPackageBroadcastReceiver = receiversCaptor.getAllValues().get(0);
- mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(1);
- mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(2);
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ verify(mMockContext, times(3)).registerReceiver(receiversCaptor.capture(), any());
+ mTestPackageBroadcastReceiver = receiversCaptor.getAllValues().get(0);
+ mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(1);
+ mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(2);
+ } else {
+ verify(mMockContext, times(4)).registerReceiver(receiversCaptor.capture(), any());
+ mTestPackageBroadcastReceiver = receiversCaptor.getAllValues().get(0);
+ mTestUserChangedReceiver = receiversCaptor.getAllValues().get(1);
+ mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(2);
+ mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(3);
+ }
ArgumentCaptor<ImsServiceFeatureQueryManager.Listener> queryManagerCaptor =
ArgumentCaptor.forClass(ImsServiceFeatureQueryManager.Listener.class);
verify(mMockQueryManagerFactory).create(any(Context.class), queryManagerCaptor.capture());
@@ -2069,7 +2290,8 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> features, int times) {
processAllMessages();
// ensure that startQuery was called
- verify(mMockQueryManager, times(times)).startQuery(eq(name), any(String.class));
+ verify(mMockQueryManager, times(times)).startQuery(eq(name), any(UserHandle.class),
+ any(String.class));
mDynamicQueryListener.onComplete(name, features);
processAllMessages();
}
@@ -2078,7 +2300,8 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> features, int times) {
processAllFutureMessages();
// ensure that startQuery was called
- verify(mMockQueryManager, times(times)).startQuery(eq(name), any(String.class));
+ verify(mMockQueryManager, times(times)).startQuery(eq(name), any(UserHandle.class),
+ any(String.class));
mDynamicQueryListener.onComplete(name, features);
processAllMessages();
}
@@ -2086,8 +2309,19 @@
private void setupDynamicQueryFeaturesFailure(ComponentName name, int times) {
processAllMessages();
// ensure that startQuery was called
- verify(mMockQueryManager, times(times)).startQuery(eq(name), any(String.class));
- mDynamicQueryListener.onPermanentError(name);
+ verify(mMockQueryManager, times(times)).startQuery(eq(name), any(UserHandle.class),
+ any(String.class));
+ mDynamicQueryListener.onPermanentError(name, mContext.getUser());
+ processAllMessages();
+ }
+
+ public void userChanged(UserHandle newUser) {
+ setCurrentUser(newUser);
+ // Tell the package manager that a new device feature is installed
+ Intent userSwitchedIntent = new Intent();
+ userSwitchedIntent.setAction(Intent.ACTION_USER_SWITCHED);
+ userSwitchedIntent.putExtra(Intent.EXTRA_USER, newUser);
+ mTestUserChangedReceiver.onReceive(null, userSwitchedIntent);
processAllMessages();
}
@@ -2110,7 +2344,14 @@
processAllMessages();
}
+ private void setBoundImsServiceControllerUser(ImsServiceController controller,
+ UserHandle handle) {
+ when(controller.getBoundUser()).thenReturn(handle);
+ }
+
private void setImsServiceControllerFactory(Map<String, ImsServiceController> controllerMap) {
+ controllerMap.values()
+ .forEach(c -> setBoundImsServiceControllerUser(c, mContext.getUser()));
mTestImsResolver.setImsServiceControllerFactory(
new ImsResolver.ImsServiceControllerFactory() {
@Override
@@ -2129,6 +2370,8 @@
private void setImsServiceControllerFactory(ImsServiceController deviceController,
ImsServiceController carrierController) {
+ setBoundImsServiceControllerUser(deviceController, mContext.getUser());
+ setBoundImsServiceControllerUser(carrierController, mContext.getUser());
mTestImsResolver.setImsServiceControllerFactory(
new ImsResolver.ImsServiceControllerFactory() {
@Override
@@ -2156,6 +2399,9 @@
private void setImsServiceControllerFactory(ImsServiceController deviceController,
ImsServiceController carrierController1, ImsServiceController carrierController2) {
+ setBoundImsServiceControllerUser(deviceController, mContext.getUser());
+ setBoundImsServiceControllerUser(carrierController1, mContext.getUser());
+ setBoundImsServiceControllerUser(carrierController2, mContext.getUser());
mTestImsResolver.setImsServiceControllerFactory(
new ImsResolver.ImsServiceControllerFactory() {
@Override
@@ -2185,9 +2431,13 @@
});
}
- private void setImsServiceControllerFactory(ImsServiceController deviceController1,
- ImsServiceController deviceController2, ImsServiceController carrierController1,
- ImsServiceController carrierController2) {
+ private void setImsServiceControllerDDCFactory(ImsServiceController deviceController1,
+ ImsServiceController deviceController2, ImsServiceController carrierController1) {
+ setBoundImsServiceControllerUser(deviceController1, mContext.getUser());
+ setBoundImsServiceControllerUser(deviceController2, mContext.getUser());
+ if (carrierController1 != null) {
+ setBoundImsServiceControllerUser(carrierController1, mContext.getUser());
+ }
mTestImsResolver.setImsServiceControllerFactory(
new ImsResolver.ImsServiceControllerFactory() {
@Override
@@ -2211,10 +2461,6 @@
componentName.getPackageName())) {
when(carrierController1.getComponentName()).thenReturn(componentName);
return carrierController1;
- } else if (TEST_CARRIER_2_DEFAULT_NAME.getPackageName().equals(
- componentName.getPackageName())) {
- when(carrierController2.getComponentName()).thenReturn(componentName);
- return carrierController2;
}
return null;
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerCompatTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerCompatTest.java
index 2544fc1..aa6bd7f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerCompatTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerCompatTest.java
@@ -108,9 +108,9 @@
mMmTelCompatAdapterSpy = spy(new MmTelFeatureCompatAdapter(mMockContext, SLOT_0,
mMockMmTelInterfaceAdapter));
mTestImsServiceController = new ImsServiceControllerCompat(mMockContext, mTestComponentName,
- mMockCallbacks, mHandler, REBIND_RETRY, mRepo,
+ mMockCallbacks, mHandler, REBIND_RETRY, mRepo,
(a, b, c) -> mMmTelCompatAdapterSpy);
- when(mMockContext.bindService(any(), any(), anyInt())).thenReturn(true);
+ when(mMockContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true);
when(mMockServiceControllerBinder.createMMTelFeature(anyInt()))
.thenReturn(mMockRemoteMMTelFeature);
when(mMockRemoteMMTelFeature.getConfigInterface()).thenReturn(mMockImsConfig);
@@ -146,8 +146,8 @@
verify(mMockServiceControllerBinder).createMMTelFeature(SLOT_0);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_1),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
// Remove the feature
conn.onBindingDied(mTestComponentName);
@@ -191,8 +191,9 @@
SparseIntArray slotIdToSubIdMap) {
ArgumentCaptor<ServiceConnection> serviceCaptor =
ArgumentCaptor.forClass(ServiceConnection.class);
- assertTrue(mTestImsServiceController.bind(testFeatures, slotIdToSubIdMap));
- verify(mMockContext).bindService(any(), serviceCaptor.capture(), anyInt());
+ assertTrue(mTestImsServiceController.bind(mContext.getUser(), testFeatures,
+ slotIdToSubIdMap));
+ verify(mMockContext).bindServiceAsUser(any(), serviceCaptor.capture(), anyInt(), any());
return serviceCaptor.getValue();
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
index 65b73fb..5f16d9b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
@@ -39,6 +39,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.telephony.SubscriptionManager;
import android.telephony.ims.ImsService;
import android.telephony.ims.aidl.IImsConfig;
@@ -135,6 +136,7 @@
private final Handler mHandler = new Handler(Looper.getMainLooper());
private ImsServiceController mTestImsServiceController;
private ImsFeatureBinderRepository mRepo;
+ private UserHandle mUser;
@Before
@Override
@@ -150,11 +152,12 @@
mMockCallbacks = mock(ImsServiceController.ImsServiceControllerCallbacks.class);
mFeatureFlags = mock(FeatureFlags.class);
mMockContext = mock(Context.class);
+ mUser = UserHandle.of(UserHandle.myUserId());
mRepo = new ImsFeatureBinderRepository();
mTestImsServiceController = new ImsServiceController(mMockContext, mTestComponentName,
mMockCallbacks, mHandler, REBIND_RETRY, mRepo, mFeatureFlags);
- when(mMockContext.bindService(any(), any(), anyInt())).thenReturn(true);
+ when(mMockContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true);
when(mMockServiceControllerBinder.createMmTelFeature(anyInt(), anyInt()))
.thenReturn(mMockMmTelFeature);
when(mMockServiceControllerBinder.createRcsFeature(anyInt(), anyInt()))
@@ -198,11 +201,12 @@
SparseIntArray slotIdToSubIdMap = new SparseIntArray();
slotIdToSubIdMap.put(SLOT_0, SUB_2);
- assertTrue(mTestImsServiceController.bind(testFeatures, slotIdToSubIdMap.clone()));
+ assertTrue(mTestImsServiceController.bind(mUser, testFeatures, slotIdToSubIdMap.clone()));
int expectedFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
| Context.BIND_IMPORTANT;
- verify(mMockContext).bindService(intentCaptor.capture(), any(), eq(expectedFlags));
+ verify(mMockContext).bindServiceAsUser(intentCaptor.capture(), any(), eq(expectedFlags),
+ any());
Intent testIntent = intentCaptor.getValue();
assertEquals(ImsService.SERVICE_INTERFACE, testIntent.getAction());
assertEquals(mTestComponentName, testIntent.getComponent());
@@ -222,9 +226,9 @@
bindAndConnectService(testFeatures, slotIdToSubIdMap.clone());
// already bound, should return false
- assertFalse(mTestImsServiceController.bind(testFeatures, slotIdToSubIdMap.clone()));
+ assertFalse(mTestImsServiceController.bind(mUser, testFeatures, slotIdToSubIdMap.clone()));
- verify(mMockContext, times(1)).bindService(any(), any(), anyInt());
+ verify(mMockContext, times(1)).bindServiceAsUser(any(), any(), anyInt(), any());
}
/**
@@ -250,10 +254,10 @@
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateRcsFeatureContainerExists(SLOT_0);
}
@@ -282,10 +286,10 @@
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateRcsFeatureContainerExists(SLOT_0);
@@ -313,9 +317,9 @@
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_3);
verify(mMockServiceControllerBinder, times(2)).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks, times(2)).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_3),
eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
- verify(mMockCallbacks, times(2)).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_3),
eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateRcsFeatureContainerExists(SLOT_0);
@@ -341,13 +345,13 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateMmTelFeatureContainerExists(SLOT_1);
@@ -373,12 +377,12 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_4);
verify(mMockServiceControllerBinder, times(2)).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks, times(2)).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_4),
eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_5);
verify(mMockServiceControllerBinder, times(2)).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks, times(2)).imsServiceFeatureCreated(eq(SLOT_1),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_5),
eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateMmTelFeatureContainerExists(SLOT_1);
@@ -411,13 +415,14 @@
verify(mMockServiceControllerBinder).createEmergencyOnlyMmTelFeature(SLOT_0);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0),
+ eq(SubscriptionManager.INVALID_SUBSCRIPTION_ID), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExistsWithEmergency(SLOT_0);
validateMmTelFeatureContainerExistsWithEmergency(SLOT_1);
@@ -437,8 +442,9 @@
verify(mMockServiceControllerBinder).createEmergencyOnlyMmTelFeature(SLOT_1);
verify(mMockServiceControllerBinder, times(2)).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks, times(2)).imsServiceFeatureCreated(eq(SLOT_1),
- eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1),
+ eq(SubscriptionManager.INVALID_SUBSCRIPTION_ID), eq(ImsFeature.FEATURE_MMTEL),
+ eq(mTestImsServiceController));
validateMmTelFeatureContainerExistsWithEmergency(SLOT_0);
validateMmTelFeatureContainerExistsWithEmergency(SLOT_1);
@@ -470,10 +476,10 @@
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateFeatureContainerExistsWithSipDelegate(ImsFeature.FEATURE_MMTEL, SLOT_0);
validateFeatureContainerExistsWithSipDelegate(ImsFeature.FEATURE_RCS, SLOT_0);
}
@@ -499,7 +505,8 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
// verify CAPABILITY_SIP_DELEGATE_CREATION is not set because MMTEL and RCS are not set.
validateFeatureContainerDoesNotHaveSipDelegate(ImsFeature.FEATURE_MMTEL, SLOT_0);
@@ -525,9 +532,9 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
eq(ImsFeature.FEATURE_EMERGENCY_MMTEL), eq(mTestImsServiceController));
// Make sure this callback happens, which will notify the framework of emergency calling
// availability.
@@ -553,9 +560,11 @@
verify(mMockServiceControllerBinder).createEmergencyOnlyMmTelFeature(SLOT_0);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0),
+ eq(SubscriptionManager.INVALID_SUBSCRIPTION_ID), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0),
+ eq(SubscriptionManager.INVALID_SUBSCRIPTION_ID),
eq(ImsFeature.FEATURE_EMERGENCY_MMTEL), eq(mTestImsServiceController));
// Make sure this callback happens, which will notify the framework of emergency calling
// availability.
@@ -584,17 +593,17 @@
verify(mMockServiceControllerBinder, never()).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder, never()).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
- verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
eq(ImsFeature.FEATURE_EMERGENCY_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerDoesntExist(SLOT_0);
// verify RCS feature is created
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateRcsFeatureContainerExists(SLOT_0);
}
@@ -798,9 +807,9 @@
long delay = mTestImsServiceController.getRebindDelay();
waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
- verify(mMockCallbacks, never()).imsServiceFeatureCreated(anyInt(), anyInt(),
+ verify(mMockCallbacks, never()).imsServiceFeatureCreated(anyInt(), anyInt(), anyInt(),
eq(mTestImsServiceController));
- verify(mMockCallbacks).imsServiceBindPermanentError(eq(mTestComponentName));
+ verify(mMockCallbacks).imsServiceBindPermanentError(eq(mTestComponentName), eq(mUser));
validateMmTelFeatureContainerDoesntExist(SLOT_0);
validateRcsFeatureContainerDoesntExist(SLOT_0);
}
@@ -822,8 +831,8 @@
bindAndConnectService(testFeatures, slotIdToSubIdMap.clone());
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_2);
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateRcsFeatureContainerDoesntExist(SLOT_0);
}
@@ -843,8 +852,8 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
// Create a new list with an additional item
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeaturesWithAddition = new HashSet<>(
testFeatures);
@@ -859,8 +868,8 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateMmTelFeatureContainerExists(SLOT_1);
}
@@ -880,8 +889,8 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
// Create a new list with an additional item
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeaturesWithAddition = new HashSet<>(
testFeatures);
@@ -895,8 +904,8 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateMmTelFeatureContainerExists(SLOT_1);
}
@@ -918,8 +927,8 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
assertEquals(mMockMmTelBinder, cb.container.imsFeature);
assertTrue((ImsService.CAPABILITY_EMERGENCY_OVER_MMTEL
@@ -934,9 +943,8 @@
mTestImsServiceController.changeImsServiceFeatures(testFeaturesWithAddition,
slotIdToSubIdMap.clone());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0),
- eq(ImsFeature.FEATURE_EMERGENCY_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_EMERGENCY_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExistsWithEmergency(SLOT_0);
assertEquals(mMockMmTelBinder, cb.container.imsFeature);
@@ -972,8 +980,8 @@
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateRcsFeatureContainerExists(SLOT_0);
// Add FEATURE_EMERGENCY_MMTEL and ensure it doesn't cause MMTEL bind
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeaturesWithAddition = new HashSet<>(
@@ -988,9 +996,8 @@
verify(mMockServiceControllerBinder, never()).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder, never()).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_1),
- eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerDoesntExist(SLOT_1);
}
@@ -1010,8 +1017,8 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
// Call change with the same features and make sure it is disregarded
@@ -1027,7 +1034,7 @@
verify(mMockServiceControllerBinder, never()).removeFeatureStatusCallback(anyInt(),
anyInt(), any());
verify(mMockCallbacks, times(1)).imsServiceFeatureCreated(eq(SLOT_0),
- eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
+ eq(SUB_2), eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockCallbacks, never()).imsServiceFeatureRemoved(anyInt(), anyInt(), any());
validateMmTelFeatureContainerExists(SLOT_0);
}
@@ -1050,13 +1057,13 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateMmTelFeatureContainerExists(SLOT_1);
// Create a new list with one less item
@@ -1098,13 +1105,13 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateMmTelFeatureContainerExists(SLOT_1);
// Create a new list with one less item
@@ -1149,23 +1156,23 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_RCS),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateMmTelFeatureContainerExists(SLOT_1);
validateRcsFeatureContainerExists(SLOT_0);
@@ -1205,12 +1212,12 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_4);
verify(mMockServiceControllerBinder, times(2)).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks, times(2)).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_4),
eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_4);
verify(mMockServiceControllerBinder, times(2)).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks, times(2)).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_4),
eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateRcsFeatureContainerExists(SLOT_0);
@@ -1235,13 +1242,13 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateMmTelFeatureContainerExists(SLOT_1);
@@ -1291,7 +1298,7 @@
verify(mMockServiceControllerBinder, never()).createRcsFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder, never()).removeFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateMmTelFeatureContainerDoesntExist(SLOT_0);
validateRcsFeatureContainerDoesntExist(SLOT_0);
@@ -1318,7 +1325,7 @@
long delay = REBIND_RETRY.getStartDelay();
waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
// The service should autobind after rebind event occurs
- verify(mMockContext, times(2)).bindService(any(), any(), anyInt());
+ verify(mMockContext, times(2)).bindServiceAsUser(any(), any(), anyInt(), any());
}
/**
@@ -1344,7 +1351,7 @@
long delay = REBIND_RETRY.getStartDelay();
waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
// The service should autobind after rebind event occurs
- verify(mMockContext, times(2)).bindService(any(), any(), anyInt());
+ verify(mMockContext, times(2)).bindServiceAsUser(any(), any(), anyInt(), any());
}
/**
@@ -1365,7 +1372,7 @@
conn.onBindingDied(null /*null*/);
// Be sure that there are no binds before the RETRY_TIMEOUT expires
- verify(mMockContext, times(1)).bindService(any(), any(), anyInt());
+ verify(mMockContext, times(1)).bindServiceAsUser(any(), any(), anyInt(), any());
}
/**
@@ -1390,7 +1397,7 @@
waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
// Unbind should stop the autobind from occurring.
- verify(mMockContext, times(1)).bindService(any(), any(), anyInt());
+ verify(mMockContext, times(1)).bindServiceAsUser(any(), any(), anyInt(), any());
}
/**
@@ -1412,10 +1419,10 @@
long delay = REBIND_RETRY.getStartDelay();
waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
- mTestImsServiceController.bind(testFeatures, slotIdToSubIdMap.clone());
+ mTestImsServiceController.bind(mUser, testFeatures, slotIdToSubIdMap.clone());
// Should only see two binds, not three from the auto rebind that occurs.
- verify(mMockContext, times(2)).bindService(any(), any(), anyInt());
+ verify(mMockContext, times(2)).bindServiceAsUser(any(), any(), anyInt(), any());
}
private void validateMmTelFeatureContainerExists(int slotId) {
@@ -1504,8 +1511,8 @@
SparseIntArray slotIdToSubIdMap) {
ArgumentCaptor<ServiceConnection> serviceCaptor =
ArgumentCaptor.forClass(ServiceConnection.class);
- assertTrue(mTestImsServiceController.bind(testFeatures, slotIdToSubIdMap));
- verify(mMockContext).bindService(any(), serviceCaptor.capture(), anyInt());
+ assertTrue(mTestImsServiceController.bind(mUser, testFeatures, slotIdToSubIdMap));
+ verify(mMockContext).bindServiceAsUser(any(), serviceCaptor.capture(), anyInt(), any());
return serviceCaptor.getValue();
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
index e371c59..110dade 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
@@ -4974,43 +4974,56 @@
}
@Test
- public void addCarrierRoamingSatelliteControllerStats_withExistingEntries() throws Exception {
+ public void addCarrierRoamingSatelliteControllerStats_withExistingCarrierId() throws Exception {
createEmptyTestFile();
mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
mPersistAtomsStorage.addCarrierRoamingSatelliteControllerStats(
- mCarrierRoamingSatelliteControllerStats1);
+ copyOf(mCarrierRoamingSatelliteControllerStats1));
mPersistAtomsStorage.addCarrierRoamingSatelliteControllerStats(
- mCarrierRoamingSatelliteControllerStats2);
+ copyOf(mCarrierRoamingSatelliteControllerStats1));
mPersistAtomsStorage.incTimeMillis(100L);
CarrierRoamingSatelliteControllerStats expected =
new CarrierRoamingSatelliteControllerStats();
- expected.configDataSource = mCarrierRoamingSatelliteControllerStats2.configDataSource;
+ expected.configDataSource = mCarrierRoamingSatelliteControllerStats1.configDataSource;
expected.countOfEntitlementStatusQueryRequest =
- mCarrierRoamingSatelliteControllerStats1.countOfEntitlementStatusQueryRequest
- + mCarrierRoamingSatelliteControllerStats2
- .countOfEntitlementStatusQueryRequest;
+ mCarrierRoamingSatelliteControllerStats1.countOfEntitlementStatusQueryRequest * 2;
expected.countOfSatelliteConfigUpdateRequest =
- mCarrierRoamingSatelliteControllerStats1.countOfSatelliteConfigUpdateRequest
- + mCarrierRoamingSatelliteControllerStats2
- .countOfSatelliteConfigUpdateRequest;
+ mCarrierRoamingSatelliteControllerStats1.countOfSatelliteConfigUpdateRequest * 2;
expected.countOfSatelliteNotificationDisplayed =
- mCarrierRoamingSatelliteControllerStats1.countOfSatelliteNotificationDisplayed
- + mCarrierRoamingSatelliteControllerStats2
- .countOfSatelliteNotificationDisplayed;
+ mCarrierRoamingSatelliteControllerStats1.countOfSatelliteNotificationDisplayed * 2;
expected.satelliteSessionGapMinSec =
- mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapMinSec;
+ mCarrierRoamingSatelliteControllerStats1.satelliteSessionGapMinSec;
expected.satelliteSessionGapAvgSec =
- mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapAvgSec;
+ mCarrierRoamingSatelliteControllerStats1.satelliteSessionGapAvgSec;
expected.satelliteSessionGapMaxSec =
- mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapMaxSec;
- expected.carrierId = mCarrierRoamingSatelliteControllerStats2.carrierId;
- expected.isDeviceEntitled = mCarrierRoamingSatelliteControllerStats2.isDeviceEntitled;
-
+ mCarrierRoamingSatelliteControllerStats1.satelliteSessionGapMaxSec;
+ expected.carrierId = mCarrierRoamingSatelliteControllerStats1.carrierId;
+ expected.isDeviceEntitled = mCarrierRoamingSatelliteControllerStats1.isDeviceEntitled;
verifyCurrentStateSavedToFileOnce();
CarrierRoamingSatelliteControllerStats[] output =
mPersistAtomsStorage.getCarrierRoamingSatelliteControllerStats(0L);
- assertHasStats(output, expected);
+ assertHasStats(output, expected, 1);
+ }
+
+ @Test
+ public void addCarrierRoamingSatelliteControllerStats_addNewCarrierId() throws Exception {
+ createEmptyTestFile();
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addCarrierRoamingSatelliteControllerStats(
+ copyOf(mCarrierRoamingSatelliteControllerStats1));
+ mPersistAtomsStorage.addCarrierRoamingSatelliteControllerStats(
+ copyOf(mCarrierRoamingSatelliteControllerStats2));
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ CarrierRoamingSatelliteControllerStats expected1 = mCarrierRoamingSatelliteControllerStats1;
+ CarrierRoamingSatelliteControllerStats expected2 = mCarrierRoamingSatelliteControllerStats2;
+
+ CarrierRoamingSatelliteControllerStats[] output =
+ mPersistAtomsStorage.getCarrierRoamingSatelliteControllerStats(0L);
+
+ assertHasStats(output, expected1, 1);
+ assertHasStats(output, expected2, 1);
}
@Test
@@ -6251,20 +6264,29 @@
}
private static void assertHasStats(CarrierRoamingSatelliteControllerStats[] tested,
- @Nullable CarrierRoamingSatelliteControllerStats expectedStats) {
+ @Nullable CarrierRoamingSatelliteControllerStats expectedStats, int expectedCount) {
assertNotNull(tested);
- assertEquals(tested[0].configDataSource, expectedStats.configDataSource);
- assertEquals(tested[0].countOfEntitlementStatusQueryRequest,
- expectedStats.countOfEntitlementStatusQueryRequest);
- assertEquals(tested[0].countOfSatelliteConfigUpdateRequest,
- expectedStats.countOfSatelliteConfigUpdateRequest);
- assertEquals(tested[0].countOfSatelliteNotificationDisplayed,
- expectedStats.countOfSatelliteNotificationDisplayed);
- assertEquals(tested[0].satelliteSessionGapMinSec, expectedStats.satelliteSessionGapMinSec);
- assertEquals(tested[0].satelliteSessionGapAvgSec, expectedStats.satelliteSessionGapAvgSec);
- assertEquals(tested[0].satelliteSessionGapMaxSec, expectedStats.satelliteSessionGapMaxSec);
- assertEquals(tested[0].carrierId, expectedStats.carrierId);
- assertEquals(tested[0].isDeviceEntitled, expectedStats.isDeviceEntitled);
+ int count = 0;
+ for (CarrierRoamingSatelliteControllerStats stats : tested) {
+ if (expectedStats.carrierId == stats.carrierId) {
+ assertEquals(expectedStats.configDataSource, stats.configDataSource);
+ assertEquals(expectedStats.countOfEntitlementStatusQueryRequest,
+ stats.countOfEntitlementStatusQueryRequest);
+ assertEquals(expectedStats.countOfSatelliteConfigUpdateRequest,
+ stats.countOfSatelliteConfigUpdateRequest);
+ assertEquals(expectedStats.countOfSatelliteNotificationDisplayed,
+ stats.countOfSatelliteNotificationDisplayed);
+ assertEquals(expectedStats.satelliteSessionGapMinSec,
+ stats.satelliteSessionGapMinSec);
+ assertEquals(expectedStats.satelliteSessionGapAvgSec,
+ stats.satelliteSessionGapAvgSec);
+ assertEquals(expectedStats.satelliteSessionGapMaxSec,
+ stats.satelliteSessionGapMaxSec);
+ assertEquals(expectedStats.isDeviceEntitled, stats.isDeviceEntitled);
+ count++;
+ }
+ }
+ assertEquals(expectedCount, count);
}
private static void assertHasStatsAndCount(
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java
index 8173bbc..fdb94c9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java
@@ -180,7 +180,7 @@
assertEquals(0, mTestStats.mCountOfIncomingDatagramFail);
assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsSuccess);
assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsFail);
- assertEquals(10, mTestStats.mCountOfDatagramTypeLocationSharingSuccess);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingSuccess);
assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingFail);
assertEquals(0, mTestStats.mCountOfProvisionSuccess);
assertEquals(0, mTestStats.mCountOfProvisionFail);
@@ -282,7 +282,7 @@
assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsSuccess);
assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsFail);
assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingSuccess);
- assertEquals(10, mTestStats.mCountOfDatagramTypeLocationSharingFail);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingFail);
assertEquals(0, mTestStats.mCountOfProvisionSuccess);
assertEquals(0, mTestStats.mCountOfProvisionFail);
assertEquals(0, mTestStats.mCountOfDeprovisionSuccess);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
index 2961b4d..21731f0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
@@ -92,8 +92,8 @@
// Move both send and receive to IDLE state
mDatagramControllerUT.updateSendStatus(SUB_ID, DATAGRAM_TYPE_UNKNOWN,
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, 0, SATELLITE_RESULT_SUCCESS);
- mDatagramControllerUT.updateReceiveStatus(SUB_ID, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, 0,
- SATELLITE_RESULT_SUCCESS);
+ mDatagramControllerUT.updateReceiveStatus(SUB_ID, DATAGRAM_TYPE_SOS_MESSAGE,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, 0, SATELLITE_RESULT_SUCCESS);
pushDemoModeSosDatagram(DATAGRAM_TYPE_SOS_MESSAGE);
}
@@ -197,7 +197,7 @@
errorCode);
verify(mMockSatelliteSessionController)
- .onDatagramTransferStateChanged(eq(sendState), anyInt());
+ .onDatagramTransferStateChanged(eq(sendState), anyInt(), anyInt());
verify(mMockPointingAppController).updateSendDatagramTransferState(
eq(SUB_ID), eq(datagramType), eq(sendState), eq(sendPendingCount), eq(errorCode));
@@ -219,10 +219,10 @@
int receivePendingCount = 1;
int errorCode = SATELLITE_RESULT_SUCCESS;
mDatagramControllerUT.updateReceiveStatus(
- SUB_ID, receiveState, receivePendingCount, errorCode);
+ SUB_ID, DATAGRAM_TYPE_SOS_MESSAGE, receiveState, receivePendingCount, errorCode);
verify(mMockSatelliteSessionController)
- .onDatagramTransferStateChanged(anyInt(), eq(receiveState));
+ .onDatagramTransferStateChanged(anyInt(), eq(receiveState), anyInt());
verify(mMockPointingAppController).updateReceiveDatagramTransferState(
eq(SUB_ID), eq(receiveState), eq(receivePendingCount), eq(errorCode));
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 21ee476..d964d88 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
@@ -824,7 +824,7 @@
eq(SATELLITE_RESULT_SUCCESS));
verify(mMockSmsDispatchersController).sendCarrierRoamingNbIotNtnText(eq(mPendingSms));
- mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.messageId, true);
+ mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.uniqueMessageId, true);
processAllMessages();
mInOrder.verify(mMockDatagramController)
@@ -858,7 +858,7 @@
eq(SATELLITE_RESULT_SUCCESS));
verify(mMockSmsDispatchersController).sendCarrierRoamingNbIotNtnText(eq(mPendingSms));
- mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.messageId, false);
+ mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.uniqueMessageId, false);
processAllMessages();
mInOrder.verify(mMockDatagramController)
@@ -1056,7 +1056,7 @@
eq(SATELLITE_RESULT_SUCCESS));
verify(mMockSmsDispatchersController).sendCarrierRoamingNbIotNtnText(eq(mPendingSms));
- mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.messageId, true);
+ mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.uniqueMessageId, true);
processAllMessages();
mInOrder.verify(mMockDatagramController)
@@ -1107,7 +1107,7 @@
processAllMessages();
verifyZeroInteractions(mMockSatelliteModemInterface);
- mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.messageId, true);
+ mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.uniqueMessageId, true);
processAllMessages();
mInOrder.verify(mMockDatagramController)
.updateSendStatus(eq(SUB_ID), eq(datagramTypeSms),
@@ -1204,6 +1204,6 @@
SmsDispatchersController.PendingRequest.TYPE_TEXT, null, "test-app",
Binder.getCallingUserHandle().getIdentifier(), "1111", "2222", asArrayList(null),
asArrayList(null), false, null, 0, asArrayList("text"), null, false, 0, false,
- 10, 100L, false);
+ 10, 100L, false, false);
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
index e964ced..a1f63d0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
@@ -187,6 +187,7 @@
mInOrder.verify(mMockDatagramController)
.needsWaitingForSatelliteConnected(eq(SatelliteManager.DATAGRAM_TYPE_UNKNOWN));
mInOrder.verify(mMockDatagramController).updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT), eq(0),
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(eq(false));
@@ -201,6 +202,7 @@
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING), eq(0),
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
verify(mMockSatelliteModemInterface, times(1))
@@ -225,9 +227,11 @@
moveTimeForward(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS);
processAllMessages();
mInOrder.verify(mMockDatagramController).updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED), eq(0),
eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE));
mInOrder.verify(mMockDatagramController).updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
verifyZeroInteractions(mMockSatelliteModemInterface);
@@ -266,10 +270,12 @@
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING), eq(0),
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED),
eq(0), eq(SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR));
@@ -289,10 +295,12 @@
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE),
eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
@@ -312,10 +320,12 @@
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS),
eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
assertTrue(testSatelliteDatagramCallback.waitForOnSatelliteDatagramReceived());
@@ -339,6 +349,7 @@
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS),
eq(10), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
verify(mMockSessionMetricsStats, times(1)).addCountOfSuccessfulIncomingDatagram();
@@ -356,16 +367,19 @@
verify(mMockDatagramController, times(1)).popDemoModeDatagram();
verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING),
anyInt(),
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED),
anyInt(),
eq(SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE));
verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
anyInt(),
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
@@ -387,17 +401,20 @@
verify(mMockDatagramController, never()).popDemoModeDatagram();
verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING),
anyInt(),
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
processAllFutureMessages();
verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED),
anyInt(),
eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE));
verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
anyInt(),
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
@@ -449,10 +466,12 @@
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(anyInt(),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED),
eq(10), eq(SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED));
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(anyInt(),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
}
@@ -468,6 +487,7 @@
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(anyInt(),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java
index 873078e..354b20f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java
@@ -80,7 +80,7 @@
doReturn(Arrays.asList(SATELLITE_PLMN_ARRAY))
.when(mMockSatelliteController).getSatellitePlmnsForCarrier(anyInt());
doReturn(mSatelliteSupportedServiceList).when(mMockSatelliteController)
- .getSupportedSatelliteServices(SUB_ID, SATELLITE_PLMN);
+ .getSupportedSatelliteServicesForPlmn(SUB_ID, SATELLITE_PLMN);
}
@After
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
index 7f31f30..097e295 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -16,6 +16,13 @@
package com.android.internal.telephony.satellite;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN;
+import static android.hardware.devicestate.feature.flags.Flags.FLAG_DEVICE_STATE_PROPERTY_MIGRATION;
+import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC;
+import static android.telephony.CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT;
@@ -23,6 +30,7 @@
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ESOS_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_NIDD_APN_NAME_STRING;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL;
import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA;
import static android.telephony.SubscriptionManager.SATELLITE_ENTITLEMENT_STATUS;
@@ -31,6 +39,7 @@
import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE;
import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_POOR;
import static android.telephony.satellite.SatelliteManager.KEY_DEMO_MODE_ENABLED;
+import static android.telephony.satellite.SatelliteManager.KEY_DEPROVISION_SATELLITE_TOKENS;
import static android.telephony.satellite.SatelliteManager.KEY_EMERGENCY_MODE_ENABLED;
import static android.telephony.satellite.SatelliteManager.KEY_NTN_SIGNAL_STRENGTH;
import static android.telephony.satellite.SatelliteManager.KEY_PROVISION_SATELLITE_TOKENS;
@@ -41,6 +50,7 @@
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_NEXT_VISIBILITY;
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_PROVISIONED;
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_SUPPORTED;
+import static android.telephony.satellite.SatelliteManager.METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT;
import static android.telephony.satellite.SatelliteManager.NT_RADIO_TECHNOLOGY_EMTC_NTN;
import static android.telephony.satellite.SatelliteManager.NT_RADIO_TECHNOLOGY_NB_IOT_NTN;
import static android.telephony.satellite.SatelliteManager.NT_RADIO_TECHNOLOGY_NR_NTN;
@@ -75,12 +85,13 @@
import static com.android.internal.telephony.satellite.SatelliteController.SATELLITE_MODE_ENABLED_TRUE;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
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.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -89,6 +100,7 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.anyVararg;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
@@ -104,10 +116,16 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.NotificationManager;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.hardware.devicestate.DeviceState;
+import android.net.Uri;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -119,12 +137,17 @@
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.ResultReceiver;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.telephony.AccessNetworkConstants;
import android.telephony.CarrierConfigManager;
import android.telephony.CellSignalStrength;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.Rlog;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.satellite.INtnSignalStrengthCallback;
@@ -166,6 +189,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -181,6 +205,7 @@
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@@ -206,6 +231,7 @@
private static final int TEST_WAIT_FOR_CELLULAR_MODEM_OFF_TIMEOUT_MILLIS =
(int) TimeUnit.SECONDS.toMillis(60);
+
private static final String SATELLITE_PLMN = "00103";
private List<Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener>>
mCarrierConfigChangedListenerList = new ArrayList<>();
@@ -237,6 +263,7 @@
@Mock private Resources mResources;
@Mock private SubscriptionManager mSubscriptionManager;
@Mock private SubscriptionInfo mSubscriptionInfo;
+ @Mock private PackageManager mMockPManager;
private Semaphore mIIntegerConsumerSemaphore = new Semaphore(0);
private IIntegerConsumer mIIntegerConsumer = new IIntegerConsumer.Stub() {
@@ -513,6 +540,10 @@
}
};
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule =
+ DeviceFlagsValueProvider.createCheckFlagsRule();
+
@Before
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
@@ -548,9 +579,11 @@
when(mPhone.getServiceState()).thenReturn(mServiceState);
when(mPhone.getSubId()).thenReturn(SUB_ID);
when(mPhone.getPhoneId()).thenReturn(0);
+ when(mPhone.getSignalStrengthController()).thenReturn(mSignalStrengthController);
when(mPhone2.getServiceState()).thenReturn(mServiceState2);
when(mPhone2.getSubId()).thenReturn(SUB_ID1);
when(mPhone2.getPhoneId()).thenReturn(1);
+ when(mPhone2.getSignalStrengthController()).thenReturn(mSignalStrengthController);
mContextFixture.putStringArrayResource(
R.array.config_satellite_providers,
@@ -561,6 +594,9 @@
mContextFixture.putIntResource(
R.integer.config_satellite_wait_for_cellular_modem_off_timeout_millis,
TEST_WAIT_FOR_CELLULAR_MODEM_OFF_TIMEOUT_MILLIS);
+ mContextFixture.putIntArrayResource(
+ R.array.config_foldedDeviceStates,
+ new int[0]);
doReturn(ACTIVE_SUB_IDS).when(mMockSubscriptionManagerService).getActiveSubIdList(true);
mCarrierConfigBundle = mContextFixture.getCarrierConfigBundle();
@@ -619,7 +655,7 @@
doNothing().when(mMockProvisionMetricsStats).reportProvisionMetrics();
doNothing().when(mMockControllerMetricsStats).reportDeprovisionCount(anyInt());
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
- when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
doReturn(mSST).when(mPhone).getServiceStateTracker();
doReturn(mSST).when(mPhone2).getServiceStateTracker();
doReturn(mServiceState).when(mSST).getServiceState();
@@ -922,6 +958,7 @@
@Test
public void testRequestSatelliteEnabled() {
when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mFeatureFlags.satelliteStateChangeListener()).thenReturn(true);
mIsSatelliteEnabledSemaphore.drainPermits();
// Fail to enable satellite when SatelliteController is not fully loaded yet.
@@ -978,6 +1015,7 @@
doReturn(false).when(mTelecomManager).isInEmergencyCall();
// Successfully enable satellite
+ reset(mTelephonyRegistryManager);
mIIntegerConsumerResults.clear();
mIIntegerConsumerSemaphore.drainPermits();
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
@@ -999,12 +1037,14 @@
verify(mMockDatagramController, times(2)).setDemoMode(eq(false));
verify(mMockControllerMetricsStats, times(1)).onSatelliteEnabled();
verify(mMockControllerMetricsStats, times(1)).reportServiceEnablementSuccessCount();
+ verify(mTelephonyRegistryManager).notifySatelliteStateChanged(eq(true));
// Successfully disable satellite when radio is turned off.
+ reset(mTelephonyRegistryManager);
clearInvocations(mMockSatelliteSessionController);
clearInvocations(mMockDatagramController);
mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
- when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(true);
+ mSatelliteControllerUT.isSatelliteBeingDisabled = true;
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
@@ -1023,7 +1063,8 @@
verify(mMockSatelliteSessionController, times(2)).setDemoMode(eq(false));
verify(mMockDatagramController, times(2)).setDemoMode(eq(false));
verify(mMockControllerMetricsStats, times(1)).onSatelliteDisabled();
- when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(false);
+ mSatelliteControllerUT.isSatelliteBeingDisabled = false;
+ verify(mTelephonyRegistryManager, atLeastOnce()).notifySatelliteStateChanged(eq(false));
// Fail to enable satellite when radio is off.
mIIntegerConsumerResults.clear();
@@ -1059,6 +1100,7 @@
verify(mMockControllerMetricsStats, times(1)).reportServiceEnablementFailCount();
// Successfully enable satellite when radio is on.
+ reset(mTelephonyRegistryManager);
mIIntegerConsumerResults.clear();
mIIntegerConsumerSemaphore.drainPermits();
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
@@ -1077,6 +1119,7 @@
verify(mMockDatagramController, times(3)).setDemoMode(eq(false));
verify(mMockControllerMetricsStats, times(2)).onSatelliteEnabled();
verify(mMockControllerMetricsStats, times(2)).reportServiceEnablementSuccessCount();
+ verify(mTelephonyRegistryManager).notifySatelliteStateChanged(eq(true));
// Successfully enable satellite when it is already enabled.
mIIntegerConsumerResults.clear();
@@ -1097,6 +1140,7 @@
verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
// Successfully disable satellite.
+ reset(mTelephonyRegistryManager);
mIIntegerConsumerResults.clear();
mIIntegerConsumerSemaphore.drainPermits();
setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
@@ -1105,6 +1149,7 @@
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+ verify(mTelephonyRegistryManager, atLeastOnce()).notifySatelliteStateChanged(eq(false));
// Disable satellite when satellite is already disabled.
mIIntegerConsumerResults.clear();
@@ -1171,7 +1216,7 @@
mIIntegerConsumerResults.clear();
mIIntegerConsumerSemaphore.drainPermits();
mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
- when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(true);
+ mSatelliteControllerUT.isSatelliteBeingDisabled = true;
mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -1180,7 +1225,7 @@
mIIntegerConsumerResults.clear();
mIIntegerConsumerSemaphore.drainPermits();
resetSatelliteControllerUTToOffAndProvisionedState();
- when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(false);
+ mSatelliteControllerUT.isSatelliteBeingDisabled = false;
/**
* Make areAllRadiosDisabled return false and move mWaitingForRadioDisabled to true, which
@@ -1548,7 +1593,7 @@
public void testIsSatelliteEnabled() {
logd("testIsSatelliteEnabled: starting");
setUpResponseForRequestIsSatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
- assertFalse(mSatelliteControllerUT.isSatelliteEnabled());
+ assertFalse(mSatelliteControllerUT.isSatelliteEnabledOrBeingEnabled());
mIsSatelliteEnabledSemaphore.drainPermits();
mSatelliteControllerUT.requestIsSatelliteEnabled(mIsSatelliteEnabledReceiver);
processAllMessages();
@@ -1564,7 +1609,8 @@
mSatelliteControllerUT.requestIsSatelliteEnabled(mIsSatelliteEnabledReceiver);
processAllMessages();
assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedIsSatelliteEnabledResultCode);
- assertEquals(mSatelliteControllerUT.isSatelliteEnabled(), mQueriedIsSatelliteEnabled);
+ assertEquals(mSatelliteControllerUT.isSatelliteEnabledOrBeingEnabled(),
+ mQueriedIsSatelliteEnabled);
}
@Test
@@ -1602,6 +1648,11 @@
public void onRegistrationFailure(int causeCode) {
logd("onRegistrationFailure: causeCode=" + causeCode);
}
+
+ @Override
+ public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) {
+ logd("onTerrestrialNetworkAvailableChanged: isAvailable=" + isAvailable);
+ }
};
int errorCode = mSatelliteControllerUT.registerForSatelliteModemStateChanged(callback);
assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, errorCode);
@@ -1633,6 +1684,11 @@
public void onRegistrationFailure(int causeCode) {
logd("onRegistrationFailure: causeCode=" + causeCode);
}
+
+ @Override
+ public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) {
+ logd("onTerrestrialNetworkAvailableChanged: isAvailable=" + isAvailable);
+ }
};
mSatelliteControllerUT.unregisterForModemStateChanged(callback);
verify(mMockSatelliteSessionController, never())
@@ -1683,6 +1739,14 @@
semaphore, 1, "testRegisterForSatelliteProvisionStateChanged"));
assertEquals(SATELLITE_RESULT_SUCCESS, errorCode);
+ try {
+ setSatelliteSubscriberTesting();
+ } catch (Exception ex) {
+ fail("provisionSatelliteService.setSatelliteSubscriberTesting: ex=" + ex);
+ }
+ doReturn(true).when(mMockSubscriptionManagerService).isSatelliteProvisionedForNonIpDatagram(
+ anyInt());
+
String mText = "This is test provision data.";
byte[] testProvisionData = mText.getBytes();
CancellationSignal cancellationSignal = new CancellationSignal();
@@ -1715,11 +1779,11 @@
logd("onSatelliteDatagramReceived");
}
};
- when(mMockDatagramController.registerForSatelliteDatagram(eq(SUB_ID), eq(callback)))
+ when(mMockDatagramController.registerForSatelliteDatagram(anyInt(), eq(callback)))
.thenReturn(SATELLITE_RESULT_SUCCESS);
int errorCode = mSatelliteControllerUT.registerForIncomingDatagram(callback);
assertEquals(SATELLITE_RESULT_SUCCESS, errorCode);
- verify(mMockDatagramController).registerForSatelliteDatagram(eq(SUB_ID), eq(callback));
+ verify(mMockDatagramController).registerForSatelliteDatagram(anyInt(), eq(callback));
}
@Test
@@ -1734,9 +1798,9 @@
}
};
doNothing().when(mMockDatagramController)
- .unregisterForSatelliteDatagram(eq(SUB_ID), eq(callback));
+ .unregisterForSatelliteDatagram(anyInt(), eq(callback));
mSatelliteControllerUT.unregisterForIncomingDatagram(callback);
- verify(mMockDatagramController).unregisterForSatelliteDatagram(eq(SUB_ID), eq(callback));
+ verify(mMockDatagramController).unregisterForSatelliteDatagram(anyInt(), eq(callback));
}
@Test
@@ -1829,6 +1893,8 @@
@Test
public void testProvisionSatelliteService() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
+
String mText = "This is test provision data.";
byte[] testProvisionData = mText.getBytes();
CancellationSignal cancellationSignal = new CancellationSignal();
@@ -1913,6 +1979,7 @@
@Test
public void testDeprovisionSatelliteService() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
mIIntegerConsumerSemaphore.drainPermits();
mIIntegerConsumerResults.clear();
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
@@ -1984,7 +2051,7 @@
SUB_ID);
assertEquals(EMPTY_STRING_ARRAY.length, satellitePlmnList.size());
List<Integer> supportedSatelliteServices =
- mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00101");
+ mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(SUB_ID, "00101");
assertTrue(supportedSatelliteServices.isEmpty());
String[] satelliteProviderStrArray = {"00101", "00102"};
@@ -2011,7 +2078,7 @@
satellitePlmnList = testSatelliteController.getSatellitePlmnsForCarrier(SUB_ID);
assertTrue(satellitePlmnList.isEmpty());
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00101");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00101");
assertTrue(supportedSatelliteServices.isEmpty());
// Add entitlement provided PLMNs.
@@ -2027,16 +2094,16 @@
processAllMessages();
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00102");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
assertTrue(supportedSatelliteServices.isEmpty());
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00103");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
assertTrue(supportedSatelliteServices.isEmpty());
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00104");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00104");
assertTrue(supportedSatelliteServices.isEmpty());
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00105");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00105");
assertTrue(supportedSatelliteServices.isEmpty());
// Trigger carrier config changed with carrierEnabledSatelliteFlag enabled
@@ -2055,27 +2122,27 @@
assertTrue(Arrays.equals(
expectedSupportedSatellitePlmns, satellitePlmnList.stream().toArray()));
supportedSatelliteServices =
- mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00102");
+ mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
// "00101" should return carrier config assigned value, though it is in allowed list.
assertTrue(Arrays.equals(expectedSupportedServices2,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00103");
+ mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
assertTrue(Arrays.equals(expectedSupportedServices3,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
// "00104", and "00105" should return default supported service.
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00104");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00104");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00105");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00105");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
@@ -2096,33 +2163,33 @@
assertTrue(satellitePlmnList.isEmpty());
// "00102" and "00103" should return default supported service for SUB_ID.
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00102");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00103");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
// "00104", and "00105" should return default supported service for SUB_ID.
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00104");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00104");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00105");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00105");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00102");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID1, "00102");
assertNotNull(supportedSatelliteServices);
assertTrue(Arrays.equals(expectedSupportedServices2,
supportedSatelliteServices.stream()
@@ -2130,20 +2197,20 @@
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00103");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID1, "00103");
assertTrue(Arrays.equals(expectedSupportedServices3,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
/* "00104", and "00105" should return default supported service. */
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00104");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID1, "00104");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00105");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID1, "00105");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
@@ -2491,6 +2558,7 @@
assertTrue(
mQueriedSatelliteCapabilities.getSupportedRadioTechnologies().contains(
satelliteController.getSupportedNtnRadioTechnology()));
+ assertEquals(mQueriedSatelliteCapabilities.getMaxBytesPerOutgoingDatagram(), 255);
assertTrue(satelliteController.isSatelliteAttachRequired());
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
@@ -2517,14 +2585,14 @@
clearInvocations(mMockSatelliteSessionController);
clearInvocations(mMockDatagramController);
- when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(true);
+ mSatelliteControllerUT.isSatelliteBeingDisabled = true;
sendSatelliteModemStateChangedEvent(SATELLITE_MODEM_STATE_NOT_CONNECTED, null);
processAllMessages();
verify(mMockSatelliteSessionController, times(1)).onSatelliteModemStateChanged(
SATELLITE_MODEM_STATE_NOT_CONNECTED);
clearInvocations(mMockSatelliteSessionController);
- when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(false);
+ mSatelliteControllerUT.isSatelliteBeingDisabled = false;
sendSatelliteModemStateChangedEvent(SATELLITE_MODEM_STATE_NOT_CONNECTED, null);
processAllMessages();
verify(mMockSatelliteSessionController, never()).onSatelliteModemStateChanged(
@@ -2534,7 +2602,6 @@
@Test
public void testRequestNtnSignalStrengthWithFeatureFlagEnabled() {
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
-
resetSatelliteControllerUT();
mRequestNtnSignalStrengthSemaphore.drainPermits();
@@ -3267,7 +3334,8 @@
setConfigData(new ArrayList<>());
setCarrierConfigDataPlmnList(new ArrayList<>());
invokeCarrierConfigChanged();
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "31016");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "31016");
assertEquals(new ArrayList<>(), servicesPerPlmn);
// Verify whether the carrier config plmn list is returned with conditions below
@@ -3276,13 +3344,16 @@
setConfigData(new ArrayList<>());
setCarrierConfigDataPlmnList(Arrays.asList("00101", "00102", "00104"));
invokeCarrierConfigChanged();
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00101");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00101");
assertEquals(Arrays.asList(2).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00102");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00102");
assertEquals(Arrays.asList(1, 3).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00104");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00104");
assertEquals(Arrays.asList(2).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
@@ -3292,15 +3363,19 @@
setConfigData(Arrays.asList("00101", "00102", "31024"));
setCarrierConfigDataPlmnList(Arrays.asList("00101", "00102", "00104"));
invokeCarrierConfigChanged();
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00101");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00101");
assertEquals(Arrays.asList(1).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00102");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00102");
assertEquals(Arrays.asList(3).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00104");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00104");
assertEquals(new ArrayList<>(), servicesPerPlmn.stream().sorted().toList());
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "31024");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "31024");
assertEquals(Arrays.asList(5).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
}
@@ -3580,6 +3655,10 @@
@Test
public void testHandleEventServiceStateChanged() {
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
+ CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC);
+ invokeCarrierConfigChanged();
+
// Do nothing when the satellite is not connected
doReturn(false).when(mServiceState).isUsingNonTerrestrialNetwork();
sendServiceStateChangedEvent();
@@ -3593,12 +3672,14 @@
processAllMessages();
verify(mMockNotificationManager, times(1)).notifyAsUser(anyString(), anyInt(), any(),
any());
- assertTrue(mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false));
+ // Just by showing notification we do not update the pref file , only once user interact
+ // only we will update the pref value to true.
+ assertFalse(mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false));
// Check don't display again after displayed already a system notification.
sendServiceStateChangedEvent();
processAllMessages();
- verify(mMockNotificationManager, times(1)).notifyAsUser(anyString(), anyInt(), any(),
+ verify(mMockNotificationManager, times(2)).notifyAsUser(anyString(), anyInt(), any(),
any());
}
@@ -4013,8 +4094,10 @@
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ mSatelliteControllerUT.mIsApplicationSupportsP2P = true;
mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 1);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL, true);
int[] supportedServices2 = {2};
int[] supportedServices3 = {1, 3};
PersistableBundle carrierSupportedSatelliteServicesPerProvider = new PersistableBundle();
@@ -4035,6 +4118,33 @@
processAllMessages();
assertTrue(mSatelliteControllerUT.isCarrierRoamingNtnEligible(mPhone));
+
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ when(mServiceState2.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ processAllMessages();
+ assertFalse(mSatelliteControllerUT.isCarrierRoamingNtnEligible(mPhone));
+
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ when(mServiceState2.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ mSatelliteControllerUT.overrideCarrierRoamingNtnEligibilityChanged(true, false);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isCarrierRoamingNtnEligible(mPhone));
+ }
+
+ @Test
+ public void testOverrideCarrierRoamingNtNEligibilityChange() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mSatelliteControllerUT.overrideCarrierRoamingNtnEligibilityChanged(true, false);
+ verify(mPhone, times(1)).notifyCarrierRoamingNtnEligibleStateChanged(eq(true));
+ clearInvocations(mPhone);
+
+ mSatelliteControllerUT.overrideCarrierRoamingNtnEligibilityChanged(false, false);
+ verify(mPhone, times(1)).notifyCarrierRoamingNtnEligibleStateChanged(eq(false));
+ clearInvocations(mPhone);
+
+ mSatelliteControllerUT.overrideCarrierRoamingNtnEligibilityChanged(false, true);
+ verify(mPhone, times(0)).notifyCarrierRoamingNtnEligibleStateChanged(eq(true));
+ clearInvocations(mPhone);
}
@Test
@@ -4043,10 +4153,12 @@
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ mSatelliteControllerUT.mIsApplicationSupportsP2P = true;
mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 1);
mCarrierConfigBundle.putInt(
KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT, 1 * 60);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL, true);
int[] supportedServices2 = {2};
int[] supportedServices3 = {1, 3};
PersistableBundle carrierSupportedSatelliteServicesPerProvider = new PersistableBundle();
@@ -4116,11 +4228,48 @@
assertTrue(mSatelliteControllerUT.isCarrierRoamingNtnEligible(mPhone));
verify(mPhone, times(0)).notifyCarrierRoamingNtnEligibleStateChanged(eq(true));
verify(mPhone2, times(0)).notifyCarrierRoamingNtnEligibleStateChanged(anyBoolean());
- verify(mMockNotificationManager, times(1)).cancelAsUser(anyString(), anyInt(),
+ verify(mMockNotificationManager, times(2)).cancelAsUser(anyString(), anyInt(),
any());
}
@Test
+ public void testNotifyCarrierRoamingNtnSignalStrengthChanged() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+
+ sendSignalStrengthChangedEvent(mPhone.getPhoneId());
+ processAllMessages();
+ ArgumentCaptor<NtnSignalStrength> captor = ArgumentCaptor.forClass(NtnSignalStrength.class);
+ verify(mPhone, times(1)).notifyCarrierRoamingNtnSignalStrengthChanged(
+ captor.capture());
+ NtnSignalStrength actualSignalStrength = captor.getValue();
+ assertEquals(NTN_SIGNAL_STRENGTH_NONE, actualSignalStrength.getLevel());
+ clearInvocations(mPhone);
+
+ when(mSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_GOOD);
+ when(mPhone.getSignalStrength()).thenReturn(mSignalStrength);
+ mCarrierConfigBundle.putInt(KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT, 1 * 60);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+ for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+ : mCarrierConfigChangedListenerList) {
+ pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+ /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+ );
+ }
+ processAllMessages();
+ when(mServiceState.isUsingNonTerrestrialNetwork()).thenReturn(true);
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ sendServiceStateChangedEvent();
+ processAllMessages();
+ captor = ArgumentCaptor.forClass(NtnSignalStrength.class);
+ verify(mPhone, times(1)).notifyCarrierRoamingNtnSignalStrengthChanged(
+ captor.capture());
+ actualSignalStrength = captor.getValue();
+ assertEquals(NTN_SIGNAL_STRENGTH_GOOD, actualSignalStrength.getLevel());
+ clearInvocations(mPhone);
+ }
+
+ @Test
public void testGetWwanIsInService() {
when(mServiceState.getNetworkRegistrationInfoListForTransportType(
eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
@@ -4143,16 +4292,8 @@
.thenReturn(List.of(nri));
assertTrue(mSatelliteControllerUT.getWwanIsInService(mServiceState));
- nri = new NetworkRegistrationInfo.Builder()
- .setEmergencyOnly(true)
- .build();
- when(mServiceState.getNetworkRegistrationInfoListForTransportType(
- eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
- .thenReturn(List.of(nri));
- assertTrue(mSatelliteControllerUT.getWwanIsInService(mServiceState));
-
nri = new NetworkRegistrationInfo.Builder().setRegistrationState(
- NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
.build();
when(mServiceState.getNetworkRegistrationInfoListForTransportType(
eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
@@ -4182,6 +4323,11 @@
resultErrorCode[0] = causeCode;
semaphore.release();
}
+
+ @Override
+ public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) {
+ logd("onTerrestrialNetworkAvailableChanged: isAvailable=" + isAvailable);
+ }
};
resetSatelliteControllerUTToSupportedAndProvisionedState();
mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
@@ -4200,6 +4346,86 @@
assertEquals(expectedErrorCode, resultErrorCode[0]);
}
+ @RequiresFlagsDisabled(FLAG_DEVICE_STATE_PROPERTY_MIGRATION)
+ @Test
+ public void testDetermineIsFoldable_overlayConfigurationValues() {
+ // isFoldable should return false with the base configuration.
+ assertFalse(mSatelliteControllerUT.isFoldable(mContext,
+ mSatelliteControllerUT.getSupportedDeviceStates()));
+
+ mContextFixture.putIntArrayResource(R.array.config_foldedDeviceStates, new int[2]);
+ assertTrue(mSatelliteControllerUT.isFoldable(mContext,
+ mSatelliteControllerUT.getSupportedDeviceStates()));
+ }
+
+ @RequiresFlagsEnabled(FLAG_DEVICE_STATE_PROPERTY_MIGRATION)
+ @Test
+ public void testDetermineIsFoldable_deviceStateManager() {
+ // isFoldable should return false with the base configuration.
+ assertFalse(mSatelliteControllerUT.isFoldable(mContext,
+ mSatelliteControllerUT.getSupportedDeviceStates()));
+
+ DeviceState foldedDeviceState = new DeviceState(new DeviceState.Configuration.Builder(
+ 0 /* identifier */, "FOLDED")
+ .setSystemProperties(Set.of(PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY))
+ .setPhysicalProperties(
+ Set.of(PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED))
+ .build());
+ DeviceState unfoldedDeviceState = new DeviceState(new DeviceState.Configuration.Builder(
+ 1 /* identifier */, "UNFOLDED")
+ .setSystemProperties(Set.of(PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY))
+ .setPhysicalProperties(
+ Set.of(PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN))
+ .build());
+ List<DeviceState> foldableDeviceStateList = List.of(foldedDeviceState, unfoldedDeviceState);
+ assertTrue(mSatelliteControllerUT.isFoldable(mContext, foldableDeviceStateList));
+ }
+
+ @Test
+ public void testTerrestrialNetworkAvailableChangedCallback() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ Semaphore semaphore = new Semaphore(0);
+ final int[] receivedScanResult = new int[1];
+ ISatelliteModemStateCallback callback = new ISatelliteModemStateCallback.Stub() {
+ @Override
+ public void onSatelliteModemStateChanged(int state) {
+ logd("onSatelliteModemStateChanged: state=" + state);
+ }
+
+ @Override
+ public void onEmergencyModeChanged(boolean isEmergency) {
+ logd("onEmergencyModeChanged: emergency=" + isEmergency);
+ }
+
+ @Override
+ public void onRegistrationFailure(int causeCode) {
+ logd("onRegistrationFailure: causeCode=" + causeCode);
+ }
+
+ @Override
+ public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) {
+ logd("onTerrestrialNetworkAvailableChanged: isAvailable=" + isAvailable);
+ receivedScanResult[0] = isAvailable ? 1 : 0;
+ semaphore.release();
+ }
+ };
+ resetSatelliteControllerUTToSupportedAndProvisionedState();
+ mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
+
+ int RegisterErrorCode = mSatelliteControllerUT.registerForSatelliteModemStateChanged(
+ callback);
+ assertEquals(SATELLITE_RESULT_SUCCESS, RegisterErrorCode);
+ verify(mMockSatelliteSessionController).registerForSatelliteModemStateChanged(callback);
+
+ int expectedErrorCode = 1;
+ mIIntegerConsumerResults.clear();
+ sendTerrestrialNetworkAvailableChangedEvent(true, null);
+ processAllMessages();
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegistrationFailureCallback"));
+ assertEquals(expectedErrorCode, receivedScanResult[0]);
+ }
+
private boolean mProvisionState = false;
private int mProvisionSateResultCode = -1;
private Semaphore mProvisionSateSemaphore = new Semaphore(0);
@@ -4270,6 +4496,7 @@
private void verifyRequestSatelliteSubscriberProvisionStatus() throws Exception {
setSatelliteSubscriberTesting();
List<SatelliteSubscriberInfo> list = getExpectedSatelliteSubscriberInfoList();
+ mCarrierConfigBundle.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
mCarrierConfigBundle.putString(KEY_SATELLITE_NIDD_APN_NAME_STRING, mNiddApn);
mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ESOS_SUPPORTED_BOOL, true);
for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
@@ -4316,7 +4543,6 @@
assertTrue(mProvisionState);
}
-
@Test
public void testRegisterForSatelliteSubscriptionProvisionStateChanged() throws Exception {
when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
@@ -4375,8 +4601,6 @@
inputList.add(list.get(1));
verifyProvisionSatellite(inputList);
- verify(mMockSatelliteModemInterface, times(2)).updateSatelliteSubscription(anyString(),
- any());
assertTrue(waitForForEvents(
semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
assertTrue(resultArray[1].getProvisionStatus());
@@ -4386,10 +4610,92 @@
// requested, and verify that onSatelliteSubscriptionProvisionStateChanged is not called.
verifyProvisionSatellite(inputList);
- verify(mMockSatelliteModemInterface, times(2)).updateSatelliteSubscription(anyString(),
- any());
assertFalse(waitForForEvents(
semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
+
+ // Request deprovision for subscriberID 2, verify that subscriberID 2 is set to
+ // deprovision and that subscriberID 1 is set to provision.
+ verifyDeprovisionSatellite(inputList);
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
+ assertFalse(resultArray[1].getProvisionStatus());
+ assertEquals(mSubscriberId2, resultArray[1].getSatelliteSubscriberInfo().getSubscriberId());
+ assertTrue(resultArray[0].getProvisionStatus());
+ assertEquals(mSubscriberId, resultArray[0].getSatelliteSubscriberInfo().getSubscriberId());
+
+ // Request deprovision for subscriberID 1, verify that subscriberID 1 is set to deprovision.
+ inputList = new ArrayList<>();
+ inputList.add(list.get(0));
+ verifyDeprovisionSatellite(inputList);
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
+ assertFalse(resultArray[1].getProvisionStatus());
+ assertEquals(mSubscriberId2, resultArray[1].getSatelliteSubscriberInfo().getSubscriberId());
+ assertFalse(resultArray[0].getProvisionStatus());
+ assertEquals(mSubscriberId, resultArray[0].getSatelliteSubscriberInfo().getSubscriberId());
+
+ // Request provision for subscriberID 2, verify that subscriberID 2 is set to provision.
+ inputList = new ArrayList<>();
+ inputList.add(list.get(1));
+ verifyProvisionSatellite(inputList);
+
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
+ assertTrue(resultArray[1].getProvisionStatus());
+ assertEquals(mSubscriberId2, resultArray[1].getSatelliteSubscriberInfo().getSubscriberId());
+ assertFalse(resultArray[0].getProvisionStatus());
+ assertEquals(mSubscriberId, resultArray[0].getSatelliteSubscriberInfo().getSubscriberId());
+ }
+
+ private boolean mDeprovisionDone = false;
+ private int mDeprovisionSateResultCode = -1;
+ private Semaphore mDeprovisionSateSemaphore = new Semaphore(0);
+ private ResultReceiver mDeprovisionSatelliteReceiver = new ResultReceiver(null) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ mDeprovisionSateResultCode = resultCode;
+ logd("DeprovisionSatelliteReceiver: resultCode=" + resultCode);
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
+ if (resultData.containsKey(KEY_DEPROVISION_SATELLITE_TOKENS)) {
+ mDeprovisionDone = resultData.getBoolean(KEY_DEPROVISION_SATELLITE_TOKENS);
+ logd("DeprovisionSatelliteReceiver: deprovision=" + mDeprovisionDone);
+ } else {
+ loge("KEY_DEPROVISION_SATELLITE_TOKENS does not exist.");
+ mDeprovisionDone = false;
+ }
+ } else {
+ mDeprovisionDone = false;
+ }
+ try {
+ mDeprovisionSateSemaphore.release();
+ } catch (Exception ex) {
+ loge("DeprovisionSatelliteReceiver: Got exception in releasing semaphore " + ex);
+ }
+ }
+ };
+
+ @Test
+ public void testDeprovisionSatellite() throws Exception {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+ verifyRequestSatelliteSubscriberProvisionStatus();
+ List<SatelliteSubscriberInfo> inputList = getExpectedSatelliteSubscriberInfoList();
+ verifyProvisionSatellite(inputList);
+ verifyDeprovisionSatellite(inputList);
+ }
+
+ private void verifyDeprovisionSatellite(List<SatelliteSubscriberInfo> inputList) {
+ doAnswer(invocation -> {
+ Message message = (Message) invocation.getArguments()[1];
+ AsyncResult.forMessage(message, null, new SatelliteException(SATELLITE_RESULT_SUCCESS));
+ message.sendToTarget();
+ return null;
+ }).when(mMockSatelliteModemInterface).updateSatelliteSubscription(anyString(), any());
+
+ mSatelliteControllerUT.deprovisionSatellite(inputList, mDeprovisionSatelliteReceiver);
+ processAllMessages();
+ assertEquals(SATELLITE_RESULT_SUCCESS, mDeprovisionSateResultCode);
+ assertTrue(mDeprovisionDone);
}
private void setSatelliteSubscriberTesting() throws Exception {
@@ -4506,6 +4812,7 @@
@Test
public void testCheckForSubscriberIdChange_changed() {
when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mCarrierConfigBundle.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
List<SubscriptionInfo> allSubInfos = new ArrayList<>();
String imsi = "012345";
@@ -4524,6 +4831,7 @@
.thenReturn(allSubInfos);
when(mSubscriptionInfo.isSatelliteESOSSupported()).thenReturn(true);
+ when(mSubscriptionInfo.isActive()).thenReturn(true);
when(mMockSubscriptionManagerService.getSubscriptionInfoInternal(SUB_ID))
.thenReturn(subInfoInternal);
@@ -4578,6 +4886,134 @@
eq(SUB_ID), eq(true));
}
+ @Test
+ public void testIsCarrierRoamingNtnAvailableServicesForManualConnect() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+ // CARRIER_ROAMING_NTN_CONNECT_MANUAL: 1
+ mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 1);
+
+ mSatelliteControllerUT.setSatellitePhone(1);
+ processAllMessages();
+ when(mContext.getPackageManager()).thenReturn(mMockPManager);
+ try {
+ when(mMockPManager.getApplicationInfo(anyString(),
+ anyInt())).thenReturn(getApplicationInfo());
+ } catch (PackageManager.NameNotFoundException e) {
+ logd("NameNotFoundException");
+ }
+ assertTrue(mSatelliteControllerUT
+ .isP2PSmsDisallowedOnCarrierRoamingNtn(/*subId*/ SUB_ID));
+ }
+
+ @Test
+ public void testIsCarrierRoamingNtnAvailableServicesForAutomaticConnect() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+ // CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC: 0
+ mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 0);
+
+ mSatelliteControllerUT.setSatellitePhone(1);
+ processAllMessages();
+ when(mContext.getPackageManager()).thenReturn(mMockPManager);
+ try {
+ when(mMockPManager.getApplicationInfo(anyString(),
+ anyInt())).thenReturn(getApplicationInfo());
+ } catch (PackageManager.NameNotFoundException e) {
+ logd("NameNotFoundException");
+ }
+ // If it is automatic connection case, it is not support the callback.
+ assertFalse(mSatelliteControllerUT
+ .isP2PSmsDisallowedOnCarrierRoamingNtn(/*subId*/ SUB_ID));
+ }
+
+ ApplicationInfo getApplicationInfo() {
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.metaData = new Bundle();
+ applicationInfo.metaData.putBoolean(
+ METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT, true);
+ return applicationInfo;
+ }
+
+ @Test
+ public void testRegisterApplicationStateChanged() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, false);
+ when(mMockSubscriptionManagerService.getActiveSubIdList(true))
+ .thenReturn(new int[]{SUB_ID1});
+
+ ArgumentCaptor<IntentFilter> intentFilterCaptor =
+ ArgumentCaptor.forClass(IntentFilter.class);
+ ArgumentCaptor<BroadcastReceiver> receiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mContext).registerReceiver(receiverCaptor.capture(), intentFilterCaptor.capture(),
+ anyInt());
+
+ BroadcastReceiver receiver = receiverCaptor.getValue();
+ mSatelliteControllerUT =
+ new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
+ assertFalse(mSatelliteControllerUT.isApplicationUpdated);
+ Intent intent = new Intent(Intent.ACTION_PACKAGE_ADDED);
+ intent.setData(Uri.parse("com.example.app"));
+ receiver.onReceive(mContext, intent);
+ CountDownLatch latch1 = new CountDownLatch(1);
+ new Handler(Looper.getMainLooper()).postDelayed(() -> {
+ latch1.countDown();
+ }, 100);
+ try {
+ latch1.await();
+ } catch (InterruptedException e) {
+ }
+ assertTrue(mSatelliteControllerUT.isApplicationUpdated);
+ mSatelliteControllerUT =
+ new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
+ assertFalse(mSatelliteControllerUT.isApplicationUpdated);
+ intent = new Intent(Intent.ACTION_PACKAGE_REPLACED);
+ intent.setData(Uri.parse("com.example.app"));
+ receiver.onReceive(mContext, intent);
+ CountDownLatch latch2 = new CountDownLatch(1);
+ new Handler(Looper.getMainLooper()).postDelayed(() -> {
+ latch2.countDown();
+ }, 100);
+ try {
+ latch2.await();
+ } catch (InterruptedException e) {
+ }
+ assertTrue(mSatelliteControllerUT.isApplicationUpdated);
+ mSatelliteControllerUT =
+ new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
+ assertFalse(mSatelliteControllerUT.isApplicationUpdated);
+ intent = new Intent(Intent.ACTION_PACKAGE_REMOVED);
+ intent.setData(Uri.parse("com.example.app"));
+ receiver.onReceive(mContext, intent);
+ CountDownLatch latch3 = new CountDownLatch(1);
+ new Handler(Looper.getMainLooper()).postDelayed(() -> {
+ latch3.countDown();
+ }, 100);
+ try {
+ latch3.await();
+ } catch (InterruptedException e) {
+ }
+ assertTrue(mSatelliteControllerUT.isApplicationUpdated);
+ mSatelliteControllerUT =
+ new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
+ assertFalse(mSatelliteControllerUT.isApplicationUpdated);
+ intent = new Intent(Intent.ACTION_PACKAGE_ADDED);
+ intent.setData(Uri.parse("com.example.different"));
+ receiver.onReceive(mContext, intent);
+ CountDownLatch latch4 = new CountDownLatch(1);
+ new Handler(Looper.getMainLooper()).postDelayed(() -> {
+ latch4.countDown();
+ }, 100);
+ try {
+ latch4.await();
+ } catch (InterruptedException e) {
+ }
+ assertFalse(mSatelliteControllerUT.isApplicationUpdated);
+ }
+
private void verifyProvisionStatusPerSubscriberIdGetFromDb(boolean provision) {
doReturn(provision).when(
mMockSubscriptionManagerService).isSatelliteProvisionedForNonIpDatagram(anyInt());
@@ -5084,6 +5520,13 @@
msg.sendToTarget();
}
+ private void sendSignalStrengthChangedEvent(int phoneId) {
+ Message msg = mSatelliteControllerUT.obtainMessage(
+ 57 /* EVENT_SIGNAL_STRENGTH_CHANGED */);
+ msg.obj = new AsyncResult(phoneId, null, null);
+ msg.sendToTarget();
+ }
+
private void sendCmdStartSendingNtnSignalStrengthChangedEvent(boolean shouldReport) {
Message msg = mSatelliteControllerUT.obtainMessage(
35 /* CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING */);
@@ -5127,6 +5570,14 @@
msg.sendToTarget();
}
+ private void sendTerrestrialNetworkAvailableChangedEvent(boolean isAvailable,
+ Throwable exception) {
+ Message msg = mSatelliteControllerUT.obtainMessage(
+ 55 /* EVENT_TERRESTRIAL_NETWORK_AVAILABLE_CHANGED */);
+ msg.obj = new AsyncResult(null, isAvailable, exception);
+ msg.sendToTarget();
+ }
+
private void setRadioPower(boolean on) {
mSimulatedCommands.setRadioPower(on, false, false, null);
}
@@ -5156,6 +5607,15 @@
setUpResponseForRequestIsSatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
+
+ try {
+ setSatelliteSubscriberTesting();
+ } catch (Exception ex) {
+ fail("provisionSatelliteService.setSatelliteSubscriberTesting: ex=" + ex);
+ }
+ doReturn(true).when(mMockSubscriptionManagerService).isSatelliteProvisionedForNonIpDatagram(
+ anyInt());
+
cancelRemote = mSatelliteControllerUT.provisionSatelliteService(
TEST_SATELLITE_TOKEN,
testProvisionData, mIIntegerConsumer);
@@ -5327,11 +5787,16 @@
public int satelliteModeSettingValue = SATELLITE_MODE_ENABLED_FALSE;
public boolean setSettingsKeyToAllowDeviceRotationCalled = false;
public OutcomeReceiver<Boolean, SatelliteException> isSatelliteAllowedCallback = null;
+ public static boolean isApplicationUpdated;
+ public String packageName = "com.example.app";
+ public boolean isSatelliteBeingDisabled = false;
+ public boolean mIsApplicationSupportsP2P = false;
TestSatelliteController(
Context context, Looper looper, @NonNull FeatureFlags featureFlags) {
super(context, looper, featureFlags);
logd("Constructing TestSatelliteController");
+ isApplicationUpdated = false;
}
@Override
@@ -5400,9 +5865,41 @@
return false;
}
+ @Override
+ protected List<DeviceState> getSupportedDeviceStates() {
+ return List.of(new DeviceState(new DeviceState.Configuration.Builder(0 /* identifier */,
+ "DEFAULT" /* name */).build()));
+ }
+
+ @Override
+ public boolean isSatelliteBeingDisabled() {
+ return isSatelliteBeingDisabled;
+ }
+
+ protected String getConfigSatelliteGatewayServicePackage() {
+ String packageName = "com.example.app";
+ return packageName;
+ }
+
+ @Override
+ protected void handleCarrierRoamingNtnAvailableServicesChanged(int subId) {
+ isApplicationUpdated = true;
+ }
+
+ @Override
+ public boolean isApplicationSupportsP2P(String packageName) {
+ return mIsApplicationSupportsP2P;
+ }
+
+ @Override
+ public int[] getSupportedServicesOnCarrierRoamingNtn(int subId) {
+ return new int[]{3, 5};
+ }
+
+
void setSatelliteProvisioned(@Nullable Boolean isProvisioned) {
- synchronized (mSatelliteViaOemProvisionLock) {
- mIsSatelliteViaOemProvisioned = isProvisioned;
+ synchronized (mDeviceProvisionLock) {
+ mIsDeviceProvisioned = isProvisioned;
}
}
@@ -5445,5 +5942,88 @@
public boolean isAnyWaitForSatelliteEnablingResponseTimerStarted() {
return hasMessages(EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT);
}
+
+ public int getResultReceiverTotalCount() {
+ synchronized (mResultReceiverTotalCountLock) {
+ return mResultReceiverTotalCount;
+ }
+ }
+
+ public HashMap<String, Integer> getResultReceiverCountPerMethodMap() {
+ synchronized (mResultReceiverTotalCountLock) {
+ return mResultReceiverCountPerMethodMap;
+ }
+ }
+ }
+
+ @Test
+ public void testLoggingCodeForResultReceiverCount() throws Exception {
+ final String callerSC = "SC:ResultReceiver";
+ final String callerSAC = "SAC:ResultReceiver";
+
+ doReturn(false).when(mFeatureFlags).geofenceEnhancementForBetterUx();
+
+ mSatelliteControllerUT.incrementResultReceiverCount(callerSC);
+ assertEquals(0, mSatelliteControllerUT.getResultReceiverTotalCount());
+ mSatelliteControllerUT.decrementResultReceiverCount(callerSC);
+ assertEquals(0, mSatelliteControllerUT.getResultReceiverTotalCount());
+
+ doReturn(true).when(mFeatureFlags).geofenceEnhancementForBetterUx();
+
+ mSatelliteControllerUT.incrementResultReceiverCount(callerSC);
+ assertEquals(1, mSatelliteControllerUT.getResultReceiverTotalCount());
+ assertEquals(1, mSatelliteControllerUT.getResultReceiverCountPerMethodMap().size());
+ assertEquals(1, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSC)).orElse(0));
+ assertEquals(0, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSAC)).orElse(0));
+
+ mSatelliteControllerUT.incrementResultReceiverCount(callerSC);
+ assertEquals(2, mSatelliteControllerUT.getResultReceiverTotalCount());
+ assertEquals(1, mSatelliteControllerUT.getResultReceiverCountPerMethodMap().size());
+ assertEquals(2, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSC)).orElse(0));
+ assertEquals(0, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSAC)).orElse(0));
+
+ mSatelliteControllerUT.incrementResultReceiverCount(callerSAC);
+ assertEquals(3, mSatelliteControllerUT.getResultReceiverTotalCount());
+ assertEquals(2, mSatelliteControllerUT.getResultReceiverCountPerMethodMap().size());
+ assertEquals(2, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSC)).orElse(0));
+ assertEquals(1, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSAC)).orElse(0));
+
+ mSatelliteControllerUT.decrementResultReceiverCount(callerSC);
+ assertEquals(2, mSatelliteControllerUT.getResultReceiverTotalCount());
+ assertEquals(2, mSatelliteControllerUT.getResultReceiverCountPerMethodMap().size());
+ assertEquals(1, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSC)).orElse(0));
+ assertEquals(1, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSAC)).orElse(0));
+
+ mSatelliteControllerUT.decrementResultReceiverCount(callerSC);
+ assertEquals(1, mSatelliteControllerUT.getResultReceiverTotalCount());
+ assertEquals(2, mSatelliteControllerUT.getResultReceiverCountPerMethodMap().size());
+ assertEquals(0, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSC)).orElse(0));
+ assertEquals(1, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSAC)).orElse(0));
+
+ mSatelliteControllerUT.decrementResultReceiverCount(callerSAC);
+ assertEquals(0, mSatelliteControllerUT.getResultReceiverTotalCount());
+ assertEquals(2, mSatelliteControllerUT.getResultReceiverCountPerMethodMap().size());
+ assertEquals(0, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSC)).orElse(0));
+ assertEquals(0, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSAC)).orElse(0));
+ }
+
+ @Test
+ public void testSetNtnSmsSupportedByMessagesApp() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mSatelliteControllerUT.setNtnSmsSupportedByMessagesApp(true);
+ assertTrue(mSharedPreferences.getBoolean(
+ SatelliteController.NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY, false));
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
index 358ec47..56d5731 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
@@ -29,6 +29,9 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -39,6 +42,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.hardware.devicestate.DeviceState;
import android.net.Uri;
import android.os.Bundle;
import android.os.Looper;
@@ -67,6 +71,7 @@
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.flags.Flags;
+import com.android.internal.telephony.metrics.SatelliteStats;
import org.junit.After;
import org.junit.Before;
@@ -118,6 +123,8 @@
private Uri mTestConnectionAddress = Uri.parse("tel:1234");
private TestSOSMessageRecommender mTestSOSMessageRecommender;
private ServiceState mServiceState2;
+ @Mock
+ private SatelliteStats mMockSatelliteStats;
@Before
public void setUp() throws Exception {
@@ -145,14 +152,20 @@
mServiceState2 = Mockito.mock(ServiceState.class);
when(mPhone.getServiceState()).thenReturn(mServiceState);
when(mPhone.getPhoneId()).thenReturn(PHONE_ID);
+ when(mPhone.getSignalStrengthController()).thenReturn(mSignalStrengthController);
when(mPhone2.getServiceState()).thenReturn(mServiceState2);
when(mPhone2.getPhoneId()).thenReturn(PHONE_ID2);
+ when(mPhone2.getSignalStrengthController()).thenReturn(mSignalStrengthController);
mTestSOSMessageRecommender = new TestSOSMessageRecommender(mContext, Looper.myLooper(),
mTestSatelliteController, mTestImsManager);
when(mServiceState.getState()).thenReturn(STATE_OUT_OF_SERVICE);
when(mServiceState2.getState()).thenReturn(STATE_OUT_OF_SERVICE);
when(mPhone.isImsRegistered()).thenReturn(false);
when(mPhone2.isImsRegistered()).thenReturn(false);
+ replaceInstance(SatelliteStats.class, "sInstance", null,
+ mMockSatelliteStats);
+ doNothing().when(mMockSatelliteStats).onSatelliteSosMessageRecommender(
+ any(SatelliteStats.SatelliteSosMessageRecommenderParams.class));
}
@After
@@ -165,6 +178,8 @@
testTimeoutBeforeEmergencyCallEnd(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
DEFAULT_SATELLITE_MESSAGING_PACKAGE, DEFAULT_SATELLITE_MESSAGING_CLASS,
DEFAULT_T911_HANDOVER_INTENT_ACTION);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
@@ -177,6 +192,8 @@
testTimeoutBeforeEmergencyCallEnd(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
"android.com.vendor.message", "android.com.vendor.message.SmsApp",
DEFAULT_HANDOVER_INTENT_ACTION);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
@@ -188,6 +205,8 @@
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
testTimeoutBeforeEmergencyCallEnd(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS, "", "",
DEFAULT_HANDOVER_INTENT_ACTION);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
@@ -197,6 +216,8 @@
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
testTimeoutBeforeEmergencyCallEnd(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS, "", "",
DEFAULT_HANDOVER_INTENT_ACTION);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
@@ -204,16 +225,17 @@
when(mServiceState.getState()).thenReturn(STATE_OUT_OF_SERVICE);
when(mServiceState2.getState()).thenReturn(STATE_OUT_OF_SERVICE);
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
- mTestSOSMessageRecommender.onEmergencyCallStarted(null);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(null, false);
processAllMessages();
assertFalse(mTestSOSMessageRecommender.isTimerStarted());
assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
+ verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
}
private void testTimeoutBeforeEmergencyCallEnd(int expectedHandoverType,
String expectedPackageName, String expectedClassName, String expectedAction) {
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertRegisterForStateChangedEventsTriggered(mPhone, 1, 1);
@@ -239,14 +261,16 @@
}
assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testTimeoutBeforeEmergencyCallEnd_EventDisplayEmergencyMessageNotSent() {
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
- mTestSatelliteController.setIsSatelliteViaOemProvisioned(false);
+ mTestSatelliteController.setDeviceProvisioned(false);
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertRegisterForStateChangedEventsTriggered(mPhone, 1, 1);
@@ -266,6 +290,8 @@
assertFalse(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE));
assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertFalse(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
@@ -273,7 +299,7 @@
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
mTestSatelliteController.isOemEnabledSatelliteSupported = false;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertRegisterForStateChangedEventsTriggered(mPhone, 1, 1);
@@ -302,17 +328,21 @@
@Test
public void testStopTrackingCallBeforeTimeout_ConnectionActive() {
testStopTrackingCallBeforeTimeout(Connection.STATE_ACTIVE);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertFalse(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testStopTrackingCallBeforeTimeout_ConnectionDisconnected() {
testStopTrackingCallBeforeTimeout(Connection.STATE_DISCONNECTED);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertFalse(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testNetworkStateChangedBeforeTimeout() {
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
@@ -337,11 +367,13 @@
assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testSatelliteProvisionStateChangedBeforeTimeout() {
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
@@ -357,8 +389,11 @@
assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertFalse(mTestSOSMessageRecommender.isDialerNotified());
+ reset(mMockSatelliteStats);
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
@@ -387,12 +422,14 @@
assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertUnregisterForStateChangedEventsTriggered(mPhone, 2, 2);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 2, 2);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testEmergencyCallRedialBeforeTimeout() {
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
@@ -400,7 +437,7 @@
assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 1);
assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
@@ -426,35 +463,45 @@
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertFalse(mTestSOSMessageRecommender.isTimerStarted());
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testCellularServiceStateChangedBeforeTimeout_InServiceToOutOfService() {
testCellularServiceStateChangedBeforeTimeout(
ServiceState.STATE_IN_SERVICE, STATE_OUT_OF_SERVICE);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testCellularServiceStateChangedBeforeTimeout_InServiceToPowerOff() {
testCellularServiceStateChangedBeforeTimeout(
ServiceState.STATE_IN_SERVICE, ServiceState.STATE_POWER_OFF);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testCellularServiceStateChangedBeforeTimeout_EmergencyOnlyToOutOfService() {
testCellularServiceStateChangedBeforeTimeout(
ServiceState.STATE_EMERGENCY_ONLY, STATE_OUT_OF_SERVICE);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testCellularServiceStateChangedBeforeTimeout_EmergencyOnlyToPowerOff() {
testCellularServiceStateChangedBeforeTimeout(
ServiceState.STATE_EMERGENCY_ONLY, ServiceState.STATE_POWER_OFF);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testOnEmergencyCallConnectionStateChangedWithWrongCallId() {
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
@@ -471,12 +518,15 @@
assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertFalse(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testSatelliteNotAllowedInCurrentLocation() {
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
@@ -498,38 +548,42 @@
assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertFalse(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testOnEmergencyCallStarted() {
- SatelliteController satelliteController = new SatelliteController(
- mContext, Looper.myLooper(), mFeatureFlags);
+ SatelliteController satelliteController = new MinimalSatelliteControllerWrapper(mContext,
+ Looper.myLooper(), mFeatureFlags);
TestSOSMessageRecommender testSOSMessageRecommender = new TestSOSMessageRecommender(
mContext,
Looper.myLooper(),
satelliteController, mTestImsManager);
- testSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
+ testSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertFalse(testSOSMessageRecommender.isTimerStarted());
assertEquals(0, testSOSMessageRecommender.getCountOfTimerStarted());
+ verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
}
@Test
- public void testIsSatelliteViaOemAvailable() {
+ public void testIsDeviceProvisioned() {
Boolean originalIsSatelliteViaOemProvisioned =
- mTestSatelliteController.mIsSatelliteViaOemProvisioned;
+ mTestSatelliteController.mIsDeviceProvisionedForTest;
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = null;
- assertFalse(mTestSOSMessageRecommender.isSatelliteViaOemAvailable());
+ mTestSatelliteController.mIsDeviceProvisionedForTest = null;
+ assertFalse(mTestSOSMessageRecommender.isDeviceProvisioned());
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = true;
- assertTrue(mTestSOSMessageRecommender.isSatelliteViaOemAvailable());
+ mTestSatelliteController.mIsDeviceProvisionedForTest = true;
+ assertTrue(mTestSOSMessageRecommender.isDeviceProvisioned());
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = false;
- assertFalse(mTestSOSMessageRecommender.isSatelliteViaOemAvailable());
+ mTestSatelliteController.mIsDeviceProvisionedForTest = false;
+ assertFalse(mTestSOSMessageRecommender.isDeviceProvisioned());
- mTestSatelliteController.mIsSatelliteViaOemProvisioned =
+ mTestSatelliteController.mIsDeviceProvisionedForTest =
originalIsSatelliteViaOemProvisioned;
}
@@ -538,16 +592,17 @@
// Both OEM and carrier don't support satellite
mTestSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier = false;
mTestSatelliteController.isOemEnabledSatelliteSupported = false;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertEquals(0, mTestSOSMessageRecommender.getTimeOutMillis());
// Only OEM support satellite
mTestSatelliteController.isOemEnabledSatelliteSupported = true;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertEquals(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS,
mTestSOSMessageRecommender.getTimeOutMillis());
+ verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
// Both OEM and carrier support satellite, but device is not connected to carrier satellite
// within hysteresis time. Thus, OEM timer will be used.
@@ -556,10 +611,11 @@
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
mTestSatelliteController.carrierEmergencyCallWaitForConnectionTimeoutMillis =
carrierTimeoutMillis;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertEquals(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS,
mTestSOSMessageRecommender.getTimeOutMillis());
+ verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
// Both OEM and carrier support satellite, and device is connected to carrier satellite
// within hysteresis time. Thus, carrier timer will be used.
@@ -567,9 +623,10 @@
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
mTestSatelliteController.carrierEmergencyCallWaitForConnectionTimeoutMillis =
carrierTimeoutMillis;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertEquals(carrierTimeoutMillis, mTestSOSMessageRecommender.getTimeOutMillis());
+ verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
}
@Test
@@ -577,10 +634,11 @@
mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = true;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSatelliteController.mIsDeviceProvisionedForTest = true;
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
+ verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
mSetFlagsRule.disableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
}
@@ -590,10 +648,11 @@
mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = false;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSatelliteController.mIsDeviceProvisionedForTest = false;
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
+ verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
mSetFlagsRule.disableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
}
@@ -603,23 +662,24 @@
mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = true;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSatelliteController.mIsDeviceProvisionedForTest = true;
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = false;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSatelliteController.mIsDeviceProvisionedForTest = false;
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
+ verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
mSetFlagsRule.disableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
}
private void testStopTrackingCallBeforeTimeout(
@Connection.ConnectionState int connectionState) {
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
@@ -641,7 +701,7 @@
@ServiceState.RegState int availableServiceState,
@ServiceState.RegState int unavailableServiceState) {
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
@@ -713,7 +773,7 @@
mProvisionStateChangedCallbacks;
private int mRegisterForSatelliteProvisionStateChangedCalls = 0;
private int mUnregisterForSatelliteProvisionStateChangedCalls = 0;
- private Boolean mIsSatelliteViaOemProvisioned = true;
+ private Boolean mIsDeviceProvisionedForTest = true;
private boolean mIsSatelliteConnectedViaCarrierWithinHysteresisTime = true;
public boolean isOemEnabledSatelliteSupported = true;
public boolean isCarrierEnabledSatelliteSupported = true;
@@ -734,8 +794,8 @@
}
@Override
- public Boolean isSatelliteViaOemProvisioned() {
- return mIsSatelliteViaOemProvisioned;
+ public Boolean isDeviceProvisioned() {
+ return mIsDeviceProvisionedForTest;
}
@Override
@@ -790,6 +850,12 @@
return carrierEmergencyCallWaitForConnectionTimeoutMillis;
}
+ @Override
+ protected List<DeviceState> getSupportedDeviceStates() {
+ return List.of(new DeviceState(new DeviceState.Configuration.Builder(0 /* identifier */,
+ "DEFAULT" /* name */).build()));
+ }
+
public void setSatelliteConnectedViaCarrierWithinHysteresisTime(
boolean connectedViaCarrier) {
mIsSatelliteConnectedViaCarrierWithinHysteresisTime = connectedViaCarrier;
@@ -803,12 +869,12 @@
return mUnregisterForSatelliteProvisionStateChangedCalls;
}
- public void setIsSatelliteViaOemProvisioned(boolean provisioned) {
- mIsSatelliteViaOemProvisioned = provisioned;
+ public void setDeviceProvisioned(boolean provisioned) {
+ mIsDeviceProvisionedForTest = provisioned;
}
public void sendProvisionStateChangedEvent(int subId, boolean provisioned) {
- mIsSatelliteViaOemProvisioned = provisioned;
+ mIsDeviceProvisionedForTest = provisioned;
Set<ISatelliteProvisionStateCallback> perSubscriptionCallbacks =
mProvisionStateChangedCallbacks.get(SUB_ID);
if (perSubscriptionCallbacks != null) {
@@ -823,6 +889,26 @@
}
}
+ /**
+ * Now that {@link SatelliteController} uses
+ * {@link android.hardware.devicestate.DeviceStateManager} to determine if a device is a
+ * foldable or not, we have to provide a minimal wrapper for {@link SatelliteController} for
+ * tests that want to use a non-fake {@link SatelliteController}.
+ */
+ private static class MinimalSatelliteControllerWrapper extends SatelliteController {
+
+ protected MinimalSatelliteControllerWrapper(
+ Context context, Looper looper, FeatureFlags featureFlags) {
+ super(context, looper, featureFlags);
+ }
+
+ @Override
+ protected List<DeviceState> getSupportedDeviceStates() {
+ return List.of(new DeviceState(new DeviceState.Configuration.Builder(0 /* identifier */,
+ "DEFAULT" /* name */).build()));
+ }
+ }
+
private static class TestImsManager extends ImsManager {
private final List<RegistrationManager.RegistrationCallback> mCallbacks;
@@ -896,6 +982,7 @@
isSatelliteAllowedCallback = null;
private ComponentName mSmsAppComponent = new ComponentName(
DEFAULT_SATELLITE_MESSAGING_PACKAGE, DEFAULT_SATELLITE_MESSAGING_CLASS);
+ private boolean mIsDialerNotified;
/**
* Create an instance of SatelliteSOSMessageRecommender.
@@ -924,6 +1011,12 @@
isSatelliteAllowedCallback = callback;
}
+ @Override
+ protected void reportESosRecommenderDecision(boolean isDialerNotified) {
+ super.reportESosRecommenderDecision(isDialerNotified);
+ mIsDialerNotified = isDialerNotified;
+ }
+
public boolean isTimerStarted() {
return hasMessages(EVENT_TIME_OUT);
}
@@ -939,6 +1032,10 @@
public long getTimeOutMillis() {
return mTimeoutMillis;
}
+
+ public boolean isDialerNotified() {
+ return mIsDialerNotified;
+ }
}
private static class TestConnection extends Connection {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
index b4af458..8c1ae50 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
@@ -19,29 +19,40 @@
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SMS;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS;
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_DATAGRAM_TRANSFER_STATE_SEND_FAILED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AlarmManager;
import android.content.Context;
import android.content.res.Resources;
import android.os.AsyncResult;
@@ -49,14 +60,18 @@
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.ServiceState;
import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.SatelliteManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import com.android.internal.R;
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
import org.junit.After;
import org.junit.Before;
@@ -69,6 +84,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -104,9 +120,14 @@
@Mock private DatagramReceiver mMockDatagramReceiver;
@Mock private DatagramDispatcher mMockDatagramDispatcher;
@Mock private DatagramController mMockDatagramController;
+ @Mock private ServiceState mMockServiceState;
+ @Mock private SessionMetricsStats mMockSessionMetricsStats;
+ @Mock private AlarmManager mAlarmManager;
@Captor ArgumentCaptor<Handler> mHandlerCaptor;
@Captor ArgumentCaptor<Integer> mMsgCaptor;
+ @Captor ArgumentCaptor<Executor> mExecutorArgumentCaptor;
+ @Captor ArgumentCaptor<AlarmManager.OnAlarmListener> mOnAlarmListenerArgumentCaptor;
@Before
public void setUp() throws Exception {
@@ -121,9 +142,14 @@
mMockSatelliteController);
replaceInstance(DatagramController.class, "sInstance", null,
mMockDatagramController);
+ replaceInstance(SessionMetricsStats.class, "sInstance", null,
+ mMockSessionMetricsStats);
Resources resources = mContext.getResources();
when(resources.getInteger(anyInt())).thenReturn(TEST_SATELLITE_TIMEOUT_MILLIS);
+ when(resources.getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning))
+ .thenReturn(false);
when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(false);
@@ -131,6 +157,10 @@
anyInt())).thenReturn(false);
when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(false);
when(mMockSatelliteController.getSatellitePhone()).thenReturn(mPhone);
+ when(mMockSessionMetricsStats.addCountOfAutoExitDueToScreenOff()).thenReturn(
+ mMockSessionMetricsStats);
+ when(mMockSessionMetricsStats.addCountOfAutoExitDueToTnNetwork()).thenReturn(
+ mMockSessionMetricsStats);
mSatelliteModemInterface = new TestSatelliteModemInterface(
mContext, mMockSatelliteController, Looper.myLooper(), mFeatureFlags);
mTestSatelliteSessionController = new TestSatelliteSessionController(mContext,
@@ -142,6 +172,7 @@
mTestSatelliteModemStateCallback);
assertSuccessfulModemStateChangedCallback(
mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ mTestSatelliteSessionController.setAlarmManager(mAlarmManager);
}
@After
@@ -195,6 +226,13 @@
@Test
public void testScreenOffInactivityTimer() {
when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ // Support P2P_SMS
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
doNothing().when(mDeviceStateMonitor).registerForScreenStateChanged(
eq(mTestSatelliteSessionController.getHandler()), anyInt(), any());
when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(false);
@@ -202,6 +240,7 @@
bundle.putInt(KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT,
SCREEN_OFF_INACTIVITY_TIMEOUT_SEC);
when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+ when(mMockSatelliteController.isInCarrierRoamingNbIotNtn()).thenReturn(true);
// Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
assertNotNull(mTestSatelliteSessionController);
@@ -216,12 +255,20 @@
// Notify Screen off
sendScreenStateChanged(mHandlerCaptor.getValue(), mMsgCaptor.getValue(), false);
processAllMessages();
+ clearInvocations(mMockSatelliteController);
- // Verify that the screen off inactivity timer is started.
- assertTrue(mTestSatelliteSessionController.isScreenOffInActivityTimerStarted());
-
- // Time shift to cause timeout
- moveTimeForward(SCREEN_OFF_INACTIVITY_TIMEOUT_SEC * 1000);
+ // Verify that the screen off inactivity timer is set.
+ verify(mAlarmManager).setExact(
+ eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
+ anyLong(),
+ anyString(),
+ mExecutorArgumentCaptor.capture(),
+ any(),
+ mOnAlarmListenerArgumentCaptor.capture()
+ );
+ // Notify alarm expired
+ mExecutorArgumentCaptor.getValue().execute(
+ () -> mOnAlarmListenerArgumentCaptor.getValue().onAlarm());
processAllMessages();
// Verify that SatelliteController#requestSatelliteEnabled() was called.
@@ -232,6 +279,13 @@
@Test
public void testScreenOffInactivityTimerStop() {
when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ // Support P2P_SMS
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
doNothing().when(mDeviceStateMonitor).registerForScreenStateChanged(
eq(mTestSatelliteSessionController.getHandler()), anyInt(), any());
// Satellite enabling request is for an emergency.
@@ -240,6 +294,7 @@
bundle.putInt(KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT,
SCREEN_OFF_INACTIVITY_TIMEOUT_SEC);
when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+ when(mMockSatelliteController.isInCarrierRoamingNbIotNtn()).thenReturn(true);
// Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
assertNotNull(mTestSatelliteSessionController);
@@ -266,27 +321,37 @@
sendScreenStateChanged(mHandlerCaptor.getValue(), mMsgCaptor.getValue(), false);
processAllMessages();
- // Verify that the screen off inactivity timer is started.
- assertTrue(mTestSatelliteSessionController.isScreenOffInActivityTimerStarted());
+ // Verify that the screen off inactivity timer is set.
+ verify(mAlarmManager).setExact(
+ eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
+ anyLong(),
+ anyString(),
+ mExecutorArgumentCaptor.capture(),
+ any(),
+ mOnAlarmListenerArgumentCaptor.capture()
+ );
// Notify Screen on
sendScreenStateChanged(mHandlerCaptor.getValue(), mMsgCaptor.getValue(), true);
+
processAllMessages();
- // Verify that the screen off inactivity timer is stopped
- assertFalse(mTestSatelliteSessionController.isScreenOffInActivityTimerStarted());
+ // Verify that the screen off inactivity timer is clear.
+ verify(mAlarmManager).cancel(eq(mOnAlarmListenerArgumentCaptor.getValue()));
}
@Test
public void testP2pSmsInactivityTimer() {
when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
- doNothing().when(mDeviceStateMonitor).registerForScreenStateChanged(
- eq(mTestSatelliteSessionController.getHandler()), anyInt(), any());
when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(false);
when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
when(mMockSatelliteController.isInCarrierRoamingNbIotNtn()).thenReturn(true);
PersistableBundle bundle = new PersistableBundle();
bundle.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
@@ -295,23 +360,24 @@
// Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
setupDatagramTransferringState(true);
moveToNotConnectedState();
// Verify that the P2P SMS inactivity timer is started.
- assertTrue(mTestSatelliteSessionController.isCarrierRoamingNbIotInActivityTimerStarted());
+ assertTrue(mTestSatelliteSessionController.isP2pSmsInActivityTimerStarted());
mTestSatelliteSessionController.setDeviceAlignedWithSatellite(true);
// Verify that the P2P SMS inactivity timer is stopped.
- assertFalse(mTestSatelliteSessionController.isCarrierRoamingNbIotInActivityTimerStarted());
+ assertFalse(mTestSatelliteSessionController.isP2pSmsInActivityTimerStarted());
mTestSatelliteSessionController.setDeviceAlignedWithSatellite(false);
// Verify that the P2P SMS inactivity timer is started.
- assertTrue(mTestSatelliteSessionController.isCarrierRoamingNbIotInActivityTimerStarted());
+ assertTrue(mTestSatelliteSessionController.isP2pSmsInActivityTimerStarted());
// Time shift to cause timeout
moveTimeForward(P2P_SMS_INACTIVITY_TIMEOUT_SEC * 1000);
@@ -325,8 +391,6 @@
@Test
public void testEsosInactivityTimer() {
when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
- doNothing().when(mDeviceStateMonitor).registerForScreenStateChanged(
- eq(mTestSatelliteSessionController.getHandler()), anyInt(), any());
when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(true);
@@ -338,23 +402,24 @@
// Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
setupDatagramTransferringState(true);
moveToNotConnectedState();
// Verify that the ESOS inactivity timer is started.
- assertTrue(mTestSatelliteSessionController.isCarrierRoamingNbIotInActivityTimerStarted());
+ assertTrue(mTestSatelliteSessionController.isEsosInActivityTimerStarted());
mTestSatelliteSessionController.setDeviceAlignedWithSatellite(true);
// Verify that the ESOS inactivity timer is stopped.
- assertFalse(mTestSatelliteSessionController.isCarrierRoamingNbIotInActivityTimerStarted());
+ assertFalse(mTestSatelliteSessionController.isEsosInActivityTimerStarted());
mTestSatelliteSessionController.setDeviceAlignedWithSatellite(false);
// Verify that the ESOS inactivity timer is started.
- assertTrue(mTestSatelliteSessionController.isCarrierRoamingNbIotInActivityTimerStarted());
+ assertTrue(mTestSatelliteSessionController.isEsosInActivityTimerStarted());
// Time shift to cause timeout
moveTimeForward(ESOS_INACTIVITY_TIMEOUT_SEC * 1000);
@@ -366,6 +431,543 @@
}
@Test
+ public void testEsosP2pSmsInactivityTimerCase1() {
+ // Send eSOS and SMS
+ // After 10 minutes SatelliteSessionController moves to idle
+ // TN network reports IN_SERVICE
+ // Report the callback only and don't auto exit
+
+ long passedTime = 0;
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ // Support ESOS
+ when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(true);
+ // Support P2P_SMS
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
+
+ // Setup carrier config for timer values
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
+ ESOS_INACTIVITY_TIMEOUT_SEC);
+ bundle.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
+ P2P_SMS_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ // Set up Datagram SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE
+ setupDatagramTransferringState(true);
+
+ moveToNotConnectedState();
+
+ // Notify datagram controller is in WAITING_TO_CONNECT.
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // Verify that ESOS, P2P_SMS timer are not started.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+
+ // Sent ESOS
+ sendMessage(DATAGRAM_TYPE_SOS_MESSAGE);
+
+ // Verify that ESOS, P2P_SMS timer are started.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Sent SMS
+ sendMessage(DATAGRAM_TYPE_SMS);
+
+ // Verify that ESOS, P2P_SMS timer are started.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Time shift to cause P2P_SMS timeout
+ passedTime = P2P_SMS_INACTIVITY_TIMEOUT_SEC * 1000;
+ moveTimeForward(P2P_SMS_INACTIVITY_TIMEOUT_SEC * 1000);
+ processAllMessages();
+
+ // Verify that keep ESOS timer, expired P2P_SMS timer.
+ // NOT_CONNECTED state, satellite disabling not called.
+ verifyEsosP2pSmsInactivityTimer(true, false);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockSatelliteController, never()).requestSatelliteEnabled(
+ eq(false), eq(false), eq(true), any(IIntegerConsumer.Stub.class));
+
+ // Time shift to cause ESOS timeout
+ moveTimeForward(ESOS_INACTIVITY_TIMEOUT_SEC * 1000 - passedTime);
+ processAllMessages();
+
+ // Verify that expired ESOS and P2P_SMS timer
+ // reported IDLE state, not called satellite disabling.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ verify(mMockSatelliteController, never()).requestSatelliteEnabled(
+ eq(false), eq(false), eq(true), any(IIntegerConsumer.Stub.class));
+ }
+
+ @Test
+ public void testEsosP2pSmsInactivityTimerCase2() {
+ // Send eSOS and SMS
+ // Send SMS after 3 mins
+ // Send SMS after 1 mins
+ // After 10 minutes SatelliteSessionController moves to idle
+ // TN network reports IN_SERVICE
+ // Report the callback only and don't auto exit
+
+ long passedTime = 0;
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ // Support ESOS
+ when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(true);
+ // Support P2P_SMS
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
+
+ // Setup carrier config for timer values
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
+ ESOS_INACTIVITY_TIMEOUT_SEC);
+ bundle.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
+ P2P_SMS_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ // Set up Datagram SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE
+ setupDatagramTransferringState(true);
+
+ moveToNotConnectedState();
+
+ // Notify datagram controller is in WAITING_TO_CONNECT.
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // Verify that ESOS, P2P_SMS timer are not started.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+
+ // Sent ESOS, SMS
+ sendMessage(DATAGRAM_TYPE_SOS_MESSAGE);
+ sendMessage(DATAGRAM_TYPE_SMS);
+ // Verify that ESOS, P2P_SMS timer are started.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Sent SMS again after 3 mins
+ passedTime = 3 * 60 * 1000;
+ moveTimeForward(3 * 60 * 1000);
+ processAllMessages();
+ sendMessage(DATAGRAM_TYPE_SMS);
+
+ // Sent SMS again after 1 mins
+ passedTime += 1 * 60 * 1000;
+ moveTimeForward(1 * 60 * 1000);
+ processAllMessages();
+ sendMessage(DATAGRAM_TYPE_SMS);
+
+ // Time shift to cause ESOS timeout
+ moveTimeForward(ESOS_INACTIVITY_TIMEOUT_SEC * 1000 - passedTime);
+ processAllMessages();
+
+ // Verify that expired ESOS and P2P_SMS timer
+ // reported IDLE state, not called satellite disabling.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ verify(mMockSatelliteController, never()).requestSatelliteEnabled(
+ eq(false), eq(false), eq(true), any(IIntegerConsumer.Stub.class));
+ }
+
+ @Test
+ public void testEsosP2pSmsInactivityTimerCase3() {
+ // Send eSOS and SMS
+ // Send eSOS after 5 mins
+ // After 15 minutes SatelliteSessionController moves to idle
+ // TN network reports IN_SERVICE
+ // Report the callback only and don't auto exit
+
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ // Support ESOS
+ when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(true);
+ // Support P2P_SMS
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
+
+ // Setup carrier config for timer values
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
+ ESOS_INACTIVITY_TIMEOUT_SEC);
+ bundle.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
+ P2P_SMS_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ // Set up Datagram SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE
+ setupDatagramTransferringState(true);
+
+ moveToNotConnectedState();
+
+ // Notify datagram controller is in WAITING_TO_CONNECT.
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // Verify that ESOS, P2P_SMS timer are not started.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+
+ // Sent ESOS
+ sendMessage(DATAGRAM_TYPE_SOS_MESSAGE);
+ // Verify that ESOS, P2P_SMS timer are started.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Sent ESOS after 5 mins
+ moveTimeForward(3 * 60 * 1000);
+ processAllMessages();
+ sendMessage(DATAGRAM_TYPE_SOS_MESSAGE);
+
+ // Time shift to cause ESOS timeout
+ moveTimeForward(ESOS_INACTIVITY_TIMEOUT_SEC * 1000);
+ processAllMessages();
+
+ // Verify that expired ESOS and P2P_SMS timer
+ // reported IDLE state, not called satellite disabling.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ verify(mMockSatelliteController, never()).requestSatelliteEnabled(
+ eq(false), eq(false), eq(true), any(IIntegerConsumer.Stub.class));
+ }
+
+ @Test
+ public void testEsosP2pSmsInactivityTimerCase4() {
+ // Send SMS
+ // Send SMS after 2 mins
+ // After 3 minutes SatelliteSessionController moves to idle
+ // TN network reports IN_SERVICE
+ // Report the callback only and auto exit
+
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ // Support ESOS, Satellite is not in emergency mode
+ when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(false);
+ // Support P2P_SMS
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
+
+ // Setup carrier config for timer values
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
+ ESOS_INACTIVITY_TIMEOUT_SEC);
+ bundle.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
+ P2P_SMS_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ // Set up Datagram SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE
+ setupDatagramTransferringState(true);
+
+ moveToNotConnectedState();
+
+ // Notify datagram controller is in WAITING_TO_CONNECT.
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // Verify that ESOS, P2P_SMS timer are not started.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+
+ // Sent SMS
+ sendMessage(DATAGRAM_TYPE_SMS);
+
+ // Verify that ESOS is not started, P2P_SMS timer is started.
+ verifyEsosP2pSmsInactivityTimer(false, true);
+
+ // Sent SMS again after 2 mins
+ moveTimeForward(2 * 60 * 1000);
+ processAllMessages();
+ sendMessage(DATAGRAM_TYPE_SMS);
+
+ // Verify that ESOS is not started, P2P_SMS timer is started.
+ verifyEsosP2pSmsInactivityTimer(false, true);
+
+ // Time shift to cause P2P_SMS timeout
+ moveTimeForward(P2P_SMS_INACTIVITY_TIMEOUT_SEC * 1000);
+ processAllMessages();
+ }
+
+ @Test
+ public void testEsosP2pSmsInactivityTimerCase5() {
+ // Send SMS
+ // Send ESOS after 2 mins
+ // After 12 minutes SatelliteSessionController moves to idle
+ // TN network reports IN_SERVICE
+ // Report the callback only and don'tauto exit
+
+ long passedTime = 0;
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ // Support ESOS
+ when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(true);
+ // Support P2P_SMS
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
+
+ // Setup carrier config for timer values
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
+ ESOS_INACTIVITY_TIMEOUT_SEC);
+ bundle.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
+ P2P_SMS_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ // Set up Datagram SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE
+ setupDatagramTransferringState(true);
+
+ moveToNotConnectedState();
+
+ // Notify datagram controller is in WAITING_TO_CONNECT.
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // Verify that ESOS, P2P_SMS timer are not started.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+
+ // Sent SMS
+ sendMessage(DATAGRAM_TYPE_SMS);
+
+ // Verify that ESOS is not started, P2P_SMS timer is started.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Sent ESOS again after 2 mins
+ passedTime = 2 * 60 * 1000;
+ moveTimeForward(2 * 60 * 1000);
+ processAllMessages();
+ sendMessage(DATAGRAM_TYPE_SOS_MESSAGE);
+
+ // Verify that ESOS is not started, P2P_SMS timer is started.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Time shift
+ moveTimeForward(ESOS_INACTIVITY_TIMEOUT_SEC * 1000 - passedTime);
+ processAllMessages();
+ verifyEsosP2pSmsInactivityTimer(true, false);
+
+ // Time shift
+ moveTimeForward(passedTime);
+ processAllMessages();
+
+ // Verify that expired P2P_SMS timer
+ // reported IDLE state, called satellite disabling.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ verify(mMockSatelliteController, never()).requestSatelliteEnabled(
+ eq(false), eq(false), eq(true), any(IIntegerConsumer.Stub.class));
+ }
+
+ @Test
+ public void testEsosP2pSmsInactivityTimerInConnectedState() {
+ // Send eSOS and SMS
+ // After 10 minutes SatelliteSessionController moves to idle
+ // TN network reports IN_SERVICE
+ // Report the callback only and don't auto exit
+
+ long passedTime = 0;
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ // Support ESOS
+ when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(true);
+ // Support P2P_SMS
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
+
+ // Setup carrier config for timer values
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
+ ESOS_INACTIVITY_TIMEOUT_SEC);
+ bundle.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
+ P2P_SMS_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ // Set up Datagram SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE
+ setupDatagramTransferringState(true);
+
+ moveToNotConnectedState();
+ moveNotConnectedToConnectedState();
+
+ // Verify that ESOS, P2P_SMS timer are started.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Sent ESOS
+ // CONNECTED -> TRANSFERRING -> CONNECTED
+ sendMessage(DATAGRAM_TYPE_SOS_MESSAGE);
+
+ // Verify that ESOS, P2P_SMS timer are restarted.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Sent SMS
+ // CONNECTED -> TRANSFERRING -> CONNECTED
+ sendMessage(DATAGRAM_TYPE_SMS);
+
+ // Verify that ESOS, P2P_SMS timer are restarted.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Time shift to cause P2P_SMS timeout
+ passedTime = P2P_SMS_INACTIVITY_TIMEOUT_SEC * 1000;
+ moveTimeForward(P2P_SMS_INACTIVITY_TIMEOUT_SEC * 1000);
+ processAllMessages();
+
+ // Verify that keep ESOS timer, expired P2P_SMS timer.
+ // CONNECTED state
+ verifyEsosP2pSmsInactivityTimer(true, false);
+ assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+
+ // Time shift to cause ESOS timeout
+ moveTimeForward(ESOS_INACTIVITY_TIMEOUT_SEC * 1000 - passedTime);
+ processAllMessages();
+
+ // Verify that expired ESOS and P2P_SMS timer
+ // reported IDLE state.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ }
+
+ @Test
+ public void testDisableSatelliteWhenCellularModemEnabledInIdleMode() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ doNothing().when(mDeviceStateMonitor).registerForScreenStateChanged(
+ eq(mTestSatelliteSessionController.getHandler()), anyInt(), any());
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(false);
+ when(mPhone.getServiceState()).thenReturn(mMockServiceState);
+ setUpResponseForRequestSatelliteEnabled(SATELLITE_RESULT_SUCCESS);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+
+ // Conditions for operation
+ boolean isEmergency = true;
+ // Cellular network is not IN_SERVICE and emergency only.
+ // Satellite request is emergency and emergency communication was established.
+ // Disabling satellite was not allowed
+ when(mMockServiceState.getVoiceRegState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mMockServiceState.getDataRegState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mMockServiceState.isEmergencyOnly()).thenReturn(false);
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(isEmergency);
+ when(mMockDatagramController.isEmergencyCommunicationEstablished()).thenReturn(true);
+ when(mMockSatelliteController.turnOffSatelliteSessionForEmergencyCall(
+ anyInt())).thenReturn(false);
+
+ moveToIdleState();
+
+ // Cellular network is not in STATE_IN_SERVICE or emergency only.
+ // Should not disable satellite
+ verify(mMockSatelliteController, never()).requestSatelliteEnabled(
+ eq(false), eq(false), eq(isEmergency), any(IIntegerConsumer.Stub.class));
+ verify(mMockSessionMetricsStats, never()).addCountOfAutoExitDueToTnNetwork();
+
+ // Notify cellular service is in STATE_IN_SERVICE.
+ ServiceState serviceState = new ServiceState();
+ serviceState.setVoiceRegState(ServiceState.STATE_IN_SERVICE);
+ serviceState.setDataRegState(ServiceState.STATE_OUT_OF_SERVICE);
+ serviceState.setEmergencyOnly(false);
+ mTestSatelliteSessionController.onCellularServiceStateChanged(serviceState);
+ processAllMessages();
+
+ // Satellite is in emergency mode and emergency communication was established.
+ // Should not disable satellite
+ verify(mMockSatelliteController, never()).requestSatelliteEnabled(
+ eq(false), eq(false), eq(isEmergency), any(IIntegerConsumer.Stub.class));
+ verify(mMockSessionMetricsStats, never()).addCountOfAutoExitDueToTnNetwork();
+
+ // Satellite is in emergency mode but emergency communication was not established.
+ // Disabling satellite was not allowed
+ when(mMockDatagramController.isEmergencyCommunicationEstablished()).thenReturn(false);
+ when(mMockSatelliteController.turnOffSatelliteSessionForEmergencyCall(
+ anyInt())).thenReturn(false);
+ mTestSatelliteSessionController.onCellularServiceStateChanged(serviceState);
+ processAllMessages();
+
+ // Should not disable satellite
+ verify(mMockSatelliteController, never()).requestSatelliteEnabled(
+ eq(false), eq(false), eq(isEmergency), any(IIntegerConsumer.Stub.class));
+ verify(mMockSessionMetricsStats, never()).addCountOfAutoExitDueToTnNetwork();
+ // Satellite is in emergency mode but emergency communication was not established.
+ // Disabling satellite was allowed
+ when(mMockSatelliteController.turnOffSatelliteSessionForEmergencyCall(
+ anyInt())).thenReturn(true);
+ mTestSatelliteSessionController.onCellularServiceStateChanged(serviceState);
+ processAllMessages();
+
+ // Should disable satellite
+ verify(mMockSatelliteController).requestSatelliteEnabled(
+ eq(false), eq(false), eq(isEmergency), any(IIntegerConsumer.Stub.class));
+ verify(mMockSessionMetricsStats, times(1)).addCountOfAutoExitDueToTnNetwork();
+ }
+
+ @Test
public void testStateTransition() {
/**
* Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
@@ -401,7 +1003,8 @@
// Start sending datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -413,7 +1016,8 @@
// Sending datagrams failed
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to IDLE state.
@@ -425,7 +1029,8 @@
// Start sending datagrams again
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -437,7 +1042,8 @@
// Sending datagrams is successful and done.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to LISTENING state.
@@ -450,7 +1056,8 @@
// Start receiving datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -462,7 +1069,8 @@
// Receiving datagrams is successful and done.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to LISTENING state.
@@ -475,7 +1083,8 @@
// Start receiving datagrams again
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -488,7 +1097,8 @@
// Receiving datagrams failed.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to IDLE state.
@@ -500,7 +1110,8 @@
// Start receiving datagrams again
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -511,7 +1122,8 @@
// Receiving datagrams is successful and done.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to LISTENING state.
@@ -535,7 +1147,8 @@
// Start receiving datagrams again
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -547,7 +1160,8 @@
// Start sending datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should stay at TRANSFERRING state.
@@ -558,7 +1172,8 @@
// Receiving datagrams failed.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should stay at TRANSFERRING state instead of moving to IDLE
@@ -570,7 +1185,8 @@
// Start receiving datagrams again.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should stay at TRANSFERRING state.
@@ -581,7 +1197,8 @@
// Sending datagrams failed.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should stay at TRANSFERRING state instead of moving to IDLE
@@ -657,7 +1274,8 @@
// Start sending datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// The datagram sending event should be ignored.
@@ -680,7 +1298,8 @@
// Start sending datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -695,7 +1314,8 @@
// Sending datagrams failed
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to CONNECTED state.
@@ -710,7 +1330,8 @@
// Start sending datagrams again
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -725,7 +1346,8 @@
// Sending datagrams is successful and done.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to CONNECTED state.
@@ -740,7 +1362,8 @@
// Start receiving datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -754,7 +1377,8 @@
// Receiving datagrams is successful and done.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to CONNECTED state.
@@ -769,7 +1393,8 @@
// Start receiving datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -783,7 +1408,8 @@
// Receiving datagrams is successful and done.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to CONNECTED state.
@@ -811,7 +1437,8 @@
// Start sending datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to NOT_CONNECTED state.
@@ -903,22 +1530,6 @@
SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
- // Set up error response for the request to disable cellular scanning
- mSatelliteModemInterface.setErrorCode(SatelliteManager.SATELLITE_RESULT_MODEM_ERROR);
-
- // Start sending datagrams
- mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
- processAllMessages();
-
- // SatelliteSessionController should stay at IDLE state because it failed to disable
- // cellular scanning.
- assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
- assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
-
- mSatelliteModemInterface.setErrorCode(SatelliteManager.SATELLITE_RESULT_SUCCESS);
-
// Power off the modem.
mTestSatelliteSessionController.onSatelliteEnabledStateChanged(false);
processAllMessages();
@@ -965,7 +1576,8 @@
// Start sending datagrams and the NB-IOT inactivity timer should be stopped.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
processAllMessages();
@@ -977,10 +1589,12 @@
// The NB-IOT inactivity timer should be started.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
@@ -1230,9 +1844,307 @@
assertEmergencyModeChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
}
- private void setupDatagramTransferringState(boolean isTransferring) {
- when(mMockDatagramController.isSendingInIdleState()).thenReturn(isTransferring);
- when(mMockDatagramController.isPollingInIdleState()).thenReturn(isTransferring);
+ @Test
+ public void testNotConnectedToIdleToNotConnectedStateTransition() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ when(mContext.getResources().getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning)).thenReturn(true);
+
+ assertNotNull(mTestSatelliteSessionController);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ setupDatagramTransferringState(true);
+
+ powerOnSatelliteModem();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
+ // is powered on.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be started.
+ assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Wait for timeout
+ moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
+ processAllMessages();
+
+ // SatelliteSessionController should move to IDLE state, but the state transition will
+ // be hidden because device does not support satellite modem IDLE state.
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be stopped.
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ // The transition is hidden and thus DatagramController is not notified.
+ verify(mMockDatagramController, never()).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ clearInvocations(mMockDatagramController);
+
+ // Start sending datagrams
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+ }
+
+ @Test
+ public void testNotConnectedToIdleToTransferringStateTransition() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ when(mContext.getResources().getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning)).thenReturn(true);
+
+ assertNotNull(mTestSatelliteSessionController);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ setupDatagramTransferringState(true);
+
+ powerOnSatelliteModem();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
+ // is powered on.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be started.
+ assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Wait for timeout
+ moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
+ processAllMessages();
+
+ // SatelliteSessionController should move to IDLE state, but the state transition will
+ // be hidden because device does not support satellite modem IDLE state.
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be stopped.
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ // The transition is hidden and thus DatagramController is not notified.
+ verify(mMockDatagramController, never()).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ clearInvocations(mMockDatagramController);
+
+ // Modem report CONNECTED state
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ processAllMessages();
+
+ // SatelliteSessionController should stay in IDLE state, but clients should be
+ // notified that modem has moved to CONNECTED state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Start sending datagrams
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // SatelliteSessionController should move to TRANSFERRING state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+ assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+ clearInvocations(mMockDatagramController);
+ }
+
+ @Test
+ public void testConnectedToIdleToTransferringStateTransition() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ when(mContext.getResources().getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning)).thenReturn(true);
+
+ assertNotNull(mTestSatelliteSessionController);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ setupDatagramTransferringState(false);
+
+ powerOnSatelliteModem();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
+ // is powered on.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Modem report CONNECTED state
+ setupDatagramTransferringState(true);
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ processAllMessages();
+
+ // SatelliteSessionController should move to CONNECTED state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be started.
+ assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Wait for timeout
+ moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
+ processAllMessages();
+
+ // SatelliteSessionController should move to IDLE state, but the state transition will
+ // be hidden because device does not support satellite modem IDLE state.
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be stopped.
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ // The transition is hidden and thus DatagramController is not notified.
+ verify(mMockDatagramController, never()).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ clearInvocations(mMockDatagramController);
+
+ // Start sending datagrams
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // SatelliteSessionController should move to TRANSFERRING state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+ assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+ clearInvocations(mMockDatagramController);
+ }
+
+ @Test
+ public void testConnectedToIdleToNotConnectedStateTransition() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ when(mContext.getResources().getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning)).thenReturn(true);
+
+ assertNotNull(mTestSatelliteSessionController);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ setupDatagramTransferringState(false);
+
+ powerOnSatelliteModem();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
+ // is powered on.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Modem report CONNECTED state
+ setupDatagramTransferringState(true);
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ processAllMessages();
+
+ // SatelliteSessionController should move to CONNECTED state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be started.
+ assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Wait for timeout
+ moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
+ processAllMessages();
+
+ // SatelliteSessionController should move to IDLE state, but the state transition will
+ // be hidden because device does not support satellite modem IDLE state.
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be stopped.
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ // The transition is hidden and thus DatagramController is not notified.
+ verify(mMockDatagramController, never()).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ clearInvocations(mMockDatagramController);
+
+ // Modem report NOT_CONNECTED state
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ processAllMessages();
+
+ // SatelliteSessionController should stay in IDLE state, but the clients
+ // should be notified that modem has moved to NOT_CONNECTED state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Start sending datagrams
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+ }
+
+ private void verifyEsosP2pSmsInactivityTimer(boolean esosTimer, boolean p2pSmsTimer) {
+ assertEquals(mTestSatelliteSessionController.isEsosInActivityTimerStarted(), esosTimer);
+ assertEquals(mTestSatelliteSessionController.isP2pSmsInActivityTimerStarted(),
+ p2pSmsTimer);
+ }
+
+ private void sendMessage(@SatelliteManager.DatagramType int datagramType) {
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, datagramType);
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, datagramType);
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, datagramType);
+
+ processAllMessages();
+ }
+
+ private void setupDatagramTransferringState(boolean isIdle) {
+ when(mMockDatagramController.isSendingInIdleState()).thenReturn(isIdle);
+ when(mMockDatagramController.isPollingInIdleState()).thenReturn(isIdle);
}
private void powerOnSatelliteModem() {
@@ -1293,7 +2205,8 @@
assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
// Start sending datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -1308,7 +2221,8 @@
// Sending datagrams is successful and done.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to LISTENING state.
@@ -1419,6 +2333,8 @@
}
private static class TestSatelliteSessionController extends SatelliteSessionController {
+ boolean mSatelliteEnabledForNtnOnlySubscription = true;
+
TestSatelliteSessionController(Context context, Looper looper, FeatureFlags featureFlags,
boolean isSatelliteSupported,
SatelliteModemInterface satelliteModemInterface) {
@@ -1441,16 +2357,12 @@
return hasDeferredMessages(event);
}
- boolean isScreenOffInActivityTimerStarted() {
- return hasMessages(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT);
- }
-
- boolean isCarrierRoamingNbIotInActivityTimerStarted() {
- return hasMessages(EVENT_CARRIER_ROAMING_NB_IOT_INACTIVITY_TIMER_TIMED_OUT);
- }
-
protected boolean isSatelliteEnabledForNtnOnlySubscription() {
- return true;
+ return mSatelliteEnabledForNtnOnlySubscription;
+ }
+
+ void setSatelliteEnabledForNtnOnlySubscription(boolean enabled) {
+ mSatelliteEnabledForNtnOnlySubscription = false;
}
}
@@ -1493,6 +2405,11 @@
logd("onRegistrationFailure: causeCode=" + causeCode);
}
+ @Override
+ public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) {
+ logd("onTerrestrialNetworkAvailableChanged: isAvailable=" + isAvailable);
+ }
+
public boolean waitUntilResultForModemStateChanged() {
try {
if (!mSemaphoreForModemStateChanged.tryAcquire(EVENT_PROCESSING_TIME_MILLIS,
@@ -1587,4 +2504,14 @@
msg.obj = new AsyncResult(null, screenOn, null);
h.sendMessage(msg);
}
+
+ private void setUpResponseForRequestSatelliteEnabled(
+ @SatelliteManager.SatelliteResult int expectedResult) {
+ doAnswer(invocation -> {
+ IIntegerConsumer integerConsumer = invocation.getArgument(3);
+ integerConsumer.accept(expectedResult);
+ return null;
+ }).when(mMockSatelliteController).requestSatelliteEnabled(anyBoolean(), anyBoolean(),
+ anyBoolean(), any(IIntegerConsumer.class));
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
index 4b1b4a5..5e560bc 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
@@ -457,7 +457,6 @@
doReturn(1).when(mUiccController).convertToPublicCardId(eq(FAKE_ICCID1));
doReturn(2).when(mUiccController).convertToPublicCardId(eq(FAKE_ICCID2));
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
- when(mFeatureFlags.dataOnlyCellularService()).thenReturn(true);
when(mFeatureFlags.supportPsimToEsimConversion()).thenReturn(true);
when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
mDatabaseManagerUT = new SubscriptionDatabaseManager(mContext, Looper.myLooper(),
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 925cf71..f639a51 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
@@ -24,8 +24,6 @@
import android.telephony.UiccAccessRule;
import android.telephony.ims.ImsMmTelManager;
-import com.android.internal.telephony.flags.Flags;
-
import org.junit.Rule;
import org.junit.Test;
@@ -160,7 +158,6 @@
@Test
public void testSubscriptionInfoInternalSetAndGet() {
- mSetFlagsRule.enableFlags(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE);
assertThat(mSubInfo.getSubscriptionId()).isEqualTo(1);
assertThat(mSubInfo.getIccId()).isEqualTo(SubscriptionDatabaseManagerTest.FAKE_ICCID1);
assertThat(mSubInfo.getSimSlotIndex()).isEqualTo(0);
@@ -271,7 +268,6 @@
@Test
public void testConvertToSubscriptionInfo() {
- mSetFlagsRule.enableFlags(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE);
SubscriptionInfo subInfo = mSubInfo.toSubscriptionInfo();
assertThat(subInfo.getSubscriptionId()).isEqualTo(1);
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 65790f8..66b2eb8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
@@ -70,6 +70,7 @@
import android.Manifest;
import android.annotation.NonNull;
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.PropertyInvalidatedCache;
import android.compat.testing.PlatformCompatChangeRule;
@@ -1123,9 +1124,12 @@
public void testGetAccessibleSubscriptionInfoList() {
doReturn(true).when(mEuiccManager).isEnabled();
insertSubscription(FAKE_SUBSCRIPTION_INFO2);
+ UserHandle user = UserHandle.of(ActivityManager.getCurrentUser());
doReturn(true).when(mSubscriptionManager).canManageSubscription(
any(SubscriptionInfo.class), eq(CALLING_PACKAGE));
+ doReturn(true).when(mSubscriptionManager).canManageSubscriptionAsUser(
+ any(SubscriptionInfo.class), eq(CALLING_PACKAGE), any(UserHandle.class));
// FAKE_SUBSCRIPTION_INFO2 is a not eSIM. So the list should be empty.
assertThat(mSubscriptionManagerServiceUT.getAccessibleSubscriptionInfoList(
CALLING_PACKAGE)).isEmpty();
@@ -1138,6 +1142,8 @@
doReturn(false).when(mSubscriptionManager).canManageSubscription(
any(SubscriptionInfo.class), eq(CALLING_PACKAGE));
+ doReturn(false).when(mSubscriptionManager).canManageSubscriptionAsUser(
+ any(SubscriptionInfo.class), eq(CALLING_PACKAGE), eq(user));
doReturn(true).when(mEuiccManager).isEnabled();
assertThat(mSubscriptionManagerServiceUT.getAccessibleSubscriptionInfoList(
@@ -1145,6 +1151,8 @@
doReturn(true).when(mSubscriptionManager).canManageSubscription(
any(SubscriptionInfo.class), eq(CALLING_PACKAGE));
+ doReturn(true).when(mSubscriptionManager).canManageSubscriptionAsUser(
+ any(SubscriptionInfo.class), eq(CALLING_PACKAGE), eq(user));
assertThat(mSubscriptionManagerServiceUT.getAccessibleSubscriptionInfoList(
CALLING_PACKAGE)).isEqualTo(List.of(new SubscriptionInfoInternal.Builder(
FAKE_SUBSCRIPTION_INFO1).setId(2).build().toSubscriptionInfo()));
@@ -1363,6 +1371,9 @@
doReturn(true).when(mEuiccManager).isEnabled();
doReturn(true).when(mSubscriptionManager).canManageSubscription(
any(SubscriptionInfo.class), eq(CALLING_PACKAGE));
+ UserHandle user = UserHandle.of(ActivityManager.getCurrentUser());
+ doReturn(true).when(mSubscriptionManager).canManageSubscriptionAsUser(
+ any(SubscriptionInfo.class), eq(CALLING_PACKAGE), eq(user));
assertThat(mSubscriptionManagerServiceUT.getAccessibleSubscriptionInfoList(
CALLING_PACKAGE)).isEqualTo(List.of(FAKE_SUBSCRIPTION_INFO1.toSubscriptionInfo()));
// Test getActiveSubIdList, System
@@ -1499,6 +1510,9 @@
doReturn(true).when(mEuiccManager).isEnabled();
doReturn(true).when(mSubscriptionManager).canManageSubscription(
any(SubscriptionInfo.class), eq(CALLING_PACKAGE));
+ UserHandle user = UserHandle.of(ActivityManager.getCurrentUser());
+ doReturn(true).when(mSubscriptionManager).canManageSubscriptionAsUser(
+ any(SubscriptionInfo.class), eq(CALLING_PACKAGE), eq(user));
assertThat(mSubscriptionManagerServiceUT.getAccessibleSubscriptionInfoList(
CALLING_PACKAGE)).isEqualTo(List.of(FAKE_SUBSCRIPTION_INFO1.toSubscriptionInfo()));
// Test getActiveSubIdList, System
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardTest.java
index 33b195c..bfdca0f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardTest.java
@@ -69,6 +69,7 @@
@After
public void tearDown() throws Exception {
+ mUiccCard.dispose();
mUiccCard = null;
mIccIoResult = null;
super.tearDown();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
index 58a8153..3343570 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
@@ -15,8 +15,6 @@
*/
package com.android.internal.telephony.uicc;
-import static junit.framework.Assert.fail;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -131,6 +129,7 @@
@After
public void tearDown() throws Exception {
+ if (mUiccControllerUT != null) mUiccControllerUT.dispose();
mUiccControllerUT = null;
super.tearDown();
}
@@ -145,6 +144,7 @@
com.android.internal.R.array.non_removable_euicc_slots,
nonRemovableEuiccSlots);
replaceInstance(UiccController.class, "mInstance", null, null);
+ mUiccControllerUT.dispose();
mUiccControllerUT = UiccController.make(mContext, mFeatureFlags);
processAllMessages();
}
@@ -250,7 +250,7 @@
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(mMockCard).when(mMockSlot).getUiccCard();
doReturn(mMockPort).when(mMockCard).getUiccPort(0);
doReturn("A1B2C3D4").when(mMockPort).getIccId();
@@ -296,7 +296,7 @@
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(true).when(mMockSlot).isEuicc();
// simulate slot status loaded so that the UiccController sets the card ID
@@ -323,7 +323,7 @@
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(true).when(mMockSlot).isEuicc();
// simulate slot status loaded so that the UiccController sets the card ID
@@ -351,7 +351,7 @@
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(false).when(mMockSlot).isEuicc();
doReturn(mMockCard).when(mMockSlot).getUiccCard();
doReturn("ASDF1234").when(mMockCard).getCardId();
@@ -402,7 +402,7 @@
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(false).when(mMockSlot).isEuicc();
doReturn(mMockCard).when(mMockSlot).getUiccCard();
doReturn("ASDF1234").when(mMockCard).getCardId();
@@ -453,7 +453,7 @@
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(true).when(mMockSlot).isEuicc();
doReturn(null).when(mMockSlot).getUiccCard();
doReturn(false).when(mMockSlot).isRemovable();
@@ -499,21 +499,17 @@
* The default eUICC should not be the removable slot if there is a built-in eUICC.
*/
@Test
- public void testDefaultEuiccIsNotRemovable() {
- try {
- reconfigureSlots(2, new int[]{ 1 } /* non-removable slot */);
- } catch (Exception e) {
- fail("Unable to reconfigure slots.");
- }
+ public void testDefaultEuiccIsNotRemovable() throws Exception {
+ reconfigureSlots(2, new int[]{ 1 } /* non-removable slot */);
// Give UiccController a real context so it can use shared preferences
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots so that [0] is a removable eUICC and [1] is built-in
- mUiccControllerUT.mUiccSlots[0] = mMockRemovableEuiccSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockRemovableEuiccSlot);
doReturn(true).when(mMockRemovableEuiccSlot).isEuicc();
doReturn(true).when(mMockRemovableEuiccSlot).isRemovable();
- mUiccControllerUT.mUiccSlots[1] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(1, mMockSlot);
doReturn(true).when(mMockSlot).isEuicc();
doReturn(false).when(mMockSlot).isRemovable();
@@ -550,21 +546,17 @@
* not depend on the order of the slots.
*/
@Test
- public void testDefaultEuiccIsNotRemovable_swapSlotOrder() {
- try {
- reconfigureSlots(2, new int[]{ 0 } /* non-removable slot */);
- } catch (Exception e) {
- fail("Unable to reconfigure slots.");
- }
+ public void testDefaultEuiccIsNotRemovable_swapSlotOrder() throws Exception {
+ reconfigureSlots(2, new int[]{ 0 } /* non-removable slot */);
// Give UiccController a real context so it can use shared preferences
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots so that [0] is a built-in eUICC and [1] is removable
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(true).when(mMockSlot).isEuicc();
doReturn(false).when(mMockSlot).isRemovable();
- mUiccControllerUT.mUiccSlots[1] = mMockRemovableEuiccSlot;
+ mUiccControllerUT.setUiccSlot(1, mMockRemovableEuiccSlot);
doReturn(true).when(mMockRemovableEuiccSlot).isEuicc();
doReturn(true).when(mMockRemovableEuiccSlot).isRemovable();
@@ -603,21 +595,17 @@
* the removable eUICC.
*/
@Test
- public void testDefaultEuiccIsNotRemovable_EuiccIsInactive() {
- try {
- reconfigureSlots(2, new int[]{ 1 } /* non-removable slot */);
- } catch (Exception e) {
- fail();
- }
+ public void testDefaultEuiccIsNotRemovable_EuiccIsInactive() throws Exception {
+ reconfigureSlots(2, new int[]{ 1 } /* non-removable slot */);
// Give UiccController a real context so it can use shared preferences
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots. Slot 0 is inactive here.
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(true).when(mMockSlot).isEuicc();
doReturn(false).when(mMockSlot).isRemovable();
- mUiccControllerUT.mUiccSlots[1] = mMockRemovableEuiccSlot;
+ mUiccControllerUT.setUiccSlot(1, mMockRemovableEuiccSlot);
doReturn(true).when(mMockRemovableEuiccSlot).isEuicc();
doReturn(true).when(mMockRemovableEuiccSlot).isRemovable();
@@ -669,7 +657,7 @@
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(true).when(mMockSlot).isEuicc();
doReturn(null).when(mMockSlot).getUiccCard();
//doReturn("123451234567890").when(mMockSlot).getIccId();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
index a2b42af..47b7c53 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
@@ -82,6 +82,7 @@
@After
public void tearDown() throws Exception {
+ mUiccPort.dispose();
mUiccPort = null;
mIccIoResult = null;
super.tearDown();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
index 671f273..8449ecc 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
@@ -103,6 +103,7 @@
mTestHandlerThread = null;
mTestHandler.removeCallbacksAndMessages(null);
mTestHandler = null;
+ mUiccSlot.dispose();
mUiccSlot = null;
super.tearDown();
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java
index f88bc1e..c9b159c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java
@@ -51,6 +51,8 @@
private static final int CARD_COUNT = 1;
private static final String PROVISIONING_PACKAGE_NAME = "test.provisioning.package";
+ private UiccCard mUiccCardToDispose;
+
// Mocked classes
private Resources mResources;
@@ -77,6 +79,9 @@
@After
public void tearDown() throws Exception {
super.tearDown();
+
+ if (mUiccCardToDispose != null) mUiccCardToDispose.dispose();
+ mUiccCardToDispose = null;
}
@Test @SmallTest
@@ -99,7 +104,7 @@
msg.what = integerArgumentCaptor.getValue();
// The first broadcast should be sent after initialization.
- UiccCard card = new UiccCard(mContext, mSimulatedCommands,
+ UiccCard card = mUiccCardToDispose = new UiccCard(mContext, mSimulatedCommands,
makeCardStatus(CardState.CARDSTATE_PRESENT), 0 /* phoneId */, new Object(),
IccSlotStatus.MultipleEnabledProfilesMode.NONE);
when(UiccController.getInstance().getUiccCardForPhone(0)).thenReturn(card);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccCardTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccCardTest.java
index bcb5c4c..560c9aa 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccCardTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccCardTest.java
@@ -109,7 +109,10 @@
mHandler.removeCallbacksAndMessages(null);
mHandler = null;
}
- mEuiccCard = null;
+ if (mEuiccCard != null) {
+ mEuiccCard.dispose();
+ mEuiccCard = null;
+ }
super.tearDown();
}
@@ -132,6 +135,7 @@
@Test
public void testPassEidInConstructor() {
mMockIccCardStatus.eid = "1A2B3C4D";
+ mEuiccCard.dispose();
mEuiccCard = new EuiccCard(mContextFixture.getTestDouble(), mMockCi,
mMockIccCardStatus, 0 /* phoneId */, new Object(),
IccSlotStatus.MultipleEnabledProfilesMode.NONE);
@@ -154,6 +158,7 @@
public void testLoadEidAndNotifyRegistrants() {
int channel = mockLogicalChannelResponses("BF3E065A041A2B3C4D9000");
mHandler.post(() -> {
+ mEuiccCard.dispose();
mEuiccCard = new EuiccCard(mContextFixture.getTestDouble(), mMockCi,
mMockIccCardStatus, 0 /* phoneId */, new Object(),
IccSlotStatus.MultipleEnabledProfilesMode.NONE);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccPortTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccPortTest.java
index 2fef021..f0f1af3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccPortTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccPortTest.java
@@ -141,6 +141,7 @@
public void tearDown() throws Exception {
mHandler.removeCallbacksAndMessages(null);
mHandler = null;
+ mEuiccPort.dispose();
mEuiccPort = null;
super.tearDown();
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java
index 172211c..1252ff8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java
@@ -386,7 +386,8 @@
}
@Test
- public void testConstructor_closeOpenChannelInSharedPreference() throws InterruptedException {
+ public void testConstructor_doNotCloseOpenChannelInSharedPreference()
+ throws InterruptedException {
// Open a channel and not close it, by making CI.iccTransmitApduLogicalChannel throw.
int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
doThrow(new RuntimeException()).when(mMockCi).iccTransmitApduLogicalChannel(
@@ -405,8 +406,8 @@
mLooper.processAllMessages();
// The constructor should have closed channel
- verify(mMockCi).iccCloseLogicalChannel(eq(channel), eq(true /*isEs10*/), any());
- assertEquals(-1, getChannelIdFromSharedPreferences());
+ verify(mMockCi, times(0)).iccCloseLogicalChannel(eq(channel), eq(true /*isEs10*/), any());
+ assertEquals(1, getChannelIdFromSharedPreferences());
}
@Test