Merge "(APDS) Notify modem to exit EMC mode when call is cancelled" into main
diff --git a/flags/data.aconfig b/flags/data.aconfig
index 321ac6b..ccd5db4 100644
--- a/flags/data.aconfig
+++ b/flags/data.aconfig
@@ -102,15 +102,12 @@
bug:"318519337"
}
-# OWNER=jackyu TARGET=25Q1
+# OWNER=jackyu TARGET=24Q4
flag {
name: "dds_callback"
namespace: "telephony"
description: "Adding new callback when DDS changed"
bug:"353723350"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
}
# OWNER=jackyu TARGET=25Q1
diff --git a/flags/ims.aconfig b/flags/ims.aconfig
index 4426933..4ce7508 100644
--- a/flags/ims.aconfig
+++ b/flags/ims.aconfig
@@ -138,6 +138,17 @@
}
}
+# 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"
@@ -145,3 +156,11 @@
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/uicc.aconfig b/flags/uicc.aconfig
index ad0c59f..abe4296 100644
--- a/flags/uicc.aconfig
+++ b/flags/uicc.aconfig
@@ -79,4 +79,12 @@
metadata {
purpose: PURPOSE_BUGFIX
}
-}
\ No newline at end of file
+}
+
+# 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/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/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 88ead6f..34ac832 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -178,6 +178,9 @@
/** @hide */
public static final HalVersion RADIO_HAL_VERSION_2_2 = new HalVersion(2, 2);
+ /** @hide */
+ public static final HalVersion RADIO_HAL_VERSION_2_3 = new HalVersion(2, 3);
+
// Hal version
private final Map<Integer, HalVersion> mHalVersion = new HashMap<>();
@@ -6212,6 +6215,7 @@
case 1: return RADIO_HAL_VERSION_2_0;
case 2: return RADIO_HAL_VERSION_2_1;
case 3: return RADIO_HAL_VERSION_2_2;
+ case 4: return RADIO_HAL_VERSION_2_3;
default: return RADIO_HAL_VERSION_UNKNOWN;
}
}
diff --git a/src/java/com/android/internal/telephony/SmsDispatchersController.java b/src/java/com/android/internal/telephony/SmsDispatchersController.java
index 023680a..5bcb085 100644
--- a/src/java/com/android/internal/telephony/SmsDispatchersController.java
+++ b/src/java/com/android/internal/telephony/SmsDispatchersController.java
@@ -29,7 +29,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.Resources;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Binder;
@@ -46,13 +45,14 @@
import android.telephony.ServiceState;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
-import android.telephony.TelephonyManager;
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;
@@ -67,18 +67,17 @@
import com.android.internal.telephony.gsm.GsmSMSDispatcher;
import com.android.internal.telephony.satellite.DatagramDispatcher;
import com.android.internal.telephony.satellite.SatelliteController;
-import com.android.internal.R;
import com.android.telephony.Rlog;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.concurrent.atomic.AtomicLong;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicLong;
/**
*
@@ -1258,7 +1257,7 @@
}
private void notifySmsSentToDatagramDispatcher(long messageId, boolean success) {
- if (SatelliteController.getInstance().isInCarrierRoamingNbIotNtn(mPhone)) {
+ if (SatelliteController.getInstance().shouldSendSmsToDatagramDispatcher(mPhone)) {
DatagramDispatcher.getInstance().onSendSmsDone(mPhone.getSubId(), messageId, success);
}
}
@@ -1866,7 +1865,7 @@
messageUri, persistMessage, priority, expectMore, validityPeriod, messageId,
skipShortCodeCheck, false);
- if (SatelliteController.getInstance().isInCarrierRoamingNbIotNtn(mPhone)) {
+ if (SatelliteController.getInstance().shouldSendSmsToDatagramDispatcher(mPhone)) {
// Send P2P SMS using carrier roaming NB IOT NTN
DatagramDispatcher.getInstance().sendSms(pendingRequest);
return;
@@ -2031,7 +2030,7 @@
null, 0, parts, messageUri, persistMessage, priority, expectMore,
validityPeriod, messageId, false, false);
- if (SatelliteController.getInstance().isInCarrierRoamingNbIotNtn(mPhone)) {
+ if (SatelliteController.getInstance().shouldSendSmsToDatagramDispatcher(mPhone)) {
// Send multipart P2P SMS using carrier roaming NB IOT NTN
DatagramDispatcher.getInstance().sendSms(pendingRequest);
return;
@@ -2241,7 +2240,7 @@
* to trigger SMSC to send all pending SMS to the particular subscription.
*/
public void sendMtSmsPollingMessage() {
- if (!SatelliteController.getInstance().isInCarrierRoamingNbIotNtn(mPhone)) {
+ if (!SatelliteController.getInstance().shouldSendSmsToDatagramDispatcher(mPhone)) {
logd("sendMtSmsPollingMessage: not in roaming nb iot ntn");
return;
}
@@ -2268,7 +2267,9 @@
asArrayList(null), false, null, 0, asArrayList(mtSmsPollingText), null, false, 0,
false, 5, 0L, true, true);
- DatagramDispatcher.getInstance().sendSms(pendingRequest);
+ if (SatelliteController.getInstance().shouldSendSmsToDatagramDispatcher(mPhone)) {
+ DatagramDispatcher.getInstance().sendSms(pendingRequest);
+ }
}
public interface SmsInjectionCallback {
diff --git a/src/java/com/android/internal/telephony/ims/ImsResolver.java b/src/java/com/android/internal/telephony/ims/ImsResolver.java
index eb389b7..d8b0fd4 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;
@@ -175,7 +181,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 +191,8 @@
// Map slotId->Feature
private final HashSet<ImsFeatureConfiguration.FeatureSlotPair> mSupportedFeatures;
- public ImsServiceInfo() {
+ public ImsServiceInfo(ComponentName componentName) {
+ name = componentName;
mSupportedFeatures = new HashSet<>();
}
@@ -208,37 +216,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 +323,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 +383,13 @@
}
};
+ private ActivityManagerProxy mActivityManagerProxy = new ActivityManagerProxy() {
+ @Override
+ public UserHandle getCurrentUser() {
+ return UserHandle.of(ActivityManager.getCurrentUser());
+ }
+ };
+
/**
* Testing interface for injecting mock ImsServiceControllers.
*/
@@ -470,6 +500,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;
@@ -534,6 +569,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 +601,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();
+ }
}
};
@@ -628,6 +673,11 @@
}
@VisibleForTesting
+ public void setActivityManagerProxy(ActivityManagerProxy proxy) {
+ mActivityManagerProxy = proxy;
+ }
+
+ @VisibleForTesting
public Handler getHandler() {
return mHandler;
}
@@ -660,6 +710,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 +760,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 +785,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();
+ }
}
/**
@@ -927,13 +993,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 +1140,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 +1156,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 +1202,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 +1213,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 +1239,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 +1254,69 @@
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) {
+ // 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 +1326,15 @@
private List<Integer> getSlotsForActiveCarrierService(ImsServiceInfo info) {
if (info == null) return Collections.emptyList();
+ if (mFeatureFlags.imsResolverUserAware()) {
+ Set<UserHandle> activeUsers = getActiveUsers();
+ activeUsers.retainAll(info.users);
+ if (activeUsers.isEmpty()) {
+ Log.d(TAG, "getSlotsForActiveCarrierService: ImsService " + info.name + "is not "
+ + "configured to run for users " + activeUsers + ", 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 +1364,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 +1372,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 +1396,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 +1439,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 +1452,7 @@
// by the carrier ImsService.
.filter(feature -> !doesCarrierConfigurationExist(feature.slotId,
feature.featureType))
- .collect(Collectors.toList()));
+ .toList());
}
return imsFeaturesBySlot;
}
@@ -1309,8 +1463,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 +1496,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();
+ }
}
/**
@@ -1400,7 +1561,7 @@
mEventLog.log("overrideDeviceService - device package changed (override): "
+ oldPackageName + " -> " + overridePackageName);
setDeviceConfiguration(overridePackageName, featureType);
- ImsServiceInfo info = getImsServiceInfoFromCache(overridePackageName);
+ ImsServiceInfo info = getVisibleImsServiceInfoFromCache(overridePackageName);
if (info == null || info.featureFromMetadata) {
requiresRecalc = true;
} else {
@@ -1430,7 +1591,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 +1626,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 +1634,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 +1691,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 +1775,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 +1789,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 +1804,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 +1850,85 @@
// 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;
+ // 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 +1946,25 @@
}
/**
- * 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;
+ Set<UserHandle> activeUsers = getActiveUsers();
+ activeUsers.retainAll(match.users);
+ Log.d(TAG, "getVisibleImsServiceInfoFromCache: " + packageName + ", match=" + match
+ + ", activeUsers=" + activeUsers);
+ if (!activeUsers.isEmpty()) 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 +1990,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 +2003,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/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index ea045dd..5484de6 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -34,6 +34,7 @@
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_SOS_MAX_DATAGRAM_SIZE;
+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;
@@ -62,6 +63,7 @@
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;
@@ -77,6 +79,7 @@
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;
@@ -119,6 +122,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;
@@ -140,6 +144,7 @@
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;
@@ -161,6 +166,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;
@@ -221,6 +227,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;
@@ -274,6 +288,7 @@
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;
@NonNull private static SatelliteController sInstance;
@NonNull private final Context mContext;
@@ -414,11 +429,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")
@@ -557,6 +572,7 @@
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 =
@@ -1280,8 +1296,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(
@@ -1897,6 +1913,14 @@
}
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;
+ }
+
default:
Log.w(TAG, "SatelliteControllerHandler: unexpected message code: " +
msg.what);
@@ -2012,6 +2036,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) {
@@ -2074,7 +2113,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();
+ }
}
/**
@@ -2200,10 +2319,14 @@
return false;
}
- if (mSatelliteSessionController != null) {
- return mSatelliteSessionController.isInEnablingState();
+ if (mSatelliteSessionController != null
+ && mSatelliteSessionController.isInEnablingState()) {
+ return true;
}
- return false;
+
+ synchronized (mSatelliteEnabledRequestLock) {
+ return (mSatelliteEnabledRequest != null);
+ }
}
/**
@@ -2223,10 +2346,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);
+ }
}
/**
@@ -2323,6 +2450,7 @@
synchronized (mSatelliteCapabilitiesLock) {
if (mSatelliteCapabilities != null) {
Bundle bundle = new Bundle();
+ overrideSatelliteCapabilitiesIfApplicable();
bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES,
mSatelliteCapabilities);
result.send(SATELLITE_RESULT_SUCCESS, bundle);
@@ -2393,36 +2521,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 = getSelectedSatelliteSubId();
- 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;
}
/**
@@ -2438,21 +2590,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, getSelectedSatelliteSubId()),
null);
+ }
}
/**
@@ -2471,13 +2640,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);
}
@@ -2516,11 +2685,11 @@
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;
}
@@ -2992,8 +3161,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);
@@ -3216,7 +3385,7 @@
ploge("setOemEnabledSatelliteProvisionStatus: mock modem not allowed");
return false;
}
- synchronized (mSatelliteViaOemProvisionLock) {
+ synchronized (mDeviceProvisionLock) {
if (reset) {
mOverriddenIsSatelliteViaOemProvisioned = null;
} else {
@@ -3568,6 +3737,11 @@
}
int subId = phone.getSubId();
+ int carrierRoamingNtnConnectType = getCarrierRoamingNtnConnectType(subId);
+ if (carrierRoamingNtnConnectType == CARRIER_ROAMING_NTN_CONNECT_MANUAL) {
+ return isInCarrierRoamingNbIotNtn(phone);
+ }
+
if (!isSatelliteSupportedViaCarrier(subId)) {
return false;
}
@@ -3657,7 +3831,7 @@
* @return {@code true} if phone is in carrier roaming nb iot ntn mode,
* else {@return false}
*/
- public boolean isInCarrierRoamingNbIotNtn(@NonNull Phone phone) {
+ private boolean isInCarrierRoamingNbIotNtn(@NonNull Phone phone) {
if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
plogd("isInCarrierRoamingNbIotNtn: carrier roaming nb iot ntn "
+ "feature flag is disabled");
@@ -3675,6 +3849,14 @@
+ " is not carrier roaming ntn eligible.");
return false;
}
+
+ int subId = phone.getSubId();
+ 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;
@@ -3919,8 +4101,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);
@@ -3947,8 +4129,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);
@@ -3998,21 +4180,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;
}
}
@@ -4155,6 +4337,9 @@
if (!enabled) {
mIsModemEnabledReportingNtnSignalStrength.set(false);
}
+ if (mFeatureFlags.satelliteStateChangeListener()) {
+ notifyEnabledStateChanged(enabled);
+ }
}
private void registerForPendingDatagramCount() {
@@ -4240,11 +4425,14 @@
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 {
@@ -4266,14 +4454,14 @@
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);
@@ -4293,7 +4481,8 @@
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);
@@ -4303,6 +4492,17 @@
handleStateChangedForCarrierRoamingNtnEligibility();
}
+ private void updateDeviceProvisionStatus() {
+ boolean isProvisioned = getPersistedDeviceProvisionStatus();
+ plogd("updateDeviceProvisionStatus: isProvisioned=" + isProvisioned);
+ synchronized (mDeviceProvisionLock) {
+ if (mIsDeviceProvisioned == null || mIsDeviceProvisioned != isProvisioned) {
+ mIsDeviceProvisioned = isProvisioned;
+ notifyDeviceProvisionStateChanged(isProvisioned);
+ }
+ }
+ }
+
private void notifySatelliteSubscriptionProvisionStateChanged(
@NonNull List<SatelliteSubscriberProvisionStatus> list) {
List<ISatelliteProvisionStateCallback> deadCallersList = new ArrayList<>();
@@ -4398,13 +4598,11 @@
synchronized (mSatelliteCapabilitiesLock) {
mSatelliteCapabilities = capabilities;
+ overrideSatelliteCapabilitiesIfApplicable();
}
List<ISatelliteCapabilitiesCallback> deadCallersList = new ArrayList<>();
mSatelliteCapabilitiesChangedListeners.values().forEach(listener -> {
- synchronized (this.mSatelliteCapabilitiesLock) {
- overrideSatelliteCapabilitiesIfApplicable();
- }
try {
listener.onSatelliteCapabilitiesChanged(this.mSatelliteCapabilities);
} catch (RemoteException e) {
@@ -4629,6 +4827,9 @@
sendRequestAsync(CMD_UPDATE_SATELLITE_ENABLE_ATTRIBUTES,
mSatelliteEnableAttributesUpdateRequest, null);
}
+ synchronized (mSatellitePhoneLock) {
+ updateLastNotifiedNtnModeAndNotify(mSatellitePhone);
+ }
}
}
}
@@ -4676,6 +4877,9 @@
false, "moveSatelliteToOffStateAndCleanUpResources");
}
selectBindingSatelliteSubscription();
+ synchronized (mSatellitePhoneLock) {
+ updateLastNotifiedNtnModeAndNotify(mSatellitePhone);
+ }
}
private void setDemoModeEnabled(boolean enabled) {
@@ -4872,7 +5076,9 @@
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_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);
@@ -5014,6 +5220,8 @@
}
}
}
+ // Need to update the provision status of the device
+ updateDeviceProvisionStatus();
}
@NonNull
@@ -5327,7 +5535,7 @@
}
if (isProvisionRequired) {
- Boolean satelliteProvisioned = isSatelliteViaOemProvisioned();
+ Boolean satelliteProvisioned = isDeviceProvisioned();
if (satelliteProvisioned == null) {
plogd("evaluateOemSatelliteRequestAllowed: satelliteProvisioned is null");
return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
@@ -5356,6 +5564,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);
@@ -5599,10 +5818,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,
@@ -5629,24 +5848,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 {
@@ -5678,7 +5907,7 @@
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);
}
@@ -6423,6 +6652,9 @@
if (!isNtnOnly && !isESOSSupported) {
continue;
}
+ if (!isActive && !isNtnOnly) {
+ continue;
+ }
int keyPriority = (isESOSSupported && isActive && isDefaultSmsSubId) ? 0
: (isESOSSupported && isActive) ? 1
@@ -6448,6 +6680,9 @@
logd("Old phone number is removed: id = " + subId);
isChanged = true;
}
+ if (!newSubscriberId.isEmpty()) {
+ mSubscriberIdPerSub.put(newSubscriberId, subId);
+ }
}
}
plogd("evaluateESOSProfilesPrioritization: newSubsInfoListPerPriority.size()="
@@ -6472,16 +6707,19 @@
// 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);
@@ -6654,7 +6892,7 @@
synchronized (mSatelliteTokenProvisionedLock) {
if (selectedSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
&& isSatelliteSupportedViaOem()) {
- selectedSubId = SatelliteServiceUtils.getNtnOnlySubscriptionId(mContext);
+ selectedSubId = getNtnOnlySubscriptionId();
}
mSelectedSatelliteSubId = selectedSubId;
setSatellitePhone(selectedSubId);
@@ -6671,7 +6909,12 @@
}
private boolean isActiveSubId(int subId) {
- return mSubscriptionManagerService.getSubscriptionInfo(subId).isActive();
+ 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)
@@ -6751,7 +6994,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);
@@ -6819,8 +7063,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;
@@ -6855,7 +7100,15 @@
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) {
@@ -7150,6 +7403,67 @@
}
}
+ 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()) {
@@ -7171,18 +7485,30 @@
return;
}
plogd("updateLastNotifiedNtnAvailableServicesAndNotify: phoneId= " + phone.getPhoneId());
+ int[] services = getSupportedServicesOnCarrierRoamingNtn(subId);
+ phone.notifyCarrierRoamingNtnAvailableServicesChanged(services);
+ }
- if (isSatelliteSupportedViaCarrier(subId)) {
- // TODO: Invoke SatelliteManager#getSatelliteDisallowedReasons() NOT EMPTY.
+ /** Return services that are supported on carrier roaming non-terrestrial network. */
+ public int[] getSupportedServicesOnCarrierRoamingNtn(int subId) {
+ SatelliteManager satelliteManager = mContext.getSystemService(SatelliteManager.class);
+ if (satelliteManager == null) {
+ plogd("updateLastNotifiedNtnAvailableServicesAndNotify: satelliteManager is null");
+ return new int[0];
+ }
+
+ List<Integer> satelliteDisallowedReasons = satelliteManager.getSatelliteDisallowedReasons();
+ if (isSatelliteSupportedViaCarrier(subId)
+ && (satelliteDisallowedReasons != null && !satelliteDisallowedReasons.isEmpty())) {
+ // 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();
}
- phone.notifyCarrierRoamingNtnAvailableServicesChanged(services);
- } else {
- phone.notifyCarrierRoamingNtnAvailableServicesChanged(new int[0]);
+ return services;
}
+ return new int[0];
}
/**
@@ -7263,4 +7589,30 @@
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);
+ }
+
+ /** Returns whether to send SMS to DatagramDispatcher or not. */
+ public boolean shouldSendSmsToDatagramDispatcher(@NonNull 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/SatelliteSOSMessageRecommender.java b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
index 50732fa..182f667 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
@@ -321,7 +321,7 @@
boolean isCellularAvailable = SatelliteServiceUtils.isCellularAvailable();
if (!isCellularAvailable
&& isSatelliteAllowed()
- && (isSatelliteViaOemAvailable()
+ && (isDeviceProvisioned()
|| isSatelliteConnectedViaCarrierWithinHysteresisTime())
&& shouldTrackCall(mEmergencyConnection.getState())) {
plogd("handleTimeoutEvent: Sent EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer");
@@ -359,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;
}
@@ -737,7 +737,7 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
public int getEmergencyCallToSatelliteHandoverType() {
- if (Flags.carrierRoamingNbIotNtn() && isSatelliteViaOemAvailable()
+ if (Flags.carrierRoamingNbIotNtn() && isDeviceProvisioned()
&& isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
int satelliteSubId = mSatelliteController.getSelectedSatelliteSubId();
return mSatelliteController.getCarrierRoamingNtnEmergencyCallToSatelliteHandoverType(
@@ -799,7 +799,7 @@
}
private boolean isSatelliteViaOemProvisioned() {
- Boolean provisioned = mSatelliteController.isSatelliteViaOemProvisioned();
+ Boolean provisioned = mSatelliteController.isDeviceProvisioned();
return (provisioned != null) && provisioned;
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
index 3d92e2a..8f299f8 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
@@ -57,6 +57,7 @@
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;
@@ -76,6 +77,7 @@
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;
@@ -188,6 +190,8 @@
@Nullable private DeviceStateMonitor mDeviceStateMonitor;
@NonNull private SessionMetricsStats mSessionMetricsStats;
@NonNull private FeatureFlags mFeatureFlags;
+ @SatelliteManager.SatelliteModemState private int mModemStateFromController =
+ SATELLITE_MODEM_STATE_UNKNOWN;
@NonNull private AlarmManager mAlarmManager;
private final AlarmManager.OnAlarmListener mAlarmListener = new AlarmManager.OnAlarmListener() {
@Override
@@ -309,20 +313,6 @@
mSessionMetricsStats = SessionMetricsStats.getInstance();
mAlarmManager = mContext.getSystemService(AlarmManager.class);
- if (mFeatureFlags.carrierRoamingNbIotNtn()) {
- // Register to received Cellular service state
- for (Phone phone : PhoneFactory.getPhones()) {
- if (phone == null) continue;
-
- phone.registerForServiceStateChanged(
- getHandler(), EVENT_SERVICE_STATE_CHANGED, null);
- if (DBG) {
- plogd("SatelliteSessionController: registerForServiceStateChanged phoneId "
- + phone.getPhoneId());
- }
- }
- }
-
addState(mUnavailableState);
addState(mPowerOffState);
addState(mEnablingState);
@@ -396,6 +386,10 @@
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public void onSatelliteModemStateChanged(@SatelliteManager.SatelliteModemState int state) {
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("onSatelliteModemStateChanged from SatelliteController : " + state);
+ mModemStateFromController = state;
+ }
sendMessage(EVENT_SATELLITE_MODEM_STATE_CHANGED, state);
}
@@ -924,12 +918,7 @@
handleSatelliteModemStateChanged(msg);
break;
case EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE:
- if (!mIgnoreCellularServiceState) {
- handleEventEnableCellularModemWhileSatelliteModeIsOnDone();
- } else {
- plogd("IdleState: processing: ignore "
- + "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) {
@@ -971,22 +960,6 @@
}
}
- private void handleEventEnableCellularModemWhileSatelliteModeIsOnDone() {
- if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
- Rlog.d(TAG, "handleEventEnableCellularModemWhileSatelliteModeIsOnDone: "
- + "carrierRoamingNbIotNtn is disabled");
- return;
- }
-
- ServiceState serviceState = mSatelliteController.getSatellitePhone().getServiceState();
- if (serviceState == null) {
- plogd("handleEventEnableCellularModemWhileSatelliteModeIsOnDone: "
- + "can't access ServiceState");
- return;
- }
- handleEventServiceStateChanged(serviceState);
- }
-
private void handleEventServiceStateChanged(ServiceState serviceState) {
boolean isInServiceOrEmergency =
serviceState.getVoiceRegState() == ServiceState.STATE_IN_SERVICE
@@ -1033,7 +1006,15 @@
int error = SatelliteServiceUtils.getSatelliteError(
result, "DisableCellularModemWhileSatelliteModeIsOnDone");
if (error == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
- transitionTo(mNotConnectedState);
+ if (mFeatureFlags.carrierRoamingNbIotNtn()
+ && mModemStateFromController == SATELLITE_MODEM_STATE_CONNECTED) {
+ ploge("mPreviousState : " + mPreviousState
+ + " mModemStateFromController : "
+ + mModemStateFromController + " I->C");
+ transitionTo(mConnectedState);
+ } else {
+ transitionTo(mNotConnectedState);
+ }
}
mIsDisableCellularModemInProgress = false;
} else {
@@ -1694,6 +1675,19 @@
}
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;
@@ -1805,19 +1799,19 @@
}
if (isP2pSmsInActivityTimerStarted()) {
- plogd("isEsosInActivityTimerStarted: "
+ plogd("isP2pSmsInActivityTimerStarted: "
+ "P2P_SMS inactivity timer already started");
return;
}
int subId = getSubId();
- if (!mSatelliteController.isSatelliteRoamingP2pSmSSupported(subId)) {
- plogd("evaluateStartingEsosInactivityTimer: P2P_SMS is not supported");
+ if (!isP2pSmsSupportedOnCarrierRoamingNtn(subId)) {
+ if (DBG) plogd("evaluateStartingP2pSmsInactivityTimer: P2P_SMS is not supported");
return;
}
if (mIsDeviceAlignedWithSatellite) {
- plogd("evaluateStartingEsosInactivityTimer: "
+ plogd("evaluateStartingP2pSmsInactivityTimer: "
+ "can't start P2P_SMS inactivity timer due to device aligned satellite");
return;
}
@@ -1827,10 +1821,10 @@
if (datagramController.isSendingInIdleState()
&& datagramController.isPollingInIdleState()) {
sendMessageDelayed(EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT, timeOutMillis);
- plogd("evaluateStartingEsosInactivityTimer: start P2P_SMS inactivity timer "
+ plogd("evaluateStartingP2pSmsInactivityTimer: start P2P_SMS inactivity timer "
+ timeOutMillis);
} else {
- plogd("evaluateStartingEsosInactivityTimer: "
+ plogd("evaluateStartingP2pSmsInactivityTimer: "
+ "can't start P2P_SMS inactivity timer");
}
}
@@ -1848,6 +1842,15 @@
}
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(
@@ -1943,6 +1946,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()) {
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/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/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java b/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java
index 4889187..25cdc82 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;
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/SmsDispatchersControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
index 53ecac3..b8316cb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
@@ -1086,7 +1086,8 @@
@Test
public void testSendSmsToDatagramDispatcher() {
- when(mSatelliteController.isInCarrierRoamingNbIotNtn(any(Phone.class))).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();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java
index c983d4c..1846bae 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java
@@ -23,7 +23,9 @@
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
@@ -252,6 +254,11 @@
*/
private static final int UDH_SEPTET_COST_CONCATENATED_MESSAGE = 6;
+ @Before
+ public void setUp() {
+ TelephonyManager.setupISmsForTest(Mockito.mock(ISms.class));
+ }
+
@Test
public void testCalcLengthAscii() throws Exception {
StringBuilder sb = new StringBuilder(320);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
index 1f5a26b..0b7ac22 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;
@@ -104,6 +105,7 @@
// Mocked classes
private SubscriptionInfo mMockSubInfo;
private TelephonyRegistry.ConfigurationProvider mMockConfigurationProvider;
+ private IBinder mMockIBinder;
private TelephonyCallbackWrapper mTelephonyCallback;
private List<LinkCapacityEstimate> mLinkCapacityEstimateList;
@@ -129,6 +131,7 @@
private boolean mCarrierRoamingNtnMode;
private boolean mCarrierRoamingNtnEligible;
private List<Integer> mCarrierRoamingNtnAvailableServices;
+ private boolean mIsSatelliteEnabled;
// All events contribute to TelephonyRegistry#isPhoneStatePermissionRequired
private static final Set<Integer> READ_PHONE_STATE_EVENTS;
@@ -342,6 +345,18 @@
}
}
+ public class MySatelliteStateChangeListener implements ISatelliteStateChangeListener {
+ @Override
+ public void onSatelliteEnabledStateChanged(boolean isEnabled) throws RemoteException {
+ mIsSatelliteEnabled = isEnabled;
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return mMockIBinder;
+ }
+ }
+
private void addTelephonyRegistryService() {
mServiceManagerMockedServices.put("telephony.registry", mTelephonyRegistry.asBinder());
mTelephonyRegistry.systemRunning();
@@ -354,6 +369,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);
@@ -381,6 +397,7 @@
processAllMessages();
assertEquals(mTelephonyRegistry.asBinder(),
ServiceManager.getService("telephony.registry"));
+ doReturn(new int[]{1}).when(mSubscriptionManager).getActiveSubscriptionIdList();
}
@After
@@ -1724,4 +1741,75 @@
.mapToInt(Integer::intValue).toArray();
assertTrue(Arrays.equals(carrierServices, services));
}
+
+ @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/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/satellite/SatelliteControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
index 6fab4f8..3d63d54 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -16,12 +16,12 @@
package com.android.internal.telephony.satellite;
-import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC;
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_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;
@@ -84,12 +84,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;
@@ -98,6 +99,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;
@@ -648,7 +650,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();
@@ -951,6 +953,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.
@@ -1007,6 +1010,7 @@
doReturn(false).when(mTelecomManager).isInEmergencyCall();
// Successfully enable satellite
+ reset(mTelephonyRegistryManager);
mIIntegerConsumerResults.clear();
mIIntegerConsumerSemaphore.drainPermits();
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
@@ -1028,12 +1032,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);
@@ -1052,7 +1058,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();
@@ -1088,6 +1095,7 @@
verify(mMockControllerMetricsStats, times(1)).reportServiceEnablementFailCount();
// Successfully enable satellite when radio is on.
+ reset(mTelephonyRegistryManager);
mIIntegerConsumerResults.clear();
mIIntegerConsumerSemaphore.drainPermits();
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
@@ -1106,6 +1114,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();
@@ -1126,6 +1135,7 @@
verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
// Successfully disable satellite.
+ reset(mTelephonyRegistryManager);
mIIntegerConsumerResults.clear();
mIIntegerConsumerSemaphore.drainPermits();
setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
@@ -1134,6 +1144,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();
@@ -1200,7 +1211,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));
@@ -1209,7 +1220,7 @@
mIIntegerConsumerResults.clear();
mIIntegerConsumerSemaphore.drainPermits();
resetSatelliteControllerUTToOffAndProvisionedState();
- when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(false);
+ mSatelliteControllerUT.isSatelliteBeingDisabled = false;
/**
* Make areAllRadiosDisabled return false and move mWaitingForRadioDisabled to true, which
@@ -1723,6 +1734,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();
@@ -1869,6 +1888,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();
@@ -1953,6 +1974,7 @@
@Test
public void testDeprovisionSatelliteService() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
mIIntegerConsumerSemaphore.drainPermits();
mIIntegerConsumerResults.clear();
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
@@ -2531,6 +2553,7 @@
assertTrue(
mQueriedSatelliteCapabilities.getSupportedRadioTechnologies().contains(
satelliteController.getSupportedNtnRadioTechnology()));
+ assertEquals(mQueriedSatelliteCapabilities.getMaxBytesPerOutgoingDatagram(), 255);
assertTrue(satelliteController.isSatelliteAttachRequired());
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
@@ -2557,14 +2580,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(
@@ -2574,7 +2597,6 @@
@Test
public void testRequestNtnSignalStrengthWithFeatureFlagEnabled() {
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
-
resetSatelliteControllerUT();
mRequestNtnSignalStrengthSemaphore.drainPermits();
@@ -4067,6 +4089,7 @@
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);
@@ -4125,6 +4148,7 @@
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(
@@ -4763,6 +4787,7 @@
.thenReturn(allSubInfos);
when(mSubscriptionInfo.isSatelliteESOSSupported()).thenReturn(true);
+ when(mSubscriptionInfo.isActive()).thenReturn(true);
when(mMockSubscriptionManagerService.getSubscriptionInfoInternal(SUB_ID))
.thenReturn(subInfoInternal);
@@ -5531,6 +5556,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);
@@ -5703,6 +5737,9 @@
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) {
@@ -5784,6 +5821,10 @@
}
@Override
+ public boolean isSatelliteBeingDisabled() {
+ return isSatelliteBeingDisabled;
+ }
+
protected String getConfigSatelliteGatewayServicePackage() {
String packageName = "com.example.app";
return packageName;
@@ -5794,9 +5835,20 @@
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;
}
}
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 f15ffbd..2609ffc 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
@@ -266,7 +266,7 @@
@Test
public void testTimeoutBeforeEmergencyCallEnd_EventDisplayEmergencyMessageNotSent() {
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
- mTestSatelliteController.setIsSatelliteViaOemProvisioned(false);
+ mTestSatelliteController.setDeviceProvisioned(false);
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
@@ -568,20 +568,20 @@
}
@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;
}
@@ -632,7 +632,7 @@
mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = true;
+ mTestSatelliteController.mIsDeviceProvisionedForTest = true;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
@@ -646,7 +646,7 @@
mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = false;
+ mTestSatelliteController.mIsDeviceProvisionedForTest = false;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
@@ -660,13 +660,13 @@
mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = true;
+ mTestSatelliteController.mIsDeviceProvisionedForTest = true;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = false;
+ mTestSatelliteController.mIsDeviceProvisionedForTest = false;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
@@ -771,7 +771,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;
@@ -792,8 +792,8 @@
}
@Override
- public Boolean isSatelliteViaOemProvisioned() {
- return mIsSatelliteViaOemProvisioned;
+ public Boolean isDeviceProvisioned() {
+ return mIsDeviceProvisionedForTest;
}
@Override
@@ -867,12 +867,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) {
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 eb9103a..d67880d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
@@ -60,7 +60,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
-import android.os.RemoteException;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.SatelliteManager;
@@ -222,6 +222,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);
@@ -268,6 +275,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.
@@ -330,6 +344,10 @@
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,
@@ -424,6 +442,10 @@
// 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();
@@ -507,6 +529,10 @@
// 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();
@@ -582,6 +608,10 @@
// 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();
@@ -649,6 +679,10 @@
// 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();
@@ -694,14 +728,6 @@
// Time shift to cause P2P_SMS timeout
moveTimeForward(P2P_SMS_INACTIVITY_TIMEOUT_SEC * 1000);
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, times(1)).requestSatelliteEnabled(
- eq(false), eq(false), eq(false), any(IIntegerConsumer.Stub.class));
}
@Test
@@ -721,6 +747,10 @@
// 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();
@@ -798,6 +828,10 @@
// 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();