Merge "Add feature flag to clears cached IMS phone number when device lost IMS registration." into main
diff --git a/flags/data.aconfig b/flags/data.aconfig
index 0bcd4bd..8d05a51 100644
--- a/flags/data.aconfig
+++ b/flags/data.aconfig
@@ -20,3 +20,10 @@
description: "Allow bring up MMTEL in nonVops area specified by carrier config."
bug: "241198464"
}
+
+flag {
+ name: "metered_embb_urlcc"
+ namespace: "telephony"
+ description: "Force networks that have PRIORITIZE_BANDWIDTH or PRIORITIZE_LATENCY to be metered."
+ bug: "301310451"
+}
diff --git a/src/java/com/android/internal/telephony/data/DataConfigManager.java b/src/java/com/android/internal/telephony/data/DataConfigManager.java
index 950ac10..39e7325 100644
--- a/src/java/com/android/internal/telephony/data/DataConfigManager.java
+++ b/src/java/com/android/internal/telephony/data/DataConfigManager.java
@@ -598,10 +598,20 @@
*/
public @NonNull @NetCapability Set<Integer> getMeteredNetworkCapabilities(boolean isRoaming) {
Set<Integer> meteredApnTypes = isRoaming ? mRoamingMeteredApnTypes : mMeteredApnTypes;
- return meteredApnTypes.stream()
+ Set<Integer> meteredCapabilities = meteredApnTypes.stream()
.map(DataUtils::apnTypeToNetworkCapability)
.filter(cap -> cap >= 0)
- .collect(Collectors.toUnmodifiableSet());
+ .collect(Collectors.toSet());
+
+ // Consumer slices are the slices that are allowed to be accessed by regular application to
+ // get better performance. They should be metered. This can be turned into configurations in
+ // the future.
+ if (mFeatureFlags.meteredEmbbUrlcc()) {
+ meteredCapabilities.add(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH);
+ meteredCapabilities.add(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY);
+ }
+
+ return Collections.unmodifiableSet(meteredCapabilities);
}
/**
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
index 23473d2..6773dca 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
@@ -130,6 +130,7 @@
private boolean mIsInEcm;
private boolean mIsTestEmergencyNumber;
private Runnable mOnEcmExitCompleteRunnable;
+ private int mOngoingCallProperties;
/** For emergency SMS */
private final Set<String> mOngoingEmergencySmsIds = new ArraySet<>();
@@ -447,6 +448,7 @@
return CompletableFuture.completedFuture(DisconnectCause.ERROR_UNSPECIFIED);
}
+ mOngoingCallProperties = 0;
mCallEmergencyModeFuture = new CompletableFuture<>();
if (mSmsPhone != null) {
@@ -487,6 +489,7 @@
if (Objects.equals(mOngoingCallId, callId)) {
mOngoingCallId = null;
+ mOngoingCallProperties = 0;
}
if (wasActive && mActiveEmergencyCalls.isEmpty()
@@ -520,6 +523,7 @@
mIsEmergencyCallStartedDuringEmergencySms = false;
mCallEmergencyModeFuture = null;
mOngoingCallId = null;
+ mOngoingCallProperties = 0;
mPhone = null;
}
@@ -757,10 +761,36 @@
public void onEmergencyCallStateChanged(Call.State state, String callId) {
if (state == Call.State.ACTIVE) {
mActiveEmergencyCalls.add(callId);
+ if (Objects.equals(mOngoingCallId, callId)) {
+ Rlog.i(TAG, "call connected " + callId);
+ if (mPhone != null
+ && isVoWiFi(mOngoingCallProperties)
+ && mEmergencyMode == EmergencyConstants.MODE_EMERGENCY_WLAN) {
+ // Recover normal service in cellular when VoWiFi is connected
+ mPhone.cancelEmergencyNetworkScan(true, null);
+ }
+ }
}
}
/**
+ * Handles the change of emergency call properties.
+ *
+ * @param properties the new call properties.
+ * @param callId the callId whose state has changed.
+ */
+ public void onEmergencyCallPropertiesChanged(int properties, String callId) {
+ if (Objects.equals(mOngoingCallId, callId)) {
+ mOngoingCallProperties = properties;
+ }
+ }
+
+ private static boolean isVoWiFi(int properties) {
+ return (properties & android.telecom.Connection.PROPERTY_WIFI) > 0
+ || (properties & android.telecom.Connection.PROPERTY_CROSS_SIM) > 0;
+ }
+
+ /**
* Returns {@code true} if device and carrier support emergency callback mode.
*/
@VisibleForTesting
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 896063f..5148ecb 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -794,7 +794,7 @@
}
SessionMetricsStats.getInstance()
.setInitializationResult(error)
- .setRadioTechnology(SatelliteManager.NT_RADIO_TECHNOLOGY_PROPRIETARY)
+ .setRadioTechnology(getSupportedNtnRadioTechnology())
.reportSessionMetrics();
} else {
mControllerMetricsStats.onSatelliteDisabled();
@@ -1195,14 +1195,15 @@
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
int error = evaluateOemSatelliteRequestAllowed(true);
if (error != SATELLITE_RESULT_SUCCESS) {
- result.accept(error);
+ sendErrorAndReportSessionMetrics(error, result);
return;
}
if (enableSatellite) {
if (!mIsRadioOn) {
loge("Radio is not on, can not enable satellite");
- result.accept(SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE);
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE, result);
return;
}
} else {
@@ -1216,12 +1217,14 @@
if (enableDemoMode != mIsDemoModeEnabled) {
loge("Received invalid demo mode while satellite session is enabled"
+ " enableDemoMode = " + enableDemoMode);
- result.accept(SatelliteManager.SATELLITE_RESULT_INVALID_ARGUMENTS);
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_INVALID_ARGUMENTS, result);
return;
} else {
logd("Enable request matches with current state"
+ " enableSatellite = " + enableSatellite);
- result.accept(SATELLITE_RESULT_SUCCESS);
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_SUCCESS, result);
return;
}
}
@@ -1246,13 +1249,15 @@
} else if (mSatelliteEnabledRequest.enableSatellite == request.enableSatellite) {
logd("requestSatelliteEnabled enableSatellite: " + enableSatellite
+ " is already in progress.");
- result.accept(SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS);
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS, result);
return;
} else if (mSatelliteEnabledRequest.enableSatellite == false
&& request.enableSatellite == true) {
logd("requestSatelliteEnabled enableSatellite: " + enableSatellite + " cannot be "
+ "processed. Disable satellite is already in progress.");
- result.accept(SatelliteManager.SATELLITE_RESULT_ERROR);
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_ERROR, result);
return;
}
}
@@ -1295,6 +1300,7 @@
*/
public boolean isSatelliteEnabled() {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("isSatelliteEnabled: oemEnabledSatelliteFlag is disabled");
return false;
}
if (mIsSatelliteEnabled == null) return false;
@@ -1328,6 +1334,7 @@
*/
public boolean isDemoModeEnabled() {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("isDemoModeEnabled: oemEnabledSatelliteFlag is disabled");
return false;
}
return mIsDemoModeEnabled;
@@ -1342,6 +1349,7 @@
*/
public void requestIsSatelliteSupported(int subId, @NonNull ResultReceiver result) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("requestIsSatelliteSupported: oemEnabledSatelliteFlag is disabled");
result.send(SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED, null);
return;
}
@@ -1553,6 +1561,8 @@
public void unregisterForSatelliteProvisionStateChanged(
int subId, @NonNull ISatelliteProvisionStateCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("unregisterForSatelliteProvisionStateChanged: "
+ + "oemEnabledSatelliteFlag is disabled");
return;
}
mSatelliteProvisionStateChangedListeners.remove(callback.asBinder());
@@ -1597,6 +1607,7 @@
@SatelliteManager.SatelliteResult public int registerForSatelliteModemStateChanged(int subId,
@NonNull ISatelliteStateCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("registerForSatelliteModemStateChanged: oemEnabledSatelliteFlag is disabled");
return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
}
if (mSatelliteSessionController != null) {
@@ -1620,6 +1631,7 @@
public void unregisterForSatelliteModemStateChanged(int subId,
@NonNull ISatelliteStateCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("unregisterForSatelliteModemStateChanged: oemEnabledSatelliteFlag is disabled");
return;
}
if (mSatelliteSessionController != null) {
@@ -1641,6 +1653,7 @@
@SatelliteManager.SatelliteResult public int registerForSatelliteDatagram(int subId,
@NonNull ISatelliteDatagramCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("registerForSatelliteDatagram: oemEnabledSatelliteFlag is disabled");
return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
}
if (!mSatelliteModemInterface.isSatelliteServiceSupported()) {
@@ -1660,6 +1673,7 @@
public void unregisterForSatelliteDatagram(int subId,
@NonNull ISatelliteDatagramCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("unregisterForSatelliteDatagram: oemEnabledSatelliteFlag is disabled");
return;
}
if (!mSatelliteModemInterface.isSatelliteServiceSupported()) {
@@ -1774,6 +1788,7 @@
*/
public void setDeviceAlignedWithSatellite(@NonNull int subId, @NonNull boolean isAligned) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("setDeviceAlignedWithSatellite: oemEnabledSatelliteFlag is disabled");
return;
}
mDatagramController.setDeviceAlignedWithSatellite(isAligned);
@@ -1866,6 +1881,8 @@
*/
@NonNull public Set<Integer> getSatelliteAttachRestrictionReasonsForCarrier(int subId) {
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
+ logd("getSatelliteAttachRestrictionReasonsForCarrier: carrierEnabledSatelliteFlag is "
+ + "disabled");
return new HashSet<>();
}
synchronized (mIsSatelliteEnabledLock) {
@@ -1956,9 +1973,13 @@
*/
public boolean setSatelliteServicePackageName(@Nullable String servicePackageName) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("setSatelliteServicePackageName: oemEnabledSatelliteFlag is disabled");
return false;
}
- if (!isMockModemAllowed()) return false;
+ if (!isMockModemAllowed()) {
+ logd("setSatelliteServicePackageName: mock modem not allowed");
+ return false;
+ }
// Cached states need to be cleared whenever switching satellite vendor services.
logd("setSatelliteServicePackageName: Resetting cached states");
@@ -1988,6 +2009,7 @@
*/
public boolean setSatelliteListeningTimeoutDuration(long timeoutMillis) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("setSatelliteListeningTimeoutDuration: oemEnabledSatelliteFlag is disabled");
return false;
}
if (mSatelliteSessionController == null) {
@@ -2006,6 +2028,7 @@
*/
public boolean setSatelliteDeviceAlignedTimeoutDuration(long timeoutMillis) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("setSatelliteDeviceAlignedTimeoutDuration: oemEnabledSatelliteFlag is disabled");
return false;
}
return mDatagramController.setSatelliteDeviceAlignedTimeoutDuration(timeoutMillis);
@@ -2020,6 +2043,7 @@
*/
public boolean setSatelliteGatewayServicePackageName(@Nullable String servicePackageName) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("setSatelliteGatewayServicePackageName: oemEnabledSatelliteFlag is disabled");
return false;
}
if (mSatelliteSessionController == null) {
@@ -2041,6 +2065,7 @@
public boolean setSatellitePointingUiClassName(
@Nullable String packageName, @Nullable String className) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("setSatellitePointingUiClassName: oemEnabledSatelliteFlag is disabled");
return false;
}
return mPointingAppController.setSatellitePointingUiClassName(packageName, className);
@@ -2060,6 +2085,7 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public void onSatelliteServiceConnected() {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("onSatelliteServiceConnected: oemEnabledSatelliteFlag is disabled");
return;
}
if (mSatelliteModemInterface.isSatelliteServiceSupported()) {
@@ -2110,6 +2136,7 @@
*/
public boolean isSatelliteSupported() {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("isSatelliteSupported: oemEnabledSatelliteFlag is disabled");
return false;
}
Boolean supported = isSatelliteSupportedInternal();
@@ -2123,6 +2150,7 @@
@NonNull
public List<String> getSatellitePlmnList(int subId) {
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
+ logd("getSatellitePlmnList: carrierEnabledSatelliteFlag is disabled");
return new ArrayList<>();
}
synchronized (mSupportedSatelliteServicesLock) {
@@ -2143,6 +2171,7 @@
@NonNull
public List<Integer> getSupportedSatelliteServices(int subId, String plmn) {
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
+ logd("getSupportedSatelliteServices: carrierEnabledSatelliteFlag is disabled");
return new ArrayList<>();
}
synchronized (mSupportedSatelliteServicesLock) {
@@ -2983,6 +3012,30 @@
return SATELLITE_RESULT_SUCCESS;
}
+ /**
+ * Returns the non-terrestrial network radio technology that the satellite modem currently
+ * supports. If multiple technologies are available, returns the first supported technology.
+ */
+ @VisibleForTesting
+ protected @SatelliteManager.NTRadioTechnology int getSupportedNtnRadioTechnology() {
+ synchronized (mSatelliteCapabilitiesLock) {
+ if (mSatelliteCapabilities != null) {
+ return mSatelliteCapabilities.getSupportedRadioTechnologies()
+ .stream().findFirst().orElse(SatelliteManager.NT_RADIO_TECHNOLOGY_UNKNOWN);
+ }
+ return SatelliteManager.NT_RADIO_TECHNOLOGY_UNKNOWN;
+ }
+ }
+
+ private void sendErrorAndReportSessionMetrics(@SatelliteManager.SatelliteResult int error,
+ Consumer<Integer> result) {
+ result.accept(error);
+ SessionMetricsStats.getInstance()
+ .setInitializationResult(error)
+ .setRadioTechnology(getSupportedNtnRadioTechnology())
+ .reportSessionMetrics();
+ }
+
private static void logd(@NonNull String log) {
Rlog.d(TAG, log);
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
index 62f7371..dc6ea13 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
@@ -30,6 +30,8 @@
import android.os.Message;
import android.os.RegistrantList;
import android.os.RemoteException;
+import android.telephony.IBooleanConsumer;
+import android.telephony.IIntegerConsumer;
import android.telephony.Rlog;
import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.SatelliteCapabilities;
@@ -47,8 +49,6 @@
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.ExponentialBackoff;
-import com.android.internal.telephony.IBooleanConsumer;
-import com.android.internal.telephony.IIntegerConsumer;
import java.util.Arrays;
import java.util.List;
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
index a952197..8146983 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
@@ -22,6 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.app.compat.CompatChanges;
@@ -44,9 +45,11 @@
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.os.TelephonyServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.Telephony.SimInfo;
import android.service.carrier.CarrierIdentifier;
@@ -124,6 +127,7 @@
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
+import java.util.stream.Stream;
/**
* The subscription manager service is the backend service of {@link SubscriptionManager}.
@@ -131,6 +135,8 @@
*/
public class SubscriptionManagerService extends ISub.Stub {
private static final String LOG_TAG = "SMSVC";
+ private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem";
+ private static final String BOOT_ALLOW_MOCK_MODEM_PROPERTY = "ro.boot.radio.allow_mock_modem";
/** Whether enabling verbose debugging message or not. */
private static final boolean VDBG = false;
@@ -189,6 +195,18 @@
@EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
public static final long REQUIRE_DEVICE_IDENTIFIERS_FOR_GROUP_UUID = 213902861L;
+ /**
+ * Apps targeting on Android V and beyond can only see subscriptions accessible by them
+ * according to its user Id.
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ public static final long FILTER_ACCESSIBLE_SUBS_BY_USER = 296076674L;
+
+ /** Wrap Binder methods for testing. */
+ @NonNull
+ private static final BinderWrapper BINDER_WRAPPER = new BinderWrapper();
+
/** Instance of subscription manager service. */
@NonNull
private static SubscriptionManagerService sInstance;
@@ -285,6 +303,12 @@
private final int[] mSimState;
/**
+ * {@code true} if a user profile can only see the SIMs associated with it, unless it possesses
+ * no SIMs on the device.
+ */
+ private Map<Integer, List<Integer>> mUserIdToAvailableSubs = new ConcurrentHashMap<>();
+
+ /**
* Slot index/subscription map that automatically invalidate cache in
* {@link SubscriptionManager}.
*
@@ -357,6 +381,14 @@
}
}
+ /** Binder Wrapper for test mocking. */
+ @VisibleForTesting
+ public static class BinderWrapper {
+ @NonNull public UserHandle getCallingUserHandle() {
+ return Binder.getCallingUserHandle();
+ }
+ }
+
/**
* This is the callback used for listening events from {@link SubscriptionManagerService}.
*/
@@ -511,6 +543,8 @@
*/
@Override
public void onSubscriptionChanged(int subId) {
+ updateUserIdToAvailableSubs();
+
mSubscriptionManagerServiceCallbacks.forEach(
callback -> callback.invokeFromExecutor(
() -> callback.onSubscriptionChanged(subId)));
@@ -1146,6 +1180,8 @@
if (mFeatureFlags.oemEnabledSatelliteFlag()) {
builder.setOnlyNonTerrestrialNetwork(
isSatellitePlmn(mcc + mnc) ? 1 : 0);
+ } else {
+ log("updateEmbeddedSubscriptions: oemEnabledSatelliteFlag is disabled");
}
}
// If cardId = unsupported or un-initialized, we have no reason to update DB.
@@ -1658,7 +1694,8 @@
}
/**
- * Get all subscription info records from SIMs that are inserted now or previously inserted.
+ * Get all subscription info records from SIMs visible to the calling user that are inserted now
+ * or previously inserted.
*
* <p>
* If the caller does not have {@link Manifest.permission#READ_PHONE_NUMBERS} permission,
@@ -1698,8 +1735,7 @@
throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or "
+ "carrier privilege");
}
-
- return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
+ return getSubscriptionInfoStreamAsUser(BINDER_WRAPPER.getCallingUserHandle())
// callers have READ_PHONE_STATE or READ_PRIVILEGED_PHONE_STATE can get a full
// list. Carrier apps can only get the subscriptions they have privileged.
.filter(subInfo -> TelephonyPermissions.checkCallingOrSelfReadPhoneStateNoThrow(
@@ -1828,8 +1864,8 @@
}
/**
- * Get the SubscriptionInfo(s) of the active subscriptions. The records will be sorted
- * by {@link SubscriptionInfo#getSimSlotIndex} then by
+ * Get the SubscriptionInfo(s) of the active subscriptions for calling user. The records will be
+ * sorted by {@link SubscriptionInfo#getSimSlotIndex} then by
* {@link SubscriptionInfo#getSubscriptionId}.
*
* @param callingPackage The package making the call.
@@ -1852,7 +1888,7 @@
// on the subs it has carrier privilege.
if (!TelephonyPermissions.checkReadPhoneStateOnAnyActiveSub(mContext,
Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, callingFeatureId,
- "getAllSubInfoList")) {
+ "getActiveSubscriptionInfoList")) {
// Ideally we should avoid silent failure, but since this API has already been used by
// many apps and they do not expect the security exception, we return an empty list
// here so it's consistent with pre-U behavior.
@@ -1860,14 +1896,13 @@
+ "permission. Returning empty list here.");
return Collections.emptyList();
}
-
- return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
+ return getSubscriptionInfoStreamAsUser(BINDER_WRAPPER.getCallingUserHandle())
.filter(SubscriptionInfoInternal::isActive)
// Remove the identifier if the caller does not have sufficient permission.
// carrier apps will get full subscription info on the subscriptions associated
// to them.
.map(subInfo -> conditionallyRemoveIdentifiers(subInfo.toSubscriptionInfo(),
- callingPackage, callingFeatureId, "getAllSubInfoList"))
+ callingPackage, callingFeatureId, "getActiveSubscriptionInfoList"))
.sorted(Comparator.comparing(SubscriptionInfo::getSimSlotIndex)
.thenComparing(SubscriptionInfo::getSubscriptionId))
.collect(Collectors.toList());
@@ -1897,13 +1932,7 @@
throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or "
+ "carrier privilege");
}
-
- final long token = Binder.clearCallingIdentity();
- try {
- return getActiveSubIdList(false).length;
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ return getActiveSubIdListAsUser(false, BINDER_WRAPPER.getCallingUserHandle()).length;
}
/**
@@ -1934,27 +1963,42 @@
@Nullable String callingFeatureId) {
enforcePermissions("getAvailableSubscriptionInfoList",
Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ return getAvailableSubscriptionsInternalStream()
+ .sorted(Comparator.comparing(SubscriptionInfoInternal::getSimSlotIndex)
+ .thenComparing(SubscriptionInfoInternal::getSubscriptionId))
+ .map(SubscriptionInfoInternal::toSubscriptionInfo)
+ .collect(Collectors.toList());
- // Now that all security checks pass, perform the operation as ourselves.
- final long identity = Binder.clearCallingIdentity();
- try {
- // Available eSIM profiles are reported by EuiccManager. However for physical SIMs if
- // they are in inactive slot or programmatically disabled, they are still considered
- // available. In this case we get their iccid from slot info and include their
- // subscriptionInfos.
- List<String> iccIds = getIccIdsOfInsertedPhysicalSims();
+ }
- return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
- .filter(subInfo -> subInfo.isActive() || iccIds.contains(subInfo.getIccId())
- || (mEuiccManager != null && mEuiccManager.isEnabled()
- && subInfo.isEmbedded()))
- .map(SubscriptionInfoInternal::toSubscriptionInfo)
- .sorted(Comparator.comparing(SubscriptionInfo::getSimSlotIndex)
- .thenComparing(SubscriptionInfo::getSubscriptionId))
- .collect(Collectors.toList());
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
+ /**
+ * @return all the subscriptions visible to user on the device.
+ */
+ private Stream<SubscriptionInfoInternal> getAvailableSubscriptionsInternalStream() {
+ // Available eSIM profiles are reported by EuiccManager. However for physical SIMs if
+ // they are in inactive slot or programmatically disabled, they are still considered
+ // available. In this case we get their iccid from slot info and include their
+ // subscriptionInfos.
+ List<String> iccIds = getIccIdsOfInsertedPhysicalSims();
+
+ return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
+ .filter(subInfo -> subInfo.isActive() || iccIds.contains(subInfo.getIccId())
+ || (mEuiccManager != null && mEuiccManager.isEnabled()
+ && subInfo.isEmbedded()));
+ }
+
+ /**
+ * Tracks for each user Id, a list of subscriptions associated with it.
+ * A profile is barred from seeing unassociated subscriptions if it has its own subscription
+ * which is available to choose from the device.
+ */
+ private void updateUserIdToAvailableSubs() {
+ mUserIdToAvailableSubs = getAvailableSubscriptionsInternalStream()
+ .collect(Collectors.groupingBy(
+ SubscriptionInfoInternal::getUserId,
+ Collectors.mapping(SubscriptionInfoInternal::getSubscriptionId,
+ Collectors.toList())));
+ log("updateUserIdToAvailableSubs: " + mUserIdToAvailableSubs);
}
/**
@@ -1989,8 +2033,7 @@
// Verify that the callingPackage belongs to the calling UID
mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
-
- return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
+ return getSubscriptionInfoStreamAsUser(BINDER_WRAPPER.getCallingUserHandle())
.map(SubscriptionInfoInternal::toSubscriptionInfo)
.filter(subInfo -> subInfo.isEmbedded()
&& mSubscriptionManager.canManageSubscription(subInfo, callingPackage))
@@ -2781,10 +2824,37 @@
/**
* @return The default subscription id.
+ * @deprecated Use {@link #getDefaultSubIdAsUser}.
*/
@Override
public int getDefaultSubId() {
- return mDefaultSubId.get();
+ return getDefaultSubIdAsUser(BINDER_WRAPPER.getCallingUserHandle().getIdentifier());
+ }
+
+ /**
+ * @param userId The given user Id to check.
+ * @return The default subscription id.
+ */
+ @Override
+ public int getDefaultSubIdAsUser(@UserIdInt int userId) {
+ return getDefaultAsUser(userId, mDefaultSubId.get());
+ }
+
+ /**
+ * Get the default subscription visible to the caller.
+ * @param userId The calling user Id.
+ * @param defaultValue Useful if the user owns more than one subscription.
+ * @return The subscription Id default to use.
+ */
+ private int getDefaultAsUser(@UserIdInt int userId, int defaultValue) {
+ List<SubscriptionInfoInternal> subInfos =
+ getSubscriptionInfoStreamAsUser(UserHandle.of(userId))
+ .filter(SubscriptionInfoInternal::isActive)
+ .toList();
+ if (subInfos.size() == 1) {
+ return subInfos.get(0).getSubscriptionId();
+ }
+ return defaultValue;
}
/**
@@ -2876,10 +2946,20 @@
/**
* @return The default subscription id for voice.
+ * @deprecated Use {@link #getDefaultVoiceSubIdAsUser}.
*/
@Override
public int getDefaultVoiceSubId() {
- return mDefaultVoiceSubId.get();
+ return getDefaultVoiceSubIdAsUser(BINDER_WRAPPER.getCallingUserHandle().getIdentifier());
+ }
+
+ /**
+ * @param userId The calling user Id.
+ * @return The default voice subscription id.
+ */
+ @Override
+ public int getDefaultVoiceSubIdAsUser(@UserIdInt int userId) {
+ return getDefaultAsUser(userId, mDefaultVoiceSubId.get());
}
/**
@@ -2922,10 +3002,24 @@
/**
* @return The default subscription id for SMS.
+ * @deprecated Use {@link #getDefaultSmsSubIdAsUser}.
*/
@Override
public int getDefaultSmsSubId() {
- return mDefaultSmsSubId.get();
+ return getDefaultSmsSubIdAsUser(BINDER_WRAPPER.getCallingUserHandle().getIdentifier());
+ }
+
+ /**
+ * Get the default sms subscription id associated with the user. When a subscription is
+ * associated with personal profile or work profile, the default sms subscription id will be
+ * always the subscription it is associated with.
+ *
+ * @param userId The given user Id to check.
+ * @return The default voice id.
+ */
+ @Override
+ public int getDefaultSmsSubIdAsUser(@UserIdInt int userId) {
+ return getDefaultAsUser(userId, mDefaultSmsSubId.get());
}
/**
@@ -2982,19 +3076,30 @@
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public int[] getActiveSubIdList(boolean visibleOnly) {
enforcePermissions("getActiveSubIdList", Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ // UserHandle.ALL because this API is exposed as system API.
+ return getActiveSubIdListAsUser(visibleOnly, UserHandle.ALL);
+ }
- final long token = Binder.clearCallingIdentity();
- try {
- return mSlotIndexToSubId.values().stream()
- .filter(subId -> {
- SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
- .getSubscriptionInfoInternal(subId);
- return subInfo != null && (!visibleOnly || subInfo.isVisible()); })
- .mapToInt(x -> x)
- .toArray();
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ /**
+ * Get the active subscription id list as user.
+ * Must be used before clear Binder identity.
+ *
+ * @param visibleOnly {@code true} if only includes user visible subscription's sub id.
+ * @param user If {@code null}, uses the calling user handle to judge which subscriptions are
+ * accessible to the caller.
+ * @return List of the active subscription id.
+ */
+ private int[] getActiveSubIdListAsUser(boolean visibleOnly, @NonNull final UserHandle user) {
+ return mSlotIndexToSubId.values().stream()
+ .filter(subId -> {
+ SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
+ .getSubscriptionInfoInternal(subId);
+ return subInfo != null && (!visibleOnly || subInfo.isVisible())
+ && isSubscriptionAssociatedWithUserInternal(
+ subInfo, user.getIdentifier());
+ })
+ .mapToInt(x -> x)
+ .toArray();
}
/**
@@ -3658,26 +3763,28 @@
@NonNull UserHandle userHandle) {
enforcePermissions("isSubscriptionAssociatedWithUser",
Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
+ SubscriptionInfoInternal subInfoInternal = mSubscriptionDatabaseManager
+ .getSubscriptionInfoInternal(subscriptionId);
+ // Throw IAE if no record of the sub's association state.
+ if (subInfoInternal == null) {
+ throw new IllegalArgumentException(
+ "[isSubscriptionAssociatedWithUser]: Subscription doesn't exist: "
+ + subscriptionId);
+ }
+
+ if (mFeatureFlags.workProfileApiSplit()) {
+ return isSubscriptionAssociatedWithUserInternal(
+ subInfoInternal, userHandle.getIdentifier());
+ }
long token = Binder.clearCallingIdentity();
try {
- // Throw IAE if no record of the sub's association state.
- if (mSubscriptionDatabaseManager.getSubscriptionInfoInternal(subscriptionId) == null) {
- throw new IllegalArgumentException(
- "[isSubscriptionAssociatedWithUser]: Subscription doesn't exist: "
- + subscriptionId);
- }
-
// Get list of subscriptions associated with this user.
List<SubscriptionInfo> associatedSubscriptionsList =
getSubscriptionInfoListAssociatedWithUser(userHandle);
- if (associatedSubscriptionsList.isEmpty()) {
- return false;
- }
-
// Return true if required subscription is present in associated subscriptions list.
for (SubscriptionInfo subInfo: associatedSubscriptionsList) {
- if (subInfo.getSubscriptionId() == subscriptionId){
+ if (subInfo.getSubscriptionId() == subscriptionId) {
return true;
}
}
@@ -3688,6 +3795,25 @@
}
/**
+ * @param subInfo The subscription info to check.
+ * @param userId The caller user Id.
+ * @return {@code true} if the given user Id is allowed to access to the given subscription.
+ */
+ private boolean isSubscriptionAssociatedWithUserInternal(
+ @NonNull SubscriptionInfoInternal subInfo, @UserIdInt int userId) {
+ if (!mFeatureFlags.workProfileApiSplit()
+ || !CompatChanges.isChangeEnabled(FILTER_ACCESSIBLE_SUBS_BY_USER,
+ Binder.getCallingUid())) {
+ return true;
+ }
+ return subInfo.getUserId() == userId
+ // Can access the unassociated sub if the user doesn't have its own.
+ || (subInfo.getUserId() == UserHandle.USER_NULL
+ && mUserIdToAvailableSubs.get(userId) == null)
+ || userId == UserHandle.USER_ALL;
+ }
+
+ /**
* Get list of subscriptions associated with user.
*
* If user handle is associated with some subscriptions, return subscriptionsAssociatedWithUser
@@ -3700,11 +3826,18 @@
*
*/
@Override
- public @NonNull List<SubscriptionInfo> getSubscriptionInfoListAssociatedWithUser(
+ @NonNull
+ public List<SubscriptionInfo> getSubscriptionInfoListAssociatedWithUser(
@NonNull UserHandle userHandle) {
enforcePermissions("getSubscriptionInfoListAssociatedWithUser",
Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
+ if (mFeatureFlags.workProfileApiSplit()) {
+ return getSubscriptionInfoStreamAsUser(userHandle)
+ .map(SubscriptionInfoInternal::toSubscriptionInfo)
+ .collect(Collectors.toList());
+ }
+
long token = Binder.clearCallingIdentity();
try {
List<SubscriptionInfoInternal> subInfoList = mSubscriptionDatabaseManager
@@ -3728,20 +3861,45 @@
UserManager userManager = mContext.getSystemService(UserManager.class);
if ((userManager != null)
&& (userManager.isManagedProfile(userHandle.getIdentifier()))) {
- // For work profile, return subscriptions associated only with work profile
+ // For work profile, return subscriptions associated only with work profile even
+ // if it's empty.
return subscriptionsAssociatedWithUser;
}
- // For all other profiles, if subscriptionsAssociatedWithUser is empty return all the
- // subscriptionsWithNoAssociation.
- return subscriptionsAssociatedWithUser.isEmpty() ?
- subscriptionsWithNoAssociation : subscriptionsAssociatedWithUser;
+ // For all other profiles, if subscriptionsAssociatedWithUser is empty return all
+ // the subscriptionsWithNoAssociation.
+ return subscriptionsAssociatedWithUser.isEmpty()
+ ? subscriptionsWithNoAssociation : subscriptionsAssociatedWithUser;
} finally {
Binder.restoreCallingIdentity(token);
}
}
/**
+ * @return All active subscriptions.
+ */
+ @NonNull
+ private List<SubscriptionInfoInternal> getActiveSubscriptionInfoListAllUser() {
+ return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
+ .filter(SubscriptionInfoInternal::isActive)
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Get subscriptions accessible to the caller user.
+ *
+ * @param user The user to check.
+ * @return a stream of accessible internal subscriptions.
+ */
+ @NonNull
+ private Stream<SubscriptionInfoInternal> getSubscriptionInfoStreamAsUser(
+ @NonNull final UserHandle user) {
+ return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
+ .filter(info -> isSubscriptionAssociatedWithUserInternal(
+ info, user.getIdentifier()));
+ }
+
+ /**
* Called during setup wizard restore flow to attempt to restore the backed up sim-specific
* configs to device for all existing SIMs in the subscription database {@link SimInfo}.
* Internally, it will store the backup data in an internal file. This file will persist on
@@ -3808,14 +3966,26 @@
* @throws SecurityException if the caller does not have any permissions.
*/
private void enforcePermissions(@Nullable String message, @NonNull String ...permissions) {
+ if (!hasPermissions(permissions)) {
+ throw new SecurityException(
+ message + ". Does not have any of the following permissions. "
+ + Arrays.toString(permissions));
+ }
+ }
+
+ /**
+ * Check have any of the permissions
+ * @param permissions The permissions to check.
+ * @return {@code true} if the caller has one of the given permissions.
+ */
+ private boolean hasPermissions(@NonNull String ...permissions) {
for (String permission : permissions) {
if (mContext.checkCallingOrSelfPermission(permission)
== PackageManager.PERMISSION_GRANTED) {
- return;
+ return true;
}
}
- throw new SecurityException(message + ". Does not have any of the following permissions. "
- + Arrays.toString(permissions));
+ return false;
}
/**
@@ -3839,9 +4009,8 @@
*/
@Nullable
public SubscriptionInfo getSubscriptionInfo(int subId) {
- SubscriptionInfoInternal subscriptionInfoInternal = getSubscriptionInfoInternal(subId);
- return subscriptionInfoInternal != null
- ? subscriptionInfoInternal.toSubscriptionInfo() : null;
+ SubscriptionInfoInternal infoInternal = getSubscriptionInfoInternal(subId);
+ return infoInternal != null ? infoInternal.toSubscriptionInfo() : null;
}
/**
@@ -3958,8 +4127,7 @@
*/
@VisibleForTesting
public void updateGroupDisabled() {
- List<SubscriptionInfo> activeSubscriptions = getActiveSubscriptionInfoList(
- mContext.getOpPackageName(), mContext.getFeatureId());
+ List<SubscriptionInfoInternal> activeSubscriptions = getActiveSubscriptionInfoListAllUser();
for (SubscriptionInfo oppSubInfo : getOpportunisticSubscriptions(
mContext.getOpPackageName(), mContext.getFeatureId())) {
boolean groupDisabled = activeSubscriptions.stream()
@@ -3987,6 +4155,7 @@
*/
private boolean isSatellitePlmn(@NonNull String mccMnc) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ log("isSatellitePlmn: oemEnabledSatelliteFlag is disabled");
return false;
}
@@ -3997,11 +4166,19 @@
} catch (Resources.NotFoundException ex) {
loge("isSatellitePlmn: id= " + id + ", ex=" + ex);
}
- if (overlayMccMnc == null) {
- return false;
- } else {
- return mccMnc.equals(overlayMccMnc);
+ if (TextUtils.isEmpty(overlayMccMnc) && isMockModemAllowed()) {
+ log("isSatellitePlmn: Read config_satellite_sim_identifier from device config");
+ overlayMccMnc = DeviceConfig.getString(DeviceConfig.NAMESPACE_TELEPHONY,
+ "config_satellite_sim_identifier", "");
}
+ log("isSatellitePlmn: overlayMccMnc=" + overlayMccMnc + ", mccMnc=" + mccMnc);
+ return TextUtils.equals(mccMnc, overlayMccMnc);
+ }
+
+ private boolean isMockModemAllowed() {
+ boolean isAllowed = SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false);
+ return (SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false)
+ || SystemProperties.getBoolean(BOOT_ALLOW_MOCK_MODEM_PROPERTY, false));
}
/**
@@ -4066,6 +4243,7 @@
pw.println("activeDataSubId=" + getActiveDataSubscriptionId());
pw.println("defaultSmsSubId=" + getDefaultSmsSubId());
pw.println("areAllSubscriptionsLoaded=" + areAllSubscriptionsLoaded());
+ pw.println("mUserIdToAvailableSubs=" + mUserIdToAvailableSubs);
pw.println();
for (int i = 0; i < mSimState.length; i++) {
pw.println("mSimState[" + i + "]="
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index a7382ef..0459bf6 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -597,8 +597,6 @@
log("Received EVENT_RADIO_AVAILABLE/EVENT_RADIO_ON, calling "
+ "getIccCardStatus");
}
- mCis[phoneId].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE,
- phoneId));
// slot status should be the same on all RILs; request it only for phoneId 0
if (phoneId == 0) {
if (DBG) {
@@ -608,6 +606,8 @@
mRadioConfig.getSimSlotsStatus(obtainMessage(EVENT_GET_SLOT_STATUS_DONE,
phoneId));
}
+ mCis[phoneId].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE,
+ phoneId));
break;
case EVENT_GET_ICC_STATUS_DONE:
if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE");
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java
index 4fcf620..005b312 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java
@@ -18,18 +18,17 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import android.net.NetworkCapabilities;
import android.os.Looper;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.SignalStrength;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
+import android.telephony.data.ApnSetting;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -51,7 +50,6 @@
logd("DataConfigManagerTest +Setup!");
super.setUp(getClass().getSimpleName());
mBundle = mContextFixture.getCarrierConfigBundle();
- when(mCarrierConfigManager.getConfigForSubId(anyInt(), any())).thenReturn(mBundle);
mDataConfigManagerUT = new DataConfigManager(mPhone, Looper.myLooper(), mFeatureFlags);
logd("DataConfigManagerTest -Setup!");
}
@@ -145,4 +143,24 @@
signalStrength))
.isEqualTo(0/*OUT_OF_SERVICE_AUTO_DATA_SWITCH_SCORE*/);
}
+
+ @Test
+ public void testMeteredNetworkCapabilities() {
+ doReturn(true).when(mFeatureFlags).meteredEmbbUrlcc();
+ mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
+ new String[] {ApnSetting.TYPE_MMS_STRING, ApnSetting.TYPE_DEFAULT_STRING});
+ mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
+ new String[] {ApnSetting.TYPE_SUPL_STRING, ApnSetting.TYPE_MCX_STRING});
+ mDataConfigManagerUT.sendEmptyMessage(1/*EVENT_CARRIER_CONFIG_CHANGED*/);
+ processAllMessages();
+
+ assertThat(mDataConfigManagerUT.getMeteredNetworkCapabilities(false)).containsExactly(
+ NetworkCapabilities.NET_CAPABILITY_MMS, NetworkCapabilities.NET_CAPABILITY_INTERNET,
+ NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH,
+ NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY);
+ assertThat(mDataConfigManagerUT.getMeteredNetworkCapabilities(true)).containsExactly(
+ NetworkCapabilities.NET_CAPABILITY_SUPL, NetworkCapabilities.NET_CAPABILITY_MCX,
+ NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH,
+ NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY);
+ }
}
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 0be1927..7da79a6 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
@@ -830,6 +830,34 @@
@Test
@SmallTest
+ public void testRecoverNormalInCellularWhenVoWiFiConnected() {
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+ // Create test Phones
+ Phone testPhone = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
+ /* isRadioOn= */ true);
+ // Call startEmergencyCall() to set testPhone
+ CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(testPhone,
+ TEST_CALL_ID, false);
+
+ // Set emergency transport
+ emergencyStateTracker.onEmergencyTransportChanged(
+ EmergencyStateTracker.EMERGENCY_TYPE_CALL, MODE_EMERGENCY_WLAN);
+
+ // Set call properties
+ emergencyStateTracker.onEmergencyCallPropertiesChanged(
+ android.telecom.Connection.PROPERTY_WIFI, TEST_CALL_ID);
+
+ verify(testPhone, times(0)).cancelEmergencyNetworkScan(anyBoolean(), any());
+
+ // Set call to ACTIVE
+ emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, TEST_CALL_ID);
+
+ verify(testPhone, times(1)).cancelEmergencyNetworkScan(eq(true), any());
+ }
+
+ @Test
+ @SmallTest
public void testStartEmergencySms() {
EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
/* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
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 2feb34d..221aa0e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -764,9 +764,9 @@
verify(mMockDatagramController, times(4)).setDemoMode(eq(false));
verify(mMockControllerMetricsStats, times(2)).onSatelliteEnabled();
verify(mMockControllerMetricsStats, times(2)).reportServiceEnablementSuccessCount();
- verify(mMockSessionMetricsStats, times(3)).setInitializationResult(anyInt());
- verify(mMockSessionMetricsStats, times(3)).setRadioTechnology(anyInt());
- verify(mMockSessionMetricsStats, times(3)).reportSessionMetrics();
+ verify(mMockSessionMetricsStats, times(7)).setInitializationResult(anyInt());
+ verify(mMockSessionMetricsStats, times(7)).setRadioTechnology(anyInt());
+ verify(mMockSessionMetricsStats, times(7)).reportSessionMetrics();
// Successfully enable satellite when it is already enabled.
mIIntegerConsumerResults.clear();
@@ -921,6 +921,9 @@
assertTrue(waitForRequestSatelliteCapabilitiesResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSatelliteCapabilitiesResultCode);
assertEquals(mSatelliteCapabilities, mQueriedSatelliteCapabilities);
+ assertTrue(
+ mQueriedSatelliteCapabilities.getSupportedRadioTechnologies().contains(
+ mSatelliteControllerUT.getSupportedNtnRadioTechnology()));
resetSatelliteControllerUT();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
@@ -1992,6 +1995,9 @@
assertTrue(waitForRequestSatelliteCapabilitiesResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSatelliteCapabilitiesResultCode);
assertEquals(mEmptySatelliteCapabilities, mQueriedSatelliteCapabilities);
+ assertEquals(SatelliteManager.NT_RADIO_TECHNOLOGY_UNKNOWN,
+ mSatelliteControllerUT.getSupportedNtnRadioTechnology());
+
assertFalse(satelliteController.isSatelliteAttachRequired());
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
@@ -2007,6 +2013,9 @@
assertTrue(waitForRequestSatelliteCapabilitiesResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSatelliteCapabilitiesResultCode);
assertEquals(mSatelliteCapabilities, mQueriedSatelliteCapabilities);
+ assertTrue(
+ mQueriedSatelliteCapabilities.getSupportedRadioTechnologies().contains(
+ satelliteController.getSupportedNtnRadioTechnology()));
assertTrue(satelliteController.isSatelliteAttachRequired());
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
@@ -3023,5 +3032,12 @@
protected boolean areAllRadiosDisabled() {
return allRadiosDisabled;
}
+
+ @Override
+ protected int getSupportedNtnRadioTechnology() {
+ int ntRadioTechnology = super.getSupportedNtnRadioTechnology();
+ logd("getCurrentNtnRadioTechnology: val=" + ntRadioTechnology);
+ return ntRadioTechnology;
+ }
}
}
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 05489dc..e4e2434 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
@@ -105,7 +105,9 @@
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.euicc.EuiccController;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.subscription.SubscriptionDatabaseManager.SubscriptionDatabaseManagerCallback;
import com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.SubscriptionProvider;
+import com.android.internal.telephony.subscription.SubscriptionManagerService.BinderWrapper;
import com.android.internal.telephony.subscription.SubscriptionManagerService.SubscriptionManagerServiceCallback;
import com.android.internal.telephony.subscription.SubscriptionManagerService.SubscriptionMap;
import com.android.internal.telephony.uicc.IccCardStatus;
@@ -155,6 +157,7 @@
private SubscriptionManagerServiceCallback mMockedSubscriptionManagerServiceCallback;
private EuiccController mEuiccController;
private FeatureFlags mFlags;
+ private BinderWrapper mBinder;
private Set<Integer> mActiveSubs = new ArraySet<>();
@Rule
@@ -195,6 +198,10 @@
doReturn(FAKE_ICCID1).when(mUiccController).convertToCardString(eq(1));
doReturn(FAKE_ICCID2).when(mUiccController).convertToCardString(eq(2));
+ mBinder = Mockito.mock(BinderWrapper.class);
+ doReturn(FAKE_USER_HANDLE).when(mBinder).getCallingUserHandle();
+ replaceInstance(SubscriptionManagerService.class, "BINDER_WRAPPER", null, mBinder);
+
doReturn(new int[0]).when(mSubscriptionManager).getCompleteActiveSubscriptionIdList();
((MockContentResolver) mContext.getContentResolver()).addProvider(
@@ -256,6 +263,12 @@
return (SubscriptionDatabaseManager) field.get(mSubscriptionManagerServiceUT);
}
+ private SubscriptionDatabaseManagerCallback getSubscriptionDatabaseCallback() throws Exception {
+ Field field = SubscriptionDatabaseManager.class.getDeclaredField("mCallback");
+ field.setAccessible(true);
+ return (SubscriptionDatabaseManagerCallback) field.get(getSubscriptionDatabaseManager());
+ }
+
/**
* Insert the subscription info to the database. This is an instant insertion method. For real
* insertion sequence please use {@link #testInsertNewSim()}.
@@ -265,7 +278,6 @@
*/
private int insertSubscription(@NonNull SubscriptionInfoInternal subInfo) {
try {
- mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
subInfo = new SubscriptionInfoInternal.Builder(subInfo)
.setId(SubscriptionManager.INVALID_SUBSCRIPTION_ID).build();
int subId = getSubscriptionDatabaseManager().insertSubscriptionInfo(subInfo);
@@ -277,17 +289,12 @@
field.setAccessible(true);
SubscriptionMap<Integer, Integer> map = (SubscriptionMap<Integer, Integer>)
field.get(mSubscriptionManagerServiceUT);
- Class[] cArgs = new Class[2];
- cArgs[0] = Object.class;
- cArgs[1] = Object.class;
if (subInfo.getSimSlotIndex() >= 0) {
// Change the slot -> subId mapping
map.put(subInfo.getSimSlotIndex(), subId);
}
- mContextFixture.removeCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
- processAllMessages();
verify(mMockedSubscriptionManagerServiceCallback).onSubscriptionChanged(eq(subId));
Mockito.clearInvocations(mMockedSubscriptionManagerServiceCallback);
@@ -964,7 +971,7 @@
}
@Test
- public void testSetIconTint() throws Exception {
+ public void testSetIconTint() {
insertSubscription(FAKE_SUBSCRIPTION_INFO1);
// Should fail without MODIFY_PHONE_STATE
@@ -1150,6 +1157,299 @@
}
@Test
+ @EnableCompatChanges({SubscriptionManagerService.REQUIRE_DEVICE_IDENTIFIERS_FOR_GROUP_UUID,
+ SubscriptionManagerService.FILTER_ACCESSIBLE_SUBS_BY_USER})
+ public void testIsSubscriptionAssociatedWithUserMultiSubs() {
+ doReturn(true).when(mFlags).workProfileApiSplit();
+ mContextFixture.addCallingOrSelfPermission(
+ Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
+ insertSubscription(FAKE_SUBSCRIPTION_INFO1);
+ mSubscriptionManagerServiceUT.setSubscriptionUserHandle(
+ UserHandle.of(UserHandle.USER_NULL), 1);
+
+ // Verify sub 1 unassociated is visible to all profiles
+ assertThat(mSubscriptionManagerServiceUT.isSubscriptionAssociatedWithUser(1,
+ FAKE_USER_HANDLE)).isEqualTo(true);
+ assertThat(mSubscriptionManagerServiceUT.isSubscriptionAssociatedWithUser(1,
+ FAKE_MANAGED_PROFILE_USER_HANDLE)).isEqualTo(true);
+
+ // Assign sub 2 to work profile
+ insertSubscription(FAKE_SUBSCRIPTION_INFO2);
+ mSubscriptionManagerServiceUT.setSubscriptionUserHandle(
+ FAKE_MANAGED_PROFILE_USER_HANDLE, 2);
+ processAllMessages();
+ // Verify work profile can only see its dedicated sub 2
+ assertThat(mSubscriptionManagerServiceUT.isSubscriptionAssociatedWithUser(2,
+ FAKE_MANAGED_PROFILE_USER_HANDLE)).isEqualTo(true);
+ assertThat(mSubscriptionManagerServiceUT.isSubscriptionAssociatedWithUser(1,
+ FAKE_MANAGED_PROFILE_USER_HANDLE)).isEqualTo(false);
+ // Verify personal profile can only see the unassigned sub 1
+ assertThat(mSubscriptionManagerServiceUT.isSubscriptionAssociatedWithUser(1,
+ FAKE_USER_HANDLE)).isEqualTo(true);
+ assertThat(mSubscriptionManagerServiceUT.isSubscriptionAssociatedWithUser(2,
+ FAKE_USER_HANDLE)).isEqualTo(false);
+
+ // Sub 2 is deactivated, but still on device, verify visibility doesn't change.
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ mSubscriptionManagerServiceUT.updateSimState(
+ 1, TelephonyManager.SIM_STATE_NOT_READY, null, null);
+ processAllMessages();
+ // Verify work profile can only see its dedicated sub 2
+ assertThat(mSubscriptionManagerServiceUT.isSubscriptionAssociatedWithUser(2,
+ FAKE_MANAGED_PROFILE_USER_HANDLE)).isEqualTo(true);
+ assertThat(mSubscriptionManagerServiceUT.isSubscriptionAssociatedWithUser(1,
+ FAKE_MANAGED_PROFILE_USER_HANDLE)).isEqualTo(false);
+ // Verify personal profile can only see the unassigned sub 1
+ assertThat(mSubscriptionManagerServiceUT.isSubscriptionAssociatedWithUser(1,
+ FAKE_USER_HANDLE)).isEqualTo(true);
+ assertThat(mSubscriptionManagerServiceUT.isSubscriptionAssociatedWithUser(2,
+ FAKE_USER_HANDLE)).isEqualTo(false);
+
+ // Sub 2 is removed from the device.
+ mSubscriptionManagerServiceUT.updateSimState(
+ 1, TelephonyManager.SIM_STATE_ABSENT, null, null);
+ processAllMessages();
+ // Verify the visibility of the unassigned sub 1 is restored to both profiles.
+ assertThat(mSubscriptionManagerServiceUT.isSubscriptionAssociatedWithUser(1,
+ FAKE_USER_HANDLE)).isEqualTo(true);
+ assertThat(mSubscriptionManagerServiceUT.isSubscriptionAssociatedWithUser(1,
+ FAKE_MANAGED_PROFILE_USER_HANDLE)).isEqualTo(true);
+ }
+
+ @Test
+ @EnableCompatChanges({SubscriptionManagerService.REQUIRE_DEVICE_IDENTIFIERS_FOR_GROUP_UUID,
+ SubscriptionManagerService.FILTER_ACCESSIBLE_SUBS_BY_USER})
+ public void testSubscriptionAssociationWorkProfileCallerVisibility() {
+ // Split mode is defined as when a profile owns a dedicated sub, it loses the visibility to
+ // the unassociated sub.
+ doReturn(true).when(mFlags).workProfileApiSplit();
+ mContextFixture.addCallingOrSelfPermission(
+ Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
+ // Sub 1 is associated with work profile; Sub 2 is unassociated.
+ int subId1 = insertSubscription(FAKE_SUBSCRIPTION_INFO1);
+ mSubscriptionManagerServiceUT.setSubscriptionUserHandle(
+ FAKE_MANAGED_PROFILE_USER_HANDLE, subId1);
+ int subId2 = insertSubscription(FAKE_SUBSCRIPTION_INFO2);
+ mSubscriptionManagerServiceUT.setSubscriptionUserHandle(
+ UserHandle.of(UserHandle.USER_NULL), subId2);
+ // Set Sub 1 default data sub
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ mSubscriptionManagerServiceUT.setDefaultDataSubId(subId1);
+ processAllMessages();
+
+ // Calling from work profile
+ doReturn(FAKE_MANAGED_PROFILE_USER_HANDLE).when(mBinder).getCallingUserHandle();
+
+ // Test getAccessibleSubscriptionInfoList
+ doReturn(true).when(mEuiccManager).isEnabled();
+ doReturn(true).when(mSubscriptionManager).canManageSubscription(
+ any(SubscriptionInfo.class), eq(CALLING_PACKAGE));
+ assertThat(mSubscriptionManagerServiceUT.getAccessibleSubscriptionInfoList(
+ CALLING_PACKAGE)).isEqualTo(List.of(FAKE_SUBSCRIPTION_INFO1.toSubscriptionInfo()));
+ // Test getActiveSubIdList, System
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubIdList(false/*visible only*/))
+ .isEqualTo(new int[]{subId1, subId2});
+ // Test get getActiveSubInfoCount
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubInfoCount(
+ CALLING_PACKAGE, CALLING_FEATURE)).isEqualTo(1);
+ // Test getActiveSubscriptionInfo
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfo(
+ subId1, CALLING_PACKAGE, CALLING_FEATURE).getSubscriptionId()).isEqualTo(subId1);
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfo(
+ subId2, CALLING_PACKAGE, CALLING_FEATURE).getSubscriptionId()).isEqualTo(subId2);
+ // Test getActiveSubscriptionInfoForIccId
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoForIccId(
+ FAKE_ICCID1, CALLING_PACKAGE, CALLING_FEATURE).getSubscriptionId())
+ .isEqualTo(subId1);
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoForIccId(
+ FAKE_ICCID2, CALLING_PACKAGE, CALLING_FEATURE).getSubscriptionId())
+ .isEqualTo(subId2);
+ // Test getActiveSubscriptionInfoForSimSlotIndex
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoForSimSlotIndex(
+ 0, CALLING_PACKAGE, CALLING_FEATURE).getSubscriptionId())
+ .isEqualTo(subId1);
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoForSimSlotIndex(
+ 1, CALLING_PACKAGE, CALLING_FEATURE).getSubscriptionId())
+ .isEqualTo(subId2);
+ // Test getActiveSubscriptionInfoList
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoList(
+ CALLING_PACKAGE, CALLING_FEATURE).stream().map(SubscriptionInfo::getSubscriptionId)
+ .toList()).isEqualTo(List.of(subId1));
+ // Test getAllSubInfoList
+ assertThat(mSubscriptionManagerServiceUT.getAllSubInfoList(CALLING_PACKAGE,
+ CALLING_FEATURE).stream().map(SubscriptionInfo::getSubscriptionId).toList())
+ .isEqualTo(List.of(subId1));
+ // Test getAvailableSubscriptionInfoList
+ assertThat(mSubscriptionManagerServiceUT.getAvailableSubscriptionInfoList(CALLING_PACKAGE,
+ CALLING_FEATURE).stream().map(SubscriptionInfo::getSubscriptionId).toList())
+ .isEqualTo(List.of(subId1, subId2));
+ // Test getDefaultDataSubId
+ assertThat(mSubscriptionManagerServiceUT.getDefaultDataSubId()).isEqualTo(subId1);
+ // Test getDefault<Sms/Voice>SubIdAsUser
+ assertThat(mSubscriptionManagerServiceUT.getDefaultSmsSubIdAsUser(
+ FAKE_MANAGED_PROFILE_USER_HANDLE.getIdentifier())).isEqualTo(subId1);
+ assertThat(mSubscriptionManagerServiceUT.getDefaultSubIdAsUser(
+ FAKE_MANAGED_PROFILE_USER_HANDLE.getIdentifier())).isEqualTo(subId1);
+ assertThat(mSubscriptionManagerServiceUT.getDefaultVoiceSubIdAsUser(
+ FAKE_MANAGED_PROFILE_USER_HANDLE.getIdentifier())).isEqualTo(subId1);
+ // Test getEnabledSubscriptionId
+ assertThat(mSubscriptionManagerServiceUT.getEnabledSubscriptionId(0)).isEqualTo(
+ subId1);
+ assertThat(mSubscriptionManagerServiceUT.getEnabledSubscriptionId(1)).isEqualTo(
+ subId2);
+ // Test getOpportunisticSubscriptions
+ mSubscriptionManagerServiceUT.setOpportunistic(true, subId1, CALLING_PACKAGE);
+ mSubscriptionManagerServiceUT.setOpportunistic(true, subId2, CALLING_PACKAGE);
+ processAllMessages();
+ assertThat(mSubscriptionManagerServiceUT.getOpportunisticSubscriptions(CALLING_PACKAGE,
+ CALLING_FEATURE).stream().map(SubscriptionInfo::getSubscriptionId).toList())
+ .isEqualTo(List.of(subId1, subId2));
+ // Test getSubscriptionInfo - can get both as it's an internal getter
+ assertThat(mSubscriptionManagerServiceUT.getSubscriptionInfo(subId1).getSubscriptionId())
+ .isEqualTo(subId1);
+ assertThat(mSubscriptionManagerServiceUT.getSubscriptionInfo(subId2).getSubscriptionId())
+ .isEqualTo(subId2);
+ // Test getSubscriptionInfoListAssociatedWithUser
+ mContextFixture.addCallingOrSelfPermission(
+ Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
+ assertThat(mSubscriptionManagerServiceUT.getSubscriptionInfoListAssociatedWithUser(
+ FAKE_MANAGED_PROFILE_USER_HANDLE).stream().map(SubscriptionInfo::getSubscriptionId)
+ .toList()).isEqualTo(List.of(subId1));
+ // Test getSubscriptionsInGroup
+ setCarrierPrivilegesForSubId(true, subId1);
+ assertThat(mSubscriptionManagerServiceUT.getSubscriptionsInGroup(
+ ParcelUuid.fromString(FAKE_UUID1), CALLING_PACKAGE, CALLING_FEATURE)
+ .stream().map(SubscriptionInfo::getSubscriptionId).toList())
+ .isEqualTo(List.of(subId1));
+ // Test isActiveSubId
+ assertThat(mSubscriptionManagerServiceUT.isActiveSubId(subId1, CALLING_PACKAGE,
+ CALLING_FEATURE)).isTrue();
+ assertThat(mSubscriptionManagerServiceUT.isActiveSubId(subId2, CALLING_PACKAGE,
+ CALLING_FEATURE)).isTrue();
+ // Test isSubscriptionEnabled
+ assertThat(mSubscriptionManagerServiceUT.isSubscriptionEnabled(subId1)).isTrue();
+ assertThat(mSubscriptionManagerServiceUT.isSubscriptionEnabled(subId2)).isTrue();
+ }
+
+ @Test
+ @EnableCompatChanges({SubscriptionManagerService.REQUIRE_DEVICE_IDENTIFIERS_FOR_GROUP_UUID,
+ SubscriptionManagerService.FILTER_ACCESSIBLE_SUBS_BY_USER})
+ public void testSubscriptionAssociationPersonalCallerVisibility() {
+ // Split mode is defined as when a profile owns a dedicated sub, it loses the visibility to
+ // the unassociated sub.
+ doReturn(true).when(mFlags).workProfileApiSplit();
+ mContextFixture.addCallingOrSelfPermission(
+ Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
+ // Sub 1 is unassociated; Sub 2 is associated with work profile.
+ int subId1 = insertSubscription(FAKE_SUBSCRIPTION_INFO1);
+ mSubscriptionManagerServiceUT.setSubscriptionUserHandle(
+ UserHandle.of(UserHandle.USER_NULL), subId1);
+ int subId2 = insertSubscription(FAKE_SUBSCRIPTION_INFO2);
+ mSubscriptionManagerServiceUT.setSubscriptionUserHandle(
+ FAKE_MANAGED_PROFILE_USER_HANDLE, subId2);
+ // Set Sub 1 default data sub
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ mSubscriptionManagerServiceUT.setDefaultDataSubId(subId1);
+ processAllMessages();
+
+ // Calling from a profile that owns no dedicated subs.
+ doReturn(FAKE_USER_HANDLE).when(mBinder).getCallingUserHandle();
+
+ // Test getAccessibleSubscriptionInfoList
+ doReturn(true).when(mEuiccManager).isEnabled();
+ doReturn(true).when(mSubscriptionManager).canManageSubscription(
+ any(SubscriptionInfo.class), eq(CALLING_PACKAGE));
+ assertThat(mSubscriptionManagerServiceUT.getAccessibleSubscriptionInfoList(
+ CALLING_PACKAGE)).isEqualTo(List.of(FAKE_SUBSCRIPTION_INFO1.toSubscriptionInfo()));
+ // Test getActiveSubIdList, System
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubIdList(false/*visible only*/))
+ .isEqualTo(new int[]{subId1, subId2});
+ // Test get getActiveSubInfoCount
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubInfoCount(
+ CALLING_PACKAGE, CALLING_FEATURE)).isEqualTo(1);
+ // Test getActiveSubscriptionInfo
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfo(
+ subId1, CALLING_PACKAGE, CALLING_FEATURE).getSubscriptionId()).isEqualTo(subId1);
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfo(
+ subId2, CALLING_PACKAGE, CALLING_FEATURE).getSubscriptionId()).isEqualTo(subId2);
+ // Test getActiveSubscriptionInfoForIccId
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoForIccId(
+ FAKE_ICCID1, CALLING_PACKAGE, CALLING_FEATURE).getSubscriptionId())
+ .isEqualTo(subId1);
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoForIccId(
+ FAKE_ICCID2, CALLING_PACKAGE, CALLING_FEATURE).getSubscriptionId())
+ .isEqualTo(subId2);
+ // Test getActiveSubscriptionInfoForSimSlotIndex
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoForSimSlotIndex(
+ 0, CALLING_PACKAGE, CALLING_FEATURE).getSubscriptionId())
+ .isEqualTo(subId1);
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoForSimSlotIndex(
+ 1, CALLING_PACKAGE, CALLING_FEATURE).getSubscriptionId())
+ .isEqualTo(subId2);
+ // Test getActiveSubscriptionInfoList
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoList(
+ CALLING_PACKAGE, CALLING_FEATURE).stream()
+ .map(SubscriptionInfo::getSubscriptionId)
+ .toList()).isEqualTo(List.of(subId1));
+ // Test getAllSubInfoList
+ assertThat(mSubscriptionManagerServiceUT.getAllSubInfoList(CALLING_PACKAGE,
+ CALLING_FEATURE).stream().map(SubscriptionInfo::getSubscriptionId).toList())
+ .isEqualTo(List.of(subId1));
+ // Test getAvailableSubscriptionInfoList
+ assertThat(mSubscriptionManagerServiceUT.getAvailableSubscriptionInfoList(CALLING_PACKAGE,
+ CALLING_FEATURE).stream().map(SubscriptionInfo::getSubscriptionId).toList())
+ .isEqualTo(List.of(subId1, subId2));
+ // Test getDefaultDataSubId
+ assertThat(mSubscriptionManagerServiceUT.getDefaultDataSubId()).isEqualTo(subId1);
+ // Test getDefault<Sms/Voice>SubIdAsUser
+ assertThat(mSubscriptionManagerServiceUT.getDefaultSmsSubIdAsUser(
+ FAKE_USER_HANDLE.getIdentifier())).isEqualTo(subId1);
+ assertThat(mSubscriptionManagerServiceUT.getDefaultSubIdAsUser(
+ FAKE_USER_HANDLE.getIdentifier())).isEqualTo(subId1);
+ assertThat(mSubscriptionManagerServiceUT.getDefaultVoiceSubIdAsUser(
+ FAKE_USER_HANDLE.getIdentifier())).isEqualTo(subId1);
+ // Test getEnabledSubscriptionId
+ assertThat(mSubscriptionManagerServiceUT.getEnabledSubscriptionId(0)).isEqualTo(
+ subId1);
+ assertThat(mSubscriptionManagerServiceUT.getEnabledSubscriptionId(1)).isEqualTo(
+ subId2);
+ // Test getOpportunisticSubscriptions
+ mSubscriptionManagerServiceUT.setOpportunistic(true, subId1, CALLING_PACKAGE);
+ mSubscriptionManagerServiceUT.setOpportunistic(true, subId2, CALLING_PACKAGE);
+ processAllMessages();
+ assertThat(mSubscriptionManagerServiceUT.getOpportunisticSubscriptions(CALLING_PACKAGE,
+ CALLING_FEATURE).stream().map(SubscriptionInfo::getSubscriptionId).toList())
+ .isEqualTo(List.of(subId1, subId2));
+ // Test getSubscriptionInfo - can get both as it's an internal getter
+ assertThat(mSubscriptionManagerServiceUT.getSubscriptionInfo(subId1).getSubscriptionId())
+ .isEqualTo(subId1);
+ assertThat(mSubscriptionManagerServiceUT.getSubscriptionInfo(subId2).getSubscriptionId())
+ .isEqualTo(subId2);
+ // Test getSubscriptionInfoListAssociatedWithUser
+ mContextFixture.addCallingOrSelfPermission(
+ Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
+ assertThat(mSubscriptionManagerServiceUT.getSubscriptionInfoListAssociatedWithUser(
+ FAKE_USER_HANDLE).stream().map(SubscriptionInfo::getSubscriptionId)
+ .toList()).isEqualTo(List.of(subId1));
+ // Test getSubscriptionsInGroup
+ setCarrierPrivilegesForSubId(true, subId1);
+ assertThat(mSubscriptionManagerServiceUT.getSubscriptionsInGroup(
+ ParcelUuid.fromString(FAKE_UUID1), CALLING_PACKAGE, CALLING_FEATURE)
+ .stream().map(SubscriptionInfo::getSubscriptionId).toList())
+ .isEqualTo(List.of(subId1));
+ // Test isActiveSubId
+ assertThat(mSubscriptionManagerServiceUT.isActiveSubId(subId1, CALLING_PACKAGE,
+ CALLING_FEATURE)).isTrue();
+ assertThat(mSubscriptionManagerServiceUT.isActiveSubId(subId2, CALLING_PACKAGE,
+ CALLING_FEATURE)).isTrue();
+ // Test isSubscriptionEnabled
+ assertThat(mSubscriptionManagerServiceUT.isSubscriptionEnabled(subId1)).isTrue();
+ assertThat(mSubscriptionManagerServiceUT.isSubscriptionEnabled(subId2)).isTrue();
+ }
+
+ @Test
public void testSetUsageSetting() {
insertSubscription(FAKE_SUBSCRIPTION_INFO1);