[automerger skipped] Merge Android 24Q1 Release (ab/11220357) am: ba77c4fb28 -s ours
am skip reason: Merged-In I92da19bd0553b6c0510443a33ed1e53f814927ed with SHA-1 0d8580cb0d is already in history
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/opt/telephony/+/25973902
Change-Id: I69f2100a82803321a6da61368292123afbcdfe25
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index 121236a..c3b4373 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-
package {
// See: http://go/android-license-faq
default_applicable_licenses: [
@@ -108,6 +107,7 @@
"modules-utils-build_system",
"modules-utils-fastxmlserializer",
"modules-utils-statemachine",
+ "services-config-update",
],
optimize: {
diff --git a/flags/Android.bp b/flags/Android.bp
index 3c0deee..8f363b6 100644
--- a/flags/Android.bp
+++ b/flags/Android.bp
@@ -22,16 +22,17 @@
name: "telephony_flags",
package: "com.android.internal.telephony.flags",
srcs: [
- "data.aconfig",
- "domainselection.aconfig",
- "ims.aconfig",
- "messaging.aconfig",
- "misc.aconfig",
- "network.aconfig",
- "subscription.aconfig",
- "uicc.aconfig",
- "satellite.aconfig",
- "iwlan.aconfig",
- "telephony.aconfig",
+ "calling.aconfig",
+ "data.aconfig",
+ "domainselection.aconfig",
+ "ims.aconfig",
+ "messaging.aconfig",
+ "misc.aconfig",
+ "network.aconfig",
+ "subscription.aconfig",
+ "uicc.aconfig",
+ "satellite.aconfig",
+ "iwlan.aconfig",
+ "telephony.aconfig",
],
}
diff --git a/flags/calling.aconfig b/flags/calling.aconfig
new file mode 100644
index 0000000..82f932b
--- /dev/null
+++ b/flags/calling.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.internal.telephony.flags"
+
+flag {
+ name: "simultaneous_calling_indications"
+ namespace: "telephony"
+ description: "APIs that are used to notify simultaneous calling changes to other applications."
+ bug: "297446980"
+}
\ No newline at end of file
diff --git a/flags/data.aconfig b/flags/data.aconfig
index 267048e..cad7da7 100644
--- a/flags/data.aconfig
+++ b/flags/data.aconfig
@@ -90,3 +90,24 @@
description: "Collect vonr status in voice call metric"
bug:"288449751"
}
+
+flag {
+ name: "ignore_existing_networks_for_internet_allowed_checking"
+ namespace: "telephony"
+ description: "Ignore existing networks when checking if internet is allowed"
+ bug: "284420611"
+}
+
+flag {
+ name: "data_call_session_stats_captures_cross_sim_calling"
+ namespace: "telephony"
+ description: "The DataCallSessionStats metrics will capture whether the IWLAN PDN is set up on cross-SIM calling."
+ bug: "313956117"
+}
+
+flag {
+ name: "force_iwlan_mms"
+ namespace: "telephony"
+ description: "When QNS prefers MMS on IWLAN, MMS will be attempted on IWLAN if it can, even though if existing cellular network already supports MMS."
+ bug: "316211526"
+}
diff --git a/flags/ims.aconfig b/flags/ims.aconfig
index 4638194..d09259e 100644
--- a/flags/ims.aconfig
+++ b/flags/ims.aconfig
@@ -41,3 +41,24 @@
description: "This flag terminates active video call instead holding when accepting 2nd incoming video call as audio only"
bug:"309548300"
}
+
+flag {
+ name: "emergency_registration_state"
+ namespace: "telephony"
+ description: "This flag is created to notify emergency registration state changed."
+ bug:"312101946"
+}
+
+flag {
+ name: "call_extra_for_non_hold_supported_carriers"
+ namespace: "telephony"
+ description: "For DSDA devices, controls whether the existing call will be dropped when an incoming call on a different sub is answered, when either sub does not support hold capability."
+ bug:"315993953"
+}
+
+flag {
+ name: "update_roaming_state_to_set_wfc_mode"
+ namespace: "telephony"
+ description: "This flag updates roaming state to set wfc mode"
+ bug:"317298331"
+}
diff --git a/flags/misc.aconfig b/flags/misc.aconfig
index 835efee..dff6426 100644
--- a/flags/misc.aconfig
+++ b/flags/misc.aconfig
@@ -65,8 +65,8 @@
}
flag {
- name: "radio_info_is_radio_on"
- namespace: "telephony"
- description: "change method to show mobile radio power from service state to radio power"
- bug: "306084899"
+ name: "reset_mobile_network_settings"
+ namespace: "telephony"
+ description: "Allows applications to launch Reset Mobile Network Settings page in Settings app."
+ bug:"271921464"
}
diff --git a/flags/network.aconfig b/flags/network.aconfig
index 27489f4..e4ae5ee 100644
--- a/flags/network.aconfig
+++ b/flags/network.aconfig
@@ -17,6 +17,41 @@
flag {
name: "enable_identifier_disclosure_transparency"
namespace: "telephony"
+ description: "Guards APIs for enabling and disabling identifier disclosure transparency"
+ bug: "276752426"
+}
+
+flag {
+ name: "enable_identifier_disclosure_transparency_unsol_events"
+ namespace: "telephony"
description: "Allows the framework to register for CellularIdentifierDisclosure events and emit notifications to the user about them"
bug: "276752426"
}
+
+flag {
+ name: "enable_modem_cipher_transparency"
+ namespace: "telephony"
+ description: "Guards APIs for enabling and disabling modem cipher transparency."
+ bug: "283336425"
+}
+
+flag {
+ name: "enable_modem_cipher_transparency_unsol_events"
+ namespace: "telephony"
+ description: "Allows the framework to register for SecurityAlgorithmChanged events and emit notifications to the user when a device is using null ciphers."
+ bug: "283336425"
+}
+
+flag {
+ name: "hide_prefer_3g_item"
+ namespace: "telephony"
+ description: "Used in the Preferred Network Types menu to determine if the 3G option is displayed."
+ bug: "310639009"
+}
+
+flag {
+ name: "support_nr_sa_rrc_idle"
+ namespace: "telephony"
+ description: "Support RRC idle for NR SA."
+ bug: "301467052"
+}
diff --git a/flags/subscription.aconfig b/flags/subscription.aconfig
index 0521cb9..d2c36d6 100644
--- a/flags/subscription.aconfig
+++ b/flags/subscription.aconfig
@@ -5,4 +5,25 @@
namespace: "telephony"
description: "To support separation between personal and work from TelephonyManager and SubscriptionManager API perspective."
bug: "296076674"
+}
+
+flag {
+ name: "enforce_subscription_user_filter"
+ namespace: "telephony"
+ description: "Enabled flag means subscriptions enforce filtering result base on calling user handle. It marks the telephony completion of user filtering."
+ bug: "296076674"
+}
+
+flag {
+ name: "data_only_cellular_service"
+ namespace: "telephony"
+ description: "Supports customized cellular service capabilities per subscription."
+ bug: "296097429"
+}
+
+flag {
+ name: "data_only_service_allow_emergency_call_only"
+ namespace: "telephony"
+ description: "Support emergency call only for data only cellular service."
+ bug: "296097429"
}
\ No newline at end of file
diff --git a/flags/telephony.aconfig b/flags/telephony.aconfig
index b849d53..d59b249 100644
--- a/flags/telephony.aconfig
+++ b/flags/telephony.aconfig
@@ -13,3 +13,17 @@
description: "This flag controls telephony feature flags mapping for public APIs and CTS."
bug:"297989574"
}
+
+flag {
+ name: "prevent_system_server_and_phone_deadlock"
+ namespace: "telephony"
+ description: "This flag controls the order of the binder to prevent deadlock in system_server"
+ bug: "315973270"
+}
+
+flag {
+ name: "prevent_invocation_repeat_of_ril_call_when_device_does_not_support_voice"
+ namespace: "telephony"
+ description: "This flag prevents repeat invocation of call related APIs in RIL when the device is not voice capable"
+ bug: "290833783"
+}
\ No newline at end of file
diff --git a/flags/uicc.aconfig b/flags/uicc.aconfig
index b2024b0..5b74d1a 100644
--- a/flags/uicc.aconfig
+++ b/flags/uicc.aconfig
@@ -15,6 +15,13 @@
flag {
name: "carrier_restriction_status"
namespace: "telephony"
- description: "This flag control the visibility of the getCarrierRestrictionStatus in carrierRestrictionRules class."
+ description: "This flag controls the visibility of the getCarrierRestrictionStatus in carrierRestrictionRules class."
bug:"313553044"
+}
+
+flag {
+ name: "carrier_restriction_rules_enhancement"
+ namespace: "telephony"
+ description: "This flag controls the new enhancements to the existing carrier restrictions rules"
+ bug:"317226653"
}
\ No newline at end of file
diff --git a/proto/src/persist_atoms.proto b/proto/src/persist_atoms.proto
index d7a6062..02a4125 100644
--- a/proto/src/persist_atoms.proto
+++ b/proto/src/persist_atoms.proto
@@ -437,6 +437,7 @@
optional int64 registering_millis = 13;
optional int64 unregistered_millis = 14;
optional bool is_iwlan_cross_sim = 15;
+ optional int64 registered_times = 16;
// Internal use only
optional int64 last_used_millis = 10001;
diff --git a/src/java/com/android/internal/telephony/BaseCommands.java b/src/java/com/android/internal/telephony/BaseCommands.java
index b33b732..6f66545 100644
--- a/src/java/com/android/internal/telephony/BaseCommands.java
+++ b/src/java/com/android/internal/telephony/BaseCommands.java
@@ -120,6 +120,7 @@
protected RegistrantList mTriggerImsDeregistrationRegistrants = new RegistrantList();
protected RegistrantList mImeiInfoRegistrants = new RegistrantList();
protected RegistrantList mCellularIdentifierDisclosedRegistrants = new RegistrantList();
+ protected RegistrantList mSecurityAlgorithmUpdatedRegistrants = new RegistrantList();
@UnsupportedAppUsage
protected Registrant mGsmSmsRegistrant;
@@ -1194,4 +1195,14 @@
public void unregisterForCellularIdentifierDisclosures(Handler h) {
mCellularIdentifierDisclosedRegistrants.remove(h);
}
+
+ @Override
+ public void registerForSecurityAlgorithmUpdates(Handler h, int what, Object obj) {
+ mSecurityAlgorithmUpdatedRegistrants.add(h, what, obj);
+ }
+
+ @Override
+ public void unregisterForSecurityAlgorithmUpdates(Handler h) {
+ mSecurityAlgorithmUpdatedRegistrants.remove(h);
+ }
}
diff --git a/src/java/com/android/internal/telephony/CallTracker.java b/src/java/com/android/internal/telephony/CallTracker.java
index 38c6672..5e617f9 100644
--- a/src/java/com/android/internal/telephony/CallTracker.java
+++ b/src/java/com/android/internal/telephony/CallTracker.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony;
+import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.AsyncResult;
@@ -25,8 +26,11 @@
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import com.android.internal.telephony.flags.FeatureFlags;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -55,6 +59,9 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
protected boolean mNumberConverted = false;
+
+ protected final @NonNull FeatureFlags mFeatureFlags;
+
private final int VALID_COMPARE_LENGTH = 3;
//***** Events
@@ -77,7 +84,8 @@
protected static final int EVENT_THREE_WAY_DIAL_BLANK_FLASH = 20;
@UnsupportedAppUsage
- public CallTracker() {
+ public CallTracker(FeatureFlags featureFlags) {
+ mFeatureFlags = featureFlags;
}
protected void pollCallsWhenSafe() {
@@ -91,6 +99,14 @@
protected void
pollCallsAfterDelay() {
+ if (mFeatureFlags.preventInvocationRepeatOfRilCallWhenDeviceDoesNotSupportVoice()) {
+ if (!mCi.getHalVersion(TelephonyManager.HAL_SERVICE_VOICE)
+ .greaterOrEqual(RIL.RADIO_HAL_VERSION_1_4)) {
+ log("Skip polling because HAL_SERVICE_VOICE < RADIO_HAL_VERSION_1.4");
+ return;
+ }
+ }
+
Message msg = obtainMessage();
msg.what = EVENT_REPOLL_AFTER_DELAY;
diff --git a/src/java/com/android/internal/telephony/CellBroadcastConfigTracker.java b/src/java/com/android/internal/telephony/CellBroadcastConfigTracker.java
index 7e8663a..adb9904 100644
--- a/src/java/com/android/internal/telephony/CellBroadcastConfigTracker.java
+++ b/src/java/com/android/internal/telephony/CellBroadcastConfigTracker.java
@@ -54,6 +54,8 @@
private static final int EVENT_ACTIVATION_DONE = 3;
private static final int EVENT_RADIO_OFF = 4;
private static final int EVENT_SUBSCRIPTION_CHANGED = 5;
+ @VisibleForTesting
+ public static final int EVENT_RADIO_RESET = 6;
private static final int SMS_CB_CODE_SCHEME_MIN = 0;
private static final int SMS_CB_CODE_SCHEME_MAX = 255;
@@ -122,6 +124,7 @@
@Override
public void enter() {
mPhone.registerForRadioOffOrNotAvailable(getHandler(), EVENT_RADIO_OFF, null);
+ mPhone.mCi.registerForModemReset(getHandler(), EVENT_RADIO_RESET, null);
mPhone.getContext().getSystemService(SubscriptionManager.class)
.addOnSubscriptionsChangedListener(new HandlerExecutor(getHandler()),
mSubChangedListener);
@@ -130,6 +133,7 @@
@Override
public void exit() {
mPhone.unregisterForRadioOffOrNotAvailable(getHandler());
+ mPhone.mCi.unregisterForModemReset(getHandler());
mPhone.getContext().getSystemService(SubscriptionManager.class)
.removeOnSubscriptionsChangedListener(mSubChangedListener);
}
@@ -142,6 +146,7 @@
}
switch (msg.what) {
case EVENT_RADIO_OFF:
+ case EVENT_RADIO_RESET:
resetConfig();
break;
case EVENT_SUBSCRIPTION_CHANGED:
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index 91e6fab..ee7447c 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -2940,4 +2940,16 @@
* @param h Handler to be removed from the registrant list.
*/
default void unregisterForCellularIdentifierDisclosures(@NonNull Handler h) {}
+
+ /**
+ * Registers for security algorithm update events.
+ */
+ default void registerForSecurityAlgorithmUpdates(Handler h, int what, Object obj) {}
+
+ /**
+ * Unregisters for security algorithm update events.
+ *
+ * @param h Handler to be removed from the registrant list.
+ */
+ default void unregisterForSecurityAlgorithmUpdates(Handler h) {}
}
diff --git a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index c035329..e81d0f1 100644
--- a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -45,6 +45,7 @@
import com.android.telephony.Rlog;
import java.util.List;
+import java.util.Set;
/**
* broadcast intents
@@ -301,6 +302,11 @@
}
@Override
+ public void notifySimultaneousCellularCallingSubscriptionsChanged(Set<Integer> subIds) {
+ mTelephonyRegistryMgr.notifySimultaneousCellularCallingSubscriptionsChanged(subIds);
+ }
+
+ @Override
public void notifyCallbackModeStarted(Phone sender, @EmergencyCallbackModeType int type) {
mTelephonyRegistryMgr.notifyCallBackModeStarted(sender.getPhoneId(),
sender.getSubId(), type);
diff --git a/src/java/com/android/internal/telephony/DisplayInfoController.java b/src/java/com/android/internal/telephony/DisplayInfoController.java
index 945b640..e8a0566 100644
--- a/src/java/com/android/internal/telephony/DisplayInfoController.java
+++ b/src/java/com/android/internal/telephony/DisplayInfoController.java
@@ -108,7 +108,7 @@
TelephonyManager.NETWORK_TYPE_UNKNOWN,
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
false);
- mNetworkTypeController = new NetworkTypeController(phone, this);
+ mNetworkTypeController = new NetworkTypeController(phone, this, featureFlags);
// EVENT_UPDATE will transition from DefaultState to the current state
// and update the TelephonyDisplayInfo based on the current state.
mNetworkTypeController.sendMessage(NetworkTypeController.EVENT_UPDATE);
diff --git a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
index d76ee19..5517bc6 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
@@ -47,6 +47,7 @@
import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
import com.android.internal.telephony.domainselection.DomainSelectionResolver;
import com.android.internal.telephony.emergency.EmergencyStateTracker;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.telephony.Rlog;
@@ -155,7 +156,9 @@
//***** Constructors
- public GsmCdmaCallTracker (GsmCdmaPhone phone) {
+ public GsmCdmaCallTracker(GsmCdmaPhone phone, FeatureFlags featureFlags) {
+ super(featureFlags);
+
this.mPhone = phone;
mCi = phone.mCi;
mCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 620b871..18a5262 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -86,6 +86,7 @@
import android.telephony.NetworkScanRequest;
import android.telephony.PhoneNumberUtils;
import android.telephony.RadioAccessFamily;
+import android.telephony.SecurityAlgorithmUpdate;
import android.telephony.ServiceState;
import android.telephony.ServiceState.RilRadioTechnology;
import android.telephony.SubscriptionInfo;
@@ -118,6 +119,7 @@
import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.internal.telephony.metrics.VoiceCallSessionStats;
import com.android.internal.telephony.security.CellularIdentifierDisclosureNotifier;
+import com.android.internal.telephony.security.NullCipherNotifier;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import com.android.internal.telephony.subscription.SubscriptionManagerService.SubscriptionManagerServiceCallback;
import com.android.internal.telephony.test.SimulatedRadioControl;
@@ -255,6 +257,7 @@
private boolean mIsNullCipherAndIntegritySupported = false;
private boolean mIsIdentifierDisclosureTransparencySupported = false;
+ private boolean mIsNullCipherNotificationSupported = false;
// Create Cfu (Call forward unconditional) so that dialing number &
// mOnComplete (Message object passed by client) can be packed &
@@ -302,6 +305,7 @@
private final CallWaitingController mCallWaitingController;
private CellularIdentifierDisclosureNotifier mIdentifierDisclosureNotifier;
+ private NullCipherNotifier mNullCipherNotifier;
// Set via Carrier Config
private boolean mIsN1ModeAllowedByCarrier = true;
@@ -460,7 +464,7 @@
}
mCT = mTelephonyComponentFactory.inject(GsmCdmaCallTracker.class.getName())
- .makeGsmCdmaCallTracker(this);
+ .makeGsmCdmaCallTracker(this, mFeatureFlags);
mIccPhoneBookIntManager = mTelephonyComponentFactory
.inject(IccPhoneBookInterfaceManager.class.getName())
.makeIccPhoneBookInterfaceManager(this);
@@ -521,10 +525,10 @@
mCi.registerForImeiMappingChanged(this, EVENT_IMEI_MAPPING_CHANGED, null);
- if (mFeatureFlags.enableIdentifierDisclosureTransparency()) {
+ if (mFeatureFlags.enableIdentifierDisclosureTransparencyUnsolEvents()) {
logi(
- "enable_identifier_disclosure_transparency is on. Registering for cellular "
- + "identifier disclosures from phone "
+ "enable_identifier_disclosure_transparency_unsol_events is on. Registering for "
+ + "cellular identifier disclosures from phone "
+ getPhoneId());
mIdentifierDisclosureNotifier =
mTelephonyComponentFactory
@@ -534,6 +538,19 @@
this, EVENT_CELL_IDENTIFIER_DISCLOSURE, null);
}
+ if (mFeatureFlags.enableModemCipherTransparencyUnsolEvents()) {
+ logi(
+ "enable_modem_cipher_transparency_unsol_events is on. Registering for security "
+ + "algorithm updates from phone "
+ + getPhoneId());
+ mNullCipherNotifier =
+ mTelephonyComponentFactory
+ .inject(NullCipherNotifier.class.getName())
+ .makeNullCipherNotifier();
+ mCi.registerForSecurityAlgorithmUpdates(
+ this, EVENT_SECURITY_ALGORITHM_UPDATE, null);
+ }
+
initializeCarrierApps();
}
@@ -1825,8 +1842,11 @@
boolean check = true;
for (int itr = 0;itr < dtmfString.length(); itr++) {
if (!PhoneNumberUtils.is12Key(dtmfString.charAt(itr))) {
- Rlog.e(LOG_TAG,
- "sendDtmf called with invalid character '" + dtmfString.charAt(itr)+ "'");
+ Rlog.e(
+ LOG_TAG,
+ "sendDtmf called with invalid character '"
+ + dtmfString.charAt(itr)
+ + "'");
check = false;
break;
}
@@ -2441,6 +2461,8 @@
private void updateCarrierN1ModeSupported(@NonNull PersistableBundle b) {
if (!mFeatureFlags.enableCarrierConfigN1Control()) return;
+ if (!CarrierConfigManager.isConfigForIdentifiedCarrier(b)) return;
+
final int[] supportedNrModes = b.getIntArray(
CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY);
@@ -2580,7 +2602,7 @@
Bundle extras = new Bundle();
extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
- final TelecomManager telecomManager = TelecomManager.from(mContext);
+ final TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
telecomManager.placeCall(
Uri.fromParts(PhoneAccount.SCHEME_TEL, cfNumber, null), extras);
@@ -2833,13 +2855,15 @@
mCi.setCallWaiting(enable, serviceClass, onComplete);
} else if (mSsOverCdmaSupported) {
String cwPrefix = CdmaMmiCode.getCallWaitingPrefix(enable);
- Rlog.i(LOG_TAG, "setCallWaiting in CDMA : dial for set call waiting" + " prefix= " + cwPrefix);
+ Rlog.i(
+ LOG_TAG,
+ "setCallWaiting in CDMA : dial for set call waiting" + " prefix= " + cwPrefix);
PhoneAccountHandle phoneAccountHandle = subscriptionIdToPhoneAccountHandle(getSubId());
Bundle extras = new Bundle();
extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
- final TelecomManager telecomManager = TelecomManager.from(mContext);
+ final TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
telecomManager.placeCall(
Uri.fromParts(PhoneAccount.SCHEME_TEL, cwPrefix, null), extras);
@@ -3146,6 +3170,7 @@
handleNullCipherEnabledChange();
handleIdentifierDisclosureNotificationPreferenceChange();
+ handleNullCipherNotificationPreferenceChanged();
}
private void handleRadioOn() {
@@ -3689,10 +3714,10 @@
}
CellularIdentifierDisclosure disclosure = (CellularIdentifierDisclosure) ar.result;
- if (mFeatureFlags.enableIdentifierDisclosureTransparency()
+ if (mFeatureFlags.enableIdentifierDisclosureTransparencyUnsolEvents()
&& mIdentifierDisclosureNotifier != null
&& disclosure != null) {
- mIdentifierDisclosureNotifier.addDisclosure(disclosure);
+ mIdentifierDisclosureNotifier.addDisclosure(getSubId(), disclosure);
}
break;
@@ -3702,6 +3727,22 @@
mIsIdentifierDisclosureTransparencySupported = doesResultIndicateModemSupport(ar);
break;
+ case EVENT_SECURITY_ALGORITHM_UPDATE:
+ logd("EVENT_SECURITY_ALGORITHM_UPDATE phoneId = " + getPhoneId());
+ if (mFeatureFlags.enableModemCipherTransparencyUnsolEvents()
+ && mNullCipherNotifier != null) {
+ ar = (AsyncResult) msg.obj;
+ SecurityAlgorithmUpdate update = (SecurityAlgorithmUpdate) ar.result;
+ mNullCipherNotifier.onSecurityAlgorithmUpdate(getPhoneId(), update);
+ }
+ break;
+
+ case EVENT_SET_SECURITY_ALGORITHMS_UPDATED_ENABLED_DONE:
+ logd("EVENT_SET_SECURITY_ALGORITHMS_UPDATED_ENABLED_DONE");
+ ar = (AsyncResult) msg.obj;
+ mIsNullCipherNotificationSupported = doesResultIndicateModemSupport(ar);
+ break;
+
default:
super.handleMessage(msg);
}
@@ -4961,7 +5002,7 @@
}
private PhoneAccountHandle subscriptionIdToPhoneAccountHandle(final int subId) {
- final TelecomManager telecomManager = TelecomManager.from(mContext);
+ final TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
final TelephonyManager telephonyManager = TelephonyManager.from(mContext);
final Iterator<PhoneAccountHandle> phoneAccounts =
telecomManager.getCallCapablePhoneAccounts(true).listIterator();
@@ -5182,7 +5223,7 @@
}
private void updateVoNrSettings(@NonNull PersistableBundle config) {
- if (mSimState != TelephonyManager.SIM_STATE_LOADED) {
+ if (getIccCard().getState() != IccCardConstants.State.LOADED) {
return;
}
@@ -5310,15 +5351,23 @@
public void handleIdentifierDisclosureNotificationPreferenceChange() {
if (!mFeatureFlags.enableIdentifierDisclosureTransparency()) {
logi("Not handling identifier disclosure preference change. Feature flag "
- + "ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY disabled");
+ + "enable_identifier_disclosure_transparency disabled");
return;
}
boolean prefEnabled = getIdentifierDisclosureNotificationsPreferenceEnabled();
- if (prefEnabled) {
+ // The notifier is tied to handling unsolicited updates from the modem, not the
+ // enable/disable API, so we only toggle the enable state if the unsol events feature
+ // flag is enabled.
+ if (mFeatureFlags.enableIdentifierDisclosureTransparencyUnsolEvents()) {
+ if (prefEnabled) {
mIdentifierDisclosureNotifier.enable();
- } else {
+ } else {
mIdentifierDisclosureNotifier.disable();
+ }
+ } else {
+ logi("Not toggling enable state for disclosure notifier. Feature flag "
+ + "enable_identifier_disclosure_transparency_unsol_events is disabled");
}
mCi.setCellularIdentifierTransparencyEnabled(prefEnabled,
@@ -5326,6 +5375,33 @@
}
@Override
+ public void handleNullCipherNotificationPreferenceChanged() {
+ if (!mFeatureFlags.enableModemCipherTransparency()) {
+ logi("Not handling null cipher notification preference change. Feature flag "
+ + "enable_modem_cipher_transparency disabled");
+ return;
+ }
+ boolean prefEnabled = getNullCipherNotificationsPreferenceEnabled();
+
+ // The notifier is tied to handling unsolicited updates from the modem, not the
+ // enable/disable API.
+ if (mFeatureFlags.enableModemCipherTransparencyUnsolEvents()) {
+ if (prefEnabled) {
+ mNullCipherNotifier.enable();
+ } else {
+ mNullCipherNotifier.disable();
+ }
+ } else {
+ logi(
+ "Not toggling enable state for cipher notifier. Feature flag "
+ + "enable_modem_cipher_transparency_unsol_events is disabled.");
+ }
+
+ mCi.setSecurityAlgorithmsUpdatedEnabled(prefEnabled,
+ obtainMessage(EVENT_SET_SECURITY_ALGORITHMS_UPDATED_ENABLED_DONE));
+ }
+
+ @Override
public boolean isNullCipherAndIntegritySupported() {
return mIsNullCipherAndIntegritySupported;
}
@@ -5334,4 +5410,9 @@
public boolean isIdentifierDisclosureTransparencySupported() {
return mIsIdentifierDisclosureTransparencySupported;
}
+
+ @Override
+ public boolean isNullCipherNotificationSupported() {
+ return mIsNullCipherNotificationSupported;
+ }
}
diff --git a/src/java/com/android/internal/telephony/LocaleTracker.java b/src/java/com/android/internal/telephony/LocaleTracker.java
index 076b001..0afe119 100644
--- a/src/java/com/android/internal/telephony/LocaleTracker.java
+++ b/src/java/com/android/internal/telephony/LocaleTracker.java
@@ -41,6 +41,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.MccTable.MccMnc;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.telephony.Rlog;
@@ -154,6 +155,8 @@
@Nullable
private String mCurrentCountryIso;
+ @NonNull private final FeatureFlags mFeatureFlags;
+
/** The country override for testing purposes */
@Nullable
private String mCountryOverride;
@@ -244,12 +247,14 @@
* @param nitzStateMachine NITZ state machine
* @param looper The looper message handler
*/
- public LocaleTracker(Phone phone, NitzStateMachine nitzStateMachine, Looper looper) {
+ public LocaleTracker(Phone phone, NitzStateMachine nitzStateMachine, Looper looper,
+ FeatureFlags featureFlags) {
super(looper);
mPhone = phone;
mNitzStateMachine = nitzStateMachine;
mSimState = TelephonyManager.SIM_STATE_UNKNOWN;
mTag = LocaleTracker.class.getSimpleName() + "-" + mPhone.getPhoneId();
+ mFeatureFlags = featureFlags;
final IntentFilter filter = new IntentFilter();
filter.addAction(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED);
@@ -560,6 +565,10 @@
TelephonyProperties.operator_iso_country(newProp);
}
+ if (mFeatureFlags.oemEnabledSatelliteFlag()) {
+ TelephonyCountryDetector.getInstance(mPhone.getContext())
+ .onNetworkCountryCodeChanged(mPhone, countryIso);
+ }
Intent intent = new Intent(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED);
intent.putExtra(TelephonyManager.EXTRA_NETWORK_COUNTRY, countryIso);
intent.putExtra(TelephonyManager.EXTRA_LAST_KNOWN_NETWORK_COUNTRY,
diff --git a/src/java/com/android/internal/telephony/MultiSimSettingController.java b/src/java/com/android/internal/telephony/MultiSimSettingController.java
index d07e731..8488ab0 100644
--- a/src/java/com/android/internal/telephony/MultiSimSettingController.java
+++ b/src/java/com/android/internal/telephony/MultiSimSettingController.java
@@ -420,22 +420,13 @@
return;
}
- // b/153860050 Occasionally we receive carrier config change broadcast without subId
- // being specified in it. So here we do additional check to make sur we don't miss the
- // subId.
- if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- subId = SubscriptionManager.getSubscriptionId(phoneId);
- if (SubscriptionManager.isValidSubscriptionId(subId)) {
- CarrierConfigManager cm = mContext.getSystemService(CarrierConfigManager.class);
- if (cm != null && cm.getConfigForSubId(subId) != null) {
- loge("onCarrierConfigChanged with invalid subId while subId "
- + subId + " is active and its config is loaded");
- }
+ CarrierConfigManager cm = mContext.getSystemService(CarrierConfigManager.class);
+ if (cm != null) {
+ if (CarrierConfigManager.isConfigForIdentifiedCarrier(cm.getConfigForSubId(subId))) {
+ mCarrierConfigLoadedSubIds[phoneId] = subId;
+ reEvaluateAll();
}
}
-
- mCarrierConfigLoadedSubIds[phoneId] = subId;
- reEvaluateAll();
}
/**
diff --git a/src/java/com/android/internal/telephony/NetworkIndication.java b/src/java/com/android/internal/telephony/NetworkIndication.java
index d86c090..e847060 100644
--- a/src/java/com/android/internal/telephony/NetworkIndication.java
+++ b/src/java/com/android/internal/telephony/NetworkIndication.java
@@ -49,6 +49,7 @@
import android.telephony.LinkCapacityEstimate;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhysicalChannelConfig;
+import android.telephony.SecurityAlgorithmUpdate;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.text.TextUtils;
@@ -456,6 +457,12 @@
if (mRil.isLogOrTrace()) {
mRil.unsljLogRet(RIL_UNSOL_SECURITY_ALGORITHMS_UPDATED, securityAlgorithmUpdate);
}
+
+ SecurityAlgorithmUpdate update =
+ RILUtils.convertSecurityAlgorithmUpdate(securityAlgorithmUpdate);
+
+ mRil.mSecurityAlgorithmUpdatedRegistrants.notifyRegistrants(
+ new AsyncResult(null, update, null));
}
@Override
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index e6fb84e..ea7a6de 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -41,6 +41,7 @@
import com.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback;
import com.android.internal.telephony.data.DataUtils;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.util.IState;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.State;
@@ -74,6 +75,7 @@
private static final String ICON_5G = "5g";
private static final String ICON_5G_PLUS = "5g_plus";
private static final String STATE_CONNECTED_NR_ADVANCED = "connected_mmwave";
+ private static final String STATE_CONNECTED_RRC_IDLE = "connected_rrc_idle";
private static final String STATE_CONNECTED = "connected";
private static final String STATE_NOT_RESTRICTED_RRC_IDLE = "not_restricted_rrc_idle";
private static final String STATE_NOT_RESTRICTED_RRC_CON = "not_restricted_rrc_con";
@@ -81,8 +83,8 @@
private static final String STATE_ANY = "any";
private static final String STATE_LEGACY = "legacy";
private static final String[] ALL_STATES = {STATE_CONNECTED_NR_ADVANCED, STATE_CONNECTED,
- STATE_NOT_RESTRICTED_RRC_IDLE, STATE_NOT_RESTRICTED_RRC_CON, STATE_RESTRICTED,
- STATE_LEGACY };
+ STATE_CONNECTED_RRC_IDLE, STATE_NOT_RESTRICTED_RRC_IDLE, STATE_NOT_RESTRICTED_RRC_CON,
+ STATE_RESTRICTED, STATE_LEGACY };
/** Stop all timers and go to current state. */
public static final int EVENT_UPDATE = 0;
@@ -131,6 +133,7 @@
@NonNull private final Phone mPhone;
@NonNull private final DisplayInfoController mDisplayInfoController;
+ @NonNull private final FeatureFlags mFeatureFlags;
@NonNull private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -177,6 +180,7 @@
private boolean mIsUsingUserDataForRrcDetection = false;
private boolean mEnableNrAdvancedWhileRoaming = true;
private boolean mIsDeviceIdleMode = false;
+ private boolean mPrimaryCellChangedWhileIdle = false;
@Nullable private DataNetworkControllerCallback mNrAdvancedCapableByPcoChangedCallback = null;
@Nullable private DataNetworkControllerCallback mNrPhysicalLinkStatusChangedCallback = null;
@@ -189,16 +193,20 @@
@NonNull private Set<Integer> mRatchetedNrBands = new HashSet<>();
private int mRatchetedNrBandwidths = 0;
private int mLastAnchorNrCellId = PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN;
+ private boolean mDoesPccListIndicateIdle = false;
/**
* NetworkTypeController constructor.
*
* @param phone Phone object.
* @param displayInfoController DisplayInfoController to send override network types to.
+ * @param featureFlags FeatureFlags controlling what icon features are enabled.
*/
- public NetworkTypeController(Phone phone, DisplayInfoController displayInfoController) {
+ public NetworkTypeController(Phone phone, DisplayInfoController displayInfoController,
+ FeatureFlags featureFlags) {
super(TAG, displayInfoController);
mPhone = phone;
+ mFeatureFlags = featureFlags;
mDisplayInfoController = displayInfoController;
mOverrideNetworkType = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
mIsPhysicalChannelConfigOn = true;
@@ -210,6 +218,7 @@
addState(mLegacyState, defaultState);
addState(mIdleState, defaultState);
addState(mLteConnectedState, defaultState);
+ addState(mNrIdleState, defaultState);
addState(mNrConnectedState, defaultState);
addState(mNrConnectedAdvancedState, defaultState);
setInitialState(defaultState);
@@ -370,6 +379,9 @@
if (DBG) loge("Invalid 5G icon configuration, config = " + pair);
continue;
}
+ if (!mFeatureFlags.supportNrSaRrcIdle() && kv[0].equals(STATE_CONNECTED_RRC_IDLE)) {
+ continue;
+ }
int icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
if (kv[1].equals(ICON_5G)) {
icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA;
@@ -397,6 +409,9 @@
if (DBG) loge("Invalid 5G icon timer configuration, config = " + triple);
continue;
}
+ if (!mFeatureFlags.supportNrSaRrcIdle() && kv[0].equals(STATE_CONNECTED_RRC_IDLE)) {
+ continue;
+ }
int duration;
try {
duration = Integer.parseInt(kv[2]);
@@ -405,6 +420,10 @@
}
if (kv[0].equals(STATE_ANY)) {
for (String state : ALL_STATES) {
+ if (!mFeatureFlags.supportNrSaRrcIdle()
+ && state.equals(STATE_CONNECTED_RRC_IDLE)) {
+ continue;
+ }
OverrideTimerRule node = tempRules.get(state);
node.addTimer(kv[1], duration);
}
@@ -425,6 +444,9 @@
}
continue;
}
+ if (kv[0].equals(STATE_CONNECTED_RRC_IDLE) && !mFeatureFlags.supportNrSaRrcIdle()) {
+ continue;
+ }
int duration;
try {
duration = Integer.parseInt(kv[2]);
@@ -433,6 +455,10 @@
}
if (kv[0].equals(STATE_ANY)) {
for (String state : ALL_STATES) {
+ if (state.equals(STATE_CONNECTED_RRC_IDLE)
+ && !mFeatureFlags.supportNrSaRrcIdle()) {
+ continue;
+ }
OverrideTimerRule node = tempRules.get(state);
node.addSecondaryTimer(kv[1], duration);
}
@@ -443,6 +469,23 @@
}
}
+ // TODO: Remove this workaround to make STATE_CONNECTED_RRC_IDLE backwards compatible with
+ // STATE_CONNECTED once carrier configs are updated.
+ if (mFeatureFlags.supportNrSaRrcIdle()) {
+ OverrideTimerRule nrRules = tempRules.get(STATE_CONNECTED);
+ if (!tempRules.get(STATE_CONNECTED_RRC_IDLE).isDefined() && nrRules.isDefined()) {
+ OverrideTimerRule nrIdleRules =
+ new OverrideTimerRule(STATE_CONNECTED_RRC_IDLE, nrRules.mOverrideType);
+ for (Map.Entry<String, Integer> entry : nrIdleRules.mPrimaryTimers.entrySet()) {
+ nrIdleRules.addTimer(entry.getKey(), entry.getValue());
+ }
+ for (Map.Entry<String, Integer> entry : nrIdleRules.mSecondaryTimers.entrySet()) {
+ nrIdleRules.addSecondaryTimer(entry.getKey(), entry.getValue());
+ }
+ tempRules.put(STATE_CONNECTED_RRC_IDLE, nrIdleRules);
+ }
+ }
+
mOverrideTimerRules = tempRules;
if (DBG) log("mOverrideTimerRules: " + mOverrideTimerRules);
}
@@ -688,7 +731,9 @@
if (isNrAdvanced()) {
transitionTo(mNrConnectedAdvancedState);
} else {
- transitionTo(mNrConnectedState);
+ transitionTo(isPhysicalLinkActive()
+ || !mFeatureFlags.supportNrSaRrcIdle()
+ ? mNrConnectedState : mNrIdleState);
}
} else if (isLte(rat) && isNrNotRestricted()) {
transitionWithTimerTo(isPhysicalLinkActive()
@@ -768,7 +813,9 @@
if (isNrAdvanced()) {
transitionTo(mNrConnectedAdvancedState);
} else {
- transitionTo(mNrConnectedState);
+ transitionTo(isPhysicalLinkActive()
+ || !mFeatureFlags.supportNrSaRrcIdle()
+ ? mNrConnectedState : mNrIdleState);
}
} else if (!isLte(rat) || !isNrNotRestricted()) {
transitionWithTimerTo(mLegacyState);
@@ -850,7 +897,9 @@
if (isNrAdvanced()) {
transitionTo(mNrConnectedAdvancedState);
} else {
- transitionTo(mNrConnectedState);
+ transitionTo(isPhysicalLinkActive()
+ || !mFeatureFlags.supportNrSaRrcIdle()
+ ? mNrConnectedState : mNrIdleState);
}
} else if (!isLte(rat) || !isNrNotRestricted()) {
transitionWithTimerTo(mLegacyState);
@@ -903,6 +952,84 @@
private final LteConnectedState mLteConnectedState = new LteConnectedState();
/**
+ * Device is connected to 5G NR as the primary or secondary cell but not actively using data.
+ */
+ private final class NrIdleState extends State {
+ @Override
+ public void enter() {
+ if (DBG) log("Entering NrIdleState");
+ updateTimers();
+ updateOverrideNetworkType();
+ if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
+ mPreviousState = getName();
+ }
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (DBG) log("NrIdleState: process " + getEventName(msg.what));
+ updateTimers();
+ switch (msg.what) {
+ case EVENT_SERVICE_STATE_CHANGED:
+ mServiceState = mPhone.getServiceStateTracker().getServiceState();
+ if (DBG) log("ServiceState updated: " + mServiceState);
+ // fallthrough
+ case EVENT_UPDATE:
+ int rat = getDataNetworkType();
+ if (rat == TelephonyManager.NETWORK_TYPE_NR
+ || (isLte(rat) && isNrConnected())) {
+ if (isNrAdvanced()) {
+ transitionTo(mNrConnectedAdvancedState);
+ } else if (isPhysicalLinkActive()) {
+ transitionWithTimerTo(mNrConnectedState);
+ } else {
+ // Update in case the override network type changed
+ updateOverrideNetworkType();
+ }
+ } else if (isLte(rat) && isNrNotRestricted()) {
+ transitionWithTimerTo(isPhysicalLinkActive()
+ ? mLteConnectedState : mIdleState);
+ } else {
+ transitionWithTimerTo(mLegacyState);
+ }
+ break;
+ case EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED:
+ updatePhysicalChannelConfigs();
+ if (isUsingPhysicalChannelConfigForRrcDetection()) {
+ mPhysicalLinkStatus = getPhysicalLinkStatusFromPhysicalChannelConfig();
+ }
+ // Check NR advanced in case NR advanced bands were added
+ if (isNrAdvanced()) {
+ transitionTo(mNrConnectedAdvancedState);
+ } else if (isPhysicalLinkActive()) {
+ transitionWithTimerTo(mNrConnectedState);
+ }
+ break;
+ case EVENT_PHYSICAL_LINK_STATUS_CHANGED:
+ AsyncResult ar = (AsyncResult) msg.obj;
+ mPhysicalLinkStatus = (int) ar.result;
+ if (isPhysicalLinkActive()) {
+ transitionWithTimerTo(mNrConnectedState);
+ }
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
+ mPreviousState = getName();
+ }
+ return HANDLED;
+ }
+
+ @Override
+ public String getName() {
+ return mFeatureFlags.supportNrSaRrcIdle() ? STATE_CONNECTED_RRC_IDLE : STATE_CONNECTED;
+ }
+ }
+
+ private final NrIdleState mNrIdleState = new NrIdleState();
+
+ /**
* Device is connected to 5G NR as the primary or secondary cell.
*/
private final class NrConnectedState extends State {
@@ -931,6 +1058,8 @@
|| (isLte(rat) && isNrConnected())) {
if (isNrAdvanced()) {
transitionTo(mNrConnectedAdvancedState);
+ } else if (!isPhysicalLinkActive() && mFeatureFlags.supportNrSaRrcIdle()) {
+ transitionWithTimerTo(mNrIdleState);
} else {
// Update in case the override network type changed
updateOverrideNetworkType();
@@ -950,11 +1079,16 @@
// Check NR advanced in case NR advanced bands were added
if (isNrAdvanced()) {
transitionTo(mNrConnectedAdvancedState);
+ } else if (!isPhysicalLinkActive() && mFeatureFlags.supportNrSaRrcIdle()) {
+ transitionWithTimerTo(mNrIdleState);
}
break;
case EVENT_PHYSICAL_LINK_STATUS_CHANGED:
AsyncResult ar = (AsyncResult) msg.obj;
mPhysicalLinkStatus = (int) ar.result;
+ if (!isPhysicalLinkActive() && mFeatureFlags.supportNrSaRrcIdle()) {
+ transitionWithTimerTo(mNrIdleState);
+ }
break;
default:
return NOT_HANDLED;
@@ -1012,7 +1146,9 @@
mOverrideNetworkType =
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
}
- transitionWithTimerTo(mNrConnectedState);
+ transitionWithTimerTo(isPhysicalLinkActive()
+ || !mFeatureFlags.supportNrSaRrcIdle()
+ ? mNrConnectedState : mNrIdleState);
}
} else if (isLte(rat) && isNrNotRestricted()) {
transitionWithTimerTo(isPhysicalLinkActive()
@@ -1028,7 +1164,9 @@
}
// Check NR advanced in case NR advanced bands were removed
if (!isNrAdvanced()) {
- transitionWithTimerTo(mNrConnectedState);
+ transitionWithTimerTo(isPhysicalLinkActive()
+ || !mFeatureFlags.supportNrSaRrcIdle()
+ ? mNrConnectedState : mNrIdleState);
}
break;
case EVENT_PHYSICAL_LINK_STATUS_CHANGED:
@@ -1060,7 +1198,9 @@
if (isPccListEmpty && isUsingPhysicalChannelConfigForRrcDetection()) {
log("Physical channel configs updated: not updating PCC fields for empty PCC list "
+ "indicating RRC idle.");
+ mPrimaryCellChangedWhileIdle = false;
mPhysicalChannelConfigs = physicalChannelConfigs;
+ mDoesPccListIndicateIdle = true;
return;
}
@@ -1107,6 +1247,16 @@
mRatchetedNrBandwidths = Math.max(mRatchetedNrBandwidths, nrBandwidths);
mRatchetedNrBands.addAll(nrBands);
} else {
+ if (mFeatureFlags.supportNrSaRrcIdle() && mDoesPccListIndicateIdle
+ && isUsingPhysicalChannelConfigForRrcDetection()
+ && !mPrimaryCellChangedWhileIdle && isTimerActiveForNrSaRrcIdle()
+ && !isNrAdvancedForPccFields(nrBandwidths, nrBands)) {
+ log("Allow primary cell change during RRC idle timer without changing state: "
+ + mLastAnchorNrCellId + " -> " + anchorNrCellId);
+ mPrimaryCellChangedWhileIdle = true;
+ mLastAnchorNrCellId = anchorNrCellId;
+ return;
+ }
if (mRatchetPccFieldsForSameAnchorNrCell) {
log("Not ratcheting physical channel config fields since anchor NR cell changed: "
+ mLastAnchorNrCellId + " -> " + anchorNrCellId);
@@ -1117,6 +1267,7 @@
mLastAnchorNrCellId = anchorNrCellId;
mPhysicalChannelConfigs = physicalChannelConfigs;
+ mDoesPccListIndicateIdle = false;
if (DBG) {
log("Physical channel configs updated: anchorNrCell=" + mLastAnchorNrCellId
+ ", nrBandwidths=" + mRatchetedNrBandwidths + ", nrBands=" + mRatchetedNrBands
@@ -1165,7 +1316,11 @@
if (isNrAdvanced()) {
transitionState = mNrConnectedAdvancedState;
} else {
- transitionState = mNrConnectedState;
+ if (isPhysicalLinkActive() || !mFeatureFlags.supportNrSaRrcIdle()) {
+ transitionState = mNrConnectedState;
+ } else {
+ transitionState = mNrIdleState;
+ }
}
} else if (isLte(dataRat) && isNrNotRestricted()) {
if (isPhysicalLinkActive()) {
@@ -1248,6 +1403,16 @@
mSecondaryTimerState = "";
}
+ private boolean isTimerActiveForNrSaRrcIdle() {
+ if (mIsPrimaryTimerActive) {
+ return mPrimaryTimerState.equals(STATE_CONNECTED_RRC_IDLE);
+ } else if (mIsSecondaryTimerActive) {
+ return mSecondaryTimerState.equals(STATE_CONNECTED_RRC_IDLE);
+ } else {
+ return false;
+ }
+ }
+
/**
* Private class defining timer rules between states to prevent flickering. These rules are
* created in {@link #parseCarrierConfigs()} based on various carrier configs.
@@ -1320,6 +1485,16 @@
return secondaryTimer == null ? 0 : secondaryTimer;
}
+ /**
+ * @return Whether timer rules have been defined for this {@link #mState}.
+ */
+ public boolean isDefined() {
+ // TODO: Remove this method added to make STATE_CONNECTED_RRC_IDLE backwards compatible
+ // with STATE_CONNECTED once carrier configs are updated.
+ return mOverrideType != TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE
+ || !mPrimaryTimers.isEmpty() || !mSecondaryTimers.isEmpty();
+ }
+
@Override
public String toString() {
return "{mState=" + mState
@@ -1346,6 +1521,10 @@
* @return {@code true} if the device is in NR advanced mode (i.e. 5G+).
*/
private boolean isNrAdvanced() {
+ return isNrAdvancedForPccFields(mRatchetedNrBandwidths, mRatchetedNrBands);
+ }
+
+ private boolean isNrAdvancedForPccFields(int bandwidths, Set<Integer> bands) {
// Check PCO requirement. For carriers using PCO to indicate whether the data connection is
// NR advanced capable, mNrAdvancedCapablePcoId should be configured to non-zero.
if (mNrAdvancedCapablePcoId > 0 && !mIsNrAdvancedAllowedByPco) {
@@ -1362,10 +1541,9 @@
// Check if meeting minimum bandwidth requirement. For most carriers, there is no minimum
// bandwidth requirement and mNrAdvancedThresholdBandwidth is 0.
- if (mNrAdvancedThresholdBandwidth > 0
- && mRatchetedNrBandwidths < mNrAdvancedThresholdBandwidth) {
+ if (mNrAdvancedThresholdBandwidth > 0 && bandwidths < mNrAdvancedThresholdBandwidth) {
if (DBG) {
- log("isNrAdvanced: false because bandwidths=" + mRatchetedNrBandwidths
+ log("isNrAdvanced: false because bandwidths=" + bandwidths
+ " does not meet the threshold=" + mNrAdvancedThresholdBandwidth);
}
return false;
@@ -1373,24 +1551,24 @@
// If all above tests passed, then check if the device is using millimeter wave bands or
// carrier designated bands.
- return isNrMmwave() || isAdditionalNrAdvancedBand();
+ return isNrMmwave() || isAdditionalNrAdvancedBand(bands);
}
private boolean isNrMmwave() {
return mServiceState.getNrFrequencyRange() == ServiceState.FREQUENCY_RANGE_MMWAVE;
}
- private boolean isAdditionalNrAdvancedBand() {
- if (mAdditionalNrAdvancedBands.isEmpty() || mRatchetedNrBands.isEmpty()) {
+ private boolean isAdditionalNrAdvancedBand(Set<Integer> bands) {
+ if (mAdditionalNrAdvancedBands.isEmpty() || bands.isEmpty()) {
if (DBG && !mAdditionalNrAdvancedBands.isEmpty()) {
// Only log if mAdditionalNrAdvancedBands is empty to prevent log spam
log("isAdditionalNrAdvancedBand: false because bands are empty; configs="
- + mAdditionalNrAdvancedBands + ", bands=" + mRatchetedNrBands);
+ + mAdditionalNrAdvancedBands + ", bands=" + bands);
}
return false;
}
Set<Integer> intersection = new HashSet<>(mAdditionalNrAdvancedBands);
- intersection.retainAll(mRatchetedNrBands);
+ intersection.retainAll(bands);
return !intersection.isEmpty();
}
@@ -1404,7 +1582,8 @@
}
private int getPhysicalLinkStatusFromPhysicalChannelConfig() {
- return (mPhysicalChannelConfigs == null || mPhysicalChannelConfigs.isEmpty())
+ return (mPhysicalChannelConfigs == null || mPhysicalChannelConfigs.isEmpty()
+ || mDoesPccListIndicateIdle)
? DataCallResponse.LINK_STATUS_DORMANT : DataCallResponse.LINK_STATUS_ACTIVE;
}
@@ -1449,6 +1628,7 @@
pw.flush();
pw.increaseIndent();
pw.println("mSubId=" + mPhone.getSubId());
+ pw.println("supportNrSaRrcIdle=" + mFeatureFlags.supportNrSaRrcIdle());
pw.println("mOverrideTimerRules=" + mOverrideTimerRules.toString());
pw.println("mLteEnhancedPattern=" + mLteEnhancedPattern);
pw.println("mIsPhysicalChannelConfigOn=" + mIsPhysicalChannelConfigOn);
@@ -1465,6 +1645,7 @@
pw.println("mAdditionalNrAdvancedBandsList=" + mAdditionalNrAdvancedBands);
pw.println("mRatchetedNrBands=" + mRatchetedNrBands);
pw.println("mLastAnchorNrCellId=" + mLastAnchorNrCellId);
+ pw.println("mDoesPccListIndicateIdle=" + mDoesPccListIndicateIdle);
pw.println("mPrimaryTimerState=" + mPrimaryTimerState);
pw.println("mSecondaryTimerState=" + mSecondaryTimerState);
pw.println("mPreviousState=" + mPreviousState);
@@ -1473,6 +1654,7 @@
pw.println("mIsNrAdvancedAllowedByPco=" + mIsNrAdvancedAllowedByPco);
pw.println("mNrAdvancedCapablePcoId=" + mNrAdvancedCapablePcoId);
pw.println("mIsUsingUserDataForRrcDetection=" + mIsUsingUserDataForRrcDetection);
+ pw.println("mPrimaryCellChangedWhileIdle=" + mPrimaryCellChangedWhileIdle);
pw.println("mEnableNrAdvancedWhileRoaming=" + mEnableNrAdvancedWhileRoaming);
pw.println("mIsDeviceIdleMode=" + mIsDeviceIdleMode);
pw.decreaseIndent();
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index d944738..3b47670 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -25,6 +25,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.hardware.radio.modem.ImeiInfo;
import android.net.Uri;
@@ -256,7 +257,9 @@
protected static final int EVENT_IMEI_MAPPING_CHANGED = 71;
protected static final int EVENT_CELL_IDENTIFIER_DISCLOSURE = 72;
protected static final int EVENT_SET_IDENTIFIER_DISCLOSURE_ENABLED_DONE = 73;
- protected static final int EVENT_LAST = EVENT_SET_IDENTIFIER_DISCLOSURE_ENABLED_DONE;
+ protected static final int EVENT_SECURITY_ALGORITHM_UPDATE = 74;
+ protected static final int EVENT_SET_SECURITY_ALGORITHMS_UPDATED_ENABLED_DONE = 75;
+ protected static final int EVENT_LAST = EVENT_SET_SECURITY_ALGORITHMS_UPDATED_ENABLED_DONE;
// For shared prefs.
private static final String GSM_ROAMING_LIST_OVERRIDE_PREFIX = "gsm_roaming_list_";
@@ -290,6 +293,9 @@
public static final String PREF_IDENTIFIER_DISCLOSURE_NOTIFICATIONS_ENABLED =
"pref_identifier_disclosure_notifications_enabled";
+ public static final String PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED =
+ "pref_null_cipher_notifications_enabled";
+
protected final FeatureFlags mFeatureFlags;
/**
@@ -1078,9 +1084,20 @@
public void notifySmsSent(String destinationAddress) {
TelephonyManager m = (TelephonyManager) getContext().getSystemService(
Context.TELEPHONY_SERVICE);
- if (m != null && m.isEmergencyNumber(destinationAddress)) {
- mLocalLog.log("Emergency SMS detected, recording time.");
- mTimeLastEmergencySmsSentMs = SystemClock.elapsedRealtime();
+ if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()) {
+ if (m != null && m.isEmergencyNumber(destinationAddress)) {
+ mLocalLog.log("Emergency SMS detected, recording time.");
+ mTimeLastEmergencySmsSentMs = SystemClock.elapsedRealtime();
+ }
+ } else {
+ if (mContext.getPackageManager() != null
+ && mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_CALLING)) {
+ if (m != null && m.isEmergencyNumber(destinationAddress)) {
+ mLocalLog.log("Emergency SMS detected, recording time.");
+ mTimeLastEmergencySmsSentMs = SystemClock.elapsedRealtime();
+ }
+ }
}
}
@@ -3749,7 +3766,7 @@
* @return {@code true} if internet data is allowed to be established.
*/
public boolean isDataAllowed() {
- return getDataNetworkController().isInternetDataAllowed();
+ return getDataNetworkController().isInternetDataAllowed(false/* ignoreExistingNetworks */);
}
/**
@@ -5175,6 +5192,28 @@
}
/**
+ * @return whether this Phone interacts with a modem that supports the null cipher
+ * notification feature.
+ */
+ public boolean isNullCipherNotificationSupported() {
+ return false;
+ }
+
+ /**
+ * @return whether the global null cipher notifications preference is enabled.
+ */
+ public boolean getNullCipherNotificationsPreferenceEnabled() {
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
+ return sp.getBoolean(PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED, false);
+ }
+
+ /**
+ * Override to handle an update to the null cipher notification preference.
+ */
+ public void handleNullCipherNotificationPreferenceChanged() {
+ }
+
+ /**
* Notifies the IMS call status to the modem.
*
* @param imsCallInfo The list of {@link ImsCallInfo}.
diff --git a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
index 78d1387..7141f37 100644
--- a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
+++ b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
@@ -34,6 +34,7 @@
import android.telephony.PhoneCapability;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.TelephonyRegistryManager;
import android.text.TextUtils;
import android.util.Log;
@@ -43,8 +44,13 @@
import com.android.telephony.Rlog;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
import java.util.NoSuchElementException;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
/**
* This class manages phone's configuration which defines the potential capability (static) of the
@@ -65,10 +71,17 @@
private static final int EVENT_GET_MODEM_STATUS_DONE = 102;
private static final int EVENT_GET_PHONE_CAPABILITY_DONE = 103;
private static final int EVENT_DEVICE_CONFIG_CHANGED = 104;
+ private static final int EVENT_GET_SIMULTANEOUS_CALLING_SUPPORT_DONE = 105;
+ private static final int EVENT_SIMULTANEOUS_CALLING_SUPPORT_CHANGED = 106;
+
private static PhoneConfigurationManager sInstance = null;
private final Context mContext;
private PhoneCapability mStaticCapability;
+ private final Set<Integer> mSlotsSupportingSimultaneousCellularCalls = new HashSet<>(3);
+ private final Set<Integer> mSubIdsSupportingSimultaneousCellularCalls = new HashSet<>(3);
+ private final HashSet<Consumer<Set<Integer>>> mSimultaneousCellularCallingListeners =
+ new HashSet<>(1);
private final RadioConfig mRadioConfig;
private final Handler mHandler;
// mPhones is obtained from PhoneFactory and can have phones corresponding to inactive modems as
@@ -81,6 +94,7 @@
/** Feature flags */
@NonNull
private final FeatureFlags mFeatureFlags;
+ private final DefaultPhoneNotifier mNotifier;
/**
* True if 'Virtual DSDA' i.e., in-call IMS connectivity on both subs with only single logical
* modem, is enabled.
@@ -122,6 +136,7 @@
mPhoneStatusMap = new HashMap<>();
mVirtualDsdaEnabled = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_TELEPHONY, KEY_ENABLE_VIRTUAL_DSDA, false);
+ mNotifier = new DefaultPhoneNotifier(mContext, mFeatureFlags);
DeviceConfig.addOnPropertiesChangedListener(
DeviceConfig.NAMESPACE_TELEPHONY, Runnable::run,
properties -> {
@@ -140,6 +155,25 @@
}
}
+ /**
+ * Updates the mapping between the slot IDs that support simultaneous calling and the
+ * associated sub IDs as well as notifies listeners.
+ */
+ private void updateSimultaneousSubIdsFromPhoneIdMappingAndNotify() {
+ if (!mFeatureFlags.simultaneousCallingIndications()) return;
+ Set<Integer> slotCandidates = mSlotsSupportingSimultaneousCellularCalls.stream()
+ .map(i -> mPhones[i].getSubId())
+ .filter(i ->i > SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+ .collect(Collectors.toSet());
+ if (mSubIdsSupportingSimultaneousCellularCalls.equals(slotCandidates)) return;
+ log("updateSimultaneousSubIdsFromPhoneIdMapping update: "
+ + mSubIdsSupportingSimultaneousCellularCalls + " -> " + slotCandidates);
+ mSubIdsSupportingSimultaneousCellularCalls.clear();
+ mSubIdsSupportingSimultaneousCellularCalls.addAll(slotCandidates);
+ mNotifier.notifySimultaneousCellularCallingSubscriptionsChanged(
+ mSubIdsSupportingSimultaneousCellularCalls);
+ }
+
private void registerForRadioState(Phone phone) {
phone.mCi.registerForAvailable(mHandler, Phone.EVENT_RADIO_AVAILABLE, phone);
}
@@ -152,18 +186,66 @@
}
}
- // If virtual DSDA is enabled for this UE, then updates maxActiveVoiceSubscriptions to 2.
- private PhoneCapability maybeUpdateMaxActiveVoiceSubscriptions(
+ /**
+ * If virtual DSDA is enabled for this UE, then increase maxActiveVoiceSubscriptions to 2.
+ */
+ private PhoneCapability maybeOverrideMaxActiveVoiceSubscriptions(
final PhoneCapability staticCapability) {
- if (staticCapability.getLogicalModemList().size() > 1 && mVirtualDsdaEnabled) {
+ boolean isVDsdaEnabled = staticCapability.getLogicalModemList().size() > 1
+ && mVirtualDsdaEnabled;
+ boolean isBkwdCompatDsdaEnabled = mFeatureFlags.simultaneousCallingIndications()
+ && mMi.getMultiSimProperty().orElse(SSSS).equals(DSDA);
+ if (isVDsdaEnabled || isBkwdCompatDsdaEnabled) {
+ // Since we already initialized maxActiveVoiceSubscriptions to the count the
+ // modem is capable of, we are only able to increase that count via this method. We do
+ // not allow a decrease of maxActiveVoiceSubscriptions:
+ int updatedMaxActiveVoiceSubscriptions =
+ Math.max(staticCapability.getMaxActiveVoiceSubscriptions(), 2);
return new PhoneCapability.Builder(staticCapability)
- .setMaxActiveVoiceSubscriptions(2)
+ .setMaxActiveVoiceSubscriptions(updatedMaxActiveVoiceSubscriptions)
.build();
} else {
return staticCapability;
}
}
+ private void maybeEnableCellularDSDASupport() {
+ boolean bkwdsCompatDsda = mFeatureFlags.simultaneousCallingIndications()
+ && getPhoneCount() > 1
+ && mMi.getMultiSimProperty().orElse(SSSS).equals(DSDA);
+ boolean halSupportSimulCalling = mRadioConfig != null
+ && mRadioConfig.getRadioConfigProxy(null).getVersion().greaterOrEqual(
+ RIL.RADIO_HAL_VERSION_2_2)
+ && getPhoneCount() > 1 && mStaticCapability.getMaxActiveVoiceSubscriptions() > 1;
+ // Register for simultaneous calling support changes in the modem if the HAL supports it
+ if (halSupportSimulCalling) {
+ updateSimultaneousCallingSupport();
+ mRadioConfig.registerForSimultaneousCallingSupportStatusChanged(mHandler,
+ EVENT_SIMULTANEOUS_CALLING_SUPPORT_CHANGED, null);
+ } else if (bkwdsCompatDsda) {
+ // For older devices that only declare that they support DSDA via modem config,
+ // set DSDA as capable now statically.
+ log("DSDA modem config detected - setting DSDA enabled");
+ for (Phone p : mPhones) {
+ mSlotsSupportingSimultaneousCellularCalls.add(p.getPhoneId());
+ }
+ updateSimultaneousSubIdsFromPhoneIdMappingAndNotify();
+ notifySimultaneousCellularCallingSlotsChanged();
+ }
+ // Register for subId updates to notify listeners when simultaneous calling is configured
+ if (mFeatureFlags.simultaneousCallingIndications()
+ && (bkwdsCompatDsda || halSupportSimulCalling)) {
+ mContext.getSystemService(TelephonyRegistryManager.class)
+ .addOnSubscriptionsChangedListener(
+ new SubscriptionManager.OnSubscriptionsChangedListener() {
+ @Override
+ public void onSubscriptionsChanged() {
+ updateSimultaneousSubIdsFromPhoneIdMappingAndNotify();
+ }
+ }, mHandler::post);
+ }
+ }
+
/**
* Static method to get instance.
*/
@@ -223,6 +305,7 @@
if (ar != null && ar.exception == null) {
mStaticCapability = (PhoneCapability) ar.result;
notifyCapabilityChanged();
+ maybeEnableCellularDSDASupport();
} else {
log(msg.what + " failure. Not getting phone capability." + ar.exception);
}
@@ -236,6 +319,45 @@
mVirtualDsdaEnabled = isVirtualDsdaEnabled;
}
break;
+ case EVENT_SIMULTANEOUS_CALLING_SUPPORT_CHANGED:
+ case EVENT_GET_SIMULTANEOUS_CALLING_SUPPORT_DONE:
+ log("Received EVENT_SLOTS_SUPPORTING_SIMULTANEOUS_CALL_CHANGED/DONE");
+ if (getPhoneCount() < 2) {
+ if (!mSlotsSupportingSimultaneousCellularCalls.isEmpty()) {
+ mSlotsSupportingSimultaneousCellularCalls.clear();
+ }
+ break;
+ }
+ ar = (AsyncResult) msg.obj;
+ if (ar != null && ar.exception == null) {
+ int[] returnedIntArray = (int[]) ar.result;
+ if (!mSlotsSupportingSimultaneousCellularCalls.isEmpty()) {
+ mSlotsSupportingSimultaneousCellularCalls.clear();
+ }
+ int maxValidPhoneSlot = getPhoneCount() - 1;
+ for (int i : returnedIntArray) {
+ if (i < 0 || i > maxValidPhoneSlot) {
+ loge("Invalid slot supporting DSDA =" + i + ". Disabling DSDA.");
+ mSlotsSupportingSimultaneousCellularCalls.clear();
+ break;
+ }
+ mSlotsSupportingSimultaneousCellularCalls.add(i);
+ }
+ // Ensure the slots supporting cellular DSDA does not exceed the phone count
+ if (mSlotsSupportingSimultaneousCellularCalls.size() > getPhoneCount()) {
+ loge("Invalid size of DSDA slots. Disabling cellular DSDA.");
+ mSlotsSupportingSimultaneousCellularCalls.clear();
+ }
+ } else {
+ log(msg.what + " failure. Not getting logical slots that support "
+ + "simultaneous calling." + ar.exception);
+ mSlotsSupportingSimultaneousCellularCalls.clear();
+ }
+ if (mFeatureFlags.simultaneousCallingIndications()) {
+ updateSimultaneousSubIdsFromPhoneIdMappingAndNotify();
+ notifySimultaneousCellularCallingSlotsChanged();
+ }
+ break;
default:
log("Unknown event: " + msg.what);
}
@@ -341,6 +463,27 @@
return mTelephonyManager.getActiveModemCount();
}
+ @VisibleForTesting
+ public Set<Integer> getSlotsSupportingSimultaneousCellularCalls() {
+ return mSlotsSupportingSimultaneousCellularCalls;
+ }
+
+ /**
+ * Get the current the list of logical slots supporting simultaneous cellular calling from the
+ * modem based on current network conditions.
+ */
+ @VisibleForTesting
+ public void updateSimultaneousCallingSupport() {
+ log("updateSimultaneousCallingSupport: sending the request for "
+ + "getting the list of logical slots supporting simultaneous cellular calling");
+ Message callback = Message.obtain(
+ mHandler, EVENT_GET_SIMULTANEOUS_CALLING_SUPPORT_DONE);
+ mRadioConfig.updateSimultaneousCallingSupport(callback);
+ log("updateSimultaneousCallingSupport: "
+ + "mSlotsSupportingSimultaneousCellularCalls = " +
+ mSlotsSupportingSimultaneousCellularCalls);
+ }
+
/**
* get static overall phone capabilities for all phones.
*/
@@ -351,7 +494,7 @@
mHandler, EVENT_GET_PHONE_CAPABILITY_DONE);
mRadioConfig.getPhoneCapability(callback);
}
- mStaticCapability = maybeUpdateMaxActiveVoiceSubscriptions(mStaticCapability);
+ mStaticCapability = maybeOverrideMaxActiveVoiceSubscriptions(mStaticCapability);
log("getStaticPhoneCapability: mStaticCapability " + mStaticCapability);
return mStaticCapability;
}
@@ -367,10 +510,31 @@
return mStaticCapability.getMaxActiveDataSubscriptions();
}
- private void notifyCapabilityChanged() {
- PhoneNotifier notifier = new DefaultPhoneNotifier(mContext, mFeatureFlags);
+ /**
+ * Register to listen to changes in the Phone slots that support simultaneous calling.
+ * @param consumer A consumer that will be used to consume the new slots supporting simultaneous
+ * cellular calling when it changes.
+ */
+ public void registerForSimultaneousCellularCallingSlotsChanged(
+ Consumer<Set<Integer>> consumer) {
+ mSimultaneousCellularCallingListeners.add(consumer);
+ }
- notifier.notifyPhoneCapabilityChanged(mStaticCapability);
+ private void notifySimultaneousCellularCallingSlotsChanged() {
+ log("notifying listeners of changes to simultaneous cellular calling - new state:"
+ + mSlotsSupportingSimultaneousCellularCalls);
+ for (Consumer<Set<Integer>> consumer : mSimultaneousCellularCallingListeners) {
+ try {
+ consumer.accept(new HashSet<>(mSlotsSupportingSimultaneousCellularCalls));
+ } catch (Exception e) {
+ log("Unexpected Exception encountered when notifying listener: " + e);
+ }
+ }
+ }
+
+ private void notifyCapabilityChanged() {
+ mNotifier.notifyPhoneCapabilityChanged(maybeOverrideMaxActiveVoiceSubscriptions(
+ mStaticCapability));
}
/**
@@ -446,6 +610,20 @@
phone.mCi.onSlotActiveStatusChange(SubscriptionManager.isValidPhoneId(phoneId));
}
+ if (numOfActiveModems > 1) {
+ // Check if cellular DSDA is supported. If it is, then send a request to the
+ // modem to refresh the list of SIM slots that currently support DSDA based on
+ // current network conditions
+ maybeEnableCellularDSDASupport();
+ } else {
+ // The number of active modems is 0 or 1, disable cellular DSDA:
+ mSlotsSupportingSimultaneousCellularCalls.clear();
+ if (mFeatureFlags.simultaneousCallingIndications()) {
+ updateSimultaneousSubIdsFromPhoneIdMappingAndNotify();
+ notifySimultaneousCellularCallingSlotsChanged();
+ }
+ }
+
// When the user enables DSDS mode, the default VOICE and SMS subId should be switched
// to "No Preference". Doing so will sync the network/sim settings and telephony.
// (see b/198123192)
@@ -621,6 +799,13 @@
Context context, int numOfActiveModems) {
PhoneFactory.onMultiSimConfigChanged(context, numOfActiveModems);
}
+
+ /**
+ * Wrapper function to query the sysprop for multi_sim_config
+ */
+ public Optional<String> getMultiSimProperty() {
+ return TelephonyProperties.multi_sim_config();
+ }
}
private static void log(String s) {
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index d29eed1..b1ff500 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -215,8 +215,8 @@
if (context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY_EUICC)) {
- sEuiccController = EuiccController.init(context);
- sEuiccCardController = EuiccCardController.init(context);
+ sEuiccController = EuiccController.init(context, sFeatureFlags);
+ sEuiccCardController = EuiccCardController.init(context, sFeatureFlags);
}
for (int i = 0; i < numPhones; i++) {
@@ -268,7 +268,7 @@
makePhoneSwitcher(maxActivePhones, sContext, Looper.myLooper(),
featureFlags);
- sProxyController = ProxyController.getInstance(context);
+ sProxyController = ProxyController.getInstance(context, featureFlags);
sIntentBroadcaster = IntentBroadcaster.getInstance(context);
@@ -276,7 +276,7 @@
for (int i = 0; i < numPhones; i++) {
sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
- Looper.myLooper(), sPhones[i]);
+ Looper.myLooper(), sPhones[i], featureFlags);
}
}
}
@@ -285,8 +285,9 @@
/**
* Upon single SIM to dual SIM switch or vice versa, we dynamically allocate or de-allocate
* Phone and CommandInterface objects.
- * @param context
- * @param activeModemCount
+ *
+ * @param context The context
+ * @param activeModemCount The number of active modems
*/
public static void onMultiSimConfigChanged(Context context, int activeModemCount) {
synchronized (sLockProxyPhones) {
@@ -313,7 +314,7 @@
sPhones[i].createImsPhone();
}
sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
- Looper.myLooper(), sPhones[i]);
+ Looper.myLooper(), sPhones[i], sFeatureFlags);
}
}
}
diff --git a/src/java/com/android/internal/telephony/PhoneNotifier.java b/src/java/com/android/internal/telephony/PhoneNotifier.java
index 20d6702..cb6b199 100644
--- a/src/java/com/android/internal/telephony/PhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/PhoneNotifier.java
@@ -39,6 +39,7 @@
import android.telephony.ims.MediaQualityStatus;
import java.util.List;
+import java.util.Set;
/**
* {@hide}
@@ -149,4 +150,7 @@
/** Notify callback mode stopped. */
void notifyCallbackModeStopped(Phone sender, @EmergencyCallbackModeType int type,
@EmergencyCallbackModeStopReason int reason);
+
+ /** Notify that simultaneous cellular calling subscriptions have changed */
+ void notifySimultaneousCellularCallingSubscriptionsChanged(Set<Integer> subIds);
}
diff --git a/src/java/com/android/internal/telephony/PhoneSubInfoController.java b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
index d30a73c..a65bfeb 100644
--- a/src/java/com/android/internal/telephony/PhoneSubInfoController.java
+++ b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
@@ -20,10 +20,12 @@
import static android.Manifest.permission.MODIFY_PHONE_STATE;
import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
+import static android.telephony.TelephonyManager.ENABLE_FEATURE_MAPPING;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
+import android.app.compat.CompatChanges;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -39,6 +41,8 @@
import android.text.TextUtils;
import android.util.EventLog;
+import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.FeatureFlagsImpl;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.uicc.IsimRecords;
@@ -58,8 +62,14 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private final Context mContext;
private AppOpsManager mAppOps;
+ private FeatureFlags mFeatureFlags;
+ private PackageManager mPackageManager;
public PhoneSubInfoController(Context context) {
+ this(context, new FeatureFlagsImpl());
+ }
+
+ public PhoneSubInfoController(Context context, FeatureFlags featureFlags) {
ServiceRegisterer phoneSubServiceRegisterer = TelephonyFrameworkInitializer
.getTelephonyServiceManager()
.getPhoneSubServiceRegisterer();
@@ -68,6 +78,8 @@
}
mAppOps = context.getSystemService(AppOpsManager.class);
mContext = context;
+ mPackageManager = context.getPackageManager();
+ mFeatureFlags = featureFlags;
}
@Deprecated
@@ -89,7 +101,13 @@
public String getNaiForSubscriber(int subId, String callingPackage, String callingFeatureId) {
return callPhoneMethodForSubIdWithReadSubscriberIdentifiersCheck(subId, callingPackage,
- callingFeatureId, "getNai", (phone)-> phone.getNai());
+ callingFeatureId, "getNai", (phone)-> {
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "getNaiForSubscriber");
+
+ return phone.getNai();
+ });
}
public String getImeiForSubscriber(int subId, String callingPackage,
@@ -102,7 +120,13 @@
String callingPackage) {
return callPhoneMethodForSubIdWithPrivilegedCheck(subId,
"getCarrierInfoForImsiEncryption",
- (phone)-> phone.getCarrierInfoForImsiEncryption(keyType, true));
+ (phone)-> {
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "getCarrierInfoForImsiEncryption");
+
+ return phone.getCarrierInfoForImsiEncryption(keyType, true);
+ });
}
public void setCarrierInfoForImsiEncryption(int subId, String callingPackage,
@@ -126,6 +150,10 @@
callPhoneMethodForSubIdWithModifyCheck(subId, callingPackage,
"resetCarrierKeysForImsiEncryption",
(phone)-> {
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "resetCarrierKeysForImsiEncryption");
+
phone.resetCarrierKeysForImsiEncryption();
return null;
});
@@ -166,12 +194,22 @@
}
if (isActive) {
return callPhoneMethodForSubIdWithReadSubscriberIdentifiersCheck(subId, callingPackage,
- callingFeatureId, message, (phone) -> phone.getSubscriberId());
+ callingFeatureId, message, (phone) -> {
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "getSubscriberIdForSubscriber");
+
+ return phone.getSubscriberId();
+ });
} else {
if (!TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers(
mContext, subId, callingPackage, callingFeatureId, message)) {
return null;
}
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getSubscriberIdForSubscriber");
+
identity = Binder.clearCallingIdentity();
try {
SubscriptionInfoInternal subInfo = SubscriptionManagerService.getInstance()
@@ -202,7 +240,13 @@
public String getIccSerialNumberForSubscriber(int subId, String callingPackage,
String callingFeatureId) {
return callPhoneMethodForSubIdWithReadSubscriberIdentifiersCheck(subId, callingPackage,
- callingFeatureId, "getIccSerialNumber", (phone) -> phone.getIccSerialNumber());
+ callingFeatureId, "getIccSerialNumber", (phone) -> {
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "getIccSerialNumberForSubscriber");
+
+ return phone.getIccSerialNumber();
+ });
}
public String getLine1Number(String callingPackage, String callingFeatureId) {
@@ -216,7 +260,13 @@
String callingFeatureId) {
return callPhoneMethodForSubIdWithReadPhoneNumberCheck(
subId, callingPackage, callingFeatureId, "getLine1Number",
- (phone)-> phone.getLine1Number());
+ (phone)-> {
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "getLine1NumberForSubscriber");
+
+ return phone.getLine1Number();
+ });
}
public String getLine1AlphaTag(String callingPackage, String callingFeatureId) {
@@ -251,6 +301,10 @@
String callingFeatureId) {
return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId,
"getVoiceMailNumber", (phone)-> {
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING,
+ "getVoiceMailNumberForSubscriber");
+
String number = PhoneNumberUtils.extractNetworkPortion(
phone.getVoiceMailNumber());
if (VDBG) log("VM: getVoiceMailNUmber: " + number);
@@ -266,7 +320,13 @@
public String getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage,
String callingFeatureId) {
return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId,
- "getVoiceMailAlphaTag", (phone)-> phone.getVoiceMailAlphaTag());
+ "getVoiceMailAlphaTag", (phone)-> {
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING,
+ "getVoiceMailAlphaTagForSubscriber");
+
+ return phone.getVoiceMailAlphaTag();
+ });
}
/**
@@ -381,6 +441,9 @@
public String getIsimDomain(int subId) {
return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getIsimDomain",
(phone) -> {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getIsimDomain");
+
IsimRecords isim = phone.getIsimRecords();
if (isim != null) {
return isim.getIsimDomain();
@@ -422,6 +485,10 @@
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();
@@ -447,6 +514,9 @@
public String getIsimIst(int subId) throws RemoteException {
return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getIsimIst",
(phone) -> {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getIsimIst");
+
IsimRecords isim = phone.getIsimRecords();
if (isim != null) {
return isim.getIsimIst();
@@ -478,6 +548,9 @@
public String getSimServiceTable(int subId, int appType) throws RemoteException {
return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getSimServiceTable",
(phone) -> {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getSimServiceTable");
+
UiccPort uiccPort = phone.getUiccPort();
if (uiccPort == null || uiccPort.getUiccProfile() == null) {
loge("getSimServiceTable(): uiccPort or uiccProfile is null");
@@ -498,6 +571,9 @@
public String getIccSimChallengeResponse(int subId, int appType, int authType, String data,
String callingPackage, String callingFeatureId) throws RemoteException {
CallPhoneMethodHelper<String> toExecute = (phone)-> {
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getIccSimChallengeResponse");
+
UiccPort uiccPort = phone.getUiccPort();
if (uiccPort == null) {
loge("getIccSimChallengeResponse() uiccPort is null");
@@ -531,7 +607,13 @@
public String getGroupIdLevel1ForSubscriber(int subId, String callingPackage,
String callingFeatureId) {
return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId,
- "getGroupIdLevel1", (phone)-> phone.getGroupIdLevel1());
+ "getGroupIdLevel1", (phone)-> {
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "getGroupIdLevel1ForSubscriber");
+
+ return phone.getGroupIdLevel1();
+ });
}
/** Below are utility methods that abstracts the flow that many public methods use:
@@ -667,6 +749,9 @@
public Uri getSmscIdentity(int subId, int appType) throws RemoteException {
Uri smscIdentityUri = callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getSmscIdentity",
(phone) -> {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getSmscIdentity");
+
try {
String smscIdentity = null;
UiccPort uiccPort = phone.getUiccPort();
@@ -690,6 +775,40 @@
return smscIdentityUri;
}
+ /**
+ * Get the current calling package name.
+ * @return the current calling package name
+ */
+ @Nullable
+ private String getCurrentPackageName() {
+ if (mPackageManager == null) return null;
+ String[] callingUids = mPackageManager.getPackagesForUid(Binder.getCallingUid());
+ return (callingUids == null) ? null : callingUids[0];
+ }
+
+ /**
+ * Make sure the device has required telephony feature
+ *
+ * @throws UnsupportedOperationException if the device does not have required telephony feature
+ */
+ private void enforceTelephonyFeatureWithException(@Nullable String callingPackage,
+ @NonNull String telephonyFeature, @NonNull String methodName) {
+ if (callingPackage == null || mPackageManager == null) {
+ return;
+ }
+
+ if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
+ || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+ Binder.getCallingUserHandle())) {
+ return;
+ }
+
+ if (!mPackageManager.hasSystemFeature(telephonyFeature)) {
+ throw new UnsupportedOperationException(
+ methodName + " is unsupported without " + telephonyFeature);
+ }
+ }
+
private void log(String s) {
Rlog.d(TAG, s);
}
diff --git a/src/java/com/android/internal/telephony/ProxyController.java b/src/java/com/android/internal/telephony/ProxyController.java
index ed9982e..01aed07 100644
--- a/src/java/com/android/internal/telephony/ProxyController.java
+++ b/src/java/com/android/internal/telephony/ProxyController.java
@@ -18,6 +18,7 @@
import static java.util.Arrays.copyOf;
+import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
@@ -33,6 +34,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.data.PhoneSwitcher;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.telephony.Rlog;
import java.util.ArrayList;
@@ -111,11 +113,12 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private int[] mOldRadioAccessFamily;
+ @NonNull
+ private final FeatureFlags mFlags;
- //***** Class Methods
- public static ProxyController getInstance(Context context) {
+ public static ProxyController getInstance(Context context, FeatureFlags flags) {
if (sProxyController == null) {
- sProxyController = new ProxyController(context);
+ sProxyController = new ProxyController(context, flags);
}
return sProxyController;
}
@@ -125,16 +128,23 @@
return sProxyController;
}
- private ProxyController(Context context) {
+ /**
+ * Constructor
+ *
+ * @param context The context
+ * @param featureFlags Feature flags
+ */
+ public ProxyController(@NonNull Context context, @NonNull FeatureFlags featureFlags) {
logd("Constructor - Enter");
mContext = context;
+ mFlags = featureFlags;
mPhones = PhoneFactory.getPhones();
mPhoneSwitcher = PhoneSwitcher.getInstance();
mUiccPhoneBookController = new UiccPhoneBookController();
mPhoneSubInfoController = new PhoneSubInfoController(mContext);
- mSmsController = new SmsController(mContext);
+ mSmsController = new SmsController(mContext, featureFlags);
mSetRadioAccessFamilyStatus = new int[mPhones.length];
mNewRadioAccessFamily = new int[mPhones.length];
mOldRadioAccessFamily = new int[mPhones.length];
diff --git a/src/java/com/android/internal/telephony/RILUtils.java b/src/java/com/android/internal/telephony/RILUtils.java
index 94f2e96..0617656 100644
--- a/src/java/com/android/internal/telephony/RILUtils.java
+++ b/src/java/com/android/internal/telephony/RILUtils.java
@@ -98,6 +98,7 @@
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_PHONE_CAPABILITY;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_RADIO_CAPABILITY;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SIMULTANEOUS_CALLING_SUPPORT;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SIM_PHONEBOOK_CAPACITY;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SIM_PHONEBOOK_RECORDS;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SIM_STATUS;
@@ -116,9 +117,11 @@
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IMS_REGISTRATION_STATE;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IMS_SEND_SMS;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_ISIM_AUTHENTICATION;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_CELLULAR_IDENTIFIER_DISCLOSED_ENABLED;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_N1_MODE_ENABLED;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_NR_DUAL_CONNECTIVITY_ENABLED;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_NULL_CIPHER_AND_INTEGRITY_ENABLED;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_SECURITY_ALGORITHMS_UPDATED_ENABLED;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_VONR_ENABLED;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_LAST_CALL_FAIL_CAUSE;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE;
@@ -157,6 +160,7 @@
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_CALL_FORWARD;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_CALL_WAITING;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_CARRIER_INFO_IMSI_ENCRYPTION;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_CELLULAR_IDENTIFIER_DISCLOSED_ENABLED;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_CLIR;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_DATA_PROFILE;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_DATA_THROTTLING;
@@ -176,6 +180,7 @@
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_PREFERRED_DATA_MODEM;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_RADIO_CAPABILITY;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SECURITY_ALGORITHMS_UPDATED_ENABLED;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SIM_CARD_POWER;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SMSC_ADDRESS;
@@ -231,6 +236,7 @@
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CDMA_PRL_CHANGED;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CELLULAR_IDENTIFIER_DISCLOSED;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CELL_INFO_LIST;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CONNECTION_SETUP_FAILURE;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_DATA_CALL_LIST_CHANGED;
@@ -272,7 +278,9 @@
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RESTRICTED_STATE_CHANGED;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RIL_CONNECTED;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RINGBACK_TONE;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SECURITY_ALGORITHMS_UPDATED;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SIGNAL_STRENGTH;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SIMULTANEOUS_CALLING_SUPPORT_CHANGED;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SIM_REFRESH;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SIM_SMS_STORAGE_FULL;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SLICING_CONFIG_CHANGED;
@@ -297,6 +305,7 @@
import android.net.LinkProperties;
import android.os.SystemClock;
import android.service.carrier.CarrierIdentifier;
+import android.telephony.CarrierInfo;
import android.telephony.AccessNetworkConstants;
import android.telephony.Annotation;
import android.telephony.BarringInfo;
@@ -334,6 +343,7 @@
import android.telephony.PhoneNumberUtils;
import android.telephony.PhysicalChannelConfig;
import android.telephony.RadioAccessSpecifier;
+import android.telephony.SecurityAlgorithmUpdate;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SignalThresholdInfo;
@@ -4030,6 +4040,9 @@
public static List<CarrierIdentifier> convertHalCarrierList(
android.hardware.radio.sim.Carrier[] carrierList) {
List<CarrierIdentifier> ret = new ArrayList<>();
+ if (carrierList == null) {
+ return ret;
+ }
for (int i = 0; i < carrierList.length; i++) {
String mcc = carrierList[i].mcc;
String mnc = carrierList[i].mnc;
@@ -4051,6 +4064,85 @@
}
/**
+ * Convert an array of CarrierInfo defined in
+ * radio/aidl/android/hardware/radio/sim/CarrierInfo.aidl to a list of CarrierInfo
+ * defined in android/service/carrier/CarrierInfo.java
+ *
+ * @param carrierInfos array of CarrierInfo defined in
+ * radio/aidl/android/hardware/radio/sim/CarrierInfo.aidl
+ * @return The converted list of CarrierInfo
+ */
+ public static List<CarrierInfo> convertAidlCarrierInfoList(
+ android.hardware.radio.sim.CarrierInfo[] carrierInfos) {
+ List<CarrierInfo> carrierInfoList = new ArrayList<>();
+ if (carrierInfos == null) {
+ loge("convertAidlCarrierInfoList received NULL carrierInfos");
+ return carrierInfoList;
+ }
+ for (int index = 0; index < carrierInfos.length; index++) {
+ String mcc = carrierInfos[index].mcc;
+ String mnc = carrierInfos[index].mnc;
+ String spn = carrierInfos[index].spn;
+ String gid1 = carrierInfos[index].gid1;
+ String gid2 = carrierInfos[index].gid2;
+ String imsi = carrierInfos[index].imsiPrefix;
+ String iccid = carrierInfos[index].iccid;
+ String impi = carrierInfos[index].impi;
+ List<android.hardware.radio.sim.Plmn> halEhplmn = carrierInfos[index].ehplmn;
+ List<String> eHplmnList = new ArrayList<>();
+ if (halEhplmn != null) {
+ for (int plmnIndex = 0; plmnIndex < halEhplmn.size(); plmnIndex++) {
+ String ehplmnMcc = halEhplmn.get(plmnIndex).mcc;
+ String ehplmnMnc = halEhplmn.get(plmnIndex).mnc;
+ eHplmnList.add(ehplmnMcc + "," + ehplmnMnc);
+ }
+ } else {
+ loge("convertAidlCarrierInfoList ehplmList is NULL");
+ }
+ CarrierInfo carrierInfo = new CarrierInfo(mcc, mnc, spn, gid1, gid2, imsi, iccid, impi,
+ eHplmnList);
+ carrierInfoList.add(carrierInfo);
+ }
+ return carrierInfoList;
+ }
+
+ /**
+ * Convert the sim policy defined in
+ * radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl to the equivalent sim
+ * policy defined in android.telephony/CarrierRestrictionRules.MultiSimPolicy
+ *
+ * @param multiSimPolicy of type defined in SimLockMultiSimPolicy.aidl
+ * @return int of type CarrierRestrictionRules.MultiSimPolicy
+ */
+ public static @CarrierRestrictionRules.MultiSimPolicy int convertAidlSimLockMultiSimPolicy(
+ int multiSimPolicy) {
+ switch (multiSimPolicy) {
+ case android.hardware.radio.sim.SimLockMultiSimPolicy.ONE_VALID_SIM_MUST_BE_PRESENT:
+ return CarrierRestrictionRules.MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT;
+ case android.hardware.radio.sim.SimLockMultiSimPolicy.APPLY_TO_ALL_SLOTS:
+ return CarrierRestrictionRules.MULTISIM_POLICY_APPLY_TO_ALL_SLOTS;
+ case android.hardware.radio.sim.SimLockMultiSimPolicy.APPLY_TO_ONLY_SLOT_1:
+ return CarrierRestrictionRules.MULTISIM_POLICY_APPLY_TO_ONLY_SLOT_1;
+ case android.hardware.radio.sim.SimLockMultiSimPolicy.VALID_SIM_MUST_PRESENT_ON_SLOT_1:
+ return CarrierRestrictionRules.MULTISIM_POLICY_VALID_SIM_MUST_PRESENT_ON_SLOT_1;
+ case android.hardware.radio.sim.SimLockMultiSimPolicy.
+ ACTIVE_SERVICE_ON_SLOT_1_TO_UNBLOCK_OTHER_SLOTS:
+ return CarrierRestrictionRules.
+ MULTISIM_POLICY_ACTIVE_SERVICE_ON_SLOT_1_TO_UNBLOCK_OTHER_SLOTS;
+ case android.hardware.radio.sim.SimLockMultiSimPolicy.
+ ACTIVE_SERVICE_ON_ANY_SLOT_TO_UNBLOCK_OTHER_SLOTS:
+ return CarrierRestrictionRules.
+ MULTISIM_POLICY_ACTIVE_SERVICE_ON_ANY_SLOT_TO_UNBLOCK_OTHER_SLOTS;
+ case android.hardware.radio.sim.SimLockMultiSimPolicy.ALL_SIMS_MUST_BE_VALID:
+ return CarrierRestrictionRules.MULTISIM_POLICY_ALL_SIMS_MUST_BE_VALID;
+ case android.hardware.radio.sim.SimLockMultiSimPolicy.SLOT_POLICY_OTHER:
+ return CarrierRestrictionRules.MULTISIM_POLICY_SLOT_POLICY_OTHER;
+ default:
+ return CarrierRestrictionRules.MULTISIM_POLICY_NONE;
+ }
+ }
+
+ /**
* Convert CardStatus defined in radio/1.0, 1.5/types.hal to IccCardStatus
* @param cardStatus CardStatus defined in radio/1.0, 1.5/types.hal
* @return The converted IccCardStatus
@@ -4381,14 +4473,20 @@
public static PhoneCapability convertHalPhoneCapability(int[] deviceNrCapabilities, Object o) {
int maxActiveVoiceCalls = 0;
int maxActiveData = 0;
- int maxActiveInternetData = 0;
boolean validationBeforeSwitchSupported = false;
List<ModemInfo> logicalModemList = new ArrayList<>();
if (o instanceof android.hardware.radio.config.PhoneCapability) {
final android.hardware.radio.config.PhoneCapability phoneCapability =
(android.hardware.radio.config.PhoneCapability) o;
maxActiveData = phoneCapability.maxActiveData;
- maxActiveInternetData = phoneCapability.maxActiveInternetData;
+ // If the maxActiveVoice field has been set, use that value. Otherwise, default to the
+ // legacy behavior and rely on the maxActiveInternetData field:
+ if (phoneCapability.maxActiveVoice ==
+ android.hardware.radio.config.PhoneCapability.UNKNOWN) {
+ maxActiveVoiceCalls = phoneCapability.maxActiveInternetData;
+ } else {
+ maxActiveVoiceCalls = phoneCapability.maxActiveVoice;
+ }
validationBeforeSwitchSupported = phoneCapability.isInternetLingeringSupported;
for (int modemId : phoneCapability.logicalModemIds) {
logicalModemList.add(new ModemInfo(modemId));
@@ -4397,16 +4495,15 @@
final android.hardware.radio.config.V1_1.PhoneCapability phoneCapability =
(android.hardware.radio.config.V1_1.PhoneCapability) o;
maxActiveData = phoneCapability.maxActiveData;
- maxActiveInternetData = phoneCapability.maxActiveInternetData;
+ // maxActiveInternetData defines how many logical modems can have internet PDN
+ // connections simultaneously. For L+L DSDS modem it’s 1, and for DSDA modem it’s 2.
+ maxActiveVoiceCalls = phoneCapability.maxActiveInternetData;
validationBeforeSwitchSupported = phoneCapability.isInternetLingeringSupported;
for (android.hardware.radio.config.V1_1.ModemInfo modemInfo :
phoneCapability.logicalModemList) {
logicalModemList.add(new ModemInfo(modemInfo.modemId));
}
}
- // maxActiveInternetData defines how many logical modems can have internet PDN connections
- // simultaneously. For L+L DSDS modem it’s 1, and for DSDA modem it’s 2.
- maxActiveVoiceCalls = maxActiveInternetData;
return new PhoneCapability(maxActiveVoiceCalls, maxActiveData, logicalModemList,
validationBeforeSwitchSupported, deviceNrCapabilities);
}
@@ -5128,6 +5225,16 @@
return "SET_LOCATION_PRIVACY_SETTING";
case RIL_REQUEST_GET_LOCATION_PRIVACY_SETTING:
return "GET_LOCATION_PRIVACY_SETTING";
+ case RIL_REQUEST_IS_CELLULAR_IDENTIFIER_DISCLOSED_ENABLED:
+ return "IS_CELLULAR_IDENTIFIER_DISCLOSED_ENABLED";
+ case RIL_REQUEST_SET_CELLULAR_IDENTIFIER_DISCLOSED_ENABLED:
+ return "SET_CELLULAR_IDENTIFIER_DISCLOSED_ENABLED";
+ case RIL_REQUEST_SET_SECURITY_ALGORITHMS_UPDATED_ENABLED:
+ return "SET_SECURITY_ALGORITHMS_UPDATED_ENABLED";
+ case RIL_REQUEST_IS_SECURITY_ALGORITHMS_UPDATED_ENABLED:
+ return "IS_SECURITY_ALGORITHMS_UPDATED_ENABLED";
+ case RIL_REQUEST_GET_SIMULTANEOUS_CALLING_SUPPORT:
+ return "GET_SIMULTANEOUS_CALLING_SUPPORT";
default:
return "<unknown request " + request + ">";
}
@@ -5250,6 +5357,10 @@
return "UNSOL_RESPONSE_SIM_PHONEBOOK_RECORDS_RECEIVED";
case RIL_UNSOL_SLICING_CONFIG_CHANGED:
return "UNSOL_SLICING_CONFIG_CHANGED";
+ case RIL_UNSOL_CELLULAR_IDENTIFIER_DISCLOSED:
+ return "UNSOL_CELLULAR_IDENTIFIER_DISCLOSED";
+ case RIL_UNSOL_SECURITY_ALGORITHMS_UPDATED:
+ return "UNSOL_SECURITY_ALGORITHMS_UPDATED";
/* The follow unsols are not defined in RIL.h */
case RIL_UNSOL_ICC_SLOT_STATUS:
return "UNSOL_ICC_SLOT_STATUS";
@@ -5273,6 +5384,8 @@
return "UNSOL_TRIGGER_IMS_DEREGISTRATION";
case RIL_UNSOL_IMEI_MAPPING_CHANGED:
return "UNSOL_IMEI_MAPPING_CHANGED";
+ case RIL_UNSOL_SIMULTANEOUS_CALLING_SUPPORT_CHANGED:
+ return "UNSOL_SIMULTANEOUS_CALLING_SUPPORT_CHANGED";
default:
return "<unknown response " + response + ">";
}
@@ -5690,6 +5803,20 @@
identifierDisclsoure.isEmergency);
}
+ /** Convert an AIDL-based SecurityAlgorithmUpdate to its Java wrapper. */
+ public static SecurityAlgorithmUpdate convertSecurityAlgorithmUpdate(
+ android.hardware.radio.network.SecurityAlgorithmUpdate securityAlgorithmUpdate) {
+ if (securityAlgorithmUpdate == null) {
+ return null;
+ }
+
+ return new SecurityAlgorithmUpdate(
+ securityAlgorithmUpdate.connectionEvent,
+ securityAlgorithmUpdate.encryption,
+ securityAlgorithmUpdate.integrity,
+ securityAlgorithmUpdate.isUnprotectedEmergency);
+ }
+
private static void logd(String log) {
Rlog.d("RILUtils", log);
}
diff --git a/src/java/com/android/internal/telephony/RadioConfig.java b/src/java/com/android/internal/telephony/RadioConfig.java
index 6bf0203..13f6502 100644
--- a/src/java/com/android/internal/telephony/RadioConfig.java
+++ b/src/java/com/android/internal/telephony/RadioConfig.java
@@ -23,6 +23,7 @@
import static com.android.internal.telephony.RILConstants.REQUEST_NOT_SUPPORTED;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_HAL_DEVICE_CAPABILITIES;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_PHONE_CAPABILITY;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SIMULTANEOUS_CALLING_SUPPORT;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SLOT_STATUS;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_PREFERRED_DATA_MODEM;
@@ -79,6 +80,8 @@
protected Registrant mSimSlotStatusRegistrant;
+ protected Registrant mSimultaneousCallingSupportStatusRegistrant;
+
private boolean isMobileDataCapable(Context context) {
final TelephonyManager tm = context.getSystemService(TelephonyManager.class);
return tm != null && tm.isDataCapable();
@@ -478,6 +481,34 @@
}
/**
+ * Wrapper function for IRadioConfig.getSimultaneousCallingSupport().
+ */
+ public void updateSimultaneousCallingSupport(Message result) {
+ RadioConfigProxy proxy = getRadioConfigProxy(null);
+ if (proxy.isEmpty()) return;
+
+ if (proxy.getVersion().less(RIL.RADIO_HAL_VERSION_2_2)) {
+ if (result != null) {
+ AsyncResult.forMessage(result, null,
+ CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+ result.sendToTarget();
+ }
+ return;
+ }
+
+ RILRequest rr = obtainRequest(RIL_REQUEST_GET_SIMULTANEOUS_CALLING_SUPPORT, result,
+ mDefaultWorkSource);
+ if (DBG) {
+ logd(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+ }
+ try {
+ proxy.updateSimultaneousCallingSupport(rr.mSerial);
+ } catch (RemoteException | RuntimeException e) {
+ resetProxyAndRequestList("updateSimultaneousCallingSupport", e);
+ }
+ }
+
+ /**
* Wrapper function for IRadioConfig.getPhoneCapability().
*/
public void getPhoneCapability(Message result) {
@@ -566,6 +597,14 @@
}
/**
+ * Register a handler to get SIM slots that support simultaneous calling changed notifications.
+ */
+ public void registerForSimultaneousCallingSupportStatusChanged(Handler h, int what,
+ Object obj) {
+ mSimultaneousCallingSupportStatusRegistrant = new Registrant(h, what, obj);
+ }
+
+ /**
* Register a handler to get SIM slot status changed notifications.
*/
public void registerForSimSlotStatusChanged(Handler h, int what, Object obj) {
diff --git a/src/java/com/android/internal/telephony/RadioConfigIndicationAidl.java b/src/java/com/android/internal/telephony/RadioConfigIndicationAidl.java
index 76e6d5e..9aa1aaa 100644
--- a/src/java/com/android/internal/telephony/RadioConfigIndicationAidl.java
+++ b/src/java/com/android/internal/telephony/RadioConfigIndicationAidl.java
@@ -17,12 +17,14 @@
package com.android.internal.telephony;
import android.os.AsyncResult;
+import android.os.RemoteException;
import android.os.Trace;
import com.android.internal.telephony.uicc.IccSlotStatus;
import com.android.telephony.Rlog;
import java.util.ArrayList;
+import java.util.Arrays;
/**
* This class is the AIDL implementation of IRadioConfigIndication interface.
@@ -51,6 +53,19 @@
}
}
+ /**
+ * Indication that the logical slots that support simultaneous calling has changed.
+ */
+ @Override
+ public void onSimultaneousCallingSupportChanged(int[] enabledLogicalSlots) {
+ ArrayList<Integer> ret = RILUtils.primitiveArrayToArrayList(enabledLogicalSlots);
+ logd("onSimultaneousCallingSupportChanged: enabledLogicalSlots = " + ret);
+ if (mRadioConfig.mSimultaneousCallingSupportStatusRegistrant != null) {
+ mRadioConfig.mSimultaneousCallingSupportStatusRegistrant.notifyRegistrant(
+ new AsyncResult(null, ret, null));
+ }
+ }
+
private static void logd(String log) {
Rlog.d(TAG, "[UNSL]< " + log);
Trace.instantForTrack(Trace.TRACE_TAG_NETWORK, "RIL", log);
diff --git a/src/java/com/android/internal/telephony/RadioConfigProxy.java b/src/java/com/android/internal/telephony/RadioConfigProxy.java
index 9d05fc5..b6c6d68 100644
--- a/src/java/com/android/internal/telephony/RadioConfigProxy.java
+++ b/src/java/com/android/internal/telephony/RadioConfigProxy.java
@@ -225,6 +225,16 @@
}
/**
+ * Wrapper function for IRadioConfig.getSimultaneousCallingSupport()
+ */
+ public void updateSimultaneousCallingSupport(int serial) throws RemoteException {
+ if (isAidl()) {
+ getAidl().getSimultaneousCallingSupport(serial);
+ }
+ // Only supported on AIDL.
+ }
+
+ /**
* Wrapper function for using IRadioConfig.setNumOfLiveModems(int32_t serial,
* byte numOfLiveModems) to switch between single-sim and multi-sim.
*/
diff --git a/src/java/com/android/internal/telephony/RadioConfigResponseAidl.java b/src/java/com/android/internal/telephony/RadioConfigResponseAidl.java
index 2049654..0a41b11 100644
--- a/src/java/com/android/internal/telephony/RadioConfigResponseAidl.java
+++ b/src/java/com/android/internal/telephony/RadioConfigResponseAidl.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony;
+import android.hardware.radio.RadioResponseInfo;
import android.os.RemoteException;
import android.telephony.PhoneCapability;
@@ -23,6 +24,7 @@
import com.android.telephony.Rlog;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Set;
/**
@@ -112,6 +114,30 @@
}
/**
+ * Response function for IRadioConfig.getSimultaneousCallingSupport().
+ */
+ @Override
+ public void getSimultaneousCallingSupportResponse(
+ android.hardware.radio.RadioResponseInfo info,
+ int[] enabledLogicalSlots)
+ throws RemoteException {
+ RILRequest rr = mRadioConfig.processResponse(info);
+ if (rr != null) {
+ ArrayList<Integer> ret = RILUtils.primitiveArrayToArrayList(enabledLogicalSlots);
+ if (info.error == android.hardware.radio.RadioError.NONE) {
+ // send response
+ RadioResponse.sendMessageResponse(rr.mResult, ret);
+ logd(rr, RILUtils.requestToString(rr.mRequest) + " " + ret);
+ } else {
+ rr.onError(info.error, enabledLogicalSlots);
+ loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+ }
+ } else {
+ loge("getSimultaneousCallingSupportResponse: Error " + info.toString());
+ }
+ }
+
+ /**
* Response function for IRadioConfig.getSimSlotsStatus().
*/
@Override
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index d19e4cb..88d541c 100644
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -681,7 +681,7 @@
}
mLocaleTracker = TelephonyComponentFactory.getInstance()
.inject(LocaleTracker.class.getName())
- .makeLocaleTracker(mPhone, mNitzState, getLooper());
+ .makeLocaleTracker(mPhone, mNitzState, getLooper(), featureFlags);
mCi.registerForImsNetworkStateChanged(this, EVENT_IMS_STATE_CHANGED, null);
mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
diff --git a/src/java/com/android/internal/telephony/SimResponse.java b/src/java/com/android/internal/telephony/SimResponse.java
index 1e1dbe5..164ec7d 100644
--- a/src/java/com/android/internal/telephony/SimResponse.java
+++ b/src/java/com/android/internal/telephony/SimResponse.java
@@ -20,7 +20,6 @@
import android.hardware.radio.RadioError;
import android.hardware.radio.RadioResponseInfo;
-import android.hardware.radio.sim.CarrierRestrictions;
import android.hardware.radio.sim.IRadioSimResponse;
import android.telephony.CarrierRestrictionRules;
import android.telephony.TelephonyManager;
@@ -116,28 +115,24 @@
if (rr == null) {
return;
}
- CarrierRestrictionRules ret;
- int policy = CarrierRestrictionRules.MULTISIM_POLICY_NONE;
- if (multiSimPolicy
- == android.hardware.radio.sim.SimLockMultiSimPolicy.ONE_VALID_SIM_MUST_BE_PRESENT) {
- policy = CarrierRestrictionRules.MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT;
- }
-
+ int policy = RILUtils.convertAidlSimLockMultiSimPolicy(multiSimPolicy);
int carrierRestrictionDefault =
CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED;
if (!carrierRestrictions.allowedCarriersPrioritized) {
carrierRestrictionDefault = CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_ALLOWED;
}
- ret = CarrierRestrictionRules.newBuilder()
- .setAllowedCarriers(RILUtils.convertHalCarrierList(
- carrierRestrictions.allowedCarriers))
- .setExcludedCarriers(RILUtils.convertHalCarrierList(
- carrierRestrictions.excludedCarriers))
- .setDefaultCarrierRestriction(carrierRestrictionDefault)
- .setMultiSimPolicy(policy)
- .setCarrierRestrictionStatus(carrierRestrictions.status)
- .build();
+ CarrierRestrictionRules ret = CarrierRestrictionRules.newBuilder().setAllowedCarriers(
+ RILUtils.convertHalCarrierList(
+ carrierRestrictions.allowedCarriers)).setExcludedCarriers(
+ RILUtils.convertHalCarrierList(
+ carrierRestrictions.excludedCarriers)).setDefaultCarrierRestriction(
+ carrierRestrictionDefault).setMultiSimPolicy(policy).setCarrierRestrictionStatus(
+ carrierRestrictions.status).setAllowedCarrierInfo(
+ RILUtils.convertAidlCarrierInfoList(
+ carrierRestrictions.allowedCarrierInfoList)).setExcludedCarrierInfo(
+ RILUtils.convertAidlCarrierInfoList(
+ carrierRestrictions.excludedCarrierInfoList)).build();
if (responseInfo.error == RadioError.NONE) {
RadioResponse.sendMessageResponse(rr.mResult, ret);
}
diff --git a/src/java/com/android/internal/telephony/SmsController.java b/src/java/com/android/internal/telephony/SmsController.java
index 97161f8..da1b07a 100644
--- a/src/java/com/android/internal/telephony/SmsController.java
+++ b/src/java/com/android/internal/telephony/SmsController.java
@@ -18,14 +18,18 @@
package com.android.internal.telephony;
+import static android.content.pm.PackageManager.FEATURE_TELEPHONY_MESSAGING;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.telephony.TelephonyManager.ENABLE_FEATURE_MAPPING;
import static com.android.internal.telephony.util.TelephonyUtils.checkDumpPermission;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
+import android.app.compat.CompatChanges;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -35,6 +39,7 @@
import android.os.Build;
import android.os.Bundle;
import android.os.TelephonyServiceManager.ServiceRegisterer;
+import android.os.UserHandle;
import android.provider.Telephony.Sms.Intents;
import android.telephony.CarrierConfigManager;
import android.telephony.SmsManager;
@@ -44,6 +49,7 @@
import android.telephony.TelephonyManager;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.util.IndentingPrintWriter;
@@ -52,6 +58,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
import java.util.List;
import java.util.Locale;
@@ -62,10 +69,14 @@
static final String LOG_TAG = "SmsController";
private final Context mContext;
+ private final PackageManager mPackageManager;
+ @NonNull private final FeatureFlags mFlags;
@VisibleForTesting
- public SmsController(Context context) {
+ public SmsController(Context context, @NonNull FeatureFlags flags) {
mContext = context;
+ mFlags = flags;
+ mPackageManager = context.getPackageManager();
ServiceRegisterer smsServiceRegisterer = TelephonyFrameworkInitializer
.getTelephonyServiceManager()
.getSmsServiceRegisterer();
@@ -279,6 +290,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "sendTextForSubscriber");
+
long token = Binder.clearCallingIdentity();
SubscriptionInfo info;
try {
@@ -396,6 +409,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "sendMultipartTextForSubscriber");
+
// Perform FDN check
if (isNumberBlockedByFDN(subId, destAddr, callingPackage)) {
sendErrorInPendingIntents(sentIntents, SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE);
@@ -462,6 +477,9 @@
@Override
public boolean enableCellBroadcastRangeForSubscriber(int subId, int startMessageId,
int endMessageId, int ranType) {
+ enforceTelephonyFeatureWithException(getCallingPackage(),
+ "enableCellBroadcastRangeForSubscriber");
+
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
if (iccSmsIntMgr != null) {
return iccSmsIntMgr.enableCellBroadcastRange(startMessageId, endMessageId, ranType);
@@ -484,6 +502,9 @@
@Override
public boolean disableCellBroadcastRangeForSubscriber(int subId, int startMessageId,
int endMessageId, int ranType) {
+ enforceTelephonyFeatureWithException(getCallingPackage(),
+ "disableCellBroadcastRangeForSubscriber");
+
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
if (iccSmsIntMgr != null) {
return iccSmsIntMgr.disableCellBroadcastRange(startMessageId, endMessageId, ranType);
@@ -496,6 +517,8 @@
@Override
public int getPremiumSmsPermission(String packageName) {
+ enforceTelephonyFeatureWithException(packageName, "getPremiumSmsPermission");
+
return getPremiumSmsPermissionForSubscriber(getPreferredSmsSubscription(), packageName);
}
@@ -513,6 +536,8 @@
@Override
public void setPremiumSmsPermission(String packageName, int permission) {
+ enforceTelephonyFeatureWithException(packageName, "setPremiumSmsPermission");
+
setPremiumSmsPermissionForSubscriber(getPreferredSmsSubscription(), packageName,
permission);
}
@@ -553,34 +578,60 @@
+ "Suppressing activity.");
return false;
}
+
+ enforceTelephonyFeatureWithException(getCallingPackage(), "isSmsSimPickActivityNeeded");
+
TelephonyManager telephonyManager =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- List<SubscriptionInfo> subInfoList;
- final long identity = Binder.clearCallingIdentity();
- try {
- subInfoList = SubscriptionManager.from(context).getActiveSubscriptionInfoList();
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
+ if (mFlags.enforceSubscriptionUserFilter()) {
+ int[] activeSubIds;
+ final UserHandle user = Binder.getCallingUserHandle();
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ activeSubIds = Arrays.stream(SubscriptionManagerService.getInstance()
+ .getActiveSubIdList(true /*visibleOnly*/))
+ .filter(sub -> SubscriptionManagerService.getInstance()
+ .isSubscriptionAssociatedWithUser(sub, user))
+ .toArray();
+ for (int activeSubId : activeSubIds) {
+ // Check if the subId is associated with the caller user profile.
+ if (activeSubId == subId) {
+ return false;
+ }
+ }
- if (subInfoList != null) {
- final int subInfoLength = subInfoList.size();
+ // If reached here and multiple SIMs and subs present, need sms sim pick activity.
+ return activeSubIds.length > 1 && telephonyManager.getSimCount() > 1;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ } else {
+ List<SubscriptionInfo> subInfoList;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ subInfoList = SubscriptionManager.from(context).getActiveSubscriptionInfoList();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
- for (int i = 0; i < subInfoLength; ++i) {
- final SubscriptionInfo sir = subInfoList.get(i);
- if (sir != null && sir.getSubscriptionId() == subId) {
- // The subscription id is valid, sms sim pick activity not needed
- return false;
+ if (subInfoList != null) {
+ final int subInfoLength = subInfoList.size();
+
+ for (int i = 0; i < subInfoLength; ++i) {
+ final SubscriptionInfo sir = subInfoList.get(i);
+ if (sir != null && sir.getSubscriptionId() == subId) {
+ // The subscription id is valid, sms sim pick activity not needed
+ return false;
+ }
+ }
+
+ // If reached here and multiple SIMs and subs present, need sms sim pick activity
+ if (subInfoLength > 1 && telephonyManager.getSimCount() > 1) {
+ return true;
}
}
-
- // If reached here and multiple SIMs and subs present, sms sim pick activity is needed
- if (subInfoLength > 1 && telephonyManager.getSimCount() > 1) {
- return true;
- }
+ return false;
}
-
- return false;
}
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -598,6 +649,8 @@
@Override
public void injectSmsPduForSubscriber(
int subId, byte[] pdu, String format, PendingIntent receivedIntent) {
+ enforceTelephonyFeatureWithException(getCallingPackage(), "injectSmsPduForSubscriber");
+
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
if (iccSmsIntMgr != null) {
iccSmsIntMgr.injectSmsPdu(pdu, format, receivedIntent);
@@ -624,6 +677,9 @@
if (SubscriptionManager.isValidSubscriptionId(defaultSubId)) {
return defaultSubId;
}
+
+ enforceTelephonyFeatureWithException(getCallingPackage(), "getPreferredSmsSubscription");
+
// No default, if there is only one sub active, choose that as the "preferred" sub id.
long token = Binder.clearCallingIdentity();
try {
@@ -692,6 +748,9 @@
@Override
public Bundle getCarrierConfigValuesForSubscriber(int subId) {
+ enforceTelephonyFeatureWithException(getCallingPackage(),
+ "getCarrierConfigValuesForSubscriber");
+
final long identity = Binder.clearCallingIdentity();
try {
final CarrierConfigManager configManager =
@@ -820,6 +879,10 @@
if (callingPkg == null) {
callingPkg = getCallingPackage();
}
+
+ enforceTelephonyFeatureWithException(callingPkg,
+ "createAppSpecificSmsTokenWithPackageInfo");
+
return getPhone(subId).getAppSmsManager().createAppSpecificSmsTokenWithPackageInfo(
subId, callingPkg, prefixes, intent);
}
@@ -829,6 +892,9 @@
if (callingPkg == null) {
callingPkg = getCallingPackage();
}
+
+ enforceTelephonyFeatureWithException(callingPkg, "createAppSpecificSmsToken");
+
return getPhone(subId).getAppSmsManager().createAppSpecificSmsToken(callingPkg, intent);
}
@@ -944,6 +1010,10 @@
if (callingPackage == null) {
callingPackage = getCallingPackage();
}
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ "getSmscAddressFromIccEfForSubscriber");
+
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
if (iccSmsIntMgr != null) {
return iccSmsIntMgr.getSmscAddressFromIccEf(callingPackage);
@@ -960,6 +1030,10 @@
if (callingPackage == null) {
callingPackage = getCallingPackage();
}
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ "setSmscAddressOnIccEfForSubscriber");
+
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
if (iccSmsIntMgr != null) {
return iccSmsIntMgr.setSmscAddressOnIccEf(callingPackage, smsc);
@@ -1035,6 +1109,9 @@
*/
@Override
public int getSmsCapacityOnIccForSubscriber(int subId) {
+ enforceTelephonyFeatureWithException(getCallingPackage(),
+ "getSmsCapacityOnIccForSubscriber");
+
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
if (iccSmsIntMgr != null ) {
@@ -1053,6 +1130,9 @@
*/
@Override
public boolean resetAllCellBroadcastRanges(int subId) {
+ enforceTelephonyFeatureWithException(getCallingPackage(),
+ "resetAllCellBroadcastRanges");
+
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
if (iccSmsIntMgr != null) {
iccSmsIntMgr.resetAllCellBroadcastRanges();
@@ -1114,4 +1194,43 @@
// Check if smscAddr is present in FDN list
return FdnUtils.isNumberBlockedByFDN(phoneId, smscAddr, defaultCountryIso);
}
+
+ /**
+ * Gets the message size of WAP from the cache.
+ *
+ * @param locationUrl the location to use as a key for looking up the size in the cache.
+ * The locationUrl may or may not have the transactionId appended to the url.
+ *
+ * @return long representing the message size
+ * @throws java.util.NoSuchElementException if the WAP push doesn't exist in the cache
+ * @throws IllegalArgumentException if the locationUrl is empty
+ */
+ @Override
+ public long getWapMessageSize(@NonNull String locationUrl) {
+ byte[] bytes = locationUrl.getBytes(StandardCharsets.ISO_8859_1);
+ return WapPushCache.getWapMessageSize(bytes);
+ }
+
+ /**
+ * Make sure the device has required telephony feature
+ *
+ * @throws UnsupportedOperationException if the device does not have required telephony feature
+ */
+ private void enforceTelephonyFeatureWithException(@Nullable String callingPackage,
+ @NonNull String methodName) {
+ if (callingPackage == null || mPackageManager == null) {
+ return;
+ }
+
+ if (!mFlags.enforceTelephonyFeatureMappingForPublicApis()
+ || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+ Binder.getCallingUserHandle())) {
+ return;
+ }
+
+ if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY_MESSAGING)) {
+ throw new UnsupportedOperationException(
+ methodName + " is unsupported without " + FEATURE_TELEPHONY_MESSAGING);
+ }
+ }
}
\ No newline at end of file
diff --git a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
index 74094a3..2c68457 100644
--- a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
+++ b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
@@ -48,6 +48,7 @@
import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
import com.android.internal.telephony.nitz.NitzStateMachineImpl;
import com.android.internal.telephony.security.CellularIdentifierDisclosureNotifier;
+import com.android.internal.telephony.security.NullCipherNotifier;
import com.android.internal.telephony.uicc.IccCardStatus;
import com.android.internal.telephony.uicc.UiccCard;
import com.android.internal.telephony.uicc.UiccProfile;
@@ -277,8 +278,14 @@
return sInstance;
}
- public GsmCdmaCallTracker makeGsmCdmaCallTracker(GsmCdmaPhone phone) {
- return new GsmCdmaCallTracker(phone);
+ /**
+ * Create a new GsmCdmaCallTracker
+ * @param phone GsmCdmaPhone
+ * @param featureFlags Telephony feature flag
+ */
+ public GsmCdmaCallTracker makeGsmCdmaCallTracker(GsmCdmaPhone phone,
+ @NonNull FeatureFlags featureFlags) {
+ return new GsmCdmaCallTracker(phone, featureFlags);
}
public SmsStorageMonitor makeSmsStorageMonitor(Phone phone) {
@@ -342,8 +349,9 @@
* Create a new UiccProfile object.
*/
public UiccProfile makeUiccProfile(Context context, CommandsInterface ci, IccCardStatus ics,
- int phoneId, UiccCard uiccCard, Object lock) {
- return new UiccProfile(context, ci, ics, phoneId, uiccCard, lock);
+ int phoneId, UiccCard uiccCard, Object lock,
+ @NonNull FeatureFlags flags) {
+ return new UiccProfile(context, ci, ics, phoneId, uiccCard, lock, flags);
}
public EriManager makeEriManager(Phone phone, int eriFileSource) {
@@ -468,8 +476,8 @@
}
public LocaleTracker makeLocaleTracker(Phone phone, NitzStateMachine nitzStateMachine,
- Looper looper) {
- return new LocaleTracker(phone, nitzStateMachine, looper);
+ Looper looper, @NonNull FeatureFlags featureFlags) {
+ return new LocaleTracker(phone, nitzStateMachine, looper, featureFlags);
}
public Phone makePhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
@@ -571,4 +579,9 @@
public CellularIdentifierDisclosureNotifier makeIdentifierDisclosureNotifier() {
return CellularIdentifierDisclosureNotifier.getInstance();
}
+
+ /** Create NullCipherNotifier. */
+ public NullCipherNotifier makeNullCipherNotifier() {
+ return NullCipherNotifier.getInstance();
+ }
}
diff --git a/src/java/com/android/internal/telephony/TelephonyCountryDetector.java b/src/java/com/android/internal/telephony/TelephonyCountryDetector.java
new file mode 100644
index 0000000..56e8b46
--- /dev/null
+++ b/src/java/com/android/internal/telephony/TelephonyCountryDetector.java
@@ -0,0 +1,572 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.location.Address;
+import android.location.Geocoder;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.telephony.Rlog;
+import android.util.Pair;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * This class is used to detect the country where the device is.
+ *
+ * {@link LocaleTracker} also tracks country of a device based on the information provided by
+ * network operators. However, it won't work when a device is out of service. In such cases and if
+ * Wi-Fi is available, {@link Geocoder} can be used to query the country for the current location of
+ * the device. {@link TelephonyCountryDetector} uses both {@link LocaleTracker} and {@link Geocoder}
+ * to track country of a device.
+ */
+public class TelephonyCountryDetector extends Handler {
+ private static final String TAG = "TelephonyCountryDetector";
+ private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem";
+ private static final String BOOT_ALLOW_MOCK_MODEM_PROPERTY = "ro.boot.radio.allow_mock_modem";
+ private static final boolean DEBUG = !"user".equals(Build.TYPE);
+ private static final int EVENT_LOCATION_CHANGED = 1;
+ private static final int EVENT_LOCATION_COUNTRY_CODE_CHANGED = 2;
+ private static final int EVENT_NETWORK_COUNTRY_CODE_CHANGED = 3;
+ private static final int EVENT_WIFI_CONNECTIVITY_STATE_CHANGED = 4;
+ private static final int EVENT_LOCATION_UPDATE_REQUEST_QUOTA_RESET = 5;
+
+ // Wait 12 hours between location updates
+ private static final long TIME_BETWEEN_LOCATION_UPDATES_MILLIS = TimeUnit.HOURS.toMillis(12);
+ // Minimum distance before a location update is triggered, in meters. We don't need this to be
+ // too exact because all we care about is in what country the device is.
+ private static final float DISTANCE_BETWEEN_LOCATION_UPDATES_METERS = 2000;
+ protected static final long WAIT_FOR_LOCATION_UPDATE_REQUEST_QUOTA_RESET_TIMEOUT_MILLIS =
+ TimeUnit.MINUTES.toMillis(30);
+
+ private static TelephonyCountryDetector sInstance;
+
+ @NonNull private final Geocoder mGeocoder;
+ @NonNull private final LocationManager mLocationManager;
+ @NonNull private final ConnectivityManager mConnectivityManager;
+ @NonNull private final Object mLock = new Object();
+ @NonNull
+ @GuardedBy("mLock")
+ private final Map<Integer, NetworkCountryCodeInfo> mNetworkCountryCodeInfoPerPhone =
+ new HashMap<>();
+ @GuardedBy("mLock")
+ private String mLocationCountryCode = null;
+ /** This should be used by CTS only */
+ @GuardedBy("mLock")
+ private String mOverriddenLocationCountryCode = null;
+ @GuardedBy("mLock")
+ private boolean mIsLocationUpdateRequested = false;
+ @GuardedBy("mLock")
+ private long mLocationCountryCodeUpdatedTimestampNanos = 0;
+ /** This should be used by CTS only */
+ @GuardedBy("mLock")
+ private long mOverriddenLocationCountryCodeUpdatedTimestampNanos = 0;
+ @GuardedBy("mLock")
+ private List<String> mOverriddenCurrentNetworkCountryCodes = null;
+ @GuardedBy("mLock")
+ private Map<String, Long> mOverriddenCachedNetworkCountryCodes = new HashMap<>();
+ @GuardedBy("mLock")
+ private boolean mIsCountryCodesOverridden = false;
+ @NonNull private final LocationListener mLocationListener = new LocationListener() {
+ @Override
+ public void onLocationChanged(Location location) {
+ logd("onLocationChanged: " + (location != null));
+ if (location != null) {
+ sendRequestAsync(EVENT_LOCATION_CHANGED, location);
+ }
+ }
+
+ @Override
+ public void onProviderDisabled(String provider) {
+ logd("onProviderDisabled: provider=" + provider);
+ }
+
+ @Override
+ public void onProviderEnabled(String provider) {
+ logd("onProviderEnabled: provider=" + provider);
+ }
+
+ @Override
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ logd("onStatusChanged: provider=" + provider + ", status=" + status
+ + ", extras=" + extras);
+ }
+ };
+
+ private class TelephonyGeocodeListener implements Geocoder.GeocodeListener {
+ private long mLocationUpdatedTime;
+ TelephonyGeocodeListener(long locationUpdatedTime) {
+ mLocationUpdatedTime = locationUpdatedTime;
+ }
+
+ @Override
+ public void onGeocode(List<Address> addresses) {
+ if (addresses != null && !addresses.isEmpty()) {
+ logd("onGeocode: addresses is available");
+ String countryCode = addresses.get(0).getCountryCode();
+ sendRequestAsync(EVENT_LOCATION_COUNTRY_CODE_CHANGED,
+ new Pair<>(countryCode, mLocationUpdatedTime));
+ } else {
+ logd("onGeocode: addresses is not available");
+ }
+ }
+
+ @Override
+ public void onError(String errorMessage) {
+ loge("GeocodeListener.onError=" + errorMessage);
+ }
+ }
+
+ /**
+ * Container class to store country code per Phone.
+ */
+ private static class NetworkCountryCodeInfo {
+ public int phoneId;
+ public String countryCode;
+ public long timestamp;
+
+ @Override
+ public String toString() {
+ return "NetworkCountryCodeInfo[phoneId: " + phoneId
+ + ", countryCode: " + countryCode
+ + ", timestamp: " + timestamp + "]";
+ }
+ }
+
+ /**
+ * Create the singleton instance of {@link TelephonyCountryDetector}.
+ *
+ * @param looper The looper to run the {@link TelephonyCountryDetector} instance.
+ * @param context The context used by the instance.
+ * @param locationManager The LocationManager instance.
+ * @param connectivityManager The ConnectivityManager instance.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected TelephonyCountryDetector(@NonNull Looper looper, @NonNull Context context,
+ @NonNull LocationManager locationManager,
+ @NonNull ConnectivityManager connectivityManager) {
+ super(looper);
+ mLocationManager = locationManager;
+ mGeocoder = new Geocoder(context);
+ mConnectivityManager = connectivityManager;
+ initialize();
+ }
+
+ /** @return the singleton instance of the {@link TelephonyCountryDetector} */
+ public static synchronized TelephonyCountryDetector getInstance(@NonNull Context context) {
+ if (sInstance == null) {
+ HandlerThread handlerThread = new HandlerThread("TelephonyCountryDetector");
+ handlerThread.start();
+ sInstance = new TelephonyCountryDetector(handlerThread.getLooper(), context,
+ context.getSystemService(LocationManager.class),
+ context.getSystemService(ConnectivityManager.class));
+ }
+ return sInstance;
+ }
+
+ /**
+ * @return The list of current network country ISOs if available, an empty list otherwise.
+ */
+ @NonNull public List<String> getCurrentNetworkCountryIso() {
+ synchronized (mLock) {
+ if (mIsCountryCodesOverridden) {
+ logd("mOverriddenCurrentNetworkCountryCodes="
+ + String.join(", ", mOverriddenCurrentNetworkCountryCodes));
+ return mOverriddenCurrentNetworkCountryCodes;
+ }
+ }
+
+ List<String> result = new ArrayList<>();
+ for (Phone phone : PhoneFactory.getPhones()) {
+ String countryIso = getNetworkCountryIsoForPhone(phone);
+ if (isValid(countryIso)) {
+ String countryIsoInUpperCase = countryIso.toUpperCase(Locale.US);
+ if (!result.contains(countryIsoInUpperCase)) {
+ result.add(countryIsoInUpperCase);
+ }
+ } else {
+ logd("getCurrentNetworkCountryIso: invalid countryIso=" + countryIso
+ + " for phoneId=" + phone.getPhoneId() + ", subId=" + phone.getSubId());
+ }
+ }
+ return result;
+ }
+
+ /**
+ * @return The cached location country code and its updated timestamp.
+ */
+ @NonNull public Pair<String, Long> getCachedLocationCountryIsoInfo() {
+ synchronized (mLock) {
+ if (mIsCountryCodesOverridden) {
+ logd("mOverriddenLocationCountryCode=" + mOverriddenLocationCountryCode
+ + " will be used");
+ return new Pair<>(mOverriddenLocationCountryCode,
+ mOverriddenLocationCountryCodeUpdatedTimestampNanos);
+ }
+ return new Pair<>(mLocationCountryCode, mLocationCountryCodeUpdatedTimestampNanos);
+ }
+ }
+
+ /**
+ * This API should be used only when {@link #getCurrentNetworkCountryIso()} returns an empty
+ * list.
+ *
+ * @return The list of cached network country codes and their updated timestamps.
+ */
+ @NonNull public Map<String, Long> getCachedNetworkCountryIsoInfo() {
+ synchronized (mLock) {
+ if (mIsCountryCodesOverridden) {
+ logd("mOverriddenCachedNetworkCountryCodes = "
+ + String.join(", ", mOverriddenCachedNetworkCountryCodes.keySet())
+ + " will be used");
+ return mOverriddenCachedNetworkCountryCodes;
+ }
+ Map<String, Long> result = new HashMap<>();
+ for (NetworkCountryCodeInfo countryCodeInfo :
+ mNetworkCountryCodeInfoPerPhone.values()) {
+ boolean alreadyAdded = result.containsKey(countryCodeInfo.countryCode);
+ if (!alreadyAdded || (alreadyAdded
+ && result.get(countryCodeInfo.countryCode) < countryCodeInfo.timestamp)) {
+ result.put(countryCodeInfo.countryCode, countryCodeInfo.timestamp);
+ }
+ }
+ return result;
+ }
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case EVENT_LOCATION_CHANGED:
+ queryCountryCodeForLocation((Location) msg.obj);
+ break;
+ case EVENT_LOCATION_COUNTRY_CODE_CHANGED:
+ setLocationCountryCode((Pair) msg.obj);
+ break;
+ case EVENT_NETWORK_COUNTRY_CODE_CHANGED:
+ handleNetworkCountryCodeChangedEvent((NetworkCountryCodeInfo) msg.obj);
+ break;
+ case EVENT_WIFI_CONNECTIVITY_STATE_CHANGED:
+ case EVENT_LOCATION_UPDATE_REQUEST_QUOTA_RESET:
+ evaluateRequestingLocationUpdates();
+ break;
+ default:
+ logw("CountryDetectorHandler: unexpected message code: " + msg.what);
+ break;
+ }
+ }
+
+ /**
+ * This API is called by {@link LocaleTracker} whenever there is a change in network country
+ * code of a phone.
+ */
+ public void onNetworkCountryCodeChanged(
+ @NonNull Phone phone, @Nullable String currentCountryCode) {
+ NetworkCountryCodeInfo networkCountryCodeInfo = new NetworkCountryCodeInfo();
+ networkCountryCodeInfo.phoneId = phone.getPhoneId();
+ networkCountryCodeInfo.countryCode = currentCountryCode;
+ sendRequestAsync(EVENT_NETWORK_COUNTRY_CODE_CHANGED, networkCountryCodeInfo);
+ }
+
+ /**
+ * This API should be used by only CTS tests to forcefully set the telephony country codes.
+ */
+ public boolean setCountryCodes(boolean reset, @NonNull List<String> currentNetworkCountryCodes,
+ @NonNull Map<String, Long> cachedNetworkCountryCodes, String locationCountryCode,
+ long locationCountryCodeTimestampNanos) {
+ if (!isMockModemAllowed()) {
+ logd("setCountryCodes: mock modem is not allowed");
+ return false;
+ }
+ logd("setCountryCodes: currentNetworkCountryCodes="
+ + String.join(", ", currentNetworkCountryCodes)
+ + ", locationCountryCode=" + locationCountryCode
+ + ", locationCountryCodeTimestampNanos" + locationCountryCodeTimestampNanos
+ + ", reset=" + reset + ", cachedNetworkCountryCodes="
+ + String.join(", ", cachedNetworkCountryCodes.keySet()));
+
+ synchronized (mLock) {
+ if (reset) {
+ mIsCountryCodesOverridden = false;
+ } else {
+ mIsCountryCodesOverridden = true;
+ mOverriddenCachedNetworkCountryCodes = cachedNetworkCountryCodes;
+ mOverriddenCurrentNetworkCountryCodes = currentNetworkCountryCodes;
+ mOverriddenLocationCountryCode = locationCountryCode;
+ mOverriddenLocationCountryCodeUpdatedTimestampNanos =
+ locationCountryCodeTimestampNanos;
+ }
+ }
+ return true;
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected void queryCountryCodeForLocation(@NonNull Location location) {
+ mGeocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1,
+ new TelephonyGeocodeListener(location.getElapsedRealtimeNanos()));
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected long getElapsedRealtimeNanos() {
+ return SystemClock.elapsedRealtimeNanos();
+ }
+
+ private void initialize() {
+ evaluateRequestingLocationUpdates();
+ registerForWifiConnectivityStateChanged();
+ }
+
+ private boolean isGeoCoderImplemented() {
+ return Geocoder.isPresent();
+ }
+
+ private void registerForLocationUpdates() {
+ // If the device does not implement Geocoder, there is no point trying to get location
+ // updates because we cannot retrieve the country based on the location anyway.
+ if (!isGeoCoderImplemented()) {
+ logd("Geocoder is not implemented on the device");
+ return;
+ }
+
+ synchronized (mLock) {
+ if (mIsLocationUpdateRequested) {
+ logd("Already registered for location updates");
+ return;
+ }
+
+ logd("Registering for location updates");
+ /*
+ * PASSIVE_PROVIDER can be used to passively receive location updates when other
+ * applications or services request them without actually requesting the locations
+ * ourselves. This provider will only return locations generated by other providers.
+ * This provider is used to make sure there is no impact on the thermal and battery of
+ * a device.
+ */
+ mLocationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER,
+ TIME_BETWEEN_LOCATION_UPDATES_MILLIS, DISTANCE_BETWEEN_LOCATION_UPDATES_METERS,
+ mLocationListener);
+ mIsLocationUpdateRequested = true;
+ mLocationListener.onLocationChanged(getLastKnownLocation());
+ }
+ }
+
+ @Nullable
+ private Location getLastKnownLocation() {
+ Location result = null;
+ for (String provider : mLocationManager.getProviders(true)) {
+ Location location = mLocationManager.getLastKnownLocation(provider);
+ if (location != null && (result == null
+ || result.getElapsedRealtimeNanos() < location.getElapsedRealtimeNanos())) {
+ result = location;
+ }
+ }
+ return result;
+ }
+
+ private void unregisterForLocationUpdates() {
+ synchronized (mLock) {
+ if (!mIsLocationUpdateRequested) {
+ logd("Location update was not requested yet");
+ return;
+ }
+ if (isLocationUpdateRequestQuotaExceeded()) {
+ logd("Removing location updates will be re-evaluated after the quota is refilled");
+ return;
+ }
+ mLocationManager.removeUpdates(mLocationListener);
+ mIsLocationUpdateRequested = false;
+ sendMessageDelayed(obtainMessage(EVENT_LOCATION_UPDATE_REQUEST_QUOTA_RESET),
+ WAIT_FOR_LOCATION_UPDATE_REQUEST_QUOTA_RESET_TIMEOUT_MILLIS);
+ }
+ }
+
+ private boolean isLocationUpdateRequestQuotaExceeded() {
+ return hasMessages(EVENT_LOCATION_UPDATE_REQUEST_QUOTA_RESET);
+ }
+
+ private boolean shouldRequestLocationUpdate() {
+ return getCurrentNetworkCountryIso().isEmpty() && isWifiNetworkConnected();
+ }
+
+ /**
+ * Posts the specified command to be executed on the main thread and returns immediately.
+ *
+ * @param command command to be executed on the main thread
+ * @param argument additional parameters required to perform of the operation
+ */
+ private void sendRequestAsync(int command, @NonNull Object argument) {
+ Message msg = this.obtainMessage(command, argument);
+ msg.sendToTarget();
+ }
+
+ private void handleNetworkCountryCodeChangedEvent(
+ @NonNull NetworkCountryCodeInfo currentNetworkCountryCodeInfo) {
+ logd("currentNetworkCountryCodeInfo=" + currentNetworkCountryCodeInfo);
+ if (isValid(currentNetworkCountryCodeInfo.countryCode)) {
+ synchronized (mLock) {
+ NetworkCountryCodeInfo cachedNetworkCountryCodeInfo =
+ mNetworkCountryCodeInfoPerPhone.computeIfAbsent(
+ currentNetworkCountryCodeInfo.phoneId,
+ k -> new NetworkCountryCodeInfo());
+ cachedNetworkCountryCodeInfo.phoneId = currentNetworkCountryCodeInfo.phoneId;
+ cachedNetworkCountryCodeInfo.timestamp = getElapsedRealtimeNanos();
+ cachedNetworkCountryCodeInfo.countryCode =
+ currentNetworkCountryCodeInfo.countryCode.toUpperCase(Locale.US);
+ }
+ } else {
+ logd("handleNetworkCountryCodeChangedEvent: Got invalid or empty country code for "
+ + "phoneId=" + currentNetworkCountryCodeInfo.phoneId);
+ synchronized (mLock) {
+ if (mNetworkCountryCodeInfoPerPhone.containsKey(
+ currentNetworkCountryCodeInfo.phoneId)) {
+ // The country code has changed from valid to invalid. Thus, we need to update
+ // the last valid timestamp.
+ NetworkCountryCodeInfo cachedNetworkCountryCodeInfo =
+ mNetworkCountryCodeInfoPerPhone.get(
+ currentNetworkCountryCodeInfo.phoneId);
+ cachedNetworkCountryCodeInfo.timestamp = getElapsedRealtimeNanos();
+ }
+ }
+ }
+ evaluateRequestingLocationUpdates();
+ }
+
+ private void setLocationCountryCode(@NonNull Pair<String, Long> countryCodeInfo) {
+ logd("Set location country code to: " + countryCodeInfo.first);
+ if (!isValid(countryCodeInfo.first)) {
+ logd("Received invalid location country code");
+ } else {
+ synchronized (mLock) {
+ mLocationCountryCode = countryCodeInfo.first.toUpperCase(Locale.US);
+ mLocationCountryCodeUpdatedTimestampNanos = countryCodeInfo.second;
+ }
+ }
+ }
+
+ private String getNetworkCountryIsoForPhone(@NonNull Phone phone) {
+ ServiceStateTracker serviceStateTracker = phone.getServiceStateTracker();
+ if (serviceStateTracker == null) {
+ logw("getNetworkCountryIsoForPhone: serviceStateTracker is null");
+ return null;
+ }
+
+ LocaleTracker localeTracker = serviceStateTracker.getLocaleTracker();
+ if (localeTracker == null) {
+ logw("getNetworkCountryIsoForPhone: localeTracker is null");
+ return null;
+ }
+
+ return localeTracker.getCurrentCountry();
+ }
+
+ private void registerForWifiConnectivityStateChanged() {
+ logd("registerForWifiConnectivityStateChanged");
+ NetworkRequest.Builder builder = new NetworkRequest.Builder();
+ builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+ ConnectivityManager.NetworkCallback networkCallback =
+ new ConnectivityManager.NetworkCallback() {
+ @Override
+ public void onAvailable(Network network) {
+ logd("Wifi network available: " + network);
+ sendRequestAsync(EVENT_WIFI_CONNECTIVITY_STATE_CHANGED, null);
+ }
+
+ @Override
+ public void onLost(Network network) {
+ logd("Wifi network lost: " + network);
+ sendRequestAsync(EVENT_WIFI_CONNECTIVITY_STATE_CHANGED, null);
+ }
+
+ @Override
+ public void onUnavailable() {
+ logd("Wifi network unavailable");
+ sendRequestAsync(EVENT_WIFI_CONNECTIVITY_STATE_CHANGED, null);
+ }
+ };
+ mConnectivityManager.registerNetworkCallback(builder.build(), networkCallback);
+ }
+
+ private void evaluateRequestingLocationUpdates() {
+ if (shouldRequestLocationUpdate()) {
+ registerForLocationUpdates();
+ } else {
+ unregisterForLocationUpdates();
+ }
+ }
+
+ private boolean isWifiNetworkConnected() {
+ Network activeNetwork = mConnectivityManager.getActiveNetwork();
+ NetworkCapabilities networkCapabilities =
+ mConnectivityManager.getNetworkCapabilities(activeNetwork);
+ return networkCapabilities != null
+ && networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
+ && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ }
+
+ /**
+ * Check whether this is a valid country code.
+ *
+ * @param countryCode A 2-Character alphanumeric country code.
+ * @return {@code true} if the countryCode is valid, {@code false} otherwise.
+ */
+ private static boolean isValid(String countryCode) {
+ return countryCode != null && countryCode.length() == 2
+ && countryCode.chars().allMatch(Character::isLetterOrDigit);
+ }
+
+ private static boolean isMockModemAllowed() {
+ return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false)
+ || SystemProperties.getBoolean(BOOT_ALLOW_MOCK_MODEM_PROPERTY, false));
+ }
+
+ private static void logd(@NonNull String log) {
+ Rlog.d(TAG, log);
+ }
+
+ private static void logw(@NonNull String log) {
+ Rlog.w(TAG, log);
+ }
+
+ private static void loge(@NonNull String log) {
+ Rlog.e(TAG, log);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/WapPushCache.java b/src/java/com/android/internal/telephony/WapPushCache.java
new file mode 100644
index 0000000..70d12e2
--- /dev/null
+++ b/src/java/com/android/internal/telephony/WapPushCache.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.annotation.NonNull;
+import android.telephony.Rlog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.NoSuchElementException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Caches WAP push PDU data for retrieval during MMS downloading.
+ * When on a satellite connection, the cached message size will be used to prevent downloading
+ * messages that exceed a threshold.
+ *
+ * The cache uses a circular buffer and will start invalidating the oldest entries after 250
+ * message sizes have been inserted.
+ * The cache also invalidates entries that have been in the cache for over 14 days.
+ */
+public class WapPushCache {
+ private static final String TAG = "WAP PUSH CACHE";
+
+ // Because we store each size twice, this represents 250 messages. That limit is chosen so
+ // that the memory footprint of the cache stays reasonably small while still supporting what
+ // we guess will be the vast majority of real use cases.
+ private static final int MAX_CACHE_SIZE = 500;
+
+ // WAP push PDUs have an expiry property, but we can't be certain that it is set accurately
+ // by the carrier. We will use our own expiry for this cache to keep it small. One example
+ // carrier has an expiry of 7 days so 14 will give us room for those with longer times as well.
+ private static final long CACHE_EXPIRY_TIME = TimeUnit.DAYS.toMillis(14);
+
+ private static final HashMap<String, CacheEntry> sMessageSizes = new LinkedHashMap<>() {
+ @Override
+ protected boolean removeEldestEntry(Entry<String, CacheEntry> eldest) {
+ return size() > MAX_CACHE_SIZE;
+ }
+ };
+
+ @VisibleForTesting
+ public static TelephonyFacade sTelephonyFacade = new TelephonyFacade();
+
+ /**
+ * Puts a WAP push PDU's messageSize in the cache.
+ *
+ * The data is stored twice, once using just locationUrl as the key and once
+ * using transactionId appended to the locationUrl. For some carriers, xMS apps
+ * append the transactionId to the location and we need to support lookup using either the
+ * original location or one modified in this way.
+
+ *
+ * @param locationUrl location of the message used as part of the cache key.
+ * @param transactionId message transaction ID used as part of the cache key.
+ * @param messageSize size of the message to be stored in the cache.
+ */
+ public static void putWapMessageSize(
+ @NonNull byte[] locationUrl,
+ @NonNull byte[] transactionId,
+ long messageSize
+ ) {
+ long expiry = sTelephonyFacade.getElapsedSinceBootMillis() + CACHE_EXPIRY_TIME;
+ if (messageSize <= 0) {
+ Rlog.e(TAG, "Invalid message size of " + messageSize + ". Not inserting.");
+ return;
+ }
+ synchronized (sMessageSizes) {
+ sMessageSizes.put(Arrays.toString(locationUrl), new CacheEntry(messageSize, expiry));
+
+ // concatenate the locationUrl and transactionId
+ byte[] joinedKey = ByteBuffer
+ .allocate(locationUrl.length + transactionId.length)
+ .put(locationUrl)
+ .put(transactionId)
+ .array();
+ sMessageSizes.put(Arrays.toString(joinedKey), new CacheEntry(messageSize, expiry));
+ invalidateOldEntries();
+ }
+ }
+
+ /**
+ * Remove entries from the cache that are older than CACHE_EXPIRY_TIME
+ */
+ private static void invalidateOldEntries() {
+ long currentTime = sTelephonyFacade.getElapsedSinceBootMillis();
+
+ // We can just remove elements from the start until one is found that does not exceed the
+ // expiry since the elements are in order of insertion.
+ for (Iterator<CacheEntry> it = sMessageSizes.values().iterator(); it.hasNext(); ) {
+ CacheEntry entry = it.next();
+ if (entry.mExpiry < currentTime) {
+ it.remove();
+ } else {
+ break;
+ }
+ }
+ }
+
+ /**
+ * Gets the message size of a WAP from the cache.
+ *
+ * Because we stored the size both using the location+transactionId key and using the
+ * location only key, we should be able to find the size whether the xMS app modified
+ * the location or not.
+ *
+ * @param locationUrl the location to use as a key for looking up the size in the cache.
+ *
+ * @return long representing the message size of the WAP
+ * @throws NoSuchElementException if the WAP doesn't exist in the cache
+ * @throws IllegalArgumentException if the locationUrl is empty
+ */
+ public static long getWapMessageSize(@NonNull byte[] locationUrl) {
+ if (locationUrl.length == 0) {
+ throw new IllegalArgumentException("Found empty locationUrl");
+ }
+ CacheEntry entry = sMessageSizes.get(Arrays.toString(locationUrl));
+ if (entry == null) {
+ throw new NoSuchElementException(
+ "No cached WAP size for locationUrl " + Arrays.toString(locationUrl)
+ );
+ }
+ return entry.mSize;
+ }
+
+ /**
+ * Clears all elements from the cache
+ */
+ @VisibleForTesting
+ public static void clear() {
+ sMessageSizes.clear();
+ }
+
+ /**
+ * Returns a count of the number of elements in the cache
+ * @return count of elements
+ */
+ @VisibleForTesting
+ public static int size() {
+ return sMessageSizes.size();
+ }
+
+
+
+ private static class CacheEntry {
+ CacheEntry(long size, long expiry) {
+ mSize = size;
+ mExpiry = expiry;
+ }
+ private final long mSize;
+ private final long mExpiry;
+ }
+}
diff --git a/src/java/com/android/internal/telephony/WapPushOverSms.java b/src/java/com/android/internal/telephony/WapPushOverSms.java
index d6ea4ad..7669411 100644
--- a/src/java/com/android/internal/telephony/WapPushOverSms.java
+++ b/src/java/com/android/internal/telephony/WapPushOverSms.java
@@ -262,6 +262,13 @@
if (parsedPdu != null && parsedPdu.getMessageType() == MESSAGE_TYPE_NOTIFICATION_IND) {
final NotificationInd nInd = (NotificationInd) parsedPdu;
+ // save the WAP push message size so that if a download request is made for it
+ // while on a satellite connection we can check if the size is under the threshold
+ WapPushCache.putWapMessageSize(
+ nInd.getContentLocation(),
+ nInd.getTransactionId(),
+ nInd.getMessageSize()
+ );
if (nInd.getFrom() != null
&& BlockChecker.isBlocked(mContext, nInd.getFrom().getString(), null)) {
result.statusCode = Intents.RESULT_SMS_HANDLED;
diff --git a/src/java/com/android/internal/telephony/analytics/TelephonyAnalytics.java b/src/java/com/android/internal/telephony/analytics/TelephonyAnalytics.java
index d7a70be..e74e40e 100644
--- a/src/java/com/android/internal/telephony/analytics/TelephonyAnalytics.java
+++ b/src/java/com/android/internal/telephony/analytics/TelephonyAnalytics.java
@@ -264,7 +264,11 @@
callType = CallType.NORMAL_CALL.value;
}
if (isOverIms) {
- disconnectCauseString = sImsCodeMap.get(disconnectCause);
+ disconnectCauseString =
+ sImsCodeMap.getOrDefault(disconnectCause, "UNKNOWN_REJECT_CAUSE");
+ if (disconnectCauseString.equals("UNKNOWN_REJECT_CAUSE")) {
+ Rlog.d(TAG, "UNKNOWN_REJECT_CAUSE: " + disconnectCause);
+ }
status =
disconnectCause == ImsReasonInfo.CODE_USER_TERMINATED
|| disconnectCause
diff --git a/src/java/com/android/internal/telephony/cat/CatService.java b/src/java/com/android/internal/telephony/cat/CatService.java
index fa2b19b..cadb02e 100644
--- a/src/java/com/android/internal/telephony/cat/CatService.java
+++ b/src/java/com/android/internal/telephony/cat/CatService.java
@@ -49,6 +49,8 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.ProxyController;
import com.android.internal.telephony.SmsController;
+import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.FeatureFlagsImpl;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.uicc.IccCardStatus.CardState;
import com.android.internal.telephony.uicc.IccFileHandler;
@@ -104,6 +106,8 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private static CatService[] sInstance = null;
@UnsupportedAppUsage
+ private static final FeatureFlags sFlags = new FeatureFlagsImpl();
+ @UnsupportedAppUsage
private CommandsInterface mCmdIf;
@UnsupportedAppUsage
private Context mContext;
@@ -487,7 +491,8 @@
destAddr = ((SendSMSParams) cmdParams).mDestAddress.text;
}
if (text != null && destAddr != null) {
- ProxyController proxyController = ProxyController.getInstance(mContext);
+ ProxyController proxyController = ProxyController
+ .getInstance(mContext, sFlags);
SubscriptionManager subscriptionManager = (SubscriptionManager)
mContext.getSystemService(
Context.TELEPHONY_SUBSCRIPTION_SERVICE);
diff --git a/src/java/com/android/internal/telephony/data/AutoDataSwitchController.java b/src/java/com/android/internal/telephony/data/AutoDataSwitchController.java
index e8cd8f0..8cffe72 100644
--- a/src/java/com/android/internal/telephony/data/AutoDataSwitchController.java
+++ b/src/java/com/android/internal/telephony/data/AutoDataSwitchController.java
@@ -38,6 +38,7 @@
import android.telephony.AccessNetworkConstants;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.NetworkRegistrationInfo.RegistrationState;
+import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -48,6 +49,7 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.FeatureFlagsImpl;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.util.NotificationChannelController;
@@ -126,7 +128,7 @@
private final @NonNull LocalLog mLocalLog = new LocalLog(128);
private final @NonNull Context mContext;
- private final @NonNull FeatureFlags mFlags;
+ private static @NonNull FeatureFlags sFeatureFlags = new FeatureFlagsImpl();
private final @NonNull SubscriptionManagerService mSubscriptionManagerService;
private final @NonNull PhoneSwitcher mPhoneSwitcher;
private final @NonNull AutoDataSwitchControllerCallback mPhoneSwitcherCallback;
@@ -173,7 +175,10 @@
* How preferred the current phone is.
*/
enum UsableState {
- HOME(1), ROAMING_ENABLED(0), NOT_USABLE(-1);
+ HOME(2),
+ ROAMING_ENABLED(1),
+ NON_TERRESTRIAL(0),
+ NOT_USABLE(-1);
/**
* The higher the score, the more preferred.
* HOME is preferred over ROAMING assuming roaming is metered.
@@ -186,8 +191,7 @@
/** The phone */
@NonNull private final Phone mPhone;
/** Data registration state of the phone */
- @RegistrationState private int mDataRegState = NetworkRegistrationInfo
- .REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING;
+ @RegistrationState private int mDataRegState;
/** Current Telephony display info of the phone */
@NonNull private TelephonyDisplayInfo mDisplayInfo;
/** Signal strength of the phone */
@@ -196,6 +200,10 @@
private boolean mListeningForEvents;
private PhoneSignalStatus(@NonNull Phone phone) {
this.mPhone = phone;
+ this.mDataRegState = phone.getServiceState().getNetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_PS,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .getRegistrationState();
this.mDisplayInfo = phone.getDisplayInfoController().getTelephonyDisplayInfo();
this.mSignalStrength = phone.getSignalStrength();
}
@@ -214,12 +222,24 @@
* @return The current usable state of the phone.
*/
private UsableState getUsableState() {
+ ServiceState serviceState = mPhone.getServiceState();
+ boolean isUsingNonTerrestrialNetwork = sFeatureFlags.carrierEnabledSatelliteFlag()
+ && (serviceState != null) && serviceState.isUsingNonTerrestrialNetwork();
+
switch (mDataRegState) {
case NetworkRegistrationInfo.REGISTRATION_STATE_HOME:
+ if (isUsingNonTerrestrialNetwork) {
+ return UsableState.NON_TERRESTRIAL;
+ }
return UsableState.HOME;
case NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING:
- return mPhone.getDataRoamingEnabled()
- ? UsableState.ROAMING_ENABLED : UsableState.NOT_USABLE;
+ if (mPhone.getDataRoamingEnabled()) {
+ if (isUsingNonTerrestrialNetwork) {
+ return UsableState.NON_TERRESTRIAL;
+ }
+ return UsableState.ROAMING_ENABLED;
+ }
+ return UsableState.NOT_USABLE;
default:
return UsableState.NOT_USABLE;
}
@@ -275,7 +295,7 @@
@NonNull AutoDataSwitchControllerCallback phoneSwitcherCallback) {
super(looper);
mContext = context;
- mFlags = featureFlags;
+ sFeatureFlags = featureFlags;
mSubscriptionManagerService = SubscriptionManagerService.getInstance();
mPhoneSwitcher = phoneSwitcher;
mPhoneSwitcherCallback = phoneSwitcherCallback;
@@ -599,7 +619,7 @@
boolean backToDefault = false;
boolean needValidation = true;
- if (mFlags.autoSwitchAllowRoaming()) {
+ if (sFeatureFlags.autoSwitchAllowRoaming()) {
if (mDefaultNetworkIsOnNonCellular) {
debugMessage.append(", back to default as default network")
.append(" is active on nonCellular transport");
@@ -719,7 +739,7 @@
return INVALID_PHONE_INDEX;
}
- if (mFlags.autoSwitchAllowRoaming()) {
+ if (sFeatureFlags.autoSwitchAllowRoaming()) {
// check whether primary and secondary signal status are worth switching
if (!isRatSignalStrengthBasedSwitchEnabled()
&& isHomeService(mPhonesSignalStatus[defaultPhoneId].mDataRegState)) {
@@ -741,7 +761,7 @@
Phone secondaryDataPhone = null;
PhoneSignalStatus candidatePhoneStatus = mPhonesSignalStatus[phoneId];
- if (mFlags.autoSwitchAllowRoaming()) {
+ if (sFeatureFlags.autoSwitchAllowRoaming()) {
PhoneSignalStatus.UsableState currentUsableState =
mPhonesSignalStatus[defaultPhoneId].getUsableState();
PhoneSignalStatus.UsableState candidatePhoneUsableRank =
@@ -811,7 +831,7 @@
* @return {@code true} If the feature of switching base on RAT and signal strength is enabled.
*/
private boolean isRatSignalStrengthBasedSwitchEnabled() {
- return mFlags.autoDataSwitchRatSs() && mScoreTolerance >= 0;
+ return sFeatureFlags.autoDataSwitchRatSs() && mScoreTolerance >= 0;
}
/**
diff --git a/src/java/com/android/internal/telephony/data/DataNetwork.java b/src/java/com/android/internal/telephony/data/DataNetwork.java
index bba0f19..d52a3b4 100644
--- a/src/java/com/android/internal/telephony/data/DataNetwork.java
+++ b/src/java/com/android/internal/telephony/data/DataNetwork.java
@@ -31,6 +31,7 @@
import android.net.NetworkCapabilities;
import android.net.NetworkFactory;
import android.net.NetworkProvider;
+import android.net.NetworkRequest;
import android.net.NetworkScore;
import android.net.ProxyInfo;
import android.net.RouteInfo;
@@ -91,6 +92,7 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.RIL;
+import com.android.internal.telephony.data.AccessNetworksManager.AccessNetworksManagerCallback;
import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback;
import com.android.internal.telephony.data.DataEvaluation.DataAllowedReason;
import com.android.internal.telephony.data.DataNetworkController.NetworkRequestList;
@@ -743,6 +745,11 @@
private @Nullable Consumer<Integer> mNetworkValidationResultCodeCallback;
/**
+ * Callback used to listen QNS preference changes.
+ */
+ private @Nullable AccessNetworksManagerCallback mAccessNetworksManagerCallback;
+
+ /**
* The network bandwidth.
*/
public static class NetworkBandwidth {
@@ -1172,6 +1179,23 @@
getHandler(), EVENT_VOICE_CALL_ENDED, null);
}
+ if (mFlags.forceIwlanMms()) {
+ if (mDataProfile.canSatisfy(NetworkCapabilities.NET_CAPABILITY_MMS)) {
+ mAccessNetworksManagerCallback = new AccessNetworksManagerCallback(
+ getHandler()::post) {
+ @Override
+ public void onPreferredTransportChanged(
+ @NetCapability int networkCapability) {
+ if (networkCapability == NetworkCapabilities.NET_CAPABILITY_MMS) {
+ log("MMS preference changed.");
+ updateNetworkCapabilities();
+ }
+ }
+ };
+ mAccessNetworksManager.registerCallback(mAccessNetworksManagerCallback);
+ }
+ }
+
// Only add symmetric code here, for example, registering and unregistering.
// DefaultState.enter() is the starting point in the life cycle of the DataNetwork,
// and DefaultState.exit() is the end. For non-symmetric initializing works, put them
@@ -1181,6 +1205,10 @@
@Override
public void exit() {
logv("Unregistering all events.");
+ if (mFlags.forceIwlanMms() && mAccessNetworksManagerCallback != null) {
+ mAccessNetworksManager.unregisterCallback(mAccessNetworksManagerCallback);
+ }
+
// Check null for devices not supporting FEATURE_TELEPHONY_IMS.
if (mPhone.getImsPhone() != null) {
mPhone.getImsPhone().getCallTracker().unregisterForVoiceCallStarted(getHandler());
@@ -2333,6 +2361,35 @@
builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
}
+ // Check if the feature force MMS on IWLAN is enabled. When the feature is enabled, MMS
+ // will be attempted on IWLAN if possible, even if existing cellular networks already
+ // supports IWLAN.
+ if (mFlags.forceIwlanMms() && builder.build()
+ .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
+ // If QNS sets MMS preferred on IWLAN, and it is possible to setup an MMS network on
+ // IWLAN, then we need to remove the MMS capability on the cellular network. This will
+ // allow the new MMS network to be brought up on IWLAN when MMS network request arrives.
+ if (mAccessNetworksManager.getPreferredTransportByNetworkCapability(
+ NetworkCapabilities.NET_CAPABILITY_MMS)
+ == AccessNetworkConstants.TRANSPORT_TYPE_WLAN && mTransport
+ == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
+
+ DataProfile dataProfile = mDataNetworkController.getDataProfileManager()
+ .getDataProfileForNetworkRequest(new TelephonyNetworkRequest(
+ new NetworkRequest.Builder().addCapability(
+ NetworkCapabilities.NET_CAPABILITY_MMS).build(), mPhone),
+ TelephonyManager.NETWORK_TYPE_IWLAN, false, false, false);
+ // If we find another data data profile that can support MMS on IWLAN, then remove
+ // the MMS capability from this cellular network. This will allow IWLAN to be
+ // brought up for MMS later.
+ if (dataProfile != null && !dataProfile.equals(mDataProfile)) {
+ log("Found a different data profile " + mDataProfile.getApn()
+ + " that can serve MMS on IWLAN.");
+ builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
+ }
+ }
+ }
+
// If one of the capabilities are for special use, for example, IMS, CBS, then this
// network should be restricted, regardless data is enabled or not.
if (NetworkCapabilitiesUtils.inferRestrictedCapability(builder.build())
@@ -3578,7 +3635,7 @@
mNetworkValidationResultCodeCallback = resultCodeCallback;
// Request validation directly from the data service.
- mDataServiceManagers.get(mTransport).requestValidation(
+ mDataServiceManagers.get(mTransport).requestNetworkValidation(
mCid.get(mTransport), obtainMessage(EVENT_DATA_NETWORK_VALIDATION_RESPONSE));
log("handleDataNetworkValidationRequest, network validation requested");
}
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index 63fe7e5..d16387f 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -1408,22 +1408,26 @@
/**
* Evaluate if telephony frameworks would allow data setup for internet in current environment.
*
+ * @param ignoreExistingNetworks {@code true} to skip the existing network check.
* @return {@code true} if the environment is allowed for internet data. {@code false} if not
* allowed. For example, if SIM is absent, or airplane mode is on, then data is NOT allowed.
* This API does not reflect the currently internet data network status. It's possible there is
* no internet data due to weak cellular signal or network side issue, but internet data is
* still allowed in this case.
*/
- public boolean isInternetDataAllowed() {
+ public boolean isInternetDataAllowed(boolean ignoreExistingNetworks) {
TelephonyNetworkRequest internetRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.build(), mPhone);
- // If one of the existing networks can satisfy the internet request, then internet is
- // allowed.
- if (mDataNetworkList.stream().anyMatch(dataNetwork -> internetRequest.canBeSatisfiedBy(
- dataNetwork.getNetworkCapabilities()))) {
+ // If we don't skip checking existing network, then we should check If one of the
+ // existing networks can satisfy the internet request, then internet is allowed.
+ if ((!mFeatureFlags.ignoreExistingNetworksForInternetAllowedChecking()
+ || !ignoreExistingNetworks)
+ && mDataNetworkList.stream().anyMatch(
+ dataNetwork -> internetRequest.canBeSatisfiedBy(
+ dataNetwork.getNetworkCapabilities()))) {
return true;
}
@@ -3780,6 +3784,11 @@
* de-registered yet.
*/
private boolean isSafeToTearDown(@NonNull DataNetwork dataNetwork) {
+ if (dataNetwork.hasNetworkCapabilityInNetworkRequests(
+ NetworkCapabilities.NET_CAPABILITY_EIMS)) {
+ // FWK currently doesn't track emergency registration state for graceful tear down.
+ return true;
+ }
for (int imsFeature : SUPPORTED_IMS_FEATURES) {
String imsFeaturePackage = mImsFeaturePackageName.get(imsFeature);
if (imsFeaturePackage != null) {
diff --git a/src/java/com/android/internal/telephony/data/DataProfileManager.java b/src/java/com/android/internal/telephony/data/DataProfileManager.java
index b4055a3..0aaae30 100644
--- a/src/java/com/android/internal/telephony/data/DataProfileManager.java
+++ b/src/java/com/android/internal/telephony/data/DataProfileManager.java
@@ -34,6 +34,7 @@
import android.telephony.Annotation.NetworkType;
import android.telephony.AnomalyReporter;
import android.telephony.CarrierConfigManager;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager.SimState;
@@ -818,8 +819,13 @@
})
.collect(Collectors.toList());
if (dataProfiles.size() == 0) {
+ String ntnReason = "";
+ if (mFeatureFlags.carrierEnabledSatelliteFlag()) {
+ ntnReason = " and infrastructure for "
+ + NetworkRegistrationInfo.isNonTerrestrialNetworkToString(isNtn);
+ }
log("Can't find any data profile for network type "
- + TelephonyManager.getNetworkTypeName(networkType));
+ + TelephonyManager.getNetworkTypeName(networkType) + ntnReason);
return null;
}
diff --git a/src/java/com/android/internal/telephony/data/DataServiceManager.java b/src/java/com/android/internal/telephony/data/DataServiceManager.java
index 640399e..ee66a6a 100644
--- a/src/java/com/android/internal/telephony/data/DataServiceManager.java
+++ b/src/java/com/android/internal/telephony/data/DataServiceManager.java
@@ -959,8 +959,8 @@
* @param onCompleteMessage The result message for this request. Null if the client does not
* care about the result.
*/
- public void requestValidation(int cid, @Nullable Message onCompleteMessage) {
- if (DBG) log("requestValidation");
+ public void requestNetworkValidation(int cid, @Nullable Message onCompleteMessage) {
+ if (DBG) log("requestNetworkValidation");
if (!mBound) {
loge("DataService is not bound.");
sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
@@ -978,9 +978,9 @@
mMessageMap.put(callback.asBinder(), onCompleteMessage);
}
try {
- mIDataService.requestValidation(mPhone.getPhoneId(), cid, callback);
+ mIDataService.requestNetworkValidation(mPhone.getPhoneId(), cid, callback);
} catch (RemoteException e) {
- loge("Cannot invoke requestValidation on data service.");
+ loge("Cannot invoke requestNetworkValidation on data service.");
if (callback != null) {
mMessageMap.remove(callback.asBinder());
}
diff --git a/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java b/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java
index f2b6776..893509c 100644
--- a/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java
+++ b/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java
@@ -372,6 +372,7 @@
0) != 0) {
mIsAirPlaneModeEnableDuringDataStall = true;
}
+ setRecoveryAction(mLastAction);
}
break;
case EVENT_CONTENT_DSRM_ENABLED_ACTIONS_CHANGED:
@@ -527,6 +528,7 @@
// during data stalled.
if (mDataStalled && enabled) {
mMobileDataChangedToEnabledDuringDataStall = true;
+ setRecoveryAction(mLastAction);
}
}
@@ -781,7 +783,7 @@
return false;
}
- if (!mDataNetworkController.isInternetDataAllowed()) {
+ if (!mDataNetworkController.isInternetDataAllowed(true/* ignoreExistingNetworks */)) {
logl("skip data stall recovery as data not allowed.");
return false;
}
diff --git a/src/java/com/android/internal/telephony/data/DataUtils.java b/src/java/com/android/internal/telephony/data/DataUtils.java
index 259b482..0dda7b5 100644
--- a/src/java/com/android/internal/telephony/data/DataUtils.java
+++ b/src/java/com/android/internal/telephony/data/DataUtils.java
@@ -93,6 +93,7 @@
case "RCS":
return NetworkCapabilities.NET_CAPABILITY_RCS;
default:
+ loge("Illegal network capability: " + capabilityString);
return -1;
}
}
@@ -108,7 +109,7 @@
public static @NetCapability Set<Integer> getNetworkCapabilitiesFromString(
@NonNull String capabilitiesString) {
// e.g. "IMS|" is not allowed
- if (!capabilitiesString.matches("(\\s*[a-zA-Z]+\\s*)(\\|\\s*[a-zA-Z]+\\s*)*")) {
+ if (!capabilitiesString.matches("(\\s*[a-zA-Z_]+\\s*)(\\|\\s*[a-zA-Z_]+\\s*)*")) {
return Collections.singleton(-1);
}
return Arrays.stream(capabilitiesString.split("\\s*\\|\\s*"))
diff --git a/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java b/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java
index 2cdf807..377c219 100644
--- a/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java
+++ b/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony.data;
+import android.annotation.NonNull;
import android.net.NetworkCapabilities;
import android.net.NetworkFactory;
import android.net.NetworkRequest;
@@ -29,6 +30,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.NetworkRequestsStats;
import com.android.internal.util.IndentingPrintWriter;
import com.android.telephony.Rlog;
@@ -77,11 +79,22 @@
@VisibleForTesting
public final Handler mInternalHandler;
+ private final @NonNull FeatureFlags mFlags;
- public TelephonyNetworkFactory(Looper looper, Phone phone) {
+
+ /**
+ * Constructor
+ *
+ * @param looper The looper for the handler
+ * @param phone The phone instance
+ * @param featureFlags The feature flags
+ */
+ public TelephonyNetworkFactory(@NonNull Looper looper, @NonNull Phone phone,
+ @NonNull FeatureFlags featureFlags) {
super(looper, phone.getContext(), "TelephonyNetworkFactory[" + phone.getPhoneId()
+ "]", null);
mPhone = phone;
+ mFlags = featureFlags;
mInternalHandler = new InternalHandler(looper);
mAccessNetworksManager = mPhone.getAccessNetworksManager();
diff --git a/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java b/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
index f5cf950..c66aebc 100644
--- a/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
+++ b/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
@@ -19,29 +19,33 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.AsyncResult;
-import android.os.CancellationSignal;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.RemoteException;
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.AccessNetworkConstants.RadioAccessNetworkType;
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.Annotation.ApnType;
import android.telephony.Annotation.DisconnectCauses;
+import android.telephony.DisconnectCause;
import android.telephony.DomainSelectionService;
import android.telephony.DomainSelectionService.EmergencyScanType;
import android.telephony.DomainSelector;
import android.telephony.EmergencyRegResult;
import android.telephony.NetworkRegistrationInfo;
-import android.telephony.TransportSelectorCallback;
-import android.telephony.WwanSelectorCallback;
import android.telephony.data.ApnSetting;
import android.util.LocalLog;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.infra.AndroidFuture;
+import com.android.internal.telephony.IDomainSelector;
+import com.android.internal.telephony.ITransportSelectorCallback;
+import com.android.internal.telephony.ITransportSelectorResultCallback;
+import com.android.internal.telephony.IWwanSelectorCallback;
+import com.android.internal.telephony.IWwanSelectorResultCallback;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.data.AccessNetworksManager.QualifiedNetworks;
import com.android.internal.telephony.util.TelephonyUtils;
@@ -49,7 +53,6 @@
import java.io.PrintWriter;
import java.util.List;
import java.util.concurrent.CompletableFuture;
-import java.util.function.Consumer;
/**
@@ -61,6 +64,15 @@
protected static final int EVENT_EMERGENCY_NETWORK_SCAN_RESULT = 1;
protected static final int EVENT_QUALIFIED_NETWORKS_CHANGED = 2;
+ protected static final int EVENT_SERVICE_CONNECTED = 3;
+ protected static final int EVENT_SERVICE_BINDING_TIMEOUT = 4;
+
+ private static final int DEFAULT_BIND_RETRY_TIMEOUT_MS = 4 * 1000;
+
+ private static final int STATUS_DISPOSED = 1 << 0;
+ private static final int STATUS_DOMAIN_SELECTED = 1 << 1;
+ private static final int STATUS_WAIT_BINDING = 1 << 2;
+ private static final int STATUS_WAIT_SCAN_RESULT = 1 << 3;
/** Callback to receive responses from DomainSelectionConnection. */
public interface DomainSelectionConnectionCallback {
@@ -73,14 +85,20 @@
void onSelectionTerminated(@DisconnectCauses int cause);
}
- /** An internal class implementing {@link TransportSelectorCallback} interface. */
- private final class TransportSelectorCallbackWrapper implements TransportSelectorCallback {
+ /**
+ * A wrapper class for {@link ITransportSelectorCallback} interface.
+ */
+ private final class TransportSelectorCallbackAdaptor extends ITransportSelectorCallback.Stub {
@Override
- public void onCreated(@NonNull DomainSelector selector) {
+ public void onCreated(@NonNull IDomainSelector selector) {
synchronized (mLock) {
mDomainSelector = selector;
- if (mDisposed) {
- mDomainSelector.cancelSelection();
+ if (checkState(STATUS_DISPOSED)) {
+ try {
+ selector.cancelSelection();
+ } catch (RemoteException e) {
+ // ignore exception
+ }
return;
}
DomainSelectionConnection.this.onCreated();
@@ -90,18 +108,21 @@
@Override
public void onWlanSelected(boolean useEmergencyPdn) {
synchronized (mLock) {
- if (mDisposed) return;
+ if (checkState(STATUS_DISPOSED)) {
+ return;
+ }
+ setState(STATUS_DOMAIN_SELECTED);
DomainSelectionConnection.this.onWlanSelected(useEmergencyPdn);
}
}
@Override
- public @NonNull WwanSelectorCallback onWwanSelected() {
+ public @NonNull IWwanSelectorCallback onWwanSelected() {
synchronized (mLock) {
if (mWwanSelectorCallback == null) {
- mWwanSelectorCallback = new WwanSelectorCallbackWrapper();
+ mWwanSelectorCallback = new WwanSelectorCallbackAdaptor();
}
- if (mDisposed) {
+ if (checkState(STATUS_DISPOSED)) {
return mWwanSelectorCallback;
}
DomainSelectionConnection.this.onWwanSelected();
@@ -110,18 +131,31 @@
}
@Override
- public void onWwanSelected(final Consumer<WwanSelectorCallback> consumer) {
+ public void onWwanSelectedAsync(@NonNull final ITransportSelectorResultCallback cb) {
synchronized (mLock) {
- if (mDisposed) return;
+ if (checkState(STATUS_DISPOSED)) {
+ return;
+ }
if (mWwanSelectorCallback == null) {
- mWwanSelectorCallback = new WwanSelectorCallbackWrapper();
+ mWwanSelectorCallback = new WwanSelectorCallbackAdaptor();
}
initHandler();
mHandler.post(() -> {
synchronized (mLock) {
- if (mDisposed) return;
+ if (checkState(STATUS_DISPOSED)) {
+ return;
+ }
DomainSelectionConnection.this.onWwanSelected();
- consumer.accept(mWwanSelectorCallback);
+ }
+ try {
+ cb.onCompleted(mWwanSelectorCallback);
+ } catch (RemoteException e) {
+ loge("onWwanSelectedAsync executor exception=" + e);
+ synchronized (mLock) {
+ // Since remote service is not available,
+ // wait for binding or timeout.
+ waitForServiceBinding(null);
+ }
}
});
}
@@ -130,30 +164,33 @@
@Override
public void onSelectionTerminated(int cause) {
synchronized (mLock) {
- if (mDisposed) return;
+ if (checkState(STATUS_DISPOSED)) {
+ return;
+ }
DomainSelectionConnection.this.onSelectionTerminated(cause);
dispose();
}
}
}
- /** An internal class implementing {@link WwanSelectorCallback} interface. */
- private final class WwanSelectorCallbackWrapper
- implements WwanSelectorCallback, CancellationSignal.OnCancelListener {
+ /**
+ * A wrapper class for {@link IWwanSelectorCallback} interface.
+ */
+ private final class WwanSelectorCallbackAdaptor extends IWwanSelectorCallback.Stub {
@Override
- public void onRequestEmergencyNetworkScan(@NonNull List<Integer> preferredNetworks,
- @EmergencyScanType int scanType, @NonNull CancellationSignal signal,
- @NonNull Consumer<EmergencyRegResult> consumer) {
+ public void onRequestEmergencyNetworkScan(
+ @NonNull @RadioAccessNetworkType int[] preferredNetworks,
+ @EmergencyScanType int scanType, @NonNull IWwanSelectorResultCallback cb) {
synchronized (mLock) {
- if (mDisposed) return;
- if (signal != null) signal.setOnCancelListener(this);
- mResultCallback = consumer;
+ if (checkState(STATUS_DISPOSED)) {
+ return;
+ }
+ mResultCallback = cb;
initHandler();
mHandler.post(() -> {
synchronized (mLock) {
DomainSelectionConnection.this.onRequestEmergencyNetworkScan(
- preferredNetworks.stream().mapToInt(Integer::intValue).toArray(),
- scanType);
+ preferredNetworks, scanType);
}
});
}
@@ -163,7 +200,10 @@
public void onDomainSelected(@NetworkRegistrationInfo.Domain int domain,
boolean useEmergencyPdn) {
synchronized (mLock) {
- if (mDisposed) return;
+ if (checkState(STATUS_DISPOSED)) {
+ return;
+ }
+ setState(STATUS_DOMAIN_SELECTED);
DomainSelectionConnection.this.onDomainSelected(domain, useEmergencyPdn);
}
}
@@ -171,7 +211,9 @@
@Override
public void onCancel() {
synchronized (mLock) {
- if (mDisposed || mHandler == null) return;
+ if (checkState(STATUS_DISPOSED) || mHandler == null) {
+ return;
+ }
mHandler.post(() -> {
DomainSelectionConnection.this.onCancel();
});
@@ -189,14 +231,22 @@
AsyncResult ar;
switch (msg.what) {
case EVENT_EMERGENCY_NETWORK_SCAN_RESULT:
- mIsWaitingForScanResult = false;
- if (mResultCallback == null) break;
ar = (AsyncResult) msg.obj;
EmergencyRegResult regResult = (EmergencyRegResult) ar.result;
if (DBG) logd("EVENT_EMERGENCY_NETWORK_SCAN_RESULT result=" + regResult);
- CompletableFuture.runAsync(
- () -> mResultCallback.accept(regResult),
- mController.getDomainSelectionServiceExecutor());
+ synchronized (mLock) {
+ clearState(STATUS_WAIT_SCAN_RESULT);
+ if (mResultCallback != null) {
+ try {
+ mResultCallback.onComplete(regResult);
+ } catch (RemoteException e) {
+ loge("EVENT_EMERGENCY_NETWORK_SCAN_RESULT exception=" + e);
+ // Since remote service is not available,
+ // wait for binding or timeout.
+ waitForServiceBinding(null);
+ }
+ }
+ }
break;
case EVENT_QUALIFIED_NETWORKS_CHANGED:
ar = (AsyncResult) msg.obj;
@@ -206,6 +256,25 @@
}
onQualifiedNetworksChanged((List<QualifiedNetworks>) ar.result);
break;
+ case EVENT_SERVICE_CONNECTED:
+ synchronized (mLock) {
+ if (checkState(STATUS_DISPOSED) || !checkState(STATUS_WAIT_BINDING)) {
+ loge("EVENT_SERVICE_CONNECTED disposed or not waiting for binding");
+ break;
+ }
+ if (mController.selectDomain(mSelectionAttributes,
+ mTransportSelectorCallback)) {
+ clearWaitingForServiceBinding();
+ }
+ }
+ break;
+ case EVENT_SERVICE_BINDING_TIMEOUT:
+ synchronized (mLock) {
+ if (!checkState(STATUS_DISPOSED) && checkState(STATUS_WAIT_BINDING)) {
+ onServiceBindingTimeout();
+ }
+ }
+ break;
default:
loge("handleMessage unexpected msg=" + msg.what);
break;
@@ -215,10 +284,9 @@
protected String mTag = "DomainSelectionConnection";
- private boolean mDisposed = false;
private final Object mLock = new Object();
private final LocalLog mLocalLog = new LocalLog(30);
- private final @NonNull TransportSelectorCallback mTransportSelectorCallback;
+ private final @NonNull ITransportSelectorCallback mTransportSelectorCallback;
/**
* Controls the communication between {@link DomainSelectionConnection} and
@@ -229,11 +297,14 @@
private final boolean mIsEmergency;
/** Interface to receive the request to trigger emergency network scan and selected domain. */
- private @Nullable WwanSelectorCallback mWwanSelectorCallback;
+ private @Nullable IWwanSelectorCallback mWwanSelectorCallback;
/** Interface to return the result of emergency network scan. */
- private @Nullable Consumer<EmergencyRegResult> mResultCallback;
+ private @Nullable IWwanSelectorResultCallback mResultCallback;
/** Interface to the {@link DomainSelector} created for this service. */
- private @Nullable DomainSelector mDomainSelector;
+ private @Nullable IDomainSelector mDomainSelector;
+
+ /** The bit-wise OR of STATUS_* values. */
+ private int mStatus;
/** The slot requested this connection. */
protected @NonNull Phone mPhone;
@@ -246,7 +317,6 @@
private final @NonNull Looper mLooper;
protected @Nullable DomainSelectionConnectionHandler mHandler;
private boolean mRegisteredRegistrant;
- private boolean mIsWaitingForScanResult;
private @NonNull AndroidFuture<Integer> mOnComplete;
@@ -267,7 +337,7 @@
mIsEmergency = isEmergency;
mLooper = Looper.getMainLooper();
- mTransportSelectorCallback = new TransportSelectorCallbackWrapper();
+ mTransportSelectorCallback = new TransportSelectorCallbackAdaptor();
mOnComplete = new AndroidFuture<>();
}
@@ -281,16 +351,24 @@
}
/**
- * Returns the interface for the callbacks.
+ * Returns the callback binder interface.
*
- * @return The {@link TransportSelectorCallback} interface.
+ * @return The {@link ITransportSelectorCallback} interface.
*/
- @VisibleForTesting
- public @NonNull TransportSelectorCallback getTransportSelectorCallback() {
+ public @Nullable ITransportSelectorCallback getTransportSelectorCallback() {
return mTransportSelectorCallback;
}
/**
+ * Returns the callback binder interface to handle the emergency scan result.
+ *
+ * @return The {@link IWwanSelectorResultCallback} interface.
+ */
+ public @Nullable IWwanSelectorResultCallback getEmergencyRegResultCallback() {
+ return mResultCallback;
+ }
+
+ /**
* Returns the {@link CompletableFuture} to receive the selected domain.
*
* @return The callback to receive response.
@@ -309,14 +387,20 @@
}
/**
- * Requests the domain selection servic to select a domain.
+ * Requests the domain selection service to select a domain.
*
* @param attr The attributes required to determine the domain.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
public void selectDomain(@NonNull DomainSelectionService.SelectionAttributes attr) {
- mSelectionAttributes = attr;
- mController.selectDomain(attr, getTransportSelectorCallback());
+ synchronized (mLock) {
+ mSelectionAttributes = attr;
+ if (mController.selectDomain(attr, mTransportSelectorCallback)) {
+ clearWaitingForServiceBinding();
+ } else {
+ waitForServiceBinding(attr);
+ }
+ }
}
/**
@@ -369,16 +453,25 @@
public void onRequestEmergencyNetworkScan(
@NonNull @RadioAccessNetworkType int[] preferredNetworks,
@EmergencyScanType int scanType) {
- if (mHandler == null) return;
-
// Can be overridden if required
- if (!mRegisteredRegistrant) {
- mPhone.registerForEmergencyNetworkScan(mHandler,
- EVENT_EMERGENCY_NETWORK_SCAN_RESULT, null);
- mRegisteredRegistrant = true;
+
+ synchronized (mLock) {
+ if (mHandler == null
+ || checkState(STATUS_DISPOSED)
+ || checkState(STATUS_WAIT_SCAN_RESULT)) {
+ logi("onRequestEmergencyNetworkScan waitResult="
+ + checkState(STATUS_WAIT_SCAN_RESULT));
+ return;
+ }
+
+ if (!mRegisteredRegistrant) {
+ mPhone.registerForEmergencyNetworkScan(mHandler,
+ EVENT_EMERGENCY_NETWORK_SCAN_RESULT, null);
+ mRegisteredRegistrant = true;
+ }
+ setState(STATUS_WAIT_SCAN_RESULT);
+ mPhone.triggerEmergencyNetworkScan(preferredNetworks, scanType, null);
}
- mIsWaitingForScanResult = true;
- mPhone.triggerEmergencyNetworkScan(preferredNetworks, scanType, null);
}
/**
@@ -413,8 +506,8 @@
}
private void onCancel(boolean resetScan) {
- if (mIsWaitingForScanResult) {
- mIsWaitingForScanResult = false;
+ if (checkState(STATUS_WAIT_SCAN_RESULT)) {
+ clearState(STATUS_WAIT_SCAN_RESULT);
mPhone.cancelEmergencyNetworkScan(resetScan, null);
}
}
@@ -425,10 +518,15 @@
*/
public void cancelSelection() {
synchronized (mLock) {
- if (mDomainSelector != null) {
- mDomainSelector.cancelSelection();
+ try {
+ if (mDomainSelector != null) {
+ mDomainSelector.cancelSelection();
+ }
+ } catch (RemoteException e) {
+ loge("cancelSelection exception=" + e);
+ } finally {
+ dispose();
}
- dispose();
}
}
@@ -440,11 +538,31 @@
*/
public @NonNull CompletableFuture<Integer> reselectDomain(
@NonNull DomainSelectionService.SelectionAttributes attr) {
- mSelectionAttributes = attr;
- if (mDomainSelector == null) return null;
- mOnComplete = new AndroidFuture<>();
- mDomainSelector.reselectDomain(attr);
- return mOnComplete;
+ synchronized (mLock) {
+ mSelectionAttributes = attr;
+ mOnComplete = new AndroidFuture<>();
+ clearState(STATUS_DOMAIN_SELECTED);
+ try {
+ if (mDomainSelector == null) {
+ // Service connection has been disconnected.
+ mSelectionAttributes = getSelectionAttributesToRebindService();
+ if (mController.selectDomain(mSelectionAttributes,
+ mTransportSelectorCallback)) {
+ clearWaitingForServiceBinding();
+ } else {
+ waitForServiceBinding(null);
+ }
+ } else {
+ mDomainSelector.reselectDomain(attr);
+ }
+ } catch (RemoteException e) {
+ loge("reselectDomain exception=" + e);
+ // Since remote service is not available, wait for binding or timeout.
+ waitForServiceBinding(null);
+ } finally {
+ return mOnComplete;
+ }
+ }
}
/**
@@ -452,21 +570,102 @@
*/
public void finishSelection() {
synchronized (mLock) {
- if (mDomainSelector != null) {
- mDomainSelector.finishSelection();
+ try {
+ if (mDomainSelector != null) {
+ mDomainSelector.finishSelection();
+ }
+ } catch (RemoteException e) {
+ loge("finishSelection exception=" + e);
+ } finally {
+ dispose();
}
- dispose();
+ }
+ }
+
+ /** Indicates that the service connection has been connected. */
+ public void onServiceConnected() {
+ synchronized (mLock) {
+ if (checkState(STATUS_DISPOSED) || !checkState(STATUS_WAIT_BINDING)) {
+ logi("onServiceConnected disposed or not waiting for the binding");
+ return;
+ }
+ initHandler();
+ mHandler.sendEmptyMessage(EVENT_SERVICE_CONNECTED);
}
}
/** Indicates that the service connection has been removed. */
public void onServiceDisconnected() {
- // Can be overridden.
- dispose();
+ synchronized (mLock) {
+ if (mHandler != null) {
+ mHandler.removeMessages(EVENT_SERVICE_CONNECTED);
+ }
+ if (checkState(STATUS_DISPOSED) || checkState(STATUS_DOMAIN_SELECTED)) {
+ // If there is an on-going dialing, recovery shall happen
+ // when dialing fails and reselectDomain() is called.
+ mDomainSelector = null;
+ mResultCallback = null;
+ return;
+ }
+ // Since remote service is not available, wait for binding or timeout.
+ waitForServiceBinding(null);
+ }
+ }
+
+ private void waitForServiceBinding(DomainSelectionService.SelectionAttributes attr) {
+ if (checkState(STATUS_DISPOSED) || checkState(STATUS_WAIT_BINDING)) {
+ // Already done.
+ return;
+ }
+ setState(STATUS_WAIT_BINDING);
+ mDomainSelector = null;
+ mResultCallback = null;
+ mSelectionAttributes = (attr != null) ? attr : getSelectionAttributesToRebindService();
+ initHandler();
+ mHandler.sendEmptyMessageDelayed(EVENT_SERVICE_BINDING_TIMEOUT,
+ DEFAULT_BIND_RETRY_TIMEOUT_MS);
+ }
+
+ private void clearWaitingForServiceBinding() {
+ if (checkState(STATUS_WAIT_BINDING)) {
+ clearState(STATUS_WAIT_BINDING);
+ if (mHandler != null) {
+ mHandler.removeMessages(EVENT_SERVICE_BINDING_TIMEOUT);
+ }
+ }
+ }
+
+ protected void onServiceBindingTimeout() {
+ // Can be overridden if required
+ synchronized (mLock) {
+ if (checkState(STATUS_DISPOSED)) {
+ logi("onServiceBindingTimeout disposed");
+ return;
+ }
+ DomainSelectionConnection.this.onSelectionTerminated(
+ getTerminationCauseForSelectionTimeout());
+ dispose();
+ }
+ }
+
+ protected int getTerminationCauseForSelectionTimeout() {
+ // Can be overridden if required
+ return DisconnectCause.TIMED_OUT;
+ }
+
+ protected DomainSelectionService.SelectionAttributes
+ getSelectionAttributesToRebindService() {
+ // Can be overridden if required
+ return mSelectionAttributes;
+ }
+
+ /** Returns whether the client is waiting for the service binding. */
+ public boolean isWaitingForServiceBinding() {
+ return checkState(STATUS_WAIT_BINDING) && !checkState(STATUS_DISPOSED);
}
private void dispose() {
- mDisposed = true;
+ setState(STATUS_DISPOSED);
if (mRegisteredRegistrant) {
mPhone.unregisterForEmergencyNetworkScan(mHandler);
mRegisteredRegistrant = false;
@@ -520,6 +719,18 @@
: AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
}
+ private void setState(int stateBit) {
+ mStatus |= stateBit;
+ }
+
+ private void clearState(int stateBit) {
+ mStatus &= ~stateBit;
+ }
+
+ private boolean checkState(int stateBit) {
+ return (mStatus & stateBit) == stateBit;
+ }
+
/**
* Dumps local log.
*/
diff --git a/src/java/com/android/internal/telephony/domainselection/DomainSelectionController.java b/src/java/com/android/internal/telephony/domainselection/DomainSelectionController.java
index 52c9960..6d64a31 100644
--- a/src/java/com/android/internal/telephony/domainselection/DomainSelectionController.java
+++ b/src/java/com/android/internal/telephony/domainselection/DomainSelectionController.java
@@ -21,27 +21,33 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.RemoteException;
import android.telephony.BarringInfo;
import android.telephony.DomainSelectionService;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
-import android.telephony.TransportSelectorCallback;
import android.util.LocalLog;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.ExponentialBackoff;
+import com.android.internal.telephony.IDomainSelectionServiceController;
+import com.android.internal.telephony.ITransportSelectorCallback;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.util.TelephonyUtils;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.concurrent.Executor;
/**
* Manages the connection to {@link DomainSelectionService}.
@@ -53,10 +59,30 @@
private static final int EVENT_SERVICE_STATE_CHANGED = 1;
private static final int EVENT_BARRING_INFO_CHANGED = 2;
+ private static final int BIND_START_DELAY_MS = 2 * 1000; // 2 seconds
+ private static final int BIND_MAXIMUM_DELAY_MS = 60 * 1000; // 1 minute
+
+ /**
+ * Returns the currently defined rebind retry timeout. Used for testing.
+ */
+ @VisibleForTesting
+ public interface BindRetry {
+ /**
+ * Returns a long in milliseconds indicating how long the DomainSelectionController
+ * should wait before rebinding for the first time.
+ */
+ long getStartDelay();
+
+ /**
+ * Returns a long in milliseconds indicating the maximum time the DomainSelectionController
+ * should wait before rebinding.
+ */
+ long getMaximumDelay();
+ }
+
private final HandlerThread mHandlerThread =
new HandlerThread("DomainSelectionControllerHandler");
- private final DomainSelectionService mDomainSelectionService;
private final Handler mHandler;
// Only added or removed, never accessed on purpose.
private final LocalLog mLocalLog = new LocalLog(30);
@@ -67,6 +93,122 @@
protected final int[] mConnectionCounts;
private final ArrayList<DomainSelectionConnection> mConnections = new ArrayList<>();
+ private ComponentName mComponentName;
+ private DomainSelectionServiceConnection mServiceConnection;
+ private IDomainSelectionServiceController mIServiceController;
+ // Binding the service is in progress or the service is bound already.
+ private boolean mIsBound = false;
+
+ private ExponentialBackoff mBackoff;
+ private boolean mBackoffStarted = false;
+
+ // Retry the bind to the DomainSelectionService that has died after mBindRetry timeout.
+ private Runnable mRestartBindingRunnable = new Runnable() {
+ @Override
+ public void run() {
+ bind();
+ }
+ };
+
+ private BindRetry mBindRetry = new BindRetry() {
+ @Override
+ public long getStartDelay() {
+ return BIND_START_DELAY_MS;
+ }
+
+ @Override
+ public long getMaximumDelay() {
+ return BIND_MAXIMUM_DELAY_MS;
+ }
+ };
+
+ private class DomainSelectionServiceConnection implements ServiceConnection {
+ // 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;
+
+ /** {@inheritDoc} */
+ @Override
+ public void onServiceConnected(ComponentName unusedName, IBinder service) {
+ if (mHandler.getLooper().isCurrentThread()) {
+ onServiceConnectedInternal(service);
+ } else {
+ mHandler.post(() -> onServiceConnectedInternal(service));
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onServiceDisconnected(ComponentName unusedName) {
+ if (mHandler.getLooper().isCurrentThread()) {
+ onServiceDisconnectedInternal();
+ } else {
+ mHandler.post(() -> onServiceDisconnectedInternal());
+ }
+ }
+
+ @Override
+ public void onBindingDied(ComponentName unusedName) {
+ if (mHandler.getLooper().isCurrentThread()) {
+ onBindingDiedInternal();
+ } else {
+ mHandler.post(() -> onBindingDiedInternal());
+ }
+ }
+
+ @Override
+ public void onNullBinding(ComponentName unusedName) {
+ if (mHandler.getLooper().isCurrentThread()) {
+ onNullBindingInternal();
+ } else {
+ mHandler.post(() -> onNullBindingInternal());
+ }
+ }
+
+ private void onServiceConnectedInternal(IBinder service) {
+ synchronized (mLock) {
+ stopBackoffTimer();
+ logi("onServiceConnected with binder: " + service);
+ setServiceController(service);
+ }
+ notifyServiceConnected();
+ }
+
+ private void onServiceDisconnectedInternal() {
+ synchronized (mLock) {
+ setServiceController(null);
+ }
+ logi("onServiceDisconnected");
+ notifyServiceDisconnected();
+ }
+
+ private void onBindingDiedInternal() {
+ mIsServiceConnectionDead = true;
+ synchronized (mLock) {
+ mIsBound = false;
+ setServiceController(null);
+ unbindService();
+ notifyBindFailure();
+ }
+ loge("onBindingDied starting retrying in "
+ + mBackoff.getCurrentDelay() + " mS");
+ notifyServiceDisconnected();
+ }
+
+ private void onNullBindingInternal() {
+ loge("onNullBinding serviceDead=" + mIsServiceConnectionDead);
+ // onNullBinding will happen after onBindingDied. In this case, we should not
+ // permanently unbind and instead let the automatic rebind occur.
+ if (mIsServiceConnectionDead) return;
+ synchronized (mLock) {
+ mIsBound = false;
+ setServiceController(null);
+ unbindService();
+ }
+ notifyServiceDisconnected();
+ }
+ }
+
private final class DomainSelectionControllerHandler extends Handler {
DomainSelectionControllerHandler(Looper looper) {
super(looper);
@@ -95,25 +237,22 @@
* Creates an instance.
*
* @param context Context object from hosting application.
- * @param service The {@link DomainSelectionService} instance.
*/
- public DomainSelectionController(@NonNull Context context,
- @NonNull DomainSelectionService service) {
- this(context, service, null);
+ public DomainSelectionController(@NonNull Context context) {
+ this(context, null, null);
}
/**
* Creates an instance.
*
* @param context Context object from hosting application.
- * @param service The {@link DomainSelectionService} instance.
* @param looper Handles event messages.
+ * @param bindRetry The {@link BindRetry} instance.
*/
@VisibleForTesting
public DomainSelectionController(@NonNull Context context,
- @NonNull DomainSelectionService service, @Nullable Looper looper) {
+ @Nullable Looper looper, @Nullable BindRetry bindRetry) {
mContext = context;
- mDomainSelectionService = service;
if (looper == null) {
mHandlerThread.start();
@@ -121,6 +260,16 @@
}
mHandler = new DomainSelectionControllerHandler(looper);
+ if (bindRetry != null) {
+ mBindRetry = bindRetry;
+ }
+ mBackoff = new ExponentialBackoff(
+ mBindRetry.getStartDelay(),
+ mBindRetry.getMaximumDelay(),
+ 2, /* multiplier */
+ mHandler,
+ mRestartBindingRunnable);
+
int numPhones = TelephonyManager.getDefault().getActiveModemCount();
mConnectionCounts = new int[numPhones];
for (int i = 0; i < numPhones; i++) {
@@ -181,14 +330,24 @@
*
* @param attr Attributetes required to determine the domain.
* @param callback A callback to receive the response.
+ * @return {@code true} if it requested successfully, otherwise {@code false}.
*/
- public void selectDomain(@NonNull DomainSelectionService.SelectionAttributes attr,
- @NonNull TransportSelectorCallback callback) {
- if (attr == null || callback == null) return;
+ public boolean selectDomain(@NonNull DomainSelectionService.SelectionAttributes attr,
+ @NonNull ITransportSelectorCallback callback) {
+ if (attr == null) return false;
if (DBG) logd("selectDomain");
- Executor e = mDomainSelectionService.getCachedExecutor();
- e.execute(() -> mDomainSelectionService.onDomainSelection(attr, callback));
+ synchronized (mLock) {
+ try {
+ if (mIServiceController != null) {
+ mIServiceController.selectDomain(attr, callback);
+ return true;
+ }
+ } catch (RemoteException e) {
+ loge("selectDomain e=" + e);
+ }
+ }
+ return false;
}
/**
@@ -201,9 +360,16 @@
if (phone == null || serviceState == null) return;
if (DBG) logd("updateServiceState phoneId=" + phone.getPhoneId());
- Executor e = mDomainSelectionService.getCachedExecutor();
- e.execute(() -> mDomainSelectionService.onServiceStateUpdated(
- phone.getPhoneId(), phone.getSubId(), serviceState));
+ synchronized (mLock) {
+ try {
+ if (mIServiceController != null) {
+ mIServiceController.updateServiceState(
+ phone.getPhoneId(), phone.getSubId(), serviceState);
+ }
+ } catch (RemoteException e) {
+ loge("updateServiceState e=" + e);
+ }
+ }
}
/**
@@ -216,9 +382,16 @@
if (phone == null || info == null) return;
if (DBG) logd("updateBarringInfo phoneId=" + phone.getPhoneId());
- Executor e = mDomainSelectionService.getCachedExecutor();
- e.execute(() -> mDomainSelectionService.onBarringInfoUpdated(
- phone.getPhoneId(), phone.getSubId(), info));
+ synchronized (mLock) {
+ try {
+ if (mIServiceController != null) {
+ mIServiceController.updateBarringInfo(
+ phone.getPhoneId(), phone.getSubId(), info);
+ }
+ } catch (RemoteException e) {
+ loge("updateBarringInfo e=" + e);
+ }
+ }
}
/**
@@ -260,6 +433,19 @@
/**
* Notifies the {@link DomainSelectionConnection} instances registered
+ * of the service connection.
+ */
+ private void notifyServiceConnected() {
+ for (DomainSelectionConnection c : mConnections) {
+ c.onServiceConnected();
+ Phone phone = c.getPhone();
+ updateServiceState(phone, phone.getServiceStateTracker().getServiceState());
+ updateBarringInfo(phone, phone.mCi.getLastBarringInfo());
+ }
+ }
+
+ /**
+ * Notifies the {@link DomainSelectionConnection} instances registered
* of the service disconnection.
*/
private void notifyServiceDisconnected() {
@@ -269,11 +455,115 @@
}
/**
- * Gets the {@link Executor} which executes methods of {@link DomainSelectionService.}
- * @return {@link Executor} instance.
+ * Sets the binder interface to communicate with {@link domainSelectionService}.
*/
- public @NonNull Executor getDomainSelectionServiceExecutor() {
- return mDomainSelectionService.getCachedExecutor();
+ protected void setServiceController(@NonNull IBinder serviceController) {
+ mIServiceController = IDomainSelectionServiceController.Stub.asInterface(serviceController);
+ }
+
+ /**
+ * Sends request to bind to {@link DomainSelectionService}.
+ *
+ * @param componentName The {@link ComponentName} instance.
+ * @return {@code true} if the service is in the process of being bound, {@code false} if it
+ * has failed.
+ */
+ public boolean bind(@NonNull ComponentName componentName) {
+ mComponentName = componentName;
+ return bind();
+ }
+
+ private boolean bind() {
+ logd("bind isBindingOrBound=" + mIsBound);
+ synchronized (mLock) {
+ if (!mIsBound) {
+ mIsBound = true;
+ Intent serviceIntent = new Intent(DomainSelectionService.SERVICE_INTERFACE)
+ .setComponent(mComponentName);
+ mServiceConnection = new DomainSelectionServiceConnection();
+ int serviceFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
+ | Context.BIND_IMPORTANT;
+ logi("binding DomainSelectionService");
+ try {
+ boolean bindSucceeded = mContext.bindService(serviceIntent,
+ mServiceConnection, serviceFlags);
+ if (!bindSucceeded) {
+ loge("binding failed retrying in "
+ + mBackoff.getCurrentDelay() + " mS");
+ mIsBound = false;
+ notifyBindFailure();
+ }
+ return bindSucceeded;
+ } catch (Exception e) {
+ mIsBound = false;
+ notifyBindFailure();
+ loge("binding e=" + e.getMessage() + ", retrying in "
+ + mBackoff.getCurrentDelay() + " mS");
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Unbinds the service.
+ */
+ public void unbind() {
+ synchronized (mLock) {
+ stopBackoffTimer();
+ mIsBound = false;
+ setServiceController(null);
+ unbindService();
+ }
+ }
+
+ private void unbindService() {
+ synchronized (mLock) {
+ if (mServiceConnection != null) {
+ logi("unbinding Service");
+ mContext.unbindService(mServiceConnection);
+ mServiceConnection = null;
+ }
+ }
+ }
+
+ /**
+ * Gets the current delay to rebind service.
+ */
+ @VisibleForTesting
+ public long getBindDelay() {
+ return mBackoff.getCurrentDelay();
+ }
+
+ /**
+ * Stops backoff timer.
+ */
+ @VisibleForTesting
+ public void stopBackoffTimer() {
+ logi("stopBackoffTimer " + mBackoffStarted);
+ mBackoffStarted = false;
+ mBackoff.stop();
+ }
+
+ private void notifyBindFailure() {
+ logi("notifyBindFailure " + mBackoffStarted);
+ if (mBackoffStarted) {
+ mBackoff.notifyFailed();
+ } else {
+ mBackoffStarted = true;
+ mBackoff.start();
+ }
+ logi("notifyBindFailure currentDelay=" + getBindDelay());
+ }
+
+ /**
+ * Returns the Handler instance.
+ */
+ @VisibleForTesting
+ public Handler getHandlerForTest() {
+ return mHandler;
}
/**
diff --git a/src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java b/src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java
index 65ac8b3..3a109e1 100644
--- a/src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java
+++ b/src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java
@@ -22,8 +22,11 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.ComponentName;
import android.content.Context;
+import android.os.SystemProperties;
import android.telephony.DomainSelectionService;
+import android.text.TextUtils;
import android.util.IndentingPrintWriter;
import android.util.LocalLog;
import android.util.Log;
@@ -31,6 +34,8 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.flags.Flags;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -42,19 +47,27 @@
* selector.
*/
public class DomainSelectionResolver {
+ @VisibleForTesting
+ protected static final String PACKAGE_NAME_NONE = "none";
private static final String TAG = DomainSelectionResolver.class.getSimpleName();
+ private static final boolean DBG = TelephonyUtils.IS_DEBUGGABLE;
+ /** For test purpose only with userdebug release */
+ private static final String PROP_DISABLE_DOMAIN_SELECTION =
+ "telephony.test.disable_domain_selection";
private static DomainSelectionResolver sInstance = null;
/**
* Creates the DomainSelectionResolver singleton instance.
*
* @param context The context of the application.
- * @param deviceConfigEnabled The flag to indicate whether or not the device supports
- * the domain selection service or not.
+ * @param flattenedComponentName A flattened component name for the domain selection service
+ * to be bound to the domain selection controller.
*/
- public static void make(Context context, boolean deviceConfigEnabled) {
+ public static void make(Context context, String flattenedComponentName) {
+ Log.i(TAG, "make flag=" + Flags.apDomainSelectionEnabled()
+ + ", useOem=" + Flags.useOemDomainSelectionService());
if (sInstance == null) {
- sInstance = new DomainSelectionResolver(context, deviceConfigEnabled);
+ sInstance = new DomainSelectionResolver(context, flattenedComponentName);
}
}
@@ -86,34 +99,33 @@
@VisibleForTesting
public interface DomainSelectionControllerFactory {
/**
- * Returns a {@link DomainSelectionController} created using the specified
- * context and {@link DomainSelectionService} instance.
+ * Returns a {@link DomainSelectionController} created using the specified context.
*/
- DomainSelectionController create(@NonNull Context context,
- @NonNull DomainSelectionService service);
+ DomainSelectionController create(@NonNull Context context);
}
private DomainSelectionControllerFactory mDomainSelectionControllerFactory =
new DomainSelectionControllerFactory() {
- @Override
- public DomainSelectionController create(@NonNull Context context,
- @NonNull DomainSelectionService service) {
- return new DomainSelectionController(context, service);
- }
- };
+ @Override
+ public DomainSelectionController create(@NonNull Context context) {
+ return new DomainSelectionController(context);
+ }
+ };
// Persistent Logging
private final LocalLog mEventLog = new LocalLog(10);
private final Context mContext;
- // The flag to indicate whether the device supports the domain selection service or not.
- private final boolean mDeviceConfigEnabled;
+ // Stores the default component name to bind the domain selection service so that
+ // the test can override this component name with their own domain selection service.
+ private final ComponentName mDefaultComponentName;
// DomainSelectionController, which are bound to DomainSelectionService.
private DomainSelectionController mController;
- public DomainSelectionResolver(Context context, boolean deviceConfigEnabled) {
+ public DomainSelectionResolver(Context context, String flattenedComponentName) {
mContext = context;
- mDeviceConfigEnabled = deviceConfigEnabled;
- logi("DomainSelectionResolver created: device-config=" + deviceConfigEnabled);
+ flattenedComponentName = (flattenedComponentName == null) ? "" : flattenedComponentName;
+ mDefaultComponentName = ComponentName.unflattenFromString(flattenedComponentName);
+ logi("DomainSelectionResolver created: componentName=[" + flattenedComponentName + "]");
}
/**
@@ -126,7 +138,11 @@
* {@code false} otherwise.
*/
public boolean isDomainSelectionSupported() {
- return mDeviceConfigEnabled && PhoneFactory.getDefaultPhone()
+ if (DBG && SystemProperties.getBoolean(PROP_DISABLE_DOMAIN_SELECTION, false)) {
+ logi("Disabled for test");
+ return false;
+ }
+ return mDefaultComponentName != null && PhoneFactory.getDefaultPhone()
.getHalVersion(HAL_SERVICE_NETWORK).greaterOrEqual(RADIO_HAL_VERSION_2_1);
}
@@ -171,14 +187,62 @@
}
/**
- * Needs to be called after the constructor to create a {@link DomainSelectionController} that
- * is bound to the given {@link DomainSelectionService}.
- *
- * @param service A {@link DomainSelectionService} to be bound.
+ * Creates the {@link DomainSelectionController} and requests the domain selection controller
+ * to bind to the {@link DomainSelectionService} with the component name.
*/
- public void initialize(@NonNull DomainSelectionService service) {
- logi("Initialize.");
- mController = mDomainSelectionControllerFactory.create(mContext, service);
+ public void initialize() {
+ logi("Initialize");
+ mController = mDomainSelectionControllerFactory.create(mContext);
+ if (mDefaultComponentName != null) {
+ mController.bind(mDefaultComponentName);
+ } else {
+ logi("No component name specified for domain selection service.");
+ }
+ }
+
+ /**
+ * Sets the component name of domain selection service to be bound.
+ *
+ * NOTE: This should only be used for testing.
+ *
+ * @return {@code true} if the requested operation is successfully done,
+ * {@code false} otherwise.
+ */
+ @VisibleForTesting
+ public boolean setDomainSelectionServiceOverride(@NonNull ComponentName componentName) {
+ if (mController == null) {
+ logd("Controller is not initialized.");
+ return false;
+ }
+ logi("setDomainSelectionServiceOverride: " + componentName);
+ if (TextUtils.isEmpty(componentName.getPackageName())
+ || TextUtils.equals(PACKAGE_NAME_NONE, componentName.getPackageName())) {
+ // Unbind the active service connection to the domain selection service.
+ mController.unbind();
+ return true;
+ }
+ // Override the domain selection service with the given component name.
+ return mController.bind(componentName);
+ }
+
+ /**
+ * Clears the overridden domain selection service and restores the domain selection service
+ * with the default component.
+ *
+ * NOTE: This should only be used for testing.
+ *
+ * @return {@code true} if the requested operation is successfully done,
+ * {@code false} otherwise.
+ */
+ @VisibleForTesting
+ public boolean clearDomainSelectionServiceOverride() {
+ if (mController == null) {
+ logd("Controller is not initialized.");
+ return false;
+ }
+ logi("clearDomainSelectionServiceOverride");
+ mController.unbind();
+ return mController.bind(mDefaultComponentName);
}
/**
@@ -205,6 +269,10 @@
ipw.decreaseIndent();
}
+ private void logd(String s) {
+ Log.d(TAG, s);
+ }
+
private void logi(String s) {
Log.i(TAG, s);
mEventLog.log(s);
diff --git a/src/java/com/android/internal/telephony/domainselection/EmergencyCallDomainSelectionConnection.java b/src/java/com/android/internal/telephony/domainselection/EmergencyCallDomainSelectionConnection.java
index c397788..b64c7cb 100644
--- a/src/java/com/android/internal/telephony/domainselection/EmergencyCallDomainSelectionConnection.java
+++ b/src/java/com/android/internal/telephony/domainselection/EmergencyCallDomainSelectionConnection.java
@@ -28,6 +28,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.Annotation.DisconnectCauses;
import android.telephony.Annotation.NetCapability;
@@ -224,4 +225,24 @@
return builder.build();
}
+
+ @Override
+ protected DomainSelectionService.SelectionAttributes
+ getSelectionAttributesToRebindService() {
+ DomainSelectionService.SelectionAttributes attr = getSelectionAttributes();
+ if (attr == null) return null;
+ DomainSelectionService.SelectionAttributes.Builder builder =
+ new DomainSelectionService.SelectionAttributes.Builder(
+ attr.getSlotId(), attr.getSubId(), SELECTOR_TYPE_CALLING)
+ .setCallId(attr.getCallId())
+ .setNumber(attr.getNumber())
+ .setVideoCall(attr.isVideoCall())
+ .setEmergency(true)
+ .setExitedFromAirplaneMode(attr.isExitedFromAirplaneMode())
+ .setEmergencyRegResult(new EmergencyRegResult(AccessNetworkType.UNKNOWN,
+ NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN,
+ NetworkRegistrationInfo.DOMAIN_UNKNOWN, false, false, 0, 0,
+ "", "", ""));
+ return builder.build();
+ }
}
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
index 0692f7d..85d79ed 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
@@ -84,7 +84,9 @@
* Timeout before we continue with the emergency call without waiting for DDS switch response
* from the modem.
*/
- private static final int DEFAULT_DATA_SWITCH_TIMEOUT_MS = 1000;
+ private static final int DEFAULT_DATA_SWITCH_TIMEOUT_MS = 1 * 1000;
+ @VisibleForTesting
+ public static final int DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS = 3 * 1000;
/** Default value for if Emergency Callback Mode is supported. */
private static final boolean DEFAULT_EMERGENCY_CALLBACK_MODE_SUPPORTED = true;
/** Default Emergency Callback Mode exit timeout value. */
@@ -512,6 +514,17 @@
if (isSamePhone(mPhone, phone) && (!mActiveEmergencyCalls.isEmpty() || isInEcm())) {
mOngoingCallId = callId;
mIsTestEmergencyNumber = isTestEmergencyNumber;
+ // Ensure that domain selector requests scan.
+ mLastEmergencyRegResult = new EmergencyRegResult(
+ AccessNetworkConstants.AccessNetworkType.UNKNOWN,
+ NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN,
+ NetworkRegistrationInfo.DOMAIN_UNKNOWN, false, false, 0, 0, "", "", "");
+ if (isInEcm()) {
+ // Remove pending exit ECM runnable.
+ mHandler.removeCallbacks(mExitEcmRunnable);
+ releaseWakeLock();
+ ((GsmCdmaPhone) mPhone).notifyEcbmTimerReset(Boolean.TRUE);
+ }
return CompletableFuture.completedFuture(DisconnectCause.NOT_DISCONNECTED);
}
@@ -578,8 +591,7 @@
// If the emergency call was initiated during the emergency callback mode,
// the emergency callback mode should be restored when the emergency call is ended.
if (mActiveEmergencyCalls.isEmpty()) {
- setEmergencyMode(mPhone, EMERGENCY_TYPE_CALL, MODE_EMERGENCY_CALLBACK,
- MSG_SET_EMERGENCY_CALLBACK_MODE_DONE);
+ enterEmergencyCallbackMode();
}
} else {
exitEmergencyMode(mPhone, EMERGENCY_TYPE_CALL, false);
@@ -960,20 +972,23 @@
// ECBM (see ImsPhone#handleEnterEmergencyCallbackMode)
((GsmCdmaPhone) mPhone).notifyEmergencyCallRegistrants(true);
}
-
- // Set emergency mode on modem.
- setEmergencyMode(mPhone, EMERGENCY_TYPE_CALL, MODE_EMERGENCY_CALLBACK,
- MSG_SET_EMERGENCY_CALLBACK_MODE_DONE);
-
- // Post this runnable so we will automatically exit if no one invokes
- // exitEmergencyCallbackMode() directly.
- long delayInMillis = TelephonyProperties.ecm_exit_timer()
- .orElse(mEcmExitTimeoutMs);
- mHandler.postDelayed(mExitEcmRunnable, delayInMillis);
-
- // We don't want to go to sleep while in ECM.
- if (mWakeLock != null) mWakeLock.acquire(delayInMillis);
+ } else {
+ // Inform to reset the ECBM timer.
+ ((GsmCdmaPhone) mPhone).notifyEcbmTimerReset(Boolean.FALSE);
}
+
+ // Set emergency mode on modem.
+ setEmergencyMode(mPhone, EMERGENCY_TYPE_CALL, MODE_EMERGENCY_CALLBACK,
+ MSG_SET_EMERGENCY_CALLBACK_MODE_DONE);
+
+ // Post this runnable so we will automatically exit if no one invokes
+ // exitEmergencyCallbackMode() directly.
+ long delayInMillis = TelephonyProperties.ecm_exit_timer()
+ .orElse(mEcmExitTimeoutMs);
+ mHandler.postDelayed(mExitEcmRunnable, delayInMillis);
+
+ // We don't want to go to sleep while in ECM.
+ if (mWakeLock != null) mWakeLock.acquire(delayInMillis);
}
/**
@@ -991,14 +1006,7 @@
}
// Release wakeLock.
- if (mWakeLock != null && mWakeLock.isHeld()) {
- try {
- mWakeLock.release();
- } catch (Exception e) {
- // Ignore the exception if the system has already released this WakeLock.
- Rlog.d(TAG, "WakeLock already released: " + e.toString());
- }
- }
+ releaseWakeLock();
GsmCdmaPhone gsmCdmaPhone = (GsmCdmaPhone) mPhone;
// Send intents that ECM has changed.
@@ -1016,6 +1024,18 @@
mPhone = null;
}
+ private void releaseWakeLock() {
+ // Release wakeLock.
+ if (mWakeLock != null && mWakeLock.isHeld()) {
+ try {
+ mWakeLock.release();
+ } catch (Exception e) {
+ // Ignore the exception if the system has already released this WakeLock.
+ Rlog.d(TAG, "WakeLock already released: " + e.toString());
+ }
+ }
+ }
+
/**
* Exits emergency callback mode and triggers runnable after exit response is received.
*/
@@ -1209,6 +1229,11 @@
mRadioOnHelper = new RadioOnHelper(mContext);
}
+ final Phone phoneForEmergency = phone;
+ final String expectedCallId = mOngoingCallId;
+ final int waitForInServiceTimeout =
+ needToTurnOnRadio ? DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS : 0;
+ Rlog.i(TAG, "turnOnRadioAndSwitchDds: timeout=" + waitForInServiceTimeout);
mRadioOnHelper.triggerRadioOnAndListen(new RadioOnStateListener.Callback() {
@Override
public void onComplete(RadioOnStateListener listener, boolean isRadioReady) {
@@ -1223,25 +1248,33 @@
completeEmergencyMode(emergencyType, DisconnectCause.POWER_OFF);
}
} else {
+ if (!Objects.equals(mOngoingCallId, expectedCallId)) {
+ Rlog.i(TAG, "onComplete " + expectedCallId + " canceled.");
+ return;
+ }
switchDdsAndSetEmergencyMode(phone, emergencyType);
}
}
@Override
public boolean isOkToCall(Phone phone, int serviceState, boolean imsVoiceCapable) {
- // We currently only look to make sure that the radio is on before dialing. We
- // should be able to make emergency calls at any time after the radio has been
- // powered on and isn't in the UNAVAILABLE state, even if it is reporting the
- // OUT_OF_SERVICE state.
+ // Wait for normal service state or timeout if required.
+ if (phone == phoneForEmergency
+ && waitForInServiceTimeout > 0
+ && !isNetworkRegistered(phone)) {
+ return false;
+ }
return phone.getServiceStateTracker().isRadioOn()
&& !satelliteController.isSatelliteEnabled();
}
@Override
public boolean onTimeout(Phone phone, int serviceState, boolean imsVoiceCapable) {
- return true;
+ // onTimeout shall be called only with the Phone for emergency
+ return phone.getServiceStateTracker().isRadioOn()
+ && !satelliteController.isSatelliteEnabled();
}
- }, !isTestEmergencyNumber, phone, isTestEmergencyNumber, 0);
+ }, !isTestEmergencyNumber, phone, isTestEmergencyNumber, waitForInServiceTimeout);
} else {
switchDdsAndSetEmergencyMode(phone, emergencyType);
}
@@ -1394,6 +1427,27 @@
|| phone.getServiceState().isEmergencyOnly();
}
+ private static boolean isNetworkRegistered(Phone phone) {
+ ServiceState ss = phone.getServiceStateTracker().getServiceState();
+ if (ss != null) {
+ NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_PS,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+ if (nri != null && nri.isNetworkRegistered()) {
+ // PS is IN_SERVICE state.
+ return true;
+ }
+ nri = ss.getNetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_CS,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+ if (nri != null && nri.isNetworkRegistered()) {
+ // CS is IN_SERVICE state.
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Checks whether both {@code Phone}s are same or not.
*/
diff --git a/src/java/com/android/internal/telephony/emergency/RadioOnHelper.java b/src/java/com/android/internal/telephony/emergency/RadioOnHelper.java
index 9c4ebfa..384112d 100644
--- a/src/java/com/android/internal/telephony/emergency/RadioOnHelper.java
+++ b/src/java/com/android/internal/telephony/emergency/RadioOnHelper.java
@@ -96,7 +96,7 @@
continue;
}
- int timeoutCallbackInterval = (forEmergencyCall && phone == phoneForEmergencyCall)
+ int timeoutCallbackInterval = (phone == phoneForEmergencyCall)
? emergencyTimeoutIntervalMillis : 0;
mInProgressListeners.add(mListeners.get(i));
mListeners.get(i).waitForRadioOn(phone, this, forEmergencyCall, forEmergencyCall
diff --git a/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java b/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
index d61c146..5949f66 100644
--- a/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
+++ b/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
@@ -22,7 +22,7 @@
import android.os.Message;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
-import android.telephony.satellite.ISatelliteStateCallback;
+import android.telephony.satellite.ISatelliteModemStateCallback;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
@@ -142,7 +142,8 @@
}
};
- private final ISatelliteStateCallback mSatelliteCallback = new ISatelliteStateCallback.Stub() {
+ private final ISatelliteModemStateCallback mSatelliteCallback =
+ new ISatelliteModemStateCallback.Stub() {
@Override
public void onSatelliteModemStateChanged(int state) {
mHandler.obtainMessage(MSG_SATELLITE_ENABLED_CHANGED).sendToTarget();
@@ -504,7 +505,7 @@
if (mPhone != null) {
subId = mPhone.getSubId();
}
- mSatelliteController.unregisterForSatelliteModemStateChanged(subId, mSatelliteCallback);
+ mSatelliteController.unregisterForModemStateChanged(subId, mSatelliteCallback);
mHandler.removeMessages(MSG_SATELLITE_ENABLED_CHANGED);
}
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccCardController.java b/src/java/com/android/internal/telephony/euicc/EuiccCardController.java
index 2f73c91..6e1c8dd 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccCardController.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccCardController.java
@@ -16,14 +16,20 @@
package com.android.internal.telephony.euicc;
+import static android.content.pm.PackageManager.FEATURE_TELEPHONY_EUICC;
+import static android.telephony.TelephonyManager.ENABLE_FEATURE_MAPPING;
+
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
+import android.app.compat.CompatChanges;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ComponentInfo;
+import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Handler;
import android.os.RemoteException;
@@ -39,6 +45,7 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.uicc.UiccCard;
import com.android.internal.telephony.uicc.UiccController;
@@ -66,6 +73,8 @@
private SimSlotStatusChangedBroadcastReceiver mSimSlotStatusChangeReceiver;
private EuiccController mEuiccController;
private UiccController mUiccController;
+ private FeatureFlags mFeatureFlags;
+ private PackageManager mPackageManager;
private static EuiccCardController sInstance;
@@ -87,10 +96,10 @@
}
/** Initialize the instance. Should only be called once. */
- public static EuiccCardController init(Context context) {
+ public static EuiccCardController init(Context context, FeatureFlags featureFlags) {
synchronized (EuiccCardController.class) {
if (sInstance == null) {
- sInstance = new EuiccCardController(context);
+ sInstance = new EuiccCardController(context, featureFlags);
} else {
Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
}
@@ -110,8 +119,9 @@
return sInstance;
}
- private EuiccCardController(Context context) {
- this(context, new Handler(), EuiccController.get(), UiccController.getInstance());
+ private EuiccCardController(Context context, FeatureFlags featureFlags) {
+ this(context, new Handler(), EuiccController.get(), UiccController.getInstance(),
+ featureFlags);
TelephonyFrameworkInitializer
.getTelephonyServiceManager()
.getEuiccCardControllerServiceRegisterer()
@@ -123,13 +133,16 @@
Context context,
Handler handler,
EuiccController euiccController,
- UiccController uiccController) {
+ UiccController uiccController,
+ FeatureFlags featureFlags) {
mContext = context;
mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
mEuiccMainThreadHandler = handler;
mUiccController = uiccController;
mEuiccController = euiccController;
+ mFeatureFlags = featureFlags;
+ mPackageManager = context.getPackageManager();
if (isBootUp(mContext)) {
mSimSlotStatusChangeReceiver = new SimSlotStatusChangedBroadcastReceiver();
@@ -293,6 +306,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "getAllProfiles");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -342,6 +357,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "getProfile");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -390,6 +407,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "getEnabledProfile");
+
String iccId = null;
boolean isValidSlotPort = false;
// get the iccid whether or not the port is active
@@ -474,6 +493,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "disableProfile");
+
EuiccPort port = getEuiccPortFromIccId(cardId, iccid);
if (port == null) {
try {
@@ -522,6 +543,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "switchToProfile");
+
EuiccPort port = getEuiccPort(cardId, portIndex);
if (port == null) {
try {
@@ -588,6 +611,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "setNickname");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -636,6 +661,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "deleteProfile");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -687,6 +714,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "resetMemory");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -738,6 +767,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "getDefaultSmdpAddress");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -786,6 +817,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "getSmdsAddress");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -834,6 +867,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "setDefaultSmdpAddress");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -882,6 +917,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "getRulesAuthTable");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -931,6 +968,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "getEuiccChallenge");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -979,6 +1018,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "getEuiccInfo1");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -1027,6 +1068,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "getEuiccInfo2");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -1076,6 +1119,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "authenticateServer");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -1126,6 +1171,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "prepareDownload");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -1175,6 +1222,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "loadBoundProfilePackage");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -1226,6 +1275,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "cancelSession");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -1274,6 +1325,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "listNotifications");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -1323,6 +1376,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "retrieveNotificationList");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -1372,6 +1427,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "retrieveNotification");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -1421,6 +1478,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage, "removeNotificationFromList");
+
EuiccPort port = getFirstActiveEuiccPort(cardId);
if (port == null) {
try {
@@ -1469,6 +1528,29 @@
Binder.restoreCallingIdentity(token);
}
+ /**
+ * Make sure the device has required telephony feature
+ *
+ * @throws UnsupportedOperationException if the device does not have required telephony feature
+ */
+ private void enforceTelephonyFeatureWithException(@Nullable String callingPackage,
+ @NonNull String methodName) {
+ if (callingPackage == null || mPackageManager == null) {
+ return;
+ }
+
+ if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
+ || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+ Binder.getCallingUserHandle())) {
+ return;
+ }
+
+ if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY_EUICC)) {
+ throw new UnsupportedOperationException(
+ methodName + " is unsupported without " + FEATURE_TELEPHONY_EUICC);
+ }
+ }
+
private static void loge(String message) {
Log.e(TAG, message);
}
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccController.java b/src/java/com/android/internal/telephony/euicc/EuiccController.java
index c8f3368..a24ab43 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccController.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccController.java
@@ -15,6 +15,9 @@
*/
package com.android.internal.telephony.euicc;
+import static android.content.pm.PackageManager.FEATURE_TELEPHONY_EUICC;
+import static android.telephony.TelephonyManager.ENABLE_FEATURE_MAPPING;
+
import android.Manifest;
import android.Manifest.permission;
import android.annotation.NonNull;
@@ -60,6 +63,7 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.euicc.EuiccConnector.OtaStatusChangedCallback;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.telephony.uicc.UiccController;
@@ -111,6 +115,7 @@
private final TelephonyManager mTelephonyManager;
private final AppOpsManager mAppOpsManager;
private final PackageManager mPackageManager;
+ private final FeatureFlags mFeatureFlags;
// These values should be set or updated upon 1) system boot, 2) EuiccService/LPA is bound to
// the phone process, 3) values are updated remotely by server flags.
@@ -118,10 +123,10 @@
private List<String> mUnsupportedCountries;
/** Initialize the instance. Should only be called once. */
- public static EuiccController init(Context context) {
+ public static EuiccController init(Context context, FeatureFlags featureFlags) {
synchronized (EuiccController.class) {
if (sInstance == null) {
- sInstance = new EuiccController(context);
+ sInstance = new EuiccController(context, featureFlags);
} else {
Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
}
@@ -141,14 +146,14 @@
return sInstance;
}
- private EuiccController(Context context) {
- this(context, new EuiccConnector(context));
+ private EuiccController(Context context, FeatureFlags featureFlags) {
+ this(context, new EuiccConnector(context), featureFlags);
TelephonyFrameworkInitializer
.getTelephonyServiceManager().getEuiccControllerService().register(this);
}
@VisibleForTesting
- public EuiccController(Context context, EuiccConnector connector) {
+ public EuiccController(Context context, EuiccConnector connector, FeatureFlags featureFlags) {
mContext = context;
mConnector = connector;
mSubscriptionManager = (SubscriptionManager)
@@ -157,6 +162,7 @@
context.getSystemService(Context.TELEPHONY_SERVICE);
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
mPackageManager = context.getPackageManager();
+ mFeatureFlags = featureFlags;
}
/**
@@ -1957,6 +1963,9 @@
@Override
public boolean isSimPortAvailable(int cardId, int portIndex, String callingPackage) {
mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
+
+ enforceTelephonyFeatureWithException(callingPackage, "isSimPortAvailable");
+
// If calling app is targeted for Android U and beyond, check for other conditions
// to decide the port availability.
boolean shouldCheckConditionsForInactivePort = isCompatChangeEnabled(callingPackage,
@@ -2063,4 +2072,27 @@
+ " changeEnabled: " + changeEnabled);
return changeEnabled;
}
+
+ /**
+ * Make sure the device has required telephony feature
+ *
+ * @throws UnsupportedOperationException if the device does not have required telephony feature
+ */
+ private void enforceTelephonyFeatureWithException(@Nullable String callingPackage,
+ @NonNull String methodName) {
+ if (callingPackage == null || mPackageManager == null) {
+ return;
+ }
+
+ if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
+ || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+ Binder.getCallingUserHandle())) {
+ return;
+ }
+
+ if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY_EUICC)) {
+ throw new UnsupportedOperationException(
+ methodName + " is unsupported without " + FEATURE_TELEPHONY_EUICC);
+ }
+ }
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsNrSaModeHandler.java b/src/java/com/android/internal/telephony/imsphone/ImsNrSaModeHandler.java
index 3dedde8..234723f 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsNrSaModeHandler.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsNrSaModeHandler.java
@@ -263,9 +263,10 @@
PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId(),
KEY_NR_SA_DISABLE_POLICY_INT, KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY);
mNrSaDisablePolicy = bundle.getInt(KEY_NR_SA_DISABLE_POLICY_INT);
- mIsNrSaSupported = Arrays.stream(
- bundle.getIntArray(KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY)).anyMatch(
- value -> value == CARRIER_NR_AVAILABILITY_SA);
+ int[] nrAvailabilities = bundle.getIntArray(KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY);
+ mIsNrSaSupported = nrAvailabilities != null
+ && Arrays.stream(nrAvailabilities).anyMatch(
+ value -> value == CARRIER_NR_AVAILABILITY_SA);
Log.d(TAG, "setNrSaDisablePolicy : NrSaDisablePolicy = "
+ mNrSaDisablePolicy + ", IsNrSaSupported = " + mIsNrSaSupported);
@@ -286,7 +287,7 @@
private void setNrSaMode(boolean onOrOff) {
if (mIsNrSaSupported) {
- mPhone.getDefaultPhone().mCi.setN1ModeEnabled(onOrOff, null);
+ mPhone.getDefaultPhone().setN1ModeEnabled(onOrOff, null);
Log.i(TAG, "setNrSaMode : " + onOrOff);
setNrSaDisabledForWfc(!onOrOff);
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index b21d45d..9f3ec3b 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -24,7 +24,7 @@
import static android.telephony.ims.RegistrationManager.SUGGESTED_ACTION_TRIGGER_PLMN_BLOCK;
import static android.telephony.ims.RegistrationManager.SUGGESTED_ACTION_TRIGGER_PLMN_BLOCK_WITH_TIMEOUT;
import static android.telephony.ims.RegistrationManager.SUGGESTED_ACTION_TRIGGER_RAT_BLOCK;
-import static android.telephony.ims.RegistrationManager.SUGGESTED_ACTION_TRIGGER_CLEAR_RAT_BLOCK;
+import static android.telephony.ims.RegistrationManager.SUGGESTED_ACTION_TRIGGER_CLEAR_RAT_BLOCKS;
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BAIC;
@@ -2436,7 +2436,9 @@
if (mCT.getState() == PhoneConstants.State.IDLE) {
if (DBG) logd("updateRoamingState now: " + newRoamingState);
- mLastKnownRoamingState = newRoamingState;
+ if (!mFeatureFlags.updateRoamingStateToSetWfcMode()) {
+ mLastKnownRoamingState = newRoamingState;
+ }
CarrierConfigManager configManager = (CarrierConfigManager)
getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
// Don't set wfc mode if carrierconfig has not loaded. It will be set by GsmCdmaPhone
@@ -2445,6 +2447,9 @@
configManager.getConfigForSubId(getSubId()))) {
ImsManager imsManager = mImsManagerFactory.create(mContext, mPhoneId);
imsManager.setWfcMode(imsManager.getWfcMode(newRoamingState), newRoamingState);
+ if (mFeatureFlags.updateRoamingStateToSetWfcMode()) {
+ mLastKnownRoamingState = newRoamingState;
+ }
}
} else {
if (DBG) logd("updateRoamingState postponed: " + newRoamingState);
@@ -2531,7 +2536,7 @@
suggestedModemAction = suggestedAction;
} else if (mFeatureFlags.addRatRelatedSuggestedActionToImsRegistration()) {
if ((suggestedAction == SUGGESTED_ACTION_TRIGGER_RAT_BLOCK)
- || (suggestedAction == SUGGESTED_ACTION_TRIGGER_CLEAR_RAT_BLOCK)) {
+ || (suggestedAction == SUGGESTED_ACTION_TRIGGER_CLEAR_RAT_BLOCKS)) {
suggestedModemAction = suggestedAction;
}
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index e95433c..85d4fb1 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -1259,8 +1259,6 @@
}
}
- private @NonNull final FeatureFlags mFeatureFlags;
-
//***** Events
@@ -1273,8 +1271,9 @@
@VisibleForTesting
public ImsPhoneCallTracker(ImsPhone phone, ConnectorFactory factory, Executor executor,
FeatureFlags featureFlags) {
+ super(featureFlags);
+
this.mPhone = phone;
- mFeatureFlags = featureFlags;
mConnectorFactory = factory;
if (executor != null) {
mExecutor = executor;
diff --git a/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java b/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java
index afb87dd..e1f6309 100644
--- a/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java
+++ b/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java
@@ -19,6 +19,7 @@
import static com.android.internal.telephony.TelephonyStatsLog.DATA_CALL_SESSION__IP_TYPE__APN_PROTOCOL_IPV4;
import android.annotation.Nullable;
+import android.net.NetworkCapabilities;
import android.os.SystemClock;
import android.telephony.Annotation.ApnType;
import android.telephony.Annotation.DataFailureCause;
@@ -62,8 +63,16 @@
public static final int SIZE_LIMIT_HANDOVER_FAILURES = 15;
+ private final DefaultNetworkMonitor mDefaultNetworkMonitor;
+
public DataCallSessionStats(Phone phone) {
mPhone = phone;
+ mDefaultNetworkMonitor = PhoneFactory.getMetricsCollector().getDefaultNetworkMonitor();
+ }
+
+ private boolean isSystemDefaultNetworkMobile() {
+ NetworkCapabilities nc = mDefaultNetworkMonitor.getNetworkCapabilities();
+ return nc != null && nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
}
/** Creates a new ongoing atom when data call is set up. */
@@ -101,6 +110,9 @@
(currentRat == TelephonyManager.NETWORK_TYPE_IWLAN)
? 0
: ServiceStateStats.getBand(mPhone);
+ // Limitation: Will not capture IKE mobility between Backup Calling <-> WiFi Calling.
+ mDataCallSession.isIwlanCrossSim = currentRat == TelephonyManager.NETWORK_TYPE_IWLAN
+ && isSystemDefaultNetworkMobile();
}
// only set if apn hasn't been set during setup
@@ -199,6 +211,8 @@
if (mDataCallSession.ratAtEnd != currentRat) {
mDataCallSession.ratSwitchCount++;
mDataCallSession.ratAtEnd = currentRat;
+ mDataCallSession.isIwlanCrossSim = currentRat == TelephonyManager.NETWORK_TYPE_IWLAN
+ && isSystemDefaultNetworkMobile();
}
// band may have changed even if RAT was the same
mDataCallSession.bandAtEnd =
@@ -288,6 +302,7 @@
copy.handoverFailureRat = Arrays.copyOf(call.handoverFailureRat,
call.handoverFailureRat.length);
copy.isNonDds = call.isNonDds;
+ copy.isIwlanCrossSim = call.isIwlanCrossSim;
return copy;
}
@@ -313,6 +328,7 @@
proto.handoverFailureCauses = new int[0];
proto.handoverFailureRat = new int[0];
proto.isNonDds = false;
+ proto.isIwlanCrossSim = false;
return proto;
}
diff --git a/src/java/com/android/internal/telephony/metrics/DefaultNetworkMonitor.java b/src/java/com/android/internal/telephony/metrics/DefaultNetworkMonitor.java
new file mode 100644
index 0000000..1dab10b
--- /dev/null
+++ b/src/java/com/android/internal/telephony/metrics/DefaultNetworkMonitor.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.metrics;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.os.Handler;
+import android.os.Looper;
+
+import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.telephony.Rlog;
+
+/**
+ * Monitors the system default network registration and tracks the currently available
+ * {@link Network} and its {@link NetworkCapabilities}.
+ */
+public class DefaultNetworkMonitor extends Handler {
+
+ private static final String TAG = DefaultNetworkMonitor.class.getSimpleName();
+
+ @Nullable private NetworkCallback mDefaultNetworkCallback;
+ @Nullable private Network mNetwork;
+ @Nullable private NetworkCapabilities mNetworkCapabilities;
+
+ private final class DefaultNetworkCallback extends NetworkCallback {
+ @Override
+ public void onAvailable(@NonNull Network network) {
+ mNetwork = network;
+ }
+
+ @Override
+ public void onCapabilitiesChanged(@NonNull Network network,
+ @NonNull NetworkCapabilities nc) {
+ if (network == mNetwork) {
+ mNetworkCapabilities = nc;
+ }
+ }
+
+ @Override
+ public void onLost(@NonNull Network network) {
+ mNetwork = null;
+ mNetworkCapabilities = null;
+ }
+ }
+
+ DefaultNetworkMonitor(@NonNull Context context, @NonNull FeatureFlags featureFlags) {
+ super(Looper.myLooper());
+ if (featureFlags.dataCallSessionStatsCapturesCrossSimCalling()) {
+ registerSystemDefaultNetworkCallback(context);
+ }
+ }
+
+ private void registerSystemDefaultNetworkCallback(@NonNull Context context) {
+ if (mDefaultNetworkCallback != null) {
+ return;
+ }
+ ConnectivityManager connectivityManager =
+ context.getSystemService(ConnectivityManager.class);
+ if (connectivityManager != null) {
+ mDefaultNetworkCallback = new DefaultNetworkCallback();
+ connectivityManager.registerSystemDefaultNetworkCallback(
+ mDefaultNetworkCallback, this);
+ } else {
+ Rlog.e(TAG, "registerSystemDefaultNetworkCallback: ConnectivityManager is null!");
+ }
+ }
+
+ @Nullable public NetworkCapabilities getNetworkCapabilities() {
+ return mNetworkCapabilities;
+ }
+}
diff --git a/src/java/com/android/internal/telephony/metrics/ImsStats.java b/src/java/com/android/internal/telephony/metrics/ImsStats.java
index 04c9677..d9994aa 100644
--- a/src/java/com/android/internal/telephony/metrics/ImsStats.java
+++ b/src/java/com/android/internal/telephony/metrics/ImsStats.java
@@ -239,6 +239,10 @@
return;
}
+ stats.registeredTimes = mLastRegistrationStats.registeredTimes;
+ // initialize registeredTimes after copying mLastRegistrationStats to be updated
+ mLastRegistrationStats.registeredTimes = 0;
+
switch (mLastRegistrationState) {
case REGISTRATION_STATE_REGISTERED:
stats.registeredMillis = duration;
@@ -334,6 +338,13 @@
/** Updates the stats when IMS registration succeeds. */
public synchronized void onImsRegistered(ImsRegistrationAttributes attributes) {
+ // Updates registered_times as soon as the UE is registered
+ if (mLastRegistrationState != REGISTRATION_STATE_REGISTERED) {
+ // RegistrationStats captures in every state. Changing REGISTERED state has to capture
+ // only once.
+ mLastRegistrationStats.registeredTimes = 1;
+ }
+
conclude();
mLastTransportType = attributes.getTransportType();
@@ -341,6 +352,7 @@
if (mLastRegistrationState == REGISTRATION_STATE_NOT_REGISTERED) {
updateImsRegistrationStats();
}
+
mLastRegistrationStats.rat =
convertTransportTypeToNetworkType(attributes.getTransportType());
mLastRegistrationStats.isIwlanCrossSim = attributes.getRegistrationTechnology()
diff --git a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
index 8bd2547..cc80a2e 100644
--- a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
+++ b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
@@ -171,19 +171,20 @@
private final StatsManager mStatsManager;
private final VonrHelper mVonrHelper;
private final AirplaneModeStats mAirplaneModeStats;
+ private final DefaultNetworkMonitor mDefaultNetworkMonitor;
private final Set<DataCallSessionStats> mOngoingDataCallStats = ConcurrentHashMap.newKeySet();
private static final Random sRandom = new Random();
public MetricsCollector(Context context, @NonNull FeatureFlags featureFlags) {
this(context, new PersistAtomsStorage(context),
- new DeviceStateHelper(context), new VonrHelper(featureFlags));
+ new DeviceStateHelper(context), new VonrHelper(featureFlags), featureFlags);
}
/** Allows dependency injection. Used during unit tests. */
@VisibleForTesting
public MetricsCollector(
Context context, PersistAtomsStorage storage, DeviceStateHelper deviceStateHelper,
- VonrHelper vonrHelper) {
+ VonrHelper vonrHelper, @NonNull FeatureFlags featureFlags) {
mStorage = storage;
mDeviceStateHelper = deviceStateHelper;
mStatsManager = (StatsManager) context.getSystemService(Context.STATS_MANAGER);
@@ -232,6 +233,7 @@
}
mAirplaneModeStats = new AirplaneModeStats(context);
+ mDefaultNetworkMonitor = new DefaultNetworkMonitor(context, featureFlags);
}
/**
@@ -362,6 +364,10 @@
mOngoingDataCallStats.remove(call);
}
+ public DefaultNetworkMonitor getDefaultNetworkMonitor() {
+ return mDefaultNetworkMonitor;
+ }
+
private void concludeDataCallSessionStats() {
for (DataCallSessionStats stats : mOngoingDataCallStats) {
stats.conclude();
@@ -1118,7 +1124,8 @@
roundAndConvertMillisToSeconds(stats.utAvailableMillis),
roundAndConvertMillisToSeconds(stats.registeringMillis),
roundAndConvertMillisToSeconds(stats.unregisteredMillis),
- stats.isIwlanCrossSim);
+ stats.isIwlanCrossSim,
+ roundAndConvertMillisToSeconds(stats.registeredTimes));
}
private static StatsEvent buildStatsEvent(ImsRegistrationTermination termination) {
diff --git a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
index 101df0d..4a1fdb9 100644
--- a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
+++ b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
@@ -409,6 +409,7 @@
existingStats.utAvailableMillis += stats.utAvailableMillis;
existingStats.registeringMillis += stats.registeringMillis;
existingStats.unregisteredMillis += stats.unregisteredMillis;
+ existingStats.registeredTimes += stats.registeredTimes;
existingStats.lastUsedMillis = getWallTimeMillis();
} else {
stats.lastUsedMillis = getWallTimeMillis();
@@ -2290,6 +2291,8 @@
normalizeDurationTo24H(stats[i].registeringMillis, intervalMillis);
stats[i].unregisteredMillis =
normalizeDurationTo24H(stats[i].unregisteredMillis, intervalMillis);
+ stats[i].registeredTimes =
+ normalizeDurationTo24H(stats[i].registeredTimes, intervalMillis);
}
return stats;
}
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
index e4d16e7..ae4c1f2 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
@@ -209,7 +209,7 @@
case EVENT_SEND_SATELLITE_DATAGRAM_DONE: {
ar = (AsyncResult) msg.obj;
request = (DatagramDispatcherHandlerRequest) ar.userObj;
- int error = SatelliteServiceUtils.getSatelliteError(ar, "sendSatelliteDatagram");
+ int error = SatelliteServiceUtils.getSatelliteError(ar, "sendDatagram");
SendSatelliteDatagramArgument argument =
(SendSatelliteDatagramArgument) request.argument;
@@ -330,7 +330,7 @@
}
if (mDatagramController.needsWaitingForSatelliteConnected()) {
- logd("sendSatelliteDatagram: wait for satellite connected");
+ logd("sendDatagram: wait for satellite connected");
mDatagramController.updateSendStatus(subId,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
getPendingDatagramCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
@@ -345,7 +345,7 @@
getPendingDatagramCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
sendRequestAsync(CMD_SEND_SATELLITE_DATAGRAM, datagramArgs, phone);
} else {
- logd("sendSatelliteDatagram: mSendingDatagramInProgress="
+ logd("sendDatagram: mSendingDatagramInProgress="
+ mSendingDatagramInProgress + ", isPollingInIdleState="
+ mDatagramController.isPollingInIdleState());
}
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
index 3ac1bbd..c267fd7 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
@@ -588,13 +588,14 @@
@NonNull Consumer<Integer> callback) {
if (!mDatagramController.isSendingInIdleState()) {
// Poll request should be sent to satellite modem only when it is free.
- logd("pollPendingSatelliteDatagrams: satellite modem is busy sending datagrams.");
+ logd("pollPendingSatelliteDatagramsInternal: satellite modem is busy sending "
+ + "datagrams.");
callback.accept(SatelliteManager.SATELLITE_RESULT_MODEM_BUSY);
return;
}
if (mDatagramController.needsWaitingForSatelliteConnected()) {
- logd("pollPendingSatelliteDatagrams: wait for satellite connected");
+ logd("pollPendingSatelliteDatagramsInternal: wait for satellite connected");
synchronized (mLock) {
mPendingPollSatelliteDatagramsRequest = new DatagramReceiverHandlerRequest(
callback, SatelliteServiceUtils.getPhone(), subId);
diff --git a/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java b/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
index 26100a8..add01c0 100644
--- a/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
+++ b/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
@@ -40,7 +40,7 @@
public static void resolveNtnCapability(
@NonNull NetworkRegistrationInfo networkRegistrationInfo, int subId) {
SatelliteController satelliteController = SatelliteController.getInstance();
- List<String> satellitePlmnList = satelliteController.getSatellitePlmnList(subId);
+ List<String> satellitePlmnList = satelliteController.getSatellitePlmnsForCarrier(subId);
String registeredPlmn = networkRegistrationInfo.getRegisteredPlmn();
for (String satellitePlmn : satellitePlmnList) {
if (TextUtils.equals(satellitePlmn, registeredPlmn)) {
diff --git a/src/java/com/android/internal/telephony/satellite/PointingAppController.java b/src/java/com/android/internal/telephony/satellite/PointingAppController.java
index 9a6bd69..878ee96 100644
--- a/src/java/com/android/internal/telephony/satellite/PointingAppController.java
+++ b/src/java/com/android/internal/telephony/satellite/PointingAppController.java
@@ -376,6 +376,7 @@
loge("startPointingUI: launchIntent is null");
return;
}
+ logd("startPointingUI: needFullScreenPointingUI: " + needFullScreenPointingUI);
launchIntent.putExtra("needFullScreen", needFullScreenPointingUI);
try {
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index b4ce9c7..aaabaff 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -25,7 +25,9 @@
import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS;
import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911;
import static android.telephony.satellite.SatelliteManager.KEY_NTN_SIGNAL_STRENGTH;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT;
import static android.telephony.satellite.SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import android.annotation.ArrayRes;
@@ -37,6 +39,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.wifi.WifiManager;
@@ -68,8 +71,8 @@
import android.telephony.satellite.INtnSignalStrengthCallback;
import android.telephony.satellite.ISatelliteCapabilitiesCallback;
import android.telephony.satellite.ISatelliteDatagramCallback;
+import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.ISatelliteProvisionStateCallback;
-import android.telephony.satellite.ISatelliteStateCallback;
import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.SatelliteCapabilities;
@@ -124,6 +127,10 @@
public static final int SATELLITE_MODE_ENABLED_FALSE = 0;
public static final int INVALID_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE = -1;
+ /** Key used to read/write OEM-enabled satellite provision status in shared preferences. */
+ private static final String OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY =
+ "oem_enabled_satellite_provision_status_key";
+
/** 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;
@@ -247,9 +254,11 @@
@GuardedBy("mIsSatelliteEnabledLock")
private Boolean mIsSatelliteEnabled = null;
private boolean mIsRadioOn = false;
- private final Object mIsSatelliteProvisionedLock = new Object();
- @GuardedBy("mIsSatelliteProvisionedLock")
- private Boolean mIsSatelliteProvisioned = null;
+ private final Object mSatelliteViaOemProvisionLock = new Object();
+ @GuardedBy("mSatelliteViaOemProvisionLock")
+ private Boolean mIsSatelliteViaOemProvisioned = null;
+ @GuardedBy("mSatelliteViaOemProvisionLock")
+ private Boolean mOverriddenIsSatelliteViaOemProvisioned = null;
private final Object mSatelliteCapabilitiesLock = new Object();
@GuardedBy("mSatelliteCapabilitiesLock")
private SatelliteCapabilities mSatelliteCapabilities;
@@ -309,6 +318,22 @@
private int mEnforcedEmergencyCallToSatelliteHandoverType =
INVALID_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE;
private int mDelayInSendingEventDisplayEmergencyMessage = 0;
+ @NonNull private SharedPreferences mSharedPreferences = null;
+
+ /**
+ * Key : Subscription ID, Value: {@code true} if the EntitlementStatus is enabled,
+ * {@code false} otherwise.
+ */
+ @GuardedBy("mSupportedSatelliteServicesLock")
+ private SparseBooleanArray mSatelliteEntitlementStatusPerCarrier = new SparseBooleanArray();
+ /** Key Subscription ID, value : PLMN allowed list from entitlement. */
+ @GuardedBy("mSupportedSatelliteServicesLock")
+ private SparseArray<List<String>> mEntitlementPlmnListPerCarrier = new SparseArray<>();
+ /**
+ * Key : Subscription ID, Value : If there is an entitlementPlmnList, use it. Otherwise, use the
+ * carrierPlmnList. */
+ @GuardedBy("mSupportedSatelliteServicesLock")
+ private final SparseArray<List<String>> mMergedPlmnListPerCarrier = new SparseArray<>();
/**
* @return The singleton instance of SatelliteController.
@@ -369,13 +394,6 @@
// which is used to send and receive satellite datagrams.
mDatagramController = DatagramController.make(mContext, looper, mPointingAppController);
- requestIsSatelliteSupported(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
- new ResultReceiver(this) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- logd("requestIsSatelliteSupported: resultCode=" + resultCode);
- }
- });
mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
mIsRadioOn = phone.isRadioOn();
registerForSatelliteProvisionStateChanged();
@@ -408,6 +426,7 @@
new HandlerExecutor(new Handler(looper)), mCarrierConfigChangeListener);
mDSM.registerForSignalStrengthReportDecision(this, CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING,
null);
+ loadSatelliteSharedPreferences();
}
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
@@ -779,13 +798,6 @@
mWaitingForRadioDisabled = true;
}
setSettingsKeyForSatelliteMode(SATELLITE_MODE_ENABLED_TRUE);
-
- /**
- * TODO for NTN-based satellites: Check if satellite is acquired.
- */
- if (mNeedsSatellitePointing) {
- mPointingAppController.startPointingUI(false);
- }
evaluateToSendSatelliteEnabledSuccess();
} else {
/**
@@ -903,7 +915,7 @@
error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
} else {
boolean supported = (boolean) ar.result;
- if (DBG) logd("isSatelliteSupported: " + supported);
+ logd("isSatelliteSupported: " + supported);
bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, supported);
updateSatelliteSupportedStateWhenSatelliteServiceConnected(supported);
}
@@ -1014,19 +1026,21 @@
case EVENT_RADIO_STATE_CHANGED: {
if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON) {
mIsRadioOn = true;
- if (!mSatelliteModemInterface.isSatelliteServiceSupported()) {
+ }
+ if (mCi.getRadioState() != TelephonyManager.RADIO_POWER_UNAVAILABLE) {
+ if (mSatelliteModemInterface.isSatelliteServiceConnected()) {
synchronized (mIsSatelliteSupportedLock) {
- if (mIsSatelliteSupported == null) {
+ if (mIsSatelliteSupported == null || !mIsSatelliteSupported) {
ResultReceiver receiver = new ResultReceiver(this) {
@Override
protected void onReceiveResult(
int resultCode, Bundle resultData) {
- logd("requestIsSatelliteSupported: resultCode="
- + resultCode);
+ logd("onRadioStateChanged.requestIsSatelliteSupported: "
+ + "resultCode=" + resultCode
+ + ", resultData=" + resultData);
}
};
- requestIsSatelliteSupported(
- SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, receiver);
+ sendRequestAsync(CMD_IS_SATELLITE_SUPPORTED, receiver, null);
}
}
}
@@ -1042,25 +1056,7 @@
}
case EVENT_IS_SATELLITE_PROVISIONED_DONE: {
- ar = (AsyncResult) msg.obj;
- request = (SatelliteControllerHandlerRequest) ar.userObj;
- int error = SatelliteServiceUtils.getSatelliteError(ar,
- "isSatelliteProvisioned");
- Bundle bundle = new Bundle();
- if (error == SATELLITE_RESULT_SUCCESS) {
- if (ar.result == null) {
- loge("isSatelliteProvisioned: result is null");
- error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
- } else {
- boolean provisioned = ((int[]) ar.result)[0] == 1;
- if (DBG) logd("isSatelliteProvisioned: " + provisioned);
- bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED, provisioned);
- synchronized (mIsSatelliteProvisionedLock) {
- mIsSatelliteProvisioned = provisioned;
- }
- }
- }
- ((ResultReceiver) request.argument).send(error, bundle);
+ handleIsSatelliteProvisionedDoneEvent((AsyncResult) msg.obj);
break;
}
@@ -1081,7 +1077,7 @@
logd("pollPendingSatelliteDatagram result: " + result);
}
};
- pollPendingSatelliteDatagrams(
+ pollPendingDatagrams(
SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, internalCallback);
break;
@@ -1660,11 +1656,11 @@
return;
}
- synchronized (mIsSatelliteProvisionedLock) {
- if (mIsSatelliteProvisioned != null) {
+ synchronized (mSatelliteViaOemProvisionLock) {
+ if (mIsSatelliteViaOemProvisioned != null) {
Bundle bundle = new Bundle();
bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED,
- mIsSatelliteProvisioned);
+ mIsSatelliteViaOemProvisioned);
result.send(SATELLITE_RESULT_SUCCESS, bundle);
return;
}
@@ -1682,7 +1678,7 @@
* @return The {@link SatelliteManager.SatelliteResult} result of the operation.
*/
@SatelliteManager.SatelliteResult public int registerForSatelliteModemStateChanged(int subId,
- @NonNull ISatelliteStateCallback callback) {
+ @NonNull ISatelliteModemStateCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
logd("registerForSatelliteModemStateChanged: oemEnabledSatelliteFlag is disabled");
return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
@@ -1703,18 +1699,18 @@
*
* @param subId The subId of the subscription to unregister for satellite modem state changed.
* @param callback The callback that was passed to
- * {@link #registerForSatelliteModemStateChanged(int, ISatelliteStateCallback)}.
+ * {@link #registerForSatelliteModemStateChanged(int, ISatelliteModemStateCallback)}.
*/
- public void unregisterForSatelliteModemStateChanged(int subId,
- @NonNull ISatelliteStateCallback callback) {
+ public void unregisterForModemStateChanged(int subId,
+ @NonNull ISatelliteModemStateCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("unregisterForSatelliteModemStateChanged: oemEnabledSatelliteFlag is disabled");
+ logd("unregisterForModemStateChanged: oemEnabledSatelliteFlag is disabled");
return;
}
if (mSatelliteSessionController != null) {
mSatelliteSessionController.unregisterForSatelliteModemStateChanged(callback);
} else {
- loge("registerForSatelliteModemStateChanged: mSatelliteSessionController"
+ loge("unregisterForModemStateChanged: mSatelliteSessionController"
+ " is not initialized yet");
}
}
@@ -1727,16 +1723,16 @@
*
* @return The {@link SatelliteManager.SatelliteResult} result of the operation.
*/
- @SatelliteManager.SatelliteResult public int registerForSatelliteDatagram(int subId,
+ @SatelliteManager.SatelliteResult public int registerForIncomingDatagram(int subId,
@NonNull ISatelliteDatagramCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("registerForSatelliteDatagram: oemEnabledSatelliteFlag is disabled");
+ logd("registerForIncomingDatagram: oemEnabledSatelliteFlag is disabled");
return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
}
if (!mSatelliteModemInterface.isSatelliteServiceSupported()) {
return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
}
- logd("registerForSatelliteDatagram: callback=" + callback);
+ logd("registerForIncomingDatagram: callback=" + callback);
return mDatagramController.registerForSatelliteDatagram(subId, callback);
}
@@ -1746,18 +1742,18 @@
*
* @param subId The subId of the subscription to unregister for incoming satellite datagrams.
* @param callback The callback that was passed to
- * {@link #registerForSatelliteDatagram(int, ISatelliteDatagramCallback)}.
+ * {@link #registerForIncomingDatagram(int, ISatelliteDatagramCallback)}.
*/
- public void unregisterForSatelliteDatagram(int subId,
+ public void unregisterForIncomingDatagram(int subId,
@NonNull ISatelliteDatagramCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("unregisterForSatelliteDatagram: oemEnabledSatelliteFlag is disabled");
+ logd("unregisterForIncomingDatagram: oemEnabledSatelliteFlag is disabled");
return;
}
if (!mSatelliteModemInterface.isSatelliteServiceSupported()) {
return;
}
- logd("unregisterForSatelliteDatagram: callback=" + callback);
+ logd("unregisterForIncomingDatagram: callback=" + callback);
mDatagramController.unregisterForSatelliteDatagram(subId, callback);
}
@@ -1772,7 +1768,7 @@
* @param subId The subId of the subscription used for receiving datagrams.
* @param callback The callback to get {@link SatelliteManager.SatelliteResult} of the request.
*/
- public void pollPendingSatelliteDatagrams(int subId, @NonNull IIntegerConsumer callback) {
+ public void pollPendingDatagrams(int subId, @NonNull IIntegerConsumer callback) {
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
int error = evaluateOemSatelliteRequestAllowed(true);
if (error != SATELLITE_RESULT_SUCCESS) {
@@ -1800,9 +1796,12 @@
* full screen mode.
* @param callback The callback to get {@link SatelliteManager.SatelliteResult} of the request.
*/
- public void sendSatelliteDatagram(int subId, @SatelliteManager.DatagramType int datagramType,
+ public void sendDatagram(int subId, @SatelliteManager.DatagramType int datagramType,
SatelliteDatagram datagram, boolean needFullScreenPointingUI,
@NonNull IIntegerConsumer callback) {
+ logd("sendSatelliteDatagram: subId: " + subId + " datagramType: " + datagramType
+ + " needFullScreenPointingUI: " + needFullScreenPointingUI);
+
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
int error = evaluateOemSatelliteRequestAllowed(true);
if (error != SATELLITE_RESULT_SUCCESS) {
@@ -1883,14 +1882,14 @@
* @param reason Reason for disallowing satellite communication for carrier.
* @param callback The callback to get the result of the request.
*/
- public void addSatelliteAttachRestrictionForCarrier(int subId,
+ public void addAttachRestrictionForCarrier(int subId,
@SatelliteManager.SatelliteCommunicationRestrictionReason int reason,
@NonNull IIntegerConsumer callback) {
- if (DBG) logd("addSatelliteAttachRestrictionForCarrier(" + subId + ", " + reason + ")");
+ if (DBG) logd("addAttachRestrictionForCarrier(" + subId + ", " + reason + ")");
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
result.accept(SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
- logd("addSatelliteAttachRestrictionForCarrier: carrierEnabledSatelliteFlag is "
+ logd("addAttachRestrictionForCarrier: carrierEnabledSatelliteFlag is "
+ "disabled");
return;
}
@@ -1922,14 +1921,14 @@
* @param reason Reason for disallowing satellite communication.
* @param callback The callback to get the result of the request.
*/
- public void removeSatelliteAttachRestrictionForCarrier(int subId,
+ public void removeAttachRestrictionForCarrier(int subId,
@SatelliteManager.SatelliteCommunicationRestrictionReason int reason,
@NonNull IIntegerConsumer callback) {
- if (DBG) logd("removeSatelliteAttachRestrictionForCarrier(" + subId + ", " + reason + ")");
+ if (DBG) logd("removeAttachRestrictionForCarrier(" + subId + ", " + reason + ")");
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
result.accept(SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
- logd("removeSatelliteAttachRestrictionForCarrier: carrierEnabledSatelliteFlag is "
+ logd("removeAttachRestrictionForCarrier: carrierEnabledSatelliteFlag is "
+ "disabled");
return;
}
@@ -1952,15 +1951,15 @@
/**
* Get reasons for disallowing satellite communication, as requested by
- * {@link #addSatelliteAttachRestrictionForCarrier(int, int, IIntegerConsumer)}.
+ * {@link #addAttachRestrictionForCarrier(int, int, IIntegerConsumer)}.
*
* @param subId The subId of the subscription to request for.
*
* @return Set of reasons for disallowing satellite attach for carrier.
*/
- @NonNull public Set<Integer> getSatelliteAttachRestrictionReasonsForCarrier(int subId) {
+ @NonNull public Set<Integer> getAttachRestrictionReasonsForCarrier(int subId) {
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
- logd("getSatelliteAttachRestrictionReasonsForCarrier: carrierEnabledSatelliteFlag is "
+ logd("getAttachRestrictionReasonsForCarrier: carrierEnabledSatelliteFlag is "
+ "disabled");
return new HashSet<>();
}
@@ -2027,7 +2026,7 @@
if (error == SATELLITE_RESULT_SUCCESS) {
mNtnSignalStrengthChangedListeners.put(callback.asBinder(), callback);
} else {
- throw new ServiceSpecificException(error);
+ throw new RemoteException(new IllegalStateException("registration fails: " + error));
}
}
@@ -2058,9 +2057,9 @@
*
* @return The {@link SatelliteManager.SatelliteResult} result of the operation.
*/
- @SatelliteManager.SatelliteResult public int registerForSatelliteCapabilitiesChanged(
+ @SatelliteManager.SatelliteResult public int registerForCapabilitiesChanged(
int subId, @NonNull ISatelliteCapabilitiesCallback callback) {
- if (DBG) logd("registerForSatelliteCapabilitiesChanged()");
+ if (DBG) logd("registerForCapabilitiesChanged()");
int error = evaluateOemSatelliteRequestAllowed(true);
if (error != SATELLITE_RESULT_SUCCESS) return error;
@@ -2076,11 +2075,11 @@
* @param subId The id of the subscription to unregister for listening satellite capabilities
* changed event.
* @param callback The callback that was passed to
- * {@link #registerForSatelliteCapabilitiesChanged(int, ISatelliteCapabilitiesCallback)}
+ * {@link #registerForCapabilitiesChanged(int, ISatelliteCapabilitiesCallback)}
*/
- public void unregisterForSatelliteCapabilitiesChanged(
+ public void unregisterForCapabilitiesChanged(
int subId, @NonNull ISatelliteCapabilitiesCallback callback) {
- if (DBG) logd("unregisterForSatelliteCapabilitiesChanged()");
+ if (DBG) logd("unregisterForCapabilitiesChanged()");
int error = evaluateOemSatelliteRequestAllowed(true);
if (error == SATELLITE_RESULT_SUCCESS) {
@@ -2110,8 +2109,8 @@
synchronized (mIsSatelliteSupportedLock) {
mIsSatelliteSupported = null;
}
- synchronized (mIsSatelliteProvisionedLock) {
- mIsSatelliteProvisioned = null;
+ synchronized (mSatelliteViaOemProvisionLock) {
+ mIsSatelliteViaOemProvisioned = null;
}
synchronized (mIsSatelliteEnabledLock) {
mIsSatelliteEnabled = null;
@@ -2224,6 +2223,29 @@
return true;
}
+ /**
+ * This API can be used in only testing to override oem-enabled satellite provision status.
+ *
+ * @param reset {@code true} mean the overriding status should not be used, {@code false}
+ * otherwise.
+ * @param isProvisioned The overriding provision status.
+ * @return {@code true} if the provision status is set successfully, {@code false} otherwise.
+ */
+ public boolean setOemEnabledSatelliteProvisionStatus(boolean reset, boolean isProvisioned) {
+ if (!isMockModemAllowed()) {
+ loge("setOemEnabledSatelliteProvisionStatus: mock modem not allowed");
+ return false;
+ }
+ synchronized (mSatelliteViaOemProvisionLock) {
+ if (reset) {
+ mOverriddenIsSatelliteViaOemProvisioned = null;
+ } else {
+ mOverriddenIsSatelliteViaOemProvisioned = isProvisioned;
+ }
+ }
+ return true;
+ }
+
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
protected int getEnforcedEmergencyCallToSatelliteHandoverType() {
return mEnforcedEmergencyCallToSatelliteHandoverType;
@@ -2266,8 +2288,8 @@
@Override
protected void onReceiveResult(
int resultCode, Bundle resultData) {
- logd("requestIsSatelliteSupported: resultCode="
- + resultCode);
+ logd("onSatelliteServiceConnected.requestIsSatelliteSupported:"
+ + " resultCode=" + resultCode);
}
};
requestIsSatelliteSupported(
@@ -2320,17 +2342,13 @@
* @return The list of satellite PLMNs used for connecting to satellite networks.
*/
@NonNull
- public List<String> getSatellitePlmnList(int subId) {
+ public List<String> getSatellitePlmnsForCarrier(int subId) {
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
- logd("getSatellitePlmnList: carrierEnabledSatelliteFlag is disabled");
+ logd("getSatellitePlmnsForCarrier: carrierEnabledSatelliteFlag is disabled");
return new ArrayList<>();
}
synchronized (mSupportedSatelliteServicesLock) {
- if (mSatelliteServicesSupportedByCarriers.containsKey(subId)) {
- return new ArrayList<>(mSatelliteServicesSupportedByCarriers.get(subId).keySet());
- } else {
- return new ArrayList<>();
- }
+ return mMergedPlmnListPerCarrier.get(subId, new ArrayList<>()).stream().toList();
}
}
@@ -2472,6 +2490,53 @@
}
/**
+ * To use the satellite service, update the EntitlementStatus and the PlmnAllowedList after
+ * receiving the satellite configuration from the entitlement server. If satellite
+ * entitlement is enabled, enable satellite for the carrier. Otherwise, disable satellite.
+ *
+ * @param subId subId
+ * @param entitlementEnabled {@code true} Satellite service enabled
+ * @param allowedPlmnList plmn allowed list to use the satellite service
+ * @param callback callback for accept
+ */
+ public void onSatelliteEntitlementStatusUpdated(int subId, boolean entitlementEnabled,
+ List<String> allowedPlmnList, @Nullable IIntegerConsumer callback) {
+ if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
+ return;
+ }
+
+ if (callback == null) {
+ callback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ logd("updateSatelliteEntitlementStatus:" + result);
+ }
+ };
+ }
+
+ synchronized (mSupportedSatelliteServicesLock) {
+ if (mSatelliteEntitlementStatusPerCarrier.get(subId, false) != entitlementEnabled) {
+ logd("update the carrier satellite enabled to " + entitlementEnabled);
+ mSatelliteEntitlementStatusPerCarrier.put(subId, entitlementEnabled);
+ }
+ mMergedPlmnListPerCarrier.remove(subId);
+
+ mEntitlementPlmnListPerCarrier.put(subId, allowedPlmnList);
+ updatePlmnListPerCarrier(subId);
+ configureSatellitePlmnForCarrier(subId);
+
+ // TODO b/322143408 store entitlement status in telephony db.
+ if (mSatelliteEntitlementStatusPerCarrier.get(subId, false)) {
+ removeAttachRestrictionForCarrier(subId,
+ SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT, callback);
+ } else {
+ addAttachRestrictionForCarrier(subId,
+ SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT, callback);
+ }
+ }
+ }
+
+ /**
* If we have not successfully queried the satellite modem for its satellite service support,
* we will retry the query one more time. Otherwise, we will return the cached result.
*/
@@ -2490,7 +2555,8 @@
new ResultReceiver(this) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- logd("requestIsSatelliteSupported: resultCode=" + resultCode);
+ logd("isSatelliteSupportedViaOemInternal.requestIsSatelliteSupported:"
+ + " resultCode=" + resultCode);
}
});
return null;
@@ -2514,7 +2580,17 @@
SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE);
return;
}
- callback.accept(result);
+ if (result == SATELLITE_RESULT_SUCCESS
+ || result == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) {
+ persistOemEnabledSatelliteProvisionStatus(true);
+ synchronized (mSatelliteViaOemProvisionLock) {
+ mIsSatelliteViaOemProvisioned = true;
+ }
+ callback.accept(SATELLITE_RESULT_SUCCESS);
+ handleEventSatelliteProvisionStateChanged(true);
+ } else {
+ callback.accept(result);
+ }
}
private void handleEventDeprovisionSatelliteServiceDone(
@@ -2527,13 +2603,23 @@
logd("handleEventDeprovisionSatelliteServiceDone: result="
+ result + ", subId=" + arg.subId);
- if (arg.callback != null) {
+ if (result == SATELLITE_RESULT_SUCCESS
+ || result == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) {
+ persistOemEnabledSatelliteProvisionStatus(false);
+ synchronized (mSatelliteViaOemProvisionLock) {
+ mIsSatelliteViaOemProvisioned = false;
+ }
+ if (arg.callback != null) {
+ arg.callback.accept(SATELLITE_RESULT_SUCCESS);
+ }
+ handleEventSatelliteProvisionStateChanged(false);
+ } else if (arg.callback != null) {
arg.callback.accept(result);
- mProvisionMetricsStats.setResultCode(result)
- .setIsProvisionRequest(false)
- .reportProvisionMetrics();
- mControllerMetricsStats.reportDeprovisionCount(result);
}
+ mProvisionMetricsStats.setResultCode(result)
+ .setIsProvisionRequest(false)
+ .reportProvisionMetrics();
+ mControllerMetricsStats.reportDeprovisionCount(result);
}
private void handleStartSatelliteTransmissionUpdatesDone(@NonNull AsyncResult ar) {
@@ -2607,9 +2693,13 @@
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
protected Boolean isSatelliteViaOemProvisioned() {
- synchronized (mIsSatelliteProvisionedLock) {
- if (mIsSatelliteProvisioned != null) {
- return mIsSatelliteProvisioned;
+ synchronized (mSatelliteViaOemProvisionLock) {
+ if (mOverriddenIsSatelliteViaOemProvisioned != null) {
+ return mOverriddenIsSatelliteViaOemProvisioned;
+ }
+
+ if (mIsSatelliteViaOemProvisioned != null) {
+ return mIsSatelliteViaOemProvisioned;
}
}
@@ -2617,7 +2707,7 @@
new ResultReceiver(this) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- logd("requestIsSatelliteProvisioned: resultCode=" + resultCode);
+ logd("isSatelliteViaOemProvisioned: resultCode=" + resultCode);
}
});
return null;
@@ -2664,13 +2754,14 @@
registerForPendingDatagramCount();
registerForSatelliteModemStateChanged();
registerForNtnSignalStrengthChanged();
- registerForSatelliteCapabilitiesChanged();
+ registerForCapabilitiesChanged();
requestIsSatelliteProvisioned(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
new ResultReceiver(this) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- logd("requestIsSatelliteProvisioned: resultCode=" + resultCode);
+ logd("requestIsSatelliteProvisioned: resultCode=" + resultCode
+ + ", resultData=" + resultData);
requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
false, false,
new IIntegerConsumer.Stub() {
@@ -2685,7 +2776,8 @@
new ResultReceiver(this) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- logd("requestSatelliteCapabilities: resultCode=" + resultCode);
+ logd("requestSatelliteCapabilities: resultCode=" + resultCode
+ + ", resultData=" + resultData);
}
});
}
@@ -2748,9 +2840,9 @@
}
}
- private void registerForSatelliteCapabilitiesChanged() {
+ private void registerForCapabilitiesChanged() {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("registerForSatelliteCapabilitiesChanged: oemEnabledSatelliteFlag is disabled");
+ logd("registerForCapabilitiesChanged: oemEnabledSatelliteFlag is disabled");
return;
}
@@ -2766,8 +2858,9 @@
private void handleEventSatelliteProvisionStateChanged(boolean provisioned) {
logd("handleSatelliteProvisionStateChangedEvent: provisioned=" + provisioned);
- synchronized (mIsSatelliteProvisionedLock) {
- mIsSatelliteProvisioned = provisioned;
+ synchronized (mSatelliteViaOemProvisionLock) {
+ persistOemEnabledSatelliteProvisionStatus(provisioned);
+ mIsSatelliteViaOemProvisioned = provisioned;
}
List<ISatelliteProvisionStateCallback> deadCallersList = new ArrayList<>();
@@ -2950,13 +3043,8 @@
return;
}
synchronized (mSupportedSatelliteServicesLock) {
- List<String> carrierPlmnList;
- if (mSatelliteServicesSupportedByCarriers.containsKey(subId)) {
- carrierPlmnList =
- mSatelliteServicesSupportedByCarriers.get(subId).keySet().stream().toList();
- } else {
- carrierPlmnList = new ArrayList<>();
- }
+ List<String> carrierPlmnList = mMergedPlmnListPerCarrier.get(subId,
+ new ArrayList<>()).stream().toList();
int slotId = SubscriptionManager.getSlotIndex(subId);
mSatelliteModemInterface.setSatellitePlmn(slotId, carrierPlmnList,
SatelliteServiceUtils.mergeStrLists(
@@ -2979,6 +3067,7 @@
synchronized (mSupportedSatelliteServicesLock) {
mSatelliteServicesSupportedByCarriers.clear();
+ mMergedPlmnListPerCarrier.clear();
int[] activeSubIds = mSubscriptionManagerService.getActiveSubIdList(true);
if (activeSubIds != null) {
for (int subId : activeSubIds) {
@@ -2991,10 +3080,37 @@
}
}
+ /**
+ * If the entitlementPlmnList exist then used it.
+ * Otherwise, If the carrierPlmnList exist then used it.
+ */
+ private void updatePlmnListPerCarrier(int subId) {
+ synchronized (mSupportedSatelliteServicesLock) {
+ List<String> carrierPlmnList, entitlementPlmnList;
+ entitlementPlmnList = mEntitlementPlmnListPerCarrier.get(subId,
+ new ArrayList<>()).stream().toList();
+ if (!entitlementPlmnList.isEmpty()) {
+ mMergedPlmnListPerCarrier.put(subId, entitlementPlmnList);
+ logd("update it using entitlementPlmnList=" + entitlementPlmnList);
+ return;
+ }
+
+ if (mSatelliteServicesSupportedByCarriers.containsKey(subId)) {
+ carrierPlmnList =
+ mSatelliteServicesSupportedByCarriers.get(subId).keySet().stream().toList();
+ } else {
+ carrierPlmnList = new ArrayList<>();
+ }
+ mMergedPlmnListPerCarrier.put(subId, carrierPlmnList);
+ logd("update it using carrierPlmnList=" + carrierPlmnList);
+ }
+ }
+
private void updateSupportedSatelliteServices(int subId) {
synchronized (mSupportedSatelliteServicesLock) {
mSatelliteServicesSupportedByCarriers.put(
subId, readSupportedSatelliteServicesFromCarrierConfig(subId));
+ updatePlmnListPerCarrier(subId);
}
}
@@ -3045,6 +3161,8 @@
}
updateCarrierConfig(subId);
+ // TODO b/322143408 read the telephony db to get the entitlementStatus and update the
+ // restriction
updateSupportedSatelliteServicesForActiveSubscriptions();
configureSatellitePlmnForCarrier(subId);
@@ -3229,7 +3347,7 @@
* <ul>
* <li>Users want to enable it.</li>
* <li>There is no satellite communication restriction, which is added by
- * {@link #addSatelliteAttachRestrictionForCarrier(int, int, IIntegerConsumer)}</li>
+ * {@link #addAttachRestrictionForCarrier(int, int, IIntegerConsumer)}</li>
* <li>The carrier config {@link
* android.telephony.CarrierConfigManager#KEY_SATELLITE_ATTACH_SUPPORTED_BOOL} is set to
* {@code true}.</li>
@@ -3282,11 +3400,13 @@
return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
}
if (!mSatelliteModemInterface.isSatelliteServiceSupported()) {
+ logd("evaluateOemSatelliteRequestAllowed: satellite service is not supported");
return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
}
Boolean satelliteSupported = isSatelliteSupportedViaOemInternal();
if (satelliteSupported == null) {
+ logd("evaluateOemSatelliteRequestAllowed: satelliteSupported is null");
return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
}
if (!satelliteSupported) {
@@ -3296,6 +3416,7 @@
if (isProvisionRequired) {
Boolean satelliteProvisioned = isSatelliteViaOemProvisioned();
if (satelliteProvisioned == null) {
+ logd("evaluateOemSatelliteRequestAllowed: satelliteProvisioned is null");
return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
}
if (!satelliteProvisioned) {
@@ -3380,6 +3501,78 @@
}
}
+ private void persistOemEnabledSatelliteProvisionStatus(boolean isProvisioned) {
+ synchronized (mSatelliteViaOemProvisionLock) {
+ logd("persistOemEnabledSatelliteProvisionStatus: isProvisioned=" + isProvisioned);
+
+ if (!loadSatelliteSharedPreferences()) return;
+
+ if (mSharedPreferences == null) {
+ loge("persistOemEnabledSatelliteProvisionStatus: mSharedPreferences is null");
+ } else {
+ mSharedPreferences.edit().putBoolean(
+ OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY, isProvisioned).apply();
+ }
+ }
+ }
+
+ private boolean getPersistedOemEnabledSatelliteProvisionStatus() {
+ synchronized (mSatelliteViaOemProvisionLock) {
+ if (!loadSatelliteSharedPreferences()) return false;
+
+ if (mSharedPreferences == null) {
+ loge("getPersistedOemEnabledSatelliteProvisionStatus: mSharedPreferences is null");
+ return false;
+ } else {
+ return mSharedPreferences.getBoolean(
+ OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY, false);
+ }
+ }
+ }
+
+ private boolean loadSatelliteSharedPreferences() {
+ if (mSharedPreferences == null) {
+ try {
+ mSharedPreferences =
+ mContext.getSharedPreferences(SATELLITE_SHARED_PREF,
+ Context.MODE_PRIVATE);
+ } catch (Exception e) {
+ loge("loadSatelliteSharedPreferences: Cannot get default "
+ + "shared preferences, e=" + e);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void handleIsSatelliteProvisionedDoneEvent(@NonNull AsyncResult ar) {
+ SatelliteControllerHandlerRequest request = (SatelliteControllerHandlerRequest) ar.userObj;
+ int error = SatelliteServiceUtils.getSatelliteError(
+ ar, "handleIsSatelliteProvisionedDoneEvent");
+ boolean isSatelliteProvisionedInModem = false;
+ if (error == SATELLITE_RESULT_SUCCESS) {
+ if (ar.result == null) {
+ loge("handleIsSatelliteProvisionedDoneEvent: result is null");
+ error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
+ } else {
+ isSatelliteProvisionedInModem = ((int[]) ar.result)[0] == 1;
+ }
+ } else if (error == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) {
+ logd("handleIsSatelliteProvisionedDoneEvent: Modem does not support this request");
+ isSatelliteProvisionedInModem = true;
+ }
+ boolean isSatelliteViaOemProvisioned =
+ isSatelliteProvisionedInModem && getPersistedOemEnabledSatelliteProvisionStatus();
+ logd("isSatelliteProvisionedInModem=" + isSatelliteProvisionedInModem
+ + ", isSatelliteViaOemProvisioned=" + isSatelliteViaOemProvisioned);
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED, isSatelliteViaOemProvisioned);
+ synchronized (mSatelliteViaOemProvisionLock) {
+ mIsSatelliteViaOemProvisioned = isSatelliteViaOemProvisioned;
+ }
+ ((ResultReceiver) request.argument).send(error, bundle);
+ }
+
/**
* This API can be used by only CTS to override the cached value for the device overlay config
* value : config_send_satellite_datagram_to_modem_in_demo_mode, which determines whether
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
index 03481c6..900e124 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
@@ -915,18 +915,18 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("pollPendingSatelliteDatagrams: " + error);
+ logd("pollPendingDatagrams: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
});
} catch (RemoteException e) {
- loge("pollPendingSatelliteDatagrams: RemoteException " + e);
+ loge("pollPendingDatagrams: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("pollPendingSatelliteDatagrams: Satellite service is unavailable.");
+ loge("pollPendingDatagrams: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -951,18 +951,18 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("sendSatelliteDatagram: " + error);
+ logd("sendDatagram: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
});
} catch (RemoteException e) {
- loge("sendSatelliteDatagram: RemoteException " + e);
+ loge("sendDatagram: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("sendSatelliteDatagram: Satellite service is unavailable.");
+ loge("sendDatagram: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -1021,7 +1021,7 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("requestIsSatelliteCommunicationAllowedForCurrentLocation: "
+ logd("requestIsCommunicationAllowedForCurrentLocation: "
+ error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
@@ -1029,7 +1029,7 @@
}, new IBooleanConsumer.Stub() {
@Override
public void accept(boolean result) {
- logd("requestIsSatelliteCommunicationAllowedForCurrentLocation: "
+ logd("requestIsCommunicationAllowedForCurrentLocation: "
+ result);
Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
message, result,
@@ -1037,13 +1037,13 @@
}
});
} catch (RemoteException e) {
- loge("requestIsSatelliteCommunicationAllowedForCurrentLocation: RemoteException "
+ loge("requestIsCommunicationAllowedForCurrentLocation: RemoteException "
+ e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("requestIsSatelliteCommunicationAllowedForCurrentLocation: "
+ loge("requestIsCommunicationAllowedForCurrentLocation: "
+ "Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
@@ -1236,10 +1236,13 @@
}
}, new INtnSignalStrengthConsumer.Stub() {
@Override
- public void accept(NtnSignalStrength result) {
- logd("requestNtnSignalStrength: " + result);
+ public void accept(
+ android.telephony.satellite.stub.NtnSignalStrength result) {
+ NtnSignalStrength ntnSignalStrength =
+ SatelliteServiceUtils.fromNtnSignalStrength(result);
+ logd("requestNtnSignalStrength: " + ntnSignalStrength);
Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
- message, result,
+ message, ntnSignalStrength,
SatelliteManager.SATELLITE_RESULT_SUCCESS));
}
});
@@ -1318,6 +1321,13 @@
return mIsSatelliteServiceSupported;
}
+ /** Check if vendor satellite service is connected */
+ public boolean isSatelliteServiceConnected() {
+ synchronized (mLock) {
+ return (mSatelliteService != null);
+ }
+ }
+
/**
* This API can be used by only CTS to update satellite vendor service package name.
*
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteNetworkInfo.java b/src/java/com/android/internal/telephony/satellite/SatelliteNetworkInfo.java
new file mode 100644
index 0000000..7db9195
--- /dev/null
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteNetworkInfo.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.satellite;
+
+/**
+ * Data class of the satellite configuration received from the entitlement server.
+ */
+public class SatelliteNetworkInfo {
+ /** Stored the allowed plmn for using the satellite service. */
+ public String mPlmn;
+ /** Stored the DataPlanType. It is an optional value that can be one of the following three
+ * values.
+ * 1. "unmetered"
+ * 2. "metered"
+ * 3. empty string. */
+ public String mDataPlanType;
+
+ public SatelliteNetworkInfo(String plmn, String dataPlanType) {
+ mPlmn = plmn;
+ mDataPlanType = dataPlanType;
+ }
+}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
index f40880b..149b054 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
@@ -23,8 +23,6 @@
import static android.telephony.TelephonyManager.EXTRA_EMERGENCY_CALL_TO_SATELLITE_LAUNCH_INTENT;
import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS;
import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911;
-import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED;
-import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import static com.android.internal.telephony.satellite.SatelliteController.INVALID_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE;
@@ -39,7 +37,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.os.ResultReceiver;
+import android.os.OutcomeReceiver;
import android.os.SystemProperties;
import android.provider.DeviceConfig;
import android.telecom.Connection;
@@ -51,6 +49,7 @@
import android.telephony.ims.ImsRegistrationAttributes;
import android.telephony.ims.RegistrationManager;
import android.telephony.satellite.ISatelliteProvisionStateCallback;
+import android.telephony.satellite.SatelliteManager;
import android.text.TextUtils;
import android.util.Pair;
import android.util.SparseArray;
@@ -58,6 +57,7 @@
import com.android.ims.ImsException;
import com.android.ims.ImsManager;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
@@ -83,6 +83,7 @@
private static final int EVENT_SATELLITE_PROVISIONED_STATE_CHANGED = 4;
private static final int EVENT_EMERGENCY_CALL_CONNECTION_STATE_CHANGED = 5;
private static final int CMD_SEND_EVENT_DISPLAY_EMERGENCY_MESSAGE_FORCEFULLY = 6;
+ private static final int EVENT_SATELLITE_ACCESS_RESTRICTION_CHECKING_RESULT = 7;
@NonNull private final Context mContext;
@NonNull
@@ -94,12 +95,17 @@
/** Key: Phone ID; Value: IMS RegistrationCallback */
private SparseArray<RegistrationManager.RegistrationCallback>
mImsRegistrationCallbacks = new SparseArray<>();
- private AtomicBoolean mIsSatelliteAllowedInCurrentLocation = new AtomicBoolean();
- private final ResultReceiver mReceiverForRequestIsSatelliteAllowedForCurrentLocation;
+ @GuardedBy("mLock")
+ private boolean mIsSatelliteAllowedForCurrentLocation = false;
+ @GuardedBy("mLock")
+ private boolean mCheckingAccessRestrictionInProgress = false;
private final long mTimeoutMillis;
private final AtomicBoolean mIsSatelliteConnectedViaCarrierWithinHysteresisTime =
new AtomicBoolean(false);
+ @GuardedBy("mLock")
+ private boolean mIsTimerTimedOut = false;
protected int mCountOfTimerStarted = 0;
+ private final Object mLock = new Object();
/**
* Create an instance of SatelliteSOSMessageRecommender.
@@ -139,31 +145,6 @@
sendMessage(obtainMessage(EVENT_SATELLITE_PROVISIONED_STATE_CHANGED, provisioned));
}
};
- mReceiverForRequestIsSatelliteAllowedForCurrentLocation = new ResultReceiver(this) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- if (resultCode == SATELLITE_RESULT_SUCCESS) {
- if (resultData.containsKey(KEY_SATELLITE_COMMUNICATION_ALLOWED)) {
- boolean isSatelliteCommunicationAllowed =
- resultData.getBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED);
- mIsSatelliteAllowedInCurrentLocation.set(isSatelliteCommunicationAllowed);
- if (!isSatelliteCommunicationAllowed) {
- logd("Satellite is not allowed for current location.");
- cleanUpResources();
- }
- } else {
- loge("KEY_SATELLITE_COMMUNICATION_ALLOWED does not exist.");
- mIsSatelliteAllowedInCurrentLocation.set(false);
- cleanUpResources();
- }
- } else {
- loge("requestIsSatelliteCommunicationAllowedForCurrentLocation() resultCode="
- + resultCode);
- mIsSatelliteAllowedInCurrentLocation.set(false);
- cleanUpResources();
- }
- }
- };
}
@Override
@@ -187,6 +168,9 @@
case CMD_SEND_EVENT_DISPLAY_EMERGENCY_MESSAGE_FORCEFULLY:
handleCmdSendEventDisplayEmergencyMessageForcefully((Connection) msg.obj);
break;
+ case EVENT_SATELLITE_ACCESS_RESTRICTION_CHECKING_RESULT:
+ handleSatelliteAccessRestrictionCheckingResult((boolean) msg.obj);
+ break;
default:
logd("handleMessage: unexpected message code: " + msg.what);
break;
@@ -206,7 +190,7 @@
return;
}
- /**
+ /*
* Right now, assume that the device is connected to satellite via carrier within hysteresis
* time. However, this might not be correct when the monitoring timer expires. Thus, we
* should do this check now so that we have higher chance of sending the event
@@ -226,6 +210,7 @@
*/
public void onEmergencyCallConnectionStateChanged(
String callId, @Connection.ConnectionState int state) {
+ logd("callId=" + callId + ", state=" + state);
if (!mSatelliteController.isSatelliteSupportedViaOem()
&& !mSatelliteController.isSatelliteSupportedViaCarrier()) {
logd("onEmergencyCallConnectionStateChanged: satellite is not supported");
@@ -245,13 +230,14 @@
return;
}
if (mEmergencyConnection == null) {
- mSatelliteController.requestIsSatelliteCommunicationAllowedForCurrentLocation(
- SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
- mReceiverForRequestIsSatelliteAllowedForCurrentLocation);
handleStateChangedEventForHysteresisTimer();
registerForInterestedStateChangedEvents();
}
mEmergencyConnection = connection;
+ synchronized (mLock) {
+ mCheckingAccessRestrictionInProgress = false;
+ mIsSatelliteAllowedForCurrentLocation = false;
+ }
}
private void handleSatelliteProvisionStateChangedEvent(boolean provisioned) {
@@ -261,32 +247,59 @@
}
private void handleTimeoutEvent() {
- /**
- * The device might be connected to satellite after the emergency call started. Thus, we
- * need to do this check again so that we will have higher chance of sending the event
- * EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer.
- */
- updateSatelliteViaCarrierAvailability();
-
- boolean isDialerNotified = false;
- if (!isImsRegistered() && !isCellularAvailable()
- && mIsSatelliteAllowedInCurrentLocation.get()
- && (isSatelliteViaOemAvailable() || isSatelliteViaCarrierAvailable())
- && shouldTrackCall(mEmergencyConnection.getState())) {
- logd("handleTimeoutEvent: Sent EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer");
- Bundle extras = createExtraBundleForEventDisplayEmergencyMessage();
- mEmergencyConnection.sendConnectionEvent(
- TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE, extras);
- isDialerNotified = true;
-
+ synchronized (mLock) {
+ mIsTimerTimedOut = true;
+ evaluateSendingConnectionEventDisplayEmergencyMessage();
}
- logd("handleTimeoutEvent: isImsRegistered=" + isImsRegistered()
- + ", isCellularAvailable=" + isCellularAvailable()
- + ", mIsSatelliteAllowedInCurrentLocation="
- + mIsSatelliteAllowedInCurrentLocation.get()
- + ", shouldTrackCall=" + shouldTrackCall(mEmergencyConnection.getState()));
- reportEsosRecommenderDecision(isDialerNotified);
- cleanUpResources();
+ }
+
+ private void evaluateSendingConnectionEventDisplayEmergencyMessage() {
+ synchronized (mLock) {
+ if (mEmergencyConnection == null) {
+ loge("No emergency call is ongoing...");
+ return;
+ }
+
+ if (!mIsTimerTimedOut || mCheckingAccessRestrictionInProgress) {
+ logd("mIsTimerTimedOut=" + mIsTimerTimedOut
+ + ", mCheckingAccessRestrictionInProgress="
+ + mCheckingAccessRestrictionInProgress);
+ return;
+ }
+
+ /*
+ * The device might be connected to satellite after the emergency call started. Thus, we
+ * need to do this check again so that we will have higher chance of sending the event
+ * EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer.
+ */
+ updateSatelliteViaCarrierAvailability();
+
+ boolean isDialerNotified = false;
+ if (!isImsRegistered() && !isCellularAvailable()
+ && isSatelliteAllowed()
+ && (isSatelliteViaOemAvailable() || isSatelliteViaCarrierAvailable())
+ && shouldTrackCall(mEmergencyConnection.getState())) {
+ logd("handleTimeoutEvent: Sent EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer");
+ Bundle extras = createExtraBundleForEventDisplayEmergencyMessage();
+ mEmergencyConnection.sendConnectionEvent(
+ TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE, extras);
+ isDialerNotified = true;
+
+ }
+ logd("handleTimeoutEvent: isImsRegistered=" + isImsRegistered()
+ + ", isCellularAvailable=" + isCellularAvailable()
+ + ", isSatelliteAllowed=" + isSatelliteAllowed()
+ + ", shouldTrackCall=" + shouldTrackCall(mEmergencyConnection.getState()));
+ reportEsosRecommenderDecision(isDialerNotified);
+ cleanUpResources();
+ }
+ }
+
+ private boolean isSatelliteAllowed() {
+ synchronized (mLock) {
+ if (isSatelliteViaCarrierAvailable()) return true;
+ return mIsSatelliteAllowedForCurrentLocation;
+ }
}
private void updateSatelliteViaCarrierAvailability() {
@@ -317,7 +330,7 @@
loge("handleEmergencyCallConnectionStateChangedEvent: unexpected state changed event "
+ ", mEmergencyConnection=" + mEmergencyConnection + ", callId=" + callId
+ ", state=" + state);
- /**
+ /*
* TelephonyConnectionService sent us a connection state changed event for a call that
* we're not tracking. There must be some unexpected things happened in
* TelephonyConnectionService. Thus, we need to clean up the resources.
@@ -329,6 +342,13 @@
if (!shouldTrackCall(state)) {
reportEsosRecommenderDecision(false);
cleanUpResources();
+ } else {
+ // Location service will enter emergency mode only when connection state changes to
+ // STATE_DIALING
+ if (state == Connection.STATE_DIALING
+ && mSatelliteController.isSatelliteSupportedViaOem()) {
+ requestIsSatelliteAllowedForCurrentLocation();
+ }
}
}
@@ -341,18 +361,22 @@
.setCellularServiceState(getBestCellularServiceState())
.setIsMultiSim(isMultiSim())
.setRecommendingHandoverType(getEmergencyCallToSatelliteHandoverType())
- .setIsSatelliteAllowedInCurrentLocation(
- mIsSatelliteAllowedInCurrentLocation.get())
+ .setIsSatelliteAllowedInCurrentLocation(isSatelliteAllowed())
.build());
}
private void cleanUpResources() {
- stopTimer();
- if (mEmergencyConnection != null) {
- unregisterForInterestedStateChangedEvents();
+ synchronized (mLock) {
+ stopTimer();
+ if (mEmergencyConnection != null) {
+ unregisterForInterestedStateChangedEvents();
+ }
+ mEmergencyConnection = null;
+ mCountOfTimerStarted = 0;
+ mIsTimerTimedOut = false;
+ mCheckingAccessRestrictionInProgress = false;
+ mIsSatelliteAllowedForCurrentLocation = false;
}
- mEmergencyConnection = null;
- mCountOfTimerStarted = 0;
}
private void registerForInterestedStateChangedEvents() {
@@ -450,15 +474,28 @@
}
private void startTimer() {
- if (hasMessages(EVENT_TIME_OUT)) {
- return;
+ synchronized (mLock) {
+ if (hasMessages(EVENT_TIME_OUT)) {
+ return;
+ }
+ sendMessageDelayed(obtainMessage(EVENT_TIME_OUT), mTimeoutMillis);
+ mCountOfTimerStarted++;
+ mIsTimerTimedOut = false;
}
- sendMessageDelayed(obtainMessage(EVENT_TIME_OUT), mTimeoutMillis);
- mCountOfTimerStarted++;
}
private void stopTimer() {
- removeMessages(EVENT_TIME_OUT);
+ synchronized (mLock) {
+ removeMessages(EVENT_TIME_OUT);
+ }
+ }
+
+ private void handleSatelliteAccessRestrictionCheckingResult(boolean satelliteAllowed) {
+ synchronized (mLock) {
+ mIsSatelliteAllowedForCurrentLocation = satelliteAllowed;
+ mCheckingAccessRestrictionInProgress = false;
+ evaluateSendingConnectionEventDisplayEmergencyMessage();
+ }
}
private static long getEmergencyCallWaitForConnectionTimeoutMillis(@NonNull Context context) {
@@ -627,6 +664,42 @@
}
}
+ private void requestIsSatelliteAllowedForCurrentLocation() {
+ synchronized (mLock) {
+ if (mCheckingAccessRestrictionInProgress) {
+ logd("requestIsSatelliteCommunicationAllowedForCurrentLocation was already sent");
+ return;
+ }
+ mCheckingAccessRestrictionInProgress = true;
+ }
+
+ OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> callback =
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(Boolean result) {
+ logd("requestIsSatelliteAllowedForCurrentLocation: result=" + result);
+ sendMessage(obtainMessage(
+ EVENT_SATELLITE_ACCESS_RESTRICTION_CHECKING_RESULT, result));
+ }
+
+ @Override
+ public void onError(SatelliteManager.SatelliteException ex) {
+ logd("requestIsSatelliteAllowedForCurrentLocation: onError, ex=" + ex);
+ sendMessage(obtainMessage(
+ EVENT_SATELLITE_ACCESS_RESTRICTION_CHECKING_RESULT, false));
+ }
+ };
+ requestIsSatelliteCommunicationAllowedForCurrentLocation(callback);
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected void requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ @NonNull OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> callback) {
+ SatelliteManager satelliteManager = mContext.getSystemService(SatelliteManager.class);
+ satelliteManager.requestIsCommunicationAllowedForCurrentLocation(
+ this::post, callback);
+ }
+
private static boolean isMockModemAllowed() {
return (SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false)
|| SystemProperties.getBoolean(BOOT_ALLOW_MOCK_MODEM_PROPERTY, false));
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
index d0497eb..541a029 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
@@ -40,7 +40,7 @@
import android.os.RemoteException;
import android.os.SystemProperties;
import android.telephony.Rlog;
-import android.telephony.satellite.ISatelliteStateCallback;
+import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.stub.ISatelliteGateway;
import android.telephony.satellite.stub.SatelliteGatewayService;
@@ -130,7 +130,7 @@
private long mSatelliteStayAtListeningFromSendingMillis;
private long mSatelliteStayAtListeningFromReceivingMillis;
private long mSatelliteNbIotInactivityTimeoutMillis;
- private final ConcurrentHashMap<IBinder, ISatelliteStateCallback> mListeners;
+ private final ConcurrentHashMap<IBinder, ISatelliteModemStateCallback> mListeners;
@SatelliteManager.SatelliteModemState private int mCurrentState;
final boolean mIsSatelliteSupported;
private boolean mIsDemoMode = false;
@@ -272,7 +272,8 @@
*
* @param callback The callback to handle the satellite modem state changed event.
*/
- public void registerForSatelliteModemStateChanged(@NonNull ISatelliteStateCallback callback) {
+ public void registerForSatelliteModemStateChanged(
+ @NonNull ISatelliteModemStateCallback callback) {
try {
callback.onSatelliteModemStateChanged(mCurrentState);
mListeners.put(callback.asBinder(), callback);
@@ -286,9 +287,10 @@
* If callback was not registered before, the request will be ignored.
*
* @param callback The callback that was passed to
- * {@link #registerForSatelliteModemStateChanged(ISatelliteStateCallback)}.
+ * {@link #registerForSatelliteModemStateChanged(ISatelliteModemStateCallback)}.
*/
- public void unregisterForSatelliteModemStateChanged(@NonNull ISatelliteStateCallback callback) {
+ public void unregisterForSatelliteModemStateChanged(
+ @NonNull ISatelliteModemStateCallback callback) {
mListeners.remove(callback.asBinder());
}
@@ -809,7 +811,7 @@
private void notifyStateChangedEvent(@SatelliteManager.SatelliteModemState int state) {
mDatagramController.onSatelliteModemStateChanged(state);
- List<ISatelliteStateCallback> toBeRemoved = new ArrayList<>();
+ List<ISatelliteModemStateCallback> toBeRemoved = new ArrayList<>();
mListeners.values().forEach(listener -> {
try {
listener.onSatelliteModemStateChanged(state);
diff --git a/src/java/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifier.java b/src/java/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifier.java
index f1845c5..e7f66a3 100644
--- a/src/java/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifier.java
+++ b/src/java/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifier.java
@@ -18,47 +18,104 @@
import android.telephony.CellularIdentifierDisclosure;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.telephony.Rlog;
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
/**
* Encapsulates logic to emit notifications to the user that their cellular identifiers were
- * disclosed in the clear.
+ * disclosed in the clear. Callers add CellularIdentifierDisclosure instances by calling
+ * addDisclosure.
*
- * <p>This class will either emit notifications through SafetyCenterManager if SafetyCenter exists
- * on a device, or it will emit system notifications otherwise.
+ * <p>This class is thread safe and is designed to do costly work on worker threads. The intention
+ * is to allow callers to add disclosures from a Looper thread without worrying about blocking for
+ * IPC.
*
* @hide
*/
public class CellularIdentifierDisclosureNotifier {
private static final String TAG = "CellularIdentifierDisclosureNotifier";
+ private static final long DEFAULT_WINDOW_CLOSE_DURATION_IN_MINUTES = 15;
private static CellularIdentifierDisclosureNotifier sInstance = null;
+ private final long mWindowCloseDuration;
+ private final TimeUnit mWindowCloseUnit;
+ private final Object mEnabledLock = new Object();
+
+ @GuardedBy("mEnabledLock")
private boolean mEnabled = false;
+ // This is a single threaded executor. This is important because we want to ensure certain
+ // events are strictly serialized.
+ private ScheduledExecutorService mSerializedWorkQueue;
- @VisibleForTesting
- public CellularIdentifierDisclosureNotifier() {}
+ // This object should only be accessed from within the thread of mSerializedWorkQueue. Access
+ // outside of that thread would require additional synchronization.
+ private Map<Integer, DisclosureWindow> mWindows;
- /**
- * Add a CellularIdentifierDisclosure to be tracked by this instance.
- * If appropriate, this will trigger a user notification.
- */
- public void addDisclosure(CellularIdentifierDisclosure disclosure) {
- // TODO (b/308985417) this is a stub method for now. Logic
- // for tracking disclosures and emitting notifications will flow
- // from here.
- Rlog.d(TAG, "Identifier disclosure reported: " + disclosure);
+ public CellularIdentifierDisclosureNotifier() {
+ this(
+ Executors.newSingleThreadScheduledExecutor(),
+ DEFAULT_WINDOW_CLOSE_DURATION_IN_MINUTES,
+ TimeUnit.MINUTES);
}
/**
- * Get a singleton CellularIdentifierDisclosureNotifier.
+ * Construct a CellularIdentifierDisclosureNotifier by injection. This should only be used for
+ * testing.
+ *
+ * @param notificationQueue a ScheduledExecutorService that should only execute on a single
+ * thread.
*/
- public static synchronized CellularIdentifierDisclosureNotifier getInstance() {
- if (sInstance == null) {
- sInstance = new CellularIdentifierDisclosureNotifier();
- }
+ @VisibleForTesting
+ public CellularIdentifierDisclosureNotifier(
+ ScheduledExecutorService notificationQueue,
+ long windowCloseDuration,
+ TimeUnit windowCloseUnit) {
+ mSerializedWorkQueue = notificationQueue;
+ mWindowCloseDuration = windowCloseDuration;
+ mWindowCloseUnit = windowCloseUnit;
+ mWindows = new HashMap<>();
+ }
- return sInstance;
+ /**
+ * Add a CellularIdentifierDisclosure to be tracked by this instance. If appropriate, this will
+ * trigger a user notification.
+ */
+ public void addDisclosure(int subId, CellularIdentifierDisclosure disclosure) {
+ Rlog.d(TAG, "Identifier disclosure reported: " + disclosure);
+
+ synchronized (mEnabledLock) {
+ if (!mEnabled) {
+ Rlog.d(TAG, "Skipping disclosure because notifier was disabled.");
+ return;
+ }
+
+ // Don't notify if this disclosure happened in service of an emergency. That's a user
+ // initiated action that we don't want to interfere with.
+ if (disclosure.isEmergency()) {
+ Rlog.i(TAG, "Ignoring identifier disclosure associated with an emergency.");
+ return;
+ }
+
+ // Schedule incrementAndNotify from within the lock because we're sure at this point
+ // that we're enabled. This allows incrementAndNotify to avoid re-checking mEnabled
+ // because we know that any actions taken on disabled will be scheduled after this
+ // incrementAndNotify call.
+ try {
+ mSerializedWorkQueue.execute(incrementAndNotify(subId));
+ } catch (RejectedExecutionException e) {
+ Rlog.e(TAG, "Failed to schedule incrementAndNotify: " + e.getMessage());
+ }
+ } // end mEnabledLock
}
/**
@@ -66,8 +123,15 @@
* disclosures again and potentially emitting notifications.
*/
public void enable() {
- Rlog.d(TAG, "enabled");
- mEnabled = true;
+ synchronized (mEnabledLock) {
+ Rlog.d(TAG, "enabled");
+ mEnabled = true;
+ try {
+ mSerializedWorkQueue.execute(onEnableNotifier());
+ } catch (RejectedExecutionException e) {
+ Rlog.e(TAG, "Failed to schedule onEnableNotifier: " + e.getMessage());
+ }
+ }
}
/**
@@ -77,10 +141,221 @@
*/
public void disable() {
Rlog.d(TAG, "disabled");
- mEnabled = false;
+ synchronized (mEnabledLock) {
+ mEnabled = false;
+ try {
+ mSerializedWorkQueue.execute(onDisableNotifier());
+ } catch (RejectedExecutionException e) {
+ Rlog.e(TAG, "Failed to schedule onDisableNotifier: " + e.getMessage());
+ }
+ }
}
public boolean isEnabled() {
- return mEnabled;
+ synchronized (mEnabledLock) {
+ return mEnabled;
+ }
+ }
+
+ /** Get a singleton CellularIdentifierDisclosureNotifier. */
+ public static synchronized CellularIdentifierDisclosureNotifier getInstance() {
+ if (sInstance == null) {
+ sInstance = new CellularIdentifierDisclosureNotifier();
+ }
+
+ return sInstance;
+ }
+
+ private Runnable incrementAndNotify(int subId) {
+ return () -> {
+ DisclosureWindow window = mWindows.get(subId);
+ if (window == null) {
+ window = new DisclosureWindow(subId);
+ mWindows.put(subId, window);
+ }
+
+ window.increment(this);
+
+ int disclosureCount = window.getDisclosureCount();
+
+ Rlog.d(
+ TAG,
+ "Emitting notification for subId: "
+ + subId
+ + ". New disclosure count "
+ + disclosureCount);
+
+ // TODO (b/308985417) emit safety center issue
+ // mSafetySource.setIdentifierDisclosure(
+ // subId,
+ // disclosureCount,
+ // window.getFirstOpen(),
+ // window.getCurrentEnd());
+ };
+ }
+
+ private Runnable onDisableNotifier() {
+ return () -> {
+ Rlog.d(TAG, "On disable notifier");
+ for (DisclosureWindow window : mWindows.values()) {
+ window.close();
+ }
+ // TODO (b/308985417) disable safety center issues
+ // mSafetySource.setIdentifierDisclosureIssueEnabled(false);
+ };
+ }
+
+ private Runnable onEnableNotifier() {
+ return () -> {
+ Rlog.i(TAG, "On enable notifier");
+ // TODO (b/308985417) enable safety center issues
+ // mSafetySource.setIdentifierDisclosureIssueEnabled(true);
+ };
+ }
+
+ /**
+ * Get the disclosure count for a given subId. NOTE: This method is not thread safe. Without
+ * external synchronization, one should only call it if there are no pending tasks on the
+ * Executor passed into this class.
+ */
+ @VisibleForTesting
+ public int getCurrentDisclosureCount(int subId) {
+ DisclosureWindow window = mWindows.get(subId);
+ if (window != null) {
+ return window.getDisclosureCount();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Get the open time for a given subId. NOTE: This method is not thread safe. Without
+ * external synchronization, one should only call it if there are no pending tasks on the
+ * Executor passed into this class.
+ */
+ @VisibleForTesting
+ public Instant getFirstOpen(int subId) {
+ DisclosureWindow window = mWindows.get(subId);
+ if (window != null) {
+ return window.getFirstOpen();
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the current end time for a given subId. NOTE: This method is not thread safe. Without
+ * external synchronization, one should only call it if there are no pending tasks on the
+ * Executor passed into this class.
+ */
+ @VisibleForTesting
+ public Instant getCurrentEnd(int subId) {
+ DisclosureWindow window = mWindows.get(subId);
+ if (window != null) {
+ return window.getCurrentEnd();
+ }
+
+ return null;
+ }
+
+ /**
+ * A helper class that maintains all state associated with the disclosure window for a single
+ * subId. No methods are thread safe. Callers must implement all synchronization.
+ */
+ private static class DisclosureWindow {
+ private int mDisclosureCount;
+ private Instant mWindowFirstOpen;
+ private Instant mLastEvent;
+ private ScheduledFuture<?> mWhenWindowCloses;
+
+ private int mSubId;
+
+ DisclosureWindow(int subId) {
+ mDisclosureCount = 0;
+ mWindowFirstOpen = null;
+ mLastEvent = null;
+ mSubId = subId;
+ mWhenWindowCloses = null;
+ }
+
+ void increment(CellularIdentifierDisclosureNotifier notifier) {
+
+ mDisclosureCount++;
+
+ Instant now = Instant.now();
+ if (mDisclosureCount == 1) {
+ // Our window was opened for the first time
+ mWindowFirstOpen = now;
+ }
+
+ mLastEvent = now;
+
+ cancelWindowCloseFuture();
+
+ try {
+ mWhenWindowCloses =
+ notifier.mSerializedWorkQueue.schedule(
+ closeWindowRunnable(),
+ notifier.mWindowCloseDuration,
+ notifier.mWindowCloseUnit);
+ } catch (RejectedExecutionException e) {
+ Rlog.e(
+ TAG,
+ "Failed to schedule closeWindow for subId "
+ + mSubId
+ + " : "
+ + e.getMessage());
+ }
+ }
+
+ int getDisclosureCount() {
+ return mDisclosureCount;
+ }
+
+ Instant getFirstOpen() {
+ return mWindowFirstOpen;
+ }
+
+ Instant getCurrentEnd() {
+ return mLastEvent;
+ }
+
+ void close() {
+ mDisclosureCount = 0;
+ mWindowFirstOpen = null;
+ mLastEvent = null;
+
+ if (mWhenWindowCloses == null) {
+ return;
+ }
+ mWhenWindowCloses = null;
+ }
+
+ private Runnable closeWindowRunnable() {
+ return () -> {
+ Rlog.i(
+ TAG,
+ "Disclosure window closing for subId "
+ + mSubId
+ + ". Disclosure count was "
+ + getDisclosureCount());
+ close();
+
+ // TODO (b/308985417) clear safety center issue
+ // mSafetySource.setIdentifierDisclosure(mSubId, 0, null, null);
+ };
+ }
+
+ private boolean cancelWindowCloseFuture() {
+ if (mWhenWindowCloses == null) {
+ return false;
+ }
+
+ // Pass false to not interrupt a running Future. Nothing about our notifier is ready
+ // for this type of preemption.
+ return mWhenWindowCloses.cancel(false);
+ }
+
}
}
+
diff --git a/src/java/com/android/internal/telephony/security/NullCipherNotifier.java b/src/java/com/android/internal/telephony/security/NullCipherNotifier.java
new file mode 100644
index 0000000..0ab8299
--- /dev/null
+++ b/src/java/com/android/internal/telephony/security/NullCipherNotifier.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.security;
+
+import android.telephony.SecurityAlgorithmUpdate;
+
+import com.android.telephony.Rlog;
+
+/**
+ * Encapsulates logic to emit notifications to the user that a null cipher is in use. A null cipher
+ * is one that does not attempt to implement any encryption.
+ *
+ * <p>This class will either emit notifications through SafetyCenterManager if SafetyCenter exists
+ * on a device, or it will emit system notifications otherwise.
+ *
+ * @hide
+ */
+public class NullCipherNotifier {
+
+ private static final String TAG = "NullCipherNotifier";
+ private static NullCipherNotifier sInstance;
+
+ private boolean mEnabled = false;
+
+ /**
+ * Gets a singleton NullCipherNotifier.
+ */
+ public static synchronized NullCipherNotifier getInstance() {
+ if (sInstance == null) {
+ sInstance = new NullCipherNotifier();
+ }
+ return sInstance;
+ }
+
+ private NullCipherNotifier() {}
+
+ /**
+ * Adds a security algorithm update. If appropriate, this will trigger a user notification.
+ */
+ public void onSecurityAlgorithmUpdate(int phoneId, SecurityAlgorithmUpdate update) {
+ // TODO (b/315005938) this is a stub method for now. Logic
+ // for tracking disclosures and emitting notifications will flow
+ // from here.
+ Rlog.d(TAG, "Security algorithm update: phoneId = " + phoneId + " " + update);
+ }
+
+ /**
+ * Enables null cipher notification; {@code onSecurityAlgorithmUpdate} will start handling
+ * security algorithm updates and send notifications to the user when required.
+ */
+ public void enable() {
+ Rlog.d(TAG, "enabled");
+ mEnabled = true;
+ }
+
+ /**
+ * Clear all internal state and prevent further notifications until re-enabled. This can be
+ * used in response to a user disabling the feature for null cipher notifications. If
+ * {@code onSecurityAlgorithmUpdate} is called while in a disabled state, security algorithm
+ * updates will be dropped.
+ */
+ public void disable() {
+ Rlog.d(TAG, "disabled");
+ mEnabled = false;
+ }
+
+ public boolean isEnabled() {
+ return mEnabled;
+ }
+}
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
index 7b927f2..bbe88a8 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
@@ -281,7 +281,10 @@
SubscriptionInfoInternal::getSatelliteAttachEnabledForCarrier),
new AbstractMap.SimpleImmutableEntry<>(
SimInfo.COLUMN_IS_NTN,
- SubscriptionInfoInternal::getOnlyNonTerrestrialNetwork)
+ SubscriptionInfoInternal::getOnlyNonTerrestrialNetwork),
+ new AbstractMap.SimpleImmutableEntry<>(
+ SimInfo.COLUMN_SERVICE_CAPABILITIES,
+ SubscriptionInfoInternal::getServiceCapabilities)
);
/**
@@ -412,7 +415,10 @@
SubscriptionDatabaseManager::setSatelliteAttachEnabledForCarrier),
new AbstractMap.SimpleImmutableEntry<>(
SimInfo.COLUMN_IS_NTN,
- SubscriptionDatabaseManager::setNtn)
+ SubscriptionDatabaseManager::setNtn),
+ new AbstractMap.SimpleImmutableEntry<>(
+ SimInfo.COLUMN_SERVICE_CAPABILITIES,
+ SubscriptionDatabaseManager::setServiceCapabilities)
);
/**
@@ -2056,7 +2062,7 @@
*/
public void setGroupDisabled(int subId, boolean isGroupDisabled) {
// group disabled does not have a corresponding SimInfo column. So we only update the cache.
-
+ boolean isChanged = false;
// Grab the write lock so no other threads can read or write the cache.
mReadWriteLock.writeLock().lock();
try {
@@ -2065,12 +2071,31 @@
throw new IllegalArgumentException("setGroupDisabled: Subscription doesn't exist. "
+ "subId=" + subId);
}
+ isChanged = subInfoCache.isGroupDisabled() != isGroupDisabled;
mAllSubscriptionInfoInternalCache.put(subId,
new SubscriptionInfoInternal.Builder(subInfoCache)
.setGroupDisabled(isGroupDisabled).build());
} finally {
mReadWriteLock.writeLock().unlock();
}
+
+ if (isChanged) {
+ log("setGroupDisabled value changed, firing the callback");
+ mCallback.invokeFromExecutor(() -> mCallback.onSubscriptionChanged(subId));
+ }
+ }
+
+ /**
+ * Set service capabilities the subscription support.
+ * @param subId Subscription id.
+ * @param capabilities Service capabilities bitmasks
+ */
+ public void setServiceCapabilities(int subId, int capabilities) {
+ if (!mFeatureFlags.dataOnlyCellularService()) {
+ return;
+ }
+ writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_SERVICE_CAPABILITIES,
+ capabilities, SubscriptionInfoInternal.Builder::setServiceCapabilities);
}
/**
@@ -2302,7 +2327,10 @@
SimInfo.COLUMN_SATELLITE_ENABLED)))
.setSatelliteAttachEnabledForCarrier(cursor.getInt(
cursor.getColumnIndexOrThrow(
- SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER)));
+ SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER)))
+ .setServiceCapabilities(cursor.getInt(
+ cursor.getColumnIndexOrThrow(
+ SimInfo.COLUMN_SERVICE_CAPABILITIES)));
if (mFeatureFlags.oemEnabledSatelliteFlag()) {
builder.setOnlyNonTerrestrialNetwork(cursor.getInt(cursor.getColumnIndexOrThrow(
SimInfo.COLUMN_IS_NTN)));
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
index f08a659..aa460d5 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
@@ -444,7 +444,7 @@
/**
* Whether satellite attach for carrier is enabled or disabled by user.
- * By default, its disabled. It is intended to use integer to fit the database format.
+ * By default, its enabled. It is intended to use integer to fit the database format.
*/
private final int mIsSatelliteAttachEnabledForCarrier;
@@ -469,6 +469,11 @@
private final boolean mIsGroupDisabled;
/**
+ * Service capabilities (in the form of bitmask combination) the subscription supports.
+ */
+ private final int mServiceCapabilities;
+
+ /**
* Constructor from builder.
*
* @param builder Builder of {@link SubscriptionInfoInternal}.
@@ -543,6 +548,7 @@
// Below are the fields that do not exist in the SimInfo table.
this.mCardId = builder.mCardId;
this.mIsGroupDisabled = builder.mIsGroupDisabled;
+ this.mServiceCapabilities = builder.mServiceCapabilities;
}
/**
@@ -1193,6 +1199,13 @@
return !isOpportunistic() || TextUtils.isEmpty(mGroupUuid);
}
+ /**
+ * Return the service capabilities bitmasks the subscription supports.
+ */
+ public int getServiceCapabilities() {
+ return mServiceCapabilities;
+ }
+
/** @return converted {@link SubscriptionInfo}. */
@NonNull
public SubscriptionInfo toSubscriptionInfo() {
@@ -1229,6 +1242,8 @@
.setPortIndex(mPortIndex)
.setUsageSetting(mUsageSetting)
.setOnlyNonTerrestrialNetwork(mIsOnlyNonTerrestrialNetwork == 1)
+ .setServiceCapabilities(
+ SubscriptionManager.getServiceCapabilitiesSet(mServiceCapabilities))
.build();
}
@@ -1288,6 +1303,7 @@
+ " satellite_attach_enabled_for_carrier=" + mIsSatelliteAttachEnabledForCarrier
+ " getOnlyNonTerrestrialNetwork=" + mIsOnlyNonTerrestrialNetwork
+ " isGroupDisabled=" + mIsGroupDisabled
+ + " serviceCapabilities=" + mServiceCapabilities
+ "]";
}
@@ -1344,7 +1360,8 @@
that.mDeviceToDeviceStatusSharingContacts) && mNumberFromCarrier.equals(
that.mNumberFromCarrier) && mNumberFromIms.equals(that.mNumberFromIms)
&& mIsSatelliteAttachEnabledForCarrier == that.mIsSatelliteAttachEnabledForCarrier
- && mIsOnlyNonTerrestrialNetwork == that.mIsOnlyNonTerrestrialNetwork;
+ && mIsOnlyNonTerrestrialNetwork == that.mIsOnlyNonTerrestrialNetwork
+ && mServiceCapabilities == that.mServiceCapabilities;
}
@Override
@@ -1366,7 +1383,8 @@
mNumberFromCarrier,
mNumberFromIms, mPortIndex, mUsageSetting, mLastUsedTPMessageReference, mUserId,
mIsSatelliteEnabled, mCardId, mIsGroupDisabled,
- mIsSatelliteAttachEnabledForCarrier, mIsOnlyNonTerrestrialNetwork);
+ mIsSatelliteAttachEnabledForCarrier, mIsOnlyNonTerrestrialNetwork,
+ mServiceCapabilities);
result = 31 * result + Arrays.hashCode(mNativeAccessRules);
result = 31 * result + Arrays.hashCode(mCarrierConfigAccessRules);
result = 31 * result + Arrays.hashCode(mRcsConfig);
@@ -1732,7 +1750,7 @@
/**
* Whether satellite attach for carrier is enabled by user.
*/
- private int mIsSatelliteAttachEnabledForCarrier = 0;
+ private int mIsSatelliteAttachEnabledForCarrier = 1;
/**
* Whether this subscription is used for communicating with non-terrestrial network or not.
@@ -1754,6 +1772,11 @@
private boolean mIsGroupDisabled;
/**
+ * Service capabilities the subscription supports
+ */
+ private int mServiceCapabilities;
+
+ /**
* Default constructor.
*/
public Builder() {
@@ -1831,6 +1854,7 @@
// Below are the fields that do not exist in the SimInfo table.
mCardId = info.mCardId;
mIsGroupDisabled = info.mIsGroupDisabled;
+ mServiceCapabilities = info.mServiceCapabilities;
}
/**
@@ -2753,6 +2777,16 @@
}
/**
+ * Set the service capabilities the subscription supports.
+ * @param capabilities Cellular service capabilities bitmasks
+ * @return The builder
+ */
+ public Builder setServiceCapabilities(int capabilities) {
+ mServiceCapabilities = capabilities;
+ return this;
+ }
+
+ /**
* Build the {@link SubscriptionInfoInternal}.
*
* @return The {@link SubscriptionInfoInternal} instance.
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
index a8d05a3..ddf80a8 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
@@ -16,6 +16,9 @@
package com.android.internal.telephony.subscription;
+import static android.content.pm.PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION;
+import static android.telephony.TelephonyManager.ENABLE_FEATURE_MAPPING;
+
import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.ColorInt;
@@ -249,6 +252,10 @@
@Nullable
private EuiccController mEuiccController;
+ /** Package manager instance. */
+ @NonNull
+ private final PackageManager mPackageManager;
+
/**
* The main handler of subscription manager service. This is running on phone process's main
* thread.
@@ -455,6 +462,7 @@
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
mEuiccManager = context.getSystemService(EuiccManager.class);
mAppOpsManager = context.getSystemService(AppOpsManager.class);
+ mPackageManager = context.getPackageManager();
mUiccController = UiccController.getInstance();
mHandler = new Handler(looper);
@@ -1162,6 +1170,17 @@
builder.setDisplayNameSource(SubscriptionManager.NAME_SOURCE_CARRIER);
}
+ boolean isSatelliteSpn = false;
+ if (mFeatureFlags.oemEnabledSatelliteFlag() ) {
+ if (isSatelliteSpn(embeddedProfile.getServiceProviderName())) {
+ isSatelliteSpn = true;
+ builder.setOnlyNonTerrestrialNetwork(1);
+ }
+ } else {
+ log("updateEmupdateEmbeddedSubscriptions: oemEnabledSatelliteFlag is "
+ + "disabled");
+ }
+
if (android.os.Build.isDebuggable() &&
SystemProperties.getInt("telephony.test.bootstrap_cid", -2)
== carrierId) {
@@ -1186,11 +1205,9 @@
String mnc = cid.getMnc();
builder.setMcc(mcc);
builder.setMnc(mnc);
- if (mFeatureFlags.oemEnabledSatelliteFlag()) {
+ if (mFeatureFlags.oemEnabledSatelliteFlag() && !isSatelliteSpn) {
builder.setOnlyNonTerrestrialNetwork(
isSatellitePlmn(mcc + mnc) ? 1 : 0);
- } else {
- log("updateEmbeddedSubscriptions: oemEnabledSatelliteFlag is disabled");
}
}
// If cardId = unsupported or un-initialized, we have no reason to update DB.
@@ -1463,7 +1480,6 @@
MccTable.updateMccMncConfiguration(mContext, mccMnc);
}
setMccMnc(subId, mccMnc);
- setNtn(subId, isSatellitePlmn(mccMnc));
} else {
loge("updateSubscription: mcc/mnc is empty");
}
@@ -1700,6 +1716,39 @@
preferredUsageSetting)
+ " newSetting=" + SubscriptionManager.usageSettingToString(newUsageSetting));
}
+
+ if (mFeatureFlags.dataOnlyCellularService()) {
+ final int[] servicesFromCarrierConfig =
+ config.getIntArray(
+ CarrierConfigManager.KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY);
+ int serviceBitmasks = 0;
+ boolean allServicesAreValid = true;
+ // Check if all services from carrier config are valid before setting to db
+ if (servicesFromCarrierConfig == null) {
+ allServicesAreValid = false;
+ } else {
+ for (int service : servicesFromCarrierConfig) {
+ if (service < SubscriptionManager.SERVICE_CAPABILITY_VOICE
+ || service > SubscriptionManager.SERVICE_CAPABILITY_MAX) {
+ allServicesAreValid = false;
+ break;
+ } else {
+ serviceBitmasks |= SubscriptionManager.serviceCapabilityToBitmask(service);
+ }
+ }
+ }
+ // In case we get invalid service override, fall back to default value.
+ // DO NOT throw exception which will crash phone process.
+ if (!allServicesAreValid) {
+ serviceBitmasks = SubscriptionManager.getAllServiceCapabilityBitmasks();
+ }
+
+ if (serviceBitmasks != subInfo.getServiceCapabilities()) {
+ log("updateSubscriptionByCarrierConfig: serviceCapabilities updated from "
+ + subInfo.getServiceCapabilities() + " to " + serviceBitmasks);
+ mSubscriptionDatabaseManager.setServiceCapabilities(subId, serviceBitmasks);
+ }
+ }
}
/**
@@ -1744,6 +1793,9 @@
throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or "
+ "carrier privilege");
}
+
+ enforceTelephonyFeatureWithException(callingPackage, "getAllSubInfoList");
+
return getSubscriptionInfoStreamAsUser(BINDER_WRAPPER.getCallingUserHandle())
// callers have READ_PHONE_STATE or READ_PRIVILEGED_PHONE_STATE can get a full
// list. Carrier apps can only get the subscriptions they have privileged.
@@ -1786,6 +1838,8 @@
+ "carrier privilege");
}
+ enforceTelephonyFeatureWithException(callingPackage, "getActiveSubscriptionInfo");
+
SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
.getSubscriptionInfoInternal(subId);
if (subInfo != null && subInfo.isActive()) {
@@ -1814,6 +1868,8 @@
enforcePermissions("getActiveSubscriptionInfoForIccId",
Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ enforceTelephonyFeatureWithException(callingPackage, "getActiveSubscriptionInfoForIccId");
+
final long identity = Binder.clearCallingIdentity();
try {
iccId = IccUtils.stripTrailingFs(iccId);
@@ -1858,6 +1914,9 @@
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ "getActiveSubscriptionInfoForSimSlotIndex");
+
if (!SubscriptionManager.isValidSlotIndex(slotIndex)) {
throw new IllegalArgumentException("Invalid slot index " + slotIndex);
}
@@ -1907,10 +1966,11 @@
+ "permission. Returning empty list here.");
return Collections.emptyList();
}
- if (isForAllProfiles && !hasAcrossAllUsersPermission()) {
- //TODO(b/308809058 to determine whether the permission enforcement is needed)
- loge("getActiveSubscriptionInfoList: "
- + callingPackage + " has no appropriate permission.");
+
+ enforceTelephonyFeatureWithException(callingPackage, "getActiveSubscriptionInfoList");
+
+ if (isForAllProfiles) {
+ enforcePermissionAccessAllUserProfiles();
}
return getSubscriptionInfoStreamAsUser(isForAllProfiles
? UserHandle.ALL : BINDER_WRAPPER.getCallingUserHandle())
@@ -1951,18 +2011,21 @@
throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or "
+ "carrier privilege");
}
- if (isForAllProfiles && !hasAcrossAllUsersPermission()) {
- //TODO(b/308809058 to determine whether the permission enforcement is needed)
- loge("getActiveSubInfoCount: "
- + callingPackage + " has no appropriate permission.");
+ if (isForAllProfiles) {
+ enforcePermissionAccessAllUserProfiles();
}
+
+ enforceTelephonyFeatureWithException(callingPackage, "getActiveSubInfoCount");
+
return getActiveSubIdListAsUser(false, isForAllProfiles
? UserHandle.ALL : BINDER_WRAPPER.getCallingUserHandle()).length;
}
- /**@return {@code true} if the caller is permitted to see all subscriptions. */
- private boolean hasAcrossAllUsersPermission() {
- return hasPermissions(Manifest.permission.INTERACT_ACROSS_USERS,
+ /** @throws SecurityException if caller doesn't have one of the requested permissions. */
+ private void enforcePermissionAccessAllUserProfiles() {
+ if (!mFeatureFlags.enforceSubscriptionUserFilter()) return;
+ enforcePermissions("To access across profiles",
+ Manifest.permission.INTERACT_ACROSS_USERS,
Manifest.permission.INTERACT_ACROSS_USERS_FULL,
Manifest.permission.INTERACT_ACROSS_PROFILES);
}
@@ -1995,6 +2058,9 @@
@Nullable String callingFeatureId) {
enforcePermissions("getAvailableSubscriptionInfoList",
Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+
+ enforceTelephonyFeatureWithException(callingPackage, "getAvailableSubscriptionInfoList");
+
return getAvailableSubscriptionsInternalStream()
.sorted(Comparator.comparing(SubscriptionInfoInternal::getSimSlotIndex)
.thenComparing(SubscriptionInfoInternal::getSubscriptionId))
@@ -2079,6 +2145,8 @@
*/
@Override
public void requestEmbeddedSubscriptionInfoListRefresh(int cardId) {
+ enforcePermissions("requestEmbeddedSubscriptionInfoListRefresh",
+ Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS);
updateEmbeddedSubscriptions(List.of(cardId), null);
}
@@ -2104,6 +2172,8 @@
+ SubscriptionManager.subscriptionTypeToString(subscriptionType) + ", "
+ getCallingPackage());
+ enforceTelephonyFeatureWithException(getCurrentPackageName(), "addSubInfo");
+
// Now that all security checks passes, perform the operation as ourselves.
final long identity = Binder.clearCallingIdentity();
try {
@@ -2159,6 +2229,9 @@
logl("removeSubInfo: uniqueId=" + SubscriptionInfo.getPrintableId(uniqueId) + ", "
+ SubscriptionManager.subscriptionTypeToString(subscriptionType) + ", "
+ getCallingPackage());
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(), "removeSubInfo");
+
final long identity = Binder.clearCallingIdentity();
try {
SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
@@ -2382,6 +2455,8 @@
mContext, Binder.getCallingUid(), subId, true, "setOpportunistic",
Manifest.permission.MODIFY_PHONE_STATE);
+ enforceTelephonyFeatureWithException(callingPackage, "setOpportunistic");
+
long token = Binder.clearCallingIdentity();
try {
mSubscriptionDatabaseManager.setOpportunistic(subId, opportunistic);
@@ -2434,6 +2509,8 @@
+ " carrier privilege permission on all specified subscriptions");
}
+ enforceTelephonyFeatureWithException(callingPackage, "createSubscriptionGroup");
+
long identity = Binder.clearCallingIdentity();
try {
@@ -2470,6 +2547,10 @@
@Nullable ISetOpportunisticDataCallback callback) {
enforcePermissions("setPreferredDataSubscriptionId",
Manifest.permission.MODIFY_PHONE_STATE);
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ "setPreferredDataSubscriptionId");
+
final long token = Binder.clearCallingIdentity();
try {
@@ -2556,6 +2637,8 @@
return Collections.emptyList();
}
+ enforceTelephonyFeatureWithException(callingPackage, "getOpportunisticSubscriptions");
+
return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
// callers have READ_PHONE_STATE or READ_PRIVILEGED_PHONE_STATE can get a full
// list. Carrier apps can only get the subscriptions they have privileged.
@@ -2608,6 +2691,8 @@
throw new IllegalArgumentException("subIdList is empty.");
}
+ enforceTelephonyFeatureWithException(callingPackage, "removeSubscriptionsFromGroup");
+
long identity = Binder.clearCallingIdentity();
try {
@@ -2690,6 +2775,8 @@
+ " permissions on subscriptions and the group.");
}
+ enforceTelephonyFeatureWithException(callingPackage, "addSubscriptionsIntoGroup");
+
long identity = Binder.clearCallingIdentity();
try {
@@ -2759,6 +2846,8 @@
}
}
+ enforceTelephonyFeatureWithException(callingPackage, "getSubscriptionsInGroup");
+
return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
.map(SubscriptionInfoInternal::toSubscriptionInfo)
.filter(info -> groupUuid.equals(info.getGroupUuid())
@@ -2869,6 +2958,9 @@
*/
@Override
public int getDefaultSubIdAsUser(@UserIdInt int userId) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ "getDefaultVoiceSubIdAsUser");
+
return getDefaultAsUser(userId, mDefaultSubId.get());
}
@@ -2879,6 +2971,7 @@
* @return The subscription Id default to use.
*/
private int getDefaultAsUser(@UserIdInt int userId, int defaultValue) {
+ // TODO: Not using mFlags.enforceSubscriptionUserFilter because this affects U CTS.
if (mFeatureFlags.workProfileApiSplit()) {
List<SubscriptionInfoInternal> subInfos =
getSubscriptionInfoStreamAsUser(UserHandle.of(userId))
@@ -2944,6 +3037,8 @@
throw new RuntimeException("setDefaultDataSubId called with DEFAULT_SUBSCRIPTION_ID");
}
+ enforceTelephonyFeatureWithException(getCurrentPackageName(), "setDefaultDataSubId");
+
final long token = Binder.clearCallingIdentity();
try {
if (mDefaultDataSubId.set(subId)) {
@@ -3012,6 +3107,8 @@
throw new RuntimeException("setDefaultVoiceSubId called with DEFAULT_SUB_ID");
}
+ enforceTelephonyFeatureWithException(getCurrentPackageName(), "setDefaultVoiceSubId");
+
final long token = Binder.clearCallingIdentity();
try {
if (mDefaultVoiceSubId.set(subId)) {
@@ -3072,6 +3169,8 @@
throw new RuntimeException("setDefaultSmsSubId called with DEFAULT_SUB_ID");
}
+ enforceTelephonyFeatureWithException(getCurrentPackageName(), "setDefaultSmsSubId");
+
final long token = Binder.clearCallingIdentity();
try {
if (mDefaultSmsSubId.set(subId)) {
@@ -3110,6 +3209,9 @@
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public int[] getActiveSubIdList(boolean visibleOnly) {
enforcePermissions("getActiveSubIdList", Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(), "getActiveSubIdList");
+
// UserHandle.ALL because this API is exposed as system API.
return getActiveSubIdListAsUser(visibleOnly, UserHandle.ALL);
}
@@ -3221,6 +3323,8 @@
+ "accessed through getSubscriptionProperty.");
}
+ enforceTelephonyFeatureWithException(callingPackage, "getSubscriptionProperty");
+
final long token = Binder.clearCallingIdentity();
try {
Object value = mSubscriptionDatabaseManager.getSubscriptionProperty(subId, columnName);
@@ -3265,6 +3369,8 @@
throw new IllegalArgumentException("Invalid subscription id " + subId);
}
+ enforceTelephonyFeatureWithException(getCurrentPackageName(), "isSubscriptionEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
@@ -3294,6 +3400,8 @@
throw new IllegalArgumentException("Invalid slot index " + slotIndex);
}
+ enforceTelephonyFeatureWithException(getCurrentPackageName(), "getEnabledSubscriptionId");
+
final long identity = Binder.clearCallingIdentity();
try {
return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
@@ -3330,6 +3438,9 @@
throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or "
+ "carrier privilege");
}
+
+ enforceTelephonyFeatureWithException(callingPackage, "isActiveSubId");
+
final long identity = Binder.clearCallingIdentity();
try {
SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
@@ -3387,6 +3498,9 @@
enforcePermissions("canDisablePhysicalSubscription",
Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ "canDisablePhysicalSubscription");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = PhoneFactory.getDefaultPhone();
@@ -3420,6 +3534,9 @@
logl("setUiccApplicationsEnabled: subId=" + subId + ", enabled=" + enabled
+ ", calling package=" + getCallingPackage());
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ "setUiccApplicationsEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
@@ -3462,6 +3579,9 @@
enforcePermissions("setDeviceToDeviceStatusSharing",
Manifest.permission.MODIFY_PHONE_STATE);
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ "setDeviceToDeviceStatusSharing");
+
final long identity = Binder.clearCallingIdentity();
try {
if (sharing < SubscriptionManager.D2D_SHARING_DISABLED
@@ -3494,6 +3614,9 @@
enforcePermissions("setDeviceToDeviceStatusSharingContacts",
Manifest.permission.MODIFY_PHONE_STATE);
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ "setDeviceToDeviceStatusSharingContacts");
+
final long identity = Binder.clearCallingIdentity();
try {
Objects.requireNonNull(contacts, "contacts");
@@ -3561,6 +3684,8 @@
Manifest.permission.READ_PHONE_NUMBERS,
Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ enforceTelephonyFeatureWithException(callingPackage, "getPhoneNumber");
+
final long identity = Binder.clearCallingIdentity();
SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
@@ -3621,6 +3746,9 @@
Manifest.permission.READ_PHONE_NUMBERS,
Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ enforceTelephonyFeatureWithException(callingPackage,
+ "getPhoneNumberFromFirstAvailableSource");
+
String numberFromCarrier = getPhoneNumber(subId,
SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER, callingPackage,
callingFeatureId);
@@ -3668,6 +3796,8 @@
+ SubscriptionManager.phoneNumberSourceToString(source));
}
+ enforceTelephonyFeatureWithException(callingPackage, "setPhoneNumber");
+
Objects.requireNonNull(number, "number");
final long identity = Binder.clearCallingIdentity();
@@ -3806,7 +3936,7 @@
+ subscriptionId);
}
- if (mFeatureFlags.workProfileApiSplit()) {
+ if (mFeatureFlags.enforceSubscriptionUserFilter()) {
return isSubscriptionAssociatedWithUserInternal(
subInfoInternal, userHandle.getIdentifier());
}
@@ -3835,15 +3965,15 @@
*/
private boolean isSubscriptionAssociatedWithUserInternal(
@NonNull SubscriptionInfoInternal subInfo, @UserIdInt int userId) {
- if (!mFeatureFlags.workProfileApiSplit()
+ if (!mFeatureFlags.enforceSubscriptionUserFilter()
|| !CompatChanges.isChangeEnabled(FILTER_ACCESSIBLE_SUBS_BY_USER,
Binder.getCallingUid())) {
return true;
}
- return subInfo.getUserId() == userId
- // Can access the unassociated sub if the user doesn't have its own.
- || (subInfo.getUserId() == UserHandle.USER_NULL
+ // Can access the unassociated sub if the user doesn't have its own.
+ return (subInfo.getUserId() == UserHandle.USER_NULL
&& mUserIdToAvailableSubs.get(userId) == null)
+ || userId == subInfo.getUserId()
|| userId == UserHandle.USER_ALL;
}
@@ -3866,7 +3996,7 @@
enforcePermissions("getSubscriptionInfoListAssociatedWithUser",
Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
- if (mFeatureFlags.workProfileApiSplit()) {
+ if (mFeatureFlags.enforceSubscriptionUserFilter()) {
return getSubscriptionInfoStreamAsUser(userHandle)
.map(SubscriptionInfoInternal::toSubscriptionInfo)
.collect(Collectors.toList());
@@ -3943,6 +4073,9 @@
enforcePermissions("restoreAllSimSpecificSettingsFromBackup",
Manifest.permission.MODIFY_PHONE_STATE);
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ "restoreAllSimSpecificSettingsFromBackup");
+
long token = Binder.clearCallingIdentity();
try {
Bundle bundle = new Bundle();
@@ -4151,9 +4284,10 @@
*/
@VisibleForTesting
public void updateGroupDisabled() {
- List<SubscriptionInfoInternal> activeSubscriptions = mSubscriptionDatabaseManager
+ List<SubscriptionInfo> activeSubscriptions = mSubscriptionDatabaseManager
.getAllSubscriptions().stream()
.filter(SubscriptionInfoInternal::isActive)
+ .map(SubscriptionInfoInternal::toSubscriptionInfo)
.collect(Collectors.toList());
for (SubscriptionInfo oppSubInfo : getOpportunisticSubscriptions(
mContext.getOpPackageName(), mContext.getFeatureId())) {
@@ -4166,6 +4300,40 @@
}
/**
+ * Get the current calling package name.
+ * @return the current calling package name
+ */
+ @Nullable
+ private String getCurrentPackageName() {
+ if (mPackageManager == null) return null;
+ String[] callingUids = mPackageManager.getPackagesForUid(Binder.getCallingUid());
+ return (callingUids == null) ? null : callingUids[0];
+ }
+
+ /**
+ * Make sure the device has required telephony feature
+ *
+ * @throws UnsupportedOperationException if the device does not have required telephony feature
+ */
+ private void enforceTelephonyFeatureWithException(@Nullable String callingPackage,
+ @NonNull String methodName) {
+ if (callingPackage == null || mPackageManager == null) {
+ return;
+ }
+
+ if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
+ || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+ Binder.getCallingUserHandle())) {
+ return;
+ }
+
+ if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY_SUBSCRIPTION)) {
+ throw new UnsupportedOperationException(
+ methodName + " is unsupported without " + FEATURE_TELEPHONY_SUBSCRIPTION);
+ }
+ }
+
+ /**
* @return The logical SIM slot/sub mapping to string.
*/
@NonNull
@@ -4178,7 +4346,7 @@
/**
* @param mccMnc MccMnc value to check whether it supports non-terrestrial network or not.
* @return {@code true} if MCC/MNC is matched with in the device overlay key
- * "config_satellite_esim_identifier", {@code false} otherwise.
+ * "config_satellite_sim_plmn_identifier", {@code false} otherwise.
*/
private boolean isSatellitePlmn(@NonNull String mccMnc) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
@@ -4186,7 +4354,7 @@
return false;
}
- final int id = R.string.config_satellite_sim_identifier;
+ final int id = R.string.config_satellite_sim_plmn_identifier;
String overlayMccMnc = null;
try {
overlayMccMnc = mContext.getResources().getString(id);
@@ -4194,14 +4362,43 @@
loge("isSatellitePlmn: id= " + id + ", ex=" + ex);
}
if (TextUtils.isEmpty(overlayMccMnc) && isMockModemAllowed()) {
- log("isSatellitePlmn: Read config_satellite_sim_identifier from device config");
+ log("isSatellitePlmn: Read config_satellite_sim_plmn_identifier from device config");
overlayMccMnc = DeviceConfig.getString(DeviceConfig.NAMESPACE_TELEPHONY,
- "config_satellite_sim_identifier", "");
+ "config_satellite_sim_plmn_identifier", "");
}
log("isSatellitePlmn: overlayMccMnc=" + overlayMccMnc + ", mccMnc=" + mccMnc);
return TextUtils.equals(mccMnc, overlayMccMnc);
}
+ /**
+ * Checks and matches the service provider name (spn) with the device overlay config to
+ * determine whether non-terrestrial networks are supported.
+ * @param spn service provider name of the profile.
+ * @return {@code true} if the given spn is matched with the overlay key.
+ * "config_satellite_sim_spn_identifier", {@code false} otherwise.
+ */
+ private boolean isSatelliteSpn(@NonNull String spn) {
+ if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ log("isSatelliteSpn: oemEnabledSatelliteFlag is disabled");
+ return false;
+ }
+
+ final int id = R.string.config_satellite_sim_spn_identifier;
+ String overlaySpn = null;
+ try {
+ overlaySpn = mContext.getResources().getString(id);
+ } catch (Resources.NotFoundException ex) {
+ loge("isSatelliteSpn: id= " + id + ", ex=" + ex);
+ }
+ if (TextUtils.isEmpty(overlaySpn) && isMockModemAllowed()) {
+ log("isSatelliteSpn: Read config_satellite_sim_spn_identifier from device config");
+ overlaySpn = DeviceConfig.getString(DeviceConfig.NAMESPACE_TELEPHONY,
+ "config_satellite_sim_spn_identifier", "");
+ }
+ log("isSatelliteSpn: overlaySpn=" + overlaySpn + ", spn=" + spn);
+ return TextUtils.equals(spn, overlaySpn);
+ }
+
private boolean isMockModemAllowed() {
boolean isAllowed = SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false);
return (SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false)
diff --git a/src/java/com/android/internal/telephony/uicc/UiccPort.java b/src/java/com/android/internal/telephony/uicc/UiccPort.java
index d89eab1..fd8f1c4 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccPort.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccPort.java
@@ -29,6 +29,8 @@
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.IccLogicalChannelRequest;
import com.android.internal.telephony.TelephonyComponentFactory;
+import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.FeatureFlagsImpl;
import com.android.telephony.Rlog;
import java.io.FileDescriptor;
@@ -39,6 +41,7 @@
public class UiccPort {
protected static final String LOG_TAG = "UiccPort";
protected static final boolean DBG = true;
+ private static @NonNull FeatureFlags sFlags = new FeatureFlagsImpl();
// The lock object is created by UiccSlot that owns this UiccCard - this is to share the lock
// between UiccSlot, UiccCard, EuiccCard, UiccPort, EuiccPort and UiccProfile for now.
@@ -80,7 +83,7 @@
if (mUiccProfile == null) {
mUiccProfile = TelephonyComponentFactory.getInstance()
.inject(UiccProfile.class.getName()).makeUiccProfile(
- mContext, mCi, ics, mPhoneId, uiccCard, mLock);
+ mContext, mCi, ics, mPhoneId, uiccCard, mLock, sFlags);
} else {
mUiccProfile.update(mContext, mCi, ics);
}
diff --git a/src/java/com/android/internal/telephony/uicc/UiccProfile.java b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
index 83db022..0457971 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccProfile.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
@@ -20,6 +20,7 @@
import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT__EVENT__PIN_VERIFICATION_FAILURE;
import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT__EVENT__PIN_VERIFICATION_SUCCESS;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.usage.UsageStatsManager;
@@ -65,6 +66,7 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.TelephonyStatsLog;
import com.android.internal.telephony.cat.CatService;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
@@ -103,6 +105,7 @@
private static final String OPERATOR_BRAND_OVERRIDE_PREFIX = "operator_branding_";
+ private final @NonNull FeatureFlags mFlags;
// The lock object is created by UiccSlot that owns the UiccCard that owns this UiccProfile.
// This is to share the lock between UiccSlot, UiccCard and UiccProfile for now.
private final Object mLock;
@@ -326,8 +329,9 @@
};
public UiccProfile(Context c, CommandsInterface ci, IccCardStatus ics, int phoneId,
- UiccCard uiccCard, Object lock) {
+ UiccCard uiccCard, Object lock, @NonNull FeatureFlags flags) {
if (DBG) log("Creating profile");
+ mFlags = flags;
mLock = lock;
mUiccCard = uiccCard;
mPhoneId = phoneId;
diff --git a/tests/telephonytests/Android.bp b/tests/telephonytests/Android.bp
index 51ab617..8547581 100644
--- a/tests/telephonytests/Android.bp
+++ b/tests/telephonytests/Android.bp
@@ -42,6 +42,7 @@
"testables",
"platform-compat-test-rules",
"flag-junit",
+ "telephony_flags_core_java_lib",
],
jarjar_rules: ":jarjar-rules-telephony-tests",
diff --git a/tests/telephonytests/src/android/telephony/BinderCacheManagerTest.java b/tests/telephonytests/src/android/telephony/BinderCacheManagerTest.java
index e5b5f3a..ede37f9 100644
--- a/tests/telephonytests/src/android/telephony/BinderCacheManagerTest.java
+++ b/tests/telephonytests/src/android/telephony/BinderCacheManagerTest.java
@@ -27,8 +27,8 @@
import android.os.IBinder;
import android.os.IInterface;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
diff --git a/tests/telephonytests/src/android/telephony/SmsMessageTest.java b/tests/telephonytests/src/android/telephony/SmsMessageTest.java
index 2bd865d..5f696b1 100644
--- a/tests/telephonytests/src/android/telephony/SmsMessageTest.java
+++ b/tests/telephonytests/src/android/telephony/SmsMessageTest.java
@@ -16,12 +16,12 @@
package android.telephony;
-import android.test.suitebuilder.annotation.SmallTest;
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.SmsConstants;
-import static org.junit.Assert.assertEquals;
-
import org.junit.Test;
public class SmsMessageTest {
diff --git a/tests/telephonytests/src/android/telephony/ims/ImsCompatTests.java b/tests/telephonytests/src/android/telephony/ims/ImsCompatTests.java
index 414cb47..eebcf8f 100644
--- a/tests/telephonytests/src/android/telephony/ims/ImsCompatTests.java
+++ b/tests/telephonytests/src/android/telephony/ims/ImsCompatTests.java
@@ -22,8 +22,8 @@
import static org.mockito.Mockito.verify;
import android.telephony.ims.aidl.IImsCallSessionListener;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.ims.internal.IImsMMTelFeature;
diff --git a/tests/telephonytests/src/android/telephony/ims/ImsFeatureTest.java b/tests/telephonytests/src/android/telephony/ims/ImsFeatureTest.java
index 2df688d..2dc0b31 100644
--- a/tests/telephonytests/src/android/telephony/ims/ImsFeatureTest.java
+++ b/tests/telephonytests/src/android/telephony/ims/ImsFeatureTest.java
@@ -31,8 +31,8 @@
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.ims.internal.IImsFeatureStatusCallback;
diff --git a/tests/telephonytests/src/android/telephony/ims/ImsMmTelManagerTests.java b/tests/telephonytests/src/android/telephony/ims/ImsMmTelManagerTests.java
index df53374..afc0d50 100644
--- a/tests/telephonytests/src/android/telephony/ims/ImsMmTelManagerTests.java
+++ b/tests/telephonytests/src/android/telephony/ims/ImsMmTelManagerTests.java
@@ -26,7 +26,8 @@
import android.telephony.BinderCacheManager;
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.TelephonyTest;
diff --git a/tests/telephonytests/src/android/telephony/ims/ImsRegistrationTests.java b/tests/telephonytests/src/android/telephony/ims/ImsRegistrationTests.java
index 56ce6bc..b054a49 100644
--- a/tests/telephonytests/src/android/telephony/ims/ImsRegistrationTests.java
+++ b/tests/telephonytests/src/android/telephony/ims/ImsRegistrationTests.java
@@ -35,9 +35,9 @@
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.stub.ImsFeatureConfiguration;
import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
diff --git a/tests/telephonytests/src/android/telephony/ims/ImsServiceTest.java b/tests/telephonytests/src/android/telephony/ims/ImsServiceTest.java
index cb3ca89..d9d387c 100644
--- a/tests/telephonytests/src/android/telephony/ims/ImsServiceTest.java
+++ b/tests/telephonytests/src/android/telephony/ims/ImsServiceTest.java
@@ -39,8 +39,8 @@
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsFeatureConfiguration;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.ims.internal.IImsFeatureStatusCallback;
diff --git a/tests/telephonytests/src/android/telephony/ims/ImsStateCallbackTest.java b/tests/telephonytests/src/android/telephony/ims/ImsStateCallbackTest.java
index 9a9713d..9321a1b 100644
--- a/tests/telephonytests/src/android/telephony/ims/ImsStateCallbackTest.java
+++ b/tests/telephonytests/src/android/telephony/ims/ImsStateCallbackTest.java
@@ -28,7 +28,8 @@
import android.telephony.BinderCacheManager;
import android.telephony.ims.aidl.IImsRcsController;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.IImsStateCallback;
import com.android.internal.telephony.ITelephony;
diff --git a/tests/telephonytests/src/android/telephony/ims/MmTelFeatureTests.java b/tests/telephonytests/src/android/telephony/ims/MmTelFeatureTests.java
index b002b35..aa5db68 100644
--- a/tests/telephonytests/src/android/telephony/ims/MmTelFeatureTests.java
+++ b/tests/telephonytests/src/android/telephony/ims/MmTelFeatureTests.java
@@ -35,8 +35,8 @@
import android.telephony.ims.aidl.IImsMmTelFeature;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsCallSessionImplBase;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.ims.internal.IImsCallSession;
diff --git a/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java b/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java
index a81e93f..4889187 100644
--- a/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java
+++ b/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java
@@ -30,9 +30,9 @@
import android.telephony.ims.RcsConfig;
import android.telephony.ims.RcsConfig.Characteristic;
import android.test.mock.MockContentResolver;
-import android.test.suitebuilder.annotation.SmallTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.FakeTelephonyProvider;
diff --git a/tests/telephonytests/src/android/telephony/ims/RcsFeatureTest.java b/tests/telephonytests/src/android/telephony/ims/RcsFeatureTest.java
index fa88d71..3c5ccad 100644
--- a/tests/telephonytests/src/android/telephony/ims/RcsFeatureTest.java
+++ b/tests/telephonytests/src/android/telephony/ims/RcsFeatureTest.java
@@ -25,9 +25,9 @@
import android.telephony.ims.feature.RcsFeature;
import android.telephony.ims.stub.CapabilityExchangeEventListener;
import android.telephony.ims.stub.RcsCapabilityExchangeImplBase;
-import android.test.suitebuilder.annotation.SmallTest;
import androidx.annotation.NonNull;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.telephony.ims.ImsTestBase;
diff --git a/tests/telephonytests/src/android/telephony/mbms/MbmsReceiverTest.java b/tests/telephonytests/src/android/telephony/mbms/MbmsReceiverTest.java
index b93d400..6debad3 100644
--- a/tests/telephonytests/src/android/telephony/mbms/MbmsReceiverTest.java
+++ b/tests/telephonytests/src/android/telephony/mbms/MbmsReceiverTest.java
@@ -18,8 +18,7 @@
import static org.junit.Assert.assertEquals;
-import android.test.suitebuilder.annotation.SmallTest;
-
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ATResponseParserTest.java b/tests/telephonytests/src/com/android/internal/telephony/ATResponseParserTest.java
index 81727e4..e53e813 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ATResponseParserTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ATResponseParserTest.java
@@ -16,8 +16,9 @@
package com.android.internal.telephony;
+import androidx.test.filters.SmallTest;
+
import junit.framework.TestCase;
-import android.test.suitebuilder.annotation.SmallTest;
public class ATResponseParserTest extends TestCase {
@SmallTest
diff --git a/tests/telephonytests/src/com/android/internal/telephony/AdnRecordTest.java b/tests/telephonytests/src/com/android/internal/telephony/AdnRecordTest.java
index 8fe809c..a442b0d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/AdnRecordTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/AdnRecordTest.java
@@ -19,7 +19,8 @@
import static com.google.common.truth.Truth.assertThat;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.uicc.AdnRecord;
import com.android.internal.telephony.uicc.IccUtils;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CallAttributesTest.java b/tests/telephonytests/src/com/android/internal/telephony/CallAttributesTest.java
index 7a85926..62ff484 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CallAttributesTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CallAttributesTest.java
@@ -23,7 +23,8 @@
import android.telephony.CallQuality;
import android.telephony.PreciseCallState;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
/**
* Simple GTS test verifying the parceling and unparceling of CallAttributes.
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CallManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/CallManagerTest.java
index 62b2a45..82bbc18 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CallManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CallManagerTest.java
@@ -35,10 +35,11 @@
import android.os.Message;
import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CallQualityTest.java b/tests/telephonytests/src/com/android/internal/telephony/CallQualityTest.java
index 1a6bb51..c4ce498 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CallQualityTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CallQualityTest.java
@@ -20,8 +20,8 @@
import android.os.Parcel;
import android.telephony.CallQuality;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CallStateExceptionTest.java b/tests/telephonytests/src/com/android/internal/telephony/CallStateExceptionTest.java
index 7b6c2b7..1481633 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CallStateExceptionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CallStateExceptionTest.java
@@ -17,7 +17,7 @@
import static org.junit.Assert.assertEquals;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import org.junit.After;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CallStateTest.java b/tests/telephonytests/src/com/android/internal/telephony/CallStateTest.java
index 4e319a1..88dc591 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CallStateTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CallStateTest.java
@@ -25,7 +25,8 @@
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsCallProfile;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CallWaitingControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/CallWaitingControllerTest.java
index eb18adb..184820c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CallWaitingControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CallWaitingControllerTest.java
@@ -51,10 +51,11 @@
import android.os.Handler;
import android.os.Message;
import android.os.PersistableBundle;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierActionAgentTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierActionAgentTest.java
index 4f91994..ed45cd5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierActionAgentTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierActionAgentTest.java
@@ -31,10 +31,11 @@
import android.provider.Settings;
import android.provider.Telephony;
import android.test.mock.MockContentResolver;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierAppUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierAppUtilsTest.java
index 583a147..2a66a5f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierAppUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierAppUtilsTest.java
@@ -27,11 +27,11 @@
import android.telephony.TelephonyManager;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArrayMap;
import android.util.ArraySet;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierKeyDownloadMgrTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierKeyDownloadMgrTest.java
index e23a7f2..07482e0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierKeyDownloadMgrTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierKeyDownloadMgrTest.java
@@ -36,11 +36,12 @@
import android.telephony.ImsiEncryptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.Pair;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.flags.FeatureFlags;
import org.junit.After;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierResolverTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierResolverTest.java
index 453dbd6..a3fcd4e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierResolverTest.java
@@ -31,10 +31,11 @@
import android.telephony.TelephonyManager;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierRestrictionRulesTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierRestrictionRulesTest.java
index fdefa1d..7e86ce3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierRestrictionRulesTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierRestrictionRulesTest.java
@@ -16,11 +16,16 @@
package com.android.internal.telephony;
+import static android.telephony.CarrierRestrictionRules.MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT;
import android.os.Parcel;
import android.service.carrier.CarrierIdentifier;
+import android.telephony.CarrierInfo;
import android.telephony.CarrierRestrictionRules;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
@@ -340,4 +345,101 @@
List<Boolean> expected = Arrays.asList(false, false, false);
assertTrue(result.equals(expected));
}
+
+ @Test
+ public void testBuilderAllowedAndExcludedCarrierInfos() {
+ List<CarrierInfo> allowedCarriers = new ArrayList<>();
+ allowedCarriers.add(new CarrierInfo(MCC1, MNC1, null, null, null, null, null, null, null));
+ allowedCarriers.add(new CarrierInfo(MCC2, MNC2, null, null, null, null, null, null, null));
+
+ List<CarrierInfo> excludedCarriers = new ArrayList<>();
+ excludedCarriers.add(new CarrierInfo(MCC2, MNC2, null, null, GID1, null, null, null, null));
+
+ CarrierRestrictionRules rules =
+ CarrierRestrictionRules.newBuilder().setAllowedCarrierInfo(
+ allowedCarriers).setExcludedCarrierInfo(excludedCarriers).build();
+
+ assertEquals(false, rules.isAllCarriersAllowed());
+ assertTrue(rules.getAllowedCarriersInfoList().equals(allowedCarriers));
+ assertTrue(rules.getExcludedCarriersInfoList().equals(excludedCarriers));
+ assertEquals(CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED,
+ rules.getDefaultCarrierRestriction());
+ }
+
+ @Test
+ public void testBuilderAllowedAndExcludedCarrierInfoWithEplmn() {
+ List<String> plmns = new ArrayList<>();
+ plmns.add("**1" + "," + "123");
+ plmns.add("2*1" + "," + "1*3");
+
+ List<String> plmns2 = new ArrayList<>();
+ plmns2.add("**1" + "," + "123");
+ plmns2.add("2*1" + "," + "1*3");
+ plmns2.add("2**" + "," + "*");
+
+ List<CarrierInfo> allowedCarriers = new ArrayList<>();
+ allowedCarriers.add(new CarrierInfo(MCC1, MNC1, null, null, null, null, null, null, plmns));
+ allowedCarriers.add(
+ new CarrierInfo(MCC2, MNC2, null, null, null, null, null, null, plmns2));
+
+ List<CarrierInfo> excludedCarriers = new ArrayList<>();
+ excludedCarriers.add(new CarrierInfo(MCC2, MNC2, null, null, GID1, null, null, null, null));
+
+ CarrierRestrictionRules rules =
+ CarrierRestrictionRules.newBuilder().setAllowedCarrierInfo(
+ allowedCarriers).setExcludedCarrierInfo(excludedCarriers).build();
+
+ assertEquals(false, rules.isAllCarriersAllowed());
+ assertTrue(rules.getAllowedCarriersInfoList().equals(allowedCarriers));
+ assertTrue(rules.getExcludedCarriersInfoList().equals(excludedCarriers));
+ assertTrue(rules.getAllowedCarriersInfoList().get(0).getEhplmn().equals(plmns));
+ assertTrue(rules.getAllowedCarriersInfoList().get(1).getEhplmn().equals(plmns2));
+ assertEquals(CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED,
+ rules.getDefaultCarrierRestriction());
+ }
+
+ @Test
+ public void testBuilderAllowedAndExcludedCarrierInfoWithNullEplmn() {
+ List<String> plmns = new ArrayList<>();
+ List<CarrierInfo> allowedCarriers = new ArrayList<>();
+ allowedCarriers.add(new CarrierInfo(MCC1, MNC1, null, null, null, null, null, null, plmns));
+
+ List<CarrierInfo> excludedCarriers = new ArrayList<>();
+ excludedCarriers.add(new CarrierInfo(MCC2, MNC2, null, null, GID1, null, null, null, null));
+
+ CarrierRestrictionRules rules =
+ CarrierRestrictionRules.newBuilder().setAllowedCarrierInfo(
+ allowedCarriers).setExcludedCarrierInfo(excludedCarriers).build();
+
+ assertEquals(false, rules.isAllCarriersAllowed());
+ assertTrue(rules.getAllowedCarriersInfoList().equals(allowedCarriers));
+ assertTrue(rules.getExcludedCarriersInfoList().equals(excludedCarriers));
+ assertTrue(rules.getAllowedCarriersInfoList().get(0).getEhplmn().equals(plmns));
+ assertEquals(CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED,
+ rules.getDefaultCarrierRestriction());
+ }
+
+ @Test
+ public void testBuilderAllowedAndExcludedCarrierInfoWithSimPolicy() {
+ List<CarrierInfo> allowedCarriers = new ArrayList<>();
+ allowedCarriers.add(new CarrierInfo(MCC1, MNC1, null, null, null, null, null, null, null));
+
+ List<CarrierInfo> excludedCarriers = new ArrayList<>();
+ excludedCarriers.add(new CarrierInfo(MCC2, MNC2, null, null, GID1, null, null, null, null));
+
+ CarrierRestrictionRules rules =
+ CarrierRestrictionRules.newBuilder().
+ setAllowedCarrierInfo(allowedCarriers).
+ setExcludedCarrierInfo(excludedCarriers).
+ setDefaultCarrierRestriction(
+ CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_ALLOWED).
+ setMultiSimPolicy(MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT).build();
+
+ assertEquals(true, rules.isAllCarriersAllowed());
+ assertTrue(rules.getAllowedCarriersInfoList().equals(allowedCarriers));
+ assertTrue(rules.getExcludedCarriersInfoList().equals(excludedCarriers));
+ assertEquals(MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT, rules.getMultiSimPolicy());
+ assertEquals(CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_ALLOWED,
+ rules.getDefaultCarrierRestriction());
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
index 8ce11ae..331fcba 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
@@ -27,10 +27,11 @@
import android.os.Message;
import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceStateTrackerTest.java
index 7345022..85c73a9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceStateTrackerTest.java
@@ -43,10 +43,11 @@
import android.telephony.RadioAccessFamily;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierServicesSmsFilterTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierServicesSmsFilterTest.java
index 00adc39..e68d065 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierServicesSmsFilterTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierServicesSmsFilterTest.java
@@ -37,7 +37,8 @@
import android.service.carrier.ICarrierMessagingCallback;
import android.service.carrier.ICarrierMessagingService;
import android.service.carrier.MessagePdu;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import org.junit.After;
import org.junit.Before;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierSignalAgentTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierSignalAgentTest.java
index 4dfadd2..7710648 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierSignalAgentTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierSignalAgentTest.java
@@ -47,10 +47,11 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellBroadcastConfigTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellBroadcastConfigTrackerTest.java
index 722f6ac..6e6d4e4 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CellBroadcastConfigTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CellBroadcastConfigTrackerTest.java
@@ -416,6 +416,26 @@
}
@Test
+ public void testClearCellBroadcastConfigOnModemReset() {
+ List<CellBroadcastIdRange> ranges = new ArrayList<>();
+ ranges.add(new CellBroadcastIdRange(0, 999, SmsCbMessage.MESSAGE_FORMAT_3GPP, true));
+
+ mPhone.setCellBroadcastIdRanges(ranges, r -> assertTrue(
+ TelephonyManager.CELL_BROADCAST_RESULT_SUCCESS == r));
+ processAllMessages();
+
+ assertEquals(mPhone.getCellBroadcastIdRanges(), ranges);
+
+ Message m = mTracker.obtainMessage(CellBroadcastConfigTracker.EVENT_RADIO_RESET);
+ AsyncResult.forMessage(m);
+ m.sendToTarget();
+ processAllMessages();
+
+ // Verify the config is reset
+ assertTrue(mPhone.getCellBroadcastIdRanges().isEmpty());
+ }
+
+ @Test
public void testClearCellBroadcastConfigOnSubscriptionChanged() {
List<CellBroadcastIdRange> ranges = new ArrayList<>();
ranges.add(new CellBroadcastIdRange(0, 999, SmsCbMessage.MESSAGE_FORMAT_3GPP, true));
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityCdmaTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellIdentityCdmaTest.java
index 133b4ba..c7668ca 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityCdmaTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CellIdentityCdmaTest.java
@@ -21,7 +21,8 @@
import android.os.Parcel;
import android.telephony.CellIdentityCdma;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
/** Unit tests for {@link CellIdentityCdma}. */
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityGsmTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellIdentityGsmTest.java
index 9d39b07..cbdf3b7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityGsmTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CellIdentityGsmTest.java
@@ -19,7 +19,8 @@
import android.os.Parcel;
import android.telephony.CellIdentityGsm;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import java.util.Collections;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityLteTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellIdentityLteTest.java
index 3eb8d21..9b05b67 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityLteTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CellIdentityLteTest.java
@@ -20,7 +20,8 @@
import android.telephony.CellIdentityLte;
import android.telephony.CellInfo;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import java.util.ArrayList;
import java.util.Arrays;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityTdscdmaTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellIdentityTdscdmaTest.java
index d1da119..3926c03 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityTdscdmaTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CellIdentityTdscdmaTest.java
@@ -20,7 +20,8 @@
import android.telephony.CellIdentityTdscdma;
import android.telephony.CellInfo;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
/** Unit tests for {@link CellIdentityTdscdma}. */
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellIdentityTest.java
index 0ceed1c..0be1ae4 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CellIdentityTest.java
@@ -26,7 +26,8 @@
import android.telephony.CellIdentityWcdma;
import android.telephony.CellInfo;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityWcdmaTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellIdentityWcdmaTest.java
index 1e472fb..62caef4 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityWcdmaTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CellIdentityWcdmaTest.java
@@ -19,7 +19,8 @@
import android.os.Parcel;
import android.telephony.CellIdentityWcdma;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import java.util.Collections;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthCdmaTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthCdmaTest.java
index 063fb3c..3a20497 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthCdmaTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthCdmaTest.java
@@ -23,7 +23,8 @@
import android.os.Parcel;
import android.telephony.CellSignalStrengthCdma;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
/** Unit tests for {@link CellSignalStrengthCdma}. */
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthTdscdmaTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthTdscdmaTest.java
index 8b5c3d5..1c17fbe 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthTdscdmaTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthTdscdmaTest.java
@@ -24,7 +24,8 @@
import android.telephony.CellInfo;
import android.telephony.CellSignalStrengthTdscdma;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
/** Unit tests for {@link CellSignalStrengthCdma}. */
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthWcdmaTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthWcdmaTest.java
index 8323ba3..2a00bdb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthWcdmaTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthWcdmaTest.java
@@ -26,7 +26,8 @@
import android.telephony.CellInfo;
import android.telephony.CellSignalStrengthWcdma;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
/** Unit tests for {@link CellSignalStrengthCdma}. */
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellularNetworkServiceTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellularNetworkServiceTest.java
index 85ea855..ebf1324 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CellularNetworkServiceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CellularNetworkServiceTest.java
@@ -43,8 +43,9 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.VopsSupportInfo;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
import com.android.internal.R;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
index f7f67a5..d27ab98 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
@@ -33,7 +33,9 @@
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsCallProfile;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.imsphone.ImsPhoneCall;
@@ -379,4 +381,15 @@
assertEquals(3, cellLocationCapture.getValue().asCellLocation().getCid());
assertEquals(-1, cellLocationCapture.getValue().asCellLocation().getPsc());
}
+
+ @Test
+ @SmallTest
+ public void testSimultaneousCellularCallingSubscriptionsChanged() {
+ ArraySet<Integer> subs = new ArraySet<>(2);
+ subs.add(0);
+ subs.add(1);
+ mDefaultPhoneNotifierUT.notifySimultaneousCellularCallingSubscriptionsChanged(subs);
+ verify(mTelephonyRegistryManager).notifySimultaneousCellularCallingSubscriptionsChanged(
+ eq(subs));
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/DeviceStateMonitorTest.java b/tests/telephonytests/src/com/android/internal/telephony/DeviceStateMonitorTest.java
index 018759a..c9e4c12 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/DeviceStateMonitorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/DeviceStateMonitorTest.java
@@ -48,10 +48,11 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.test.suitebuilder.annotation.MediumTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.MediumTest;
+
import com.android.internal.telephony.flags.FeatureFlags;
import org.junit.After;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java b/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
index 2692057..7dd4093 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
@@ -130,8 +130,9 @@
+ UserHandle.USER_NULL + ","
+ Telephony.SimInfo.COLUMN_SATELLITE_ENABLED + " INTEGER DEFAULT 0,"
+ Telephony.SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER
- + " INTEGER DEFAULT 0, "
- + Telephony.SimInfo.COLUMN_IS_NTN + " INTEGER DEFAULT 0"
+ + " INTEGER DEFAULT 1, "
+ + Telephony.SimInfo.COLUMN_IS_NTN + " INTEGER DEFAULT 0,"
+ + Telephony.SimInfo.COLUMN_SERVICE_CAPABILITIES + " INTEGER DEFAULT 7"
+ ");";
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GbaManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/GbaManagerTest.java
index c658b16..bad32e9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GbaManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GbaManagerTest.java
@@ -47,11 +47,12 @@
import android.telephony.gba.GbaService;
import android.telephony.gba.IGbaService;
import android.telephony.gba.UaSecurityProtocolIdentifier;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.Log;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.metrics.RcsStats;
import org.junit.After;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java
index 5a90f4e..f76d8c5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmAlphabetTest.java
@@ -16,14 +16,12 @@
package com.android.internal.telephony;
-import com.android.internal.telephony.GsmAlphabet;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.uicc.IccUtils;
import junit.framework.TestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.SmallTest;
-
public class GsmAlphabetTest extends TestCase {
private static final String sGsmExtendedChars = "{|}\\[~]\f\u20ac";
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaCallTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaCallTest.java
index b29976f..5927807 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaCallTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaCallTest.java
@@ -16,11 +16,11 @@
package com.android.internal.telephony;
-import android.test.suitebuilder.annotation.SmallTest;
-
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
+import androidx.test.filters.SmallTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaCallTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaCallTrackerTest.java
index 369980c..7de75ae 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaCallTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaCallTrackerTest.java
@@ -33,12 +33,12 @@
import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
import android.telephony.emergency.EmergencyNumber;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.FlakyTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.PhoneInternalInterface.DialArgs;
@@ -75,7 +75,7 @@
mSimulatedCommands.setRadioPower(true, null);
mPhone.mCi = this.mSimulatedCommands;
- mCTUT = new GsmCdmaCallTracker(mPhone);
+ mCTUT = new GsmCdmaCallTracker(mPhone, mFeatureFlags);
logd("GsmCdmaCallTracker initiated, waiting for Power on");
/* Make sure radio state is power on before dial.
* When radio state changed from off to on, CallTracker
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java
index 8292e84..45f8c12 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java
@@ -25,11 +25,12 @@
import android.os.Looper;
import android.telephony.DisconnectCause;
import android.telephony.PhoneNumberUtils;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.PhoneInternalInterface.DialArgs;
import org.junit.After;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
index 935da5a..a903a34 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
@@ -23,6 +23,7 @@
import static com.android.internal.telephony.Phone.EVENT_RADIO_AVAILABLE;
import static com.android.internal.telephony.Phone.EVENT_SET_IDENTIFIER_DISCLOSURE_ENABLED_DONE;
import static com.android.internal.telephony.Phone.EVENT_SET_NULL_CIPHER_AND_INTEGRITY_DONE;
+import static com.android.internal.telephony.Phone.EVENT_SET_SECURITY_ALGORITHMS_UPDATED_ENABLED_DONE;
import static com.android.internal.telephony.Phone.EVENT_SRVCC_STATE_CHANGED;
import static com.android.internal.telephony.Phone.EVENT_UICC_APPS_ENABLEMENT_STATUS_CHANGED;
import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;
@@ -55,6 +56,7 @@
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
import android.hardware.radio.modem.ImeiInfo;
import android.os.AsyncResult;
import android.os.Bundle;
@@ -77,17 +79,18 @@
import android.telephony.LinkCapacityEstimate;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.RadioAccessFamily;
+import android.telephony.SecurityAlgorithmUpdate;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsCallProfile;
import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.Log;
import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.domainselection.DomainSelectionResolver;
import com.android.internal.telephony.emergency.EmergencyStateTracker;
@@ -692,6 +695,32 @@
@Test
@SmallTest
+ public void testEmergencySmsModeWithTelephonyFeatureMapping() {
+ String emergencyNumber = "111";
+ int timeout = 200;
+ mContextFixture.getCarrierConfigBundle().putInt(
+ CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT, timeout);
+ doReturn(true).when(mTelephonyManager).isEmergencyNumber(emergencyNumber);
+
+ // Feature flag enabled
+ // Device does not have FEATURE_TELEPHONY_CALLING
+ doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
+ doReturn(false).when(mPackageManager).hasSystemFeature(
+ eq(PackageManager.FEATURE_TELEPHONY_CALLING));
+ mPhoneUT.notifySmsSent(emergencyNumber);
+ processAllMessages();
+ assertFalse(mPhoneUT.isInEmergencySmsMode());
+
+ // Device has FEATURE_TELEPHONY_CALLING
+ doReturn(true).when(mPackageManager).hasSystemFeature(
+ eq(PackageManager.FEATURE_TELEPHONY_CALLING));
+ mPhoneUT.notifySmsSent(emergencyNumber);
+ processAllMessages();
+ assertTrue(mPhoneUT.isInEmergencySmsMode());
+ }
+
+ @Test
+ @SmallTest
public void testSendBurstDtmf() {
//Should do nothing for GSM
mPhoneUT.sendBurstDtmf("1234567890", 0, 0, null);
@@ -1481,6 +1510,44 @@
assertEquals(captor.getValue().what, Phone.EVENT_GET_RADIO_CAPABILITY);
}
+ private void setIsCarrierConfigForIdentifiedCarrier(
+ PersistableBundle carrierConfig, boolean isIdentified) {
+ carrierConfig.putBoolean(
+ CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL,
+ isIdentified);
+ }
+
+ @Test
+ public void testNrCapabilityChanged_firstRequest_incompleteCarrierConfig_changeNeeded() {
+ when(mFeatureFlags.enableCarrierConfigN1Control()).thenReturn(true);
+
+ mPhoneUT.mCi = mMockCi;
+ PersistableBundle bundle = mContextFixture.getCarrierConfigBundle();
+ bundle.putIntArray(CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY,
+ new int[]{
+ CarrierConfigManager.CARRIER_NR_AVAILABILITY_NSA});
+
+ mPhoneUT.sendMessage(mPhoneUT.obtainMessage(Phone.EVENT_CARRIER_CONFIG_CHANGED));
+ processAllMessages();
+
+
+ verify(mMockCi, never()).isN1ModeEnabled(any());
+ verify(mMockCi, never()).setN1ModeEnabled(anyBoolean(), any());
+
+ setIsCarrierConfigForIdentifiedCarrier(bundle, true);
+
+ mPhoneUT.sendMessage(mPhoneUT.obtainMessage(Phone.EVENT_CARRIER_CONFIG_CHANGED));
+ processAllMessages();
+
+ ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
+ verify(mMockCi, times(1)).isN1ModeEnabled(messageCaptor.capture());
+ AsyncResult.forMessage(messageCaptor.getValue(), Boolean.TRUE, null);
+ messageCaptor.getValue().sendToTarget();
+ processAllMessages();
+
+ verify(mMockCi, times(1)).setN1ModeEnabled(eq(false), messageCaptor.capture());
+ }
+
@Test
public void testNrCapabilityChanged_firstRequest_noChangeNeeded() {
when(mFeatureFlags.enableCarrierConfigN1Control()).thenReturn(true);
@@ -1491,6 +1558,7 @@
new int[]{
CarrierConfigManager.CARRIER_NR_AVAILABILITY_NSA,
CarrierConfigManager.CARRIER_NR_AVAILABILITY_SA});
+ setIsCarrierConfigForIdentifiedCarrier(bundle, true);
mPhoneUT.sendMessage(mPhoneUT.obtainMessage(Phone.EVENT_CARRIER_CONFIG_CHANGED));
processAllMessages();
@@ -1514,6 +1582,7 @@
new int[]{
CarrierConfigManager.CARRIER_NR_AVAILABILITY_NSA,
CarrierConfigManager.CARRIER_NR_AVAILABILITY_SA});
+ setIsCarrierConfigForIdentifiedCarrier(bundle, true);
mPhoneUT.sendMessage(mPhoneUT.obtainMessage(Phone.EVENT_CARRIER_CONFIG_CHANGED));
processAllMessages();
@@ -1525,9 +1594,6 @@
processAllMessages();
verify(mMockCi, times(1)).setN1ModeEnabled(eq(true), messageCaptor.capture());
- AsyncResult.forMessage(messageCaptor.getValue(), Boolean.TRUE, null);
- messageCaptor.getValue().sendToTarget();
- processAllMessages();
}
@Test
@@ -1542,6 +1608,7 @@
bundle.putIntArray(
CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY,
new int[]{CarrierConfigManager.CARRIER_NR_AVAILABILITY_NSA});
+ setIsCarrierConfigForIdentifiedCarrier(bundle, true);
mPhoneUT.sendMessage(mPhoneUT.obtainMessage(Phone.EVENT_CARRIER_CONFIG_CHANGED));
processAllMessages();
@@ -1549,9 +1616,6 @@
ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
verify(mMockCi, times(1)).isN1ModeEnabled(any()); // not called again
verify(mMockCi, times(1)).setN1ModeEnabled(eq(false), messageCaptor.capture());
- AsyncResult.forMessage(messageCaptor.getValue(), null, null);
- messageCaptor.getValue().sendToTarget();
- processAllMessages();
}
@Test
@@ -1565,6 +1629,7 @@
new int[]{
CarrierConfigManager.CARRIER_NR_AVAILABILITY_NSA,
CarrierConfigManager.CARRIER_NR_AVAILABILITY_SA});
+ setIsCarrierConfigForIdentifiedCarrier(bundle, true);
mPhoneUT.sendMessage(mPhoneUT.obtainMessage(Phone.EVENT_CARRIER_CONFIG_CHANGED));
processAllMessages();
@@ -1613,9 +1678,6 @@
verify(mMockCi, times(1)).isN1ModeEnabled(any()); // not called again
verify(mMockCi, times(1)).setN1ModeEnabled(eq(true), messageCaptor.capture());
- AsyncResult.forMessage(messageCaptor.getValue(), null, null);
- messageCaptor.getValue().sendToTarget();
- processAllMessages();
}
private void setupForWpsCallTest() throws Exception {
@@ -2761,7 +2823,7 @@
@Test
public void testCellularIdentifierDisclosureFlagOff() {
- when(mFeatureFlags.enableIdentifierDisclosureTransparency()).thenReturn(false);
+ when(mFeatureFlags.enableIdentifierDisclosureTransparencyUnsolEvents()).thenReturn(false);
GsmCdmaPhone phoneUT =
new GsmCdmaPhone(
@@ -2783,7 +2845,7 @@
@Test
public void testCellularIdentifierDisclosureFlagOn() {
- when(mFeatureFlags.enableIdentifierDisclosureTransparency()).thenReturn(true);
+ when(mFeatureFlags.enableIdentifierDisclosureTransparencyUnsolEvents()).thenReturn(true);
Phone phoneUT =
new GsmCdmaPhone(
@@ -2806,7 +2868,7 @@
@Test
public void testCellularIdentifierDisclosure_disclosureEventAddedToNotifier() {
- when(mFeatureFlags.enableIdentifierDisclosureTransparency()).thenReturn(true);
+ when(mFeatureFlags.enableIdentifierDisclosureTransparencyUnsolEvents()).thenReturn(true);
Phone phoneUT =
new GsmCdmaPhone(
@@ -2832,12 +2894,13 @@
new AsyncResult(null, disclosure, null)));
processAllMessages();
- verify(mIdentifierDisclosureNotifier, times(1)).addDisclosure(eq(disclosure));
+ verify(mIdentifierDisclosureNotifier, times(1))
+ .addDisclosure(eq(mPhoneUT.getSubId()), eq(disclosure));
}
@Test
public void testCellularIdentifierDisclosure_disclosureEventNull() {
- when(mFeatureFlags.enableIdentifierDisclosureTransparency()).thenReturn(true);
+ when(mFeatureFlags.enableIdentifierDisclosureTransparencyUnsolEvents()).thenReturn(true);
Phone phoneUT =
new GsmCdmaPhone(
@@ -2857,7 +2920,7 @@
processAllMessages();
verify(mIdentifierDisclosureNotifier, never())
- .addDisclosure(any(CellularIdentifierDisclosure.class));
+ .addDisclosure(eq(mPhoneUT.getSubId()), any(CellularIdentifierDisclosure.class));
}
@Test
@@ -2902,11 +2965,122 @@
sendRadioAvailableToPhone(phoneUT);
verify(mMockCi, times(1)).setCellularIdentifierTransparencyEnabled(anyBoolean(),
any(Message.class));
- sendIdentifierDisclosureEnabledSuccessToPhone(phoneUT);
+ sendRequestSuccessToPhone(phoneUT, EVENT_SET_IDENTIFIER_DISCLOSURE_ENABLED_DONE);
assertTrue(phoneUT.isIdentifierDisclosureTransparencySupported());
}
+ @Test
+ public void testSecurityAlgorithmUpdateFlagOff() {
+ when(mFeatureFlags.enableModemCipherTransparency()).thenReturn(false);
+
+ makeNewPhoneUT();
+
+ verify(mMockCi, never()).registerForSecurityAlgorithmUpdates(any(), anyInt(), any());
+ }
+
+ @Test
+ public void testSecurityAlgorithmUpdateFlagOn() {
+ when(mFeatureFlags.enableModemCipherTransparencyUnsolEvents()).thenReturn(true);
+
+ Phone phoneUT = makeNewPhoneUT();
+
+ verify(mMockCi, times(1))
+ .registerForSecurityAlgorithmUpdates(
+ eq(phoneUT),
+ eq(Phone.EVENT_SECURITY_ALGORITHM_UPDATE),
+ any());
+ }
+
+ @Test
+ public void testSecurityAlgorithm_updateAddedToNotifier() {
+ when(mFeatureFlags.enableModemCipherTransparencyUnsolEvents()).thenReturn(true);
+ Phone phoneUT = makeNewPhoneUT();
+ SecurityAlgorithmUpdate update =
+ new SecurityAlgorithmUpdate(
+ SecurityAlgorithmUpdate.CONNECTION_EVENT_PS_SIGNALLING_3G,
+ SecurityAlgorithmUpdate.SECURITY_ALGORITHM_UEA1,
+ SecurityAlgorithmUpdate.SECURITY_ALGORITHM_AUTH_HMAC_SHA2_256_128,
+ true);
+
+ phoneUT.sendMessage(
+ mPhoneUT.obtainMessage(
+ Phone.EVENT_SECURITY_ALGORITHM_UPDATE,
+ new AsyncResult(null, update, null)));
+ processAllMessages();
+
+ verify(mNullCipherNotifier, times(1)).onSecurityAlgorithmUpdate(eq(0), eq(update));
+ }
+
+ @Test
+ public void testNullCipherNotification_noModemCallOnRadioAvailable_FlagOff() {
+ when(mFeatureFlags.enableModemCipherTransparency()).thenReturn(false);
+ GsmCdmaPhone phoneUT = makeNewPhoneUT();
+ assertFalse(phoneUT.isNullCipherNotificationSupported());
+
+ sendRadioAvailableToPhone(phoneUT);
+
+ verify(mMockCi, never()).setSecurityAlgorithmsUpdatedEnabled(anyBoolean(),
+ any(Message.class));
+ assertFalse(phoneUT.isNullCipherNotificationSupported());
+ }
+
+ @Test
+ public void testNullCipherNotification_unsupportedByModemOnRadioAvailable() {
+ when(mFeatureFlags.enableModemCipherTransparency()).thenReturn(true);
+ GsmCdmaPhone phoneUT = makeNewPhoneUT();
+ assertFalse(phoneUT.isNullCipherNotificationSupported());
+
+ sendRadioAvailableToPhone(phoneUT);
+ verify(mMockCi, times(1)).setSecurityAlgorithmsUpdatedEnabled(anyBoolean(),
+ any(Message.class));
+ sendRequestNotSupportedToPhone(phoneUT, EVENT_SET_SECURITY_ALGORITHMS_UPDATED_ENABLED_DONE);
+
+ assertFalse(phoneUT.isNullCipherNotificationSupported());
+ }
+
+ @Test
+ public void testNullCipherNotification_supportedByModem() {
+ when(mFeatureFlags.enableModemCipherTransparency()).thenReturn(true);
+ GsmCdmaPhone phoneUT = makeNewPhoneUT();
+ assertFalse(phoneUT.isNullCipherNotificationSupported());
+
+ sendRadioAvailableToPhone(phoneUT);
+ verify(mMockCi, times(1)).setSecurityAlgorithmsUpdatedEnabled(anyBoolean(),
+ any(Message.class));
+ sendRequestSuccessToPhone(phoneUT, EVENT_SET_SECURITY_ALGORITHMS_UPDATED_ENABLED_DONE);
+
+ assertTrue(phoneUT.isNullCipherNotificationSupported());
+ }
+
+ @Test
+ public void testNullCipherNotification_preferenceEnabled() {
+ when(mFeatureFlags.enableModemCipherTransparency()).thenReturn(true);
+ when(mFeatureFlags.enableModemCipherTransparencyUnsolEvents()).thenReturn(true);
+ GsmCdmaPhone phoneUT = makeNewPhoneUT();
+
+ setNullCipherNotificationPreferenceEnabled(true);
+ phoneUT.handleNullCipherNotificationPreferenceChanged();
+
+ verify(mNullCipherNotifier, times(1)).enable();
+ verify(mMockCi, times(1)).setSecurityAlgorithmsUpdatedEnabled(eq(true),
+ any(Message.class));
+ }
+
+ @Test
+ public void testNullCipherNotification_preferenceDisabled() {
+ when(mFeatureFlags.enableModemCipherTransparency()).thenReturn(true);
+ when(mFeatureFlags.enableModemCipherTransparencyUnsolEvents()).thenReturn(true);
+ GsmCdmaPhone phoneUT = makeNewPhoneUT();
+
+ setNullCipherNotificationPreferenceEnabled(false);
+ phoneUT.handleNullCipherNotificationPreferenceChanged();
+
+ verify(mNullCipherNotifier, times(1)).disable();
+ verify(mMockCi, times(1)).setSecurityAlgorithmsUpdatedEnabled(eq(false),
+ any(Message.class));
+ }
+
private void sendRadioAvailableToPhone(GsmCdmaPhone phone) {
phone.sendMessage(phone.obtainMessage(EVENT_RADIO_AVAILABLE,
new AsyncResult(null, new int[]{ServiceState.RIL_RADIO_TECHNOLOGY_GSM}, null)));
@@ -2919,12 +3093,19 @@
processAllMessages();
}
- private void sendIdentifierDisclosureEnabledSuccessToPhone(GsmCdmaPhone phone) {
- phone.sendMessage(phone.obtainMessage(EVENT_SET_IDENTIFIER_DISCLOSURE_ENABLED_DONE,
- new AsyncResult(null, null, null)));
+ private void sendRequestSuccessToPhone(GsmCdmaPhone phone, int eventId) {
+ phone.sendMessage(phone.obtainMessage(eventId, new AsyncResult(null, null, null)));
processAllMessages();
}
+ private void setNullCipherNotificationPreferenceEnabled(boolean enabled) {
+ SharedPreferences sharedPreferences =
+ PreferenceManager.getDefaultSharedPreferences(mContext);
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+ editor.putBoolean(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED, enabled);
+ editor.apply();
+ }
+
private GsmCdmaPhone makeNewPhoneUT() {
return new GsmCdmaPhone(
mContext,
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java
index 3d4ef03..776715c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java
@@ -18,7 +18,8 @@
import android.telephony.TelephonyManager;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.gsm.SmsMessage;
import com.android.internal.util.HexDump;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/IccLogicalChannelRequestTest.java b/tests/telephonytests/src/com/android/internal/telephony/IccLogicalChannelRequestTest.java
index e5e6fe1..aeaa096 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/IccLogicalChannelRequestTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/IccLogicalChannelRequestTest.java
@@ -22,7 +22,8 @@
import android.os.IBinder;
import android.os.Parcel;
import android.telephony.SubscriptionManager;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import junit.framework.TestCase;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/IccServiceTableTest.java b/tests/telephonytests/src/com/android/internal/telephony/IccServiceTableTest.java
index f715266..05b5cb5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/IccServiceTableTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/IccServiceTableTest.java
@@ -17,7 +17,8 @@
package com.android.internal.telephony;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.uicc.IccServiceTable;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ImsSmsDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/ImsSmsDispatcherTest.java
index fe1404b..f64155c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ImsSmsDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ImsSmsDispatcherTest.java
@@ -38,10 +38,11 @@
import android.telephony.CarrierConfigManager;
import android.telephony.SmsMessage;
import android.telephony.ims.stub.ImsSmsImplBase;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import com.android.ims.FeatureConnector;
import com.android.ims.ImsManager;
import com.android.internal.util.HexDump;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ImsiEncryptionInfoTest.java b/tests/telephonytests/src/com/android/internal/telephony/ImsiEncryptionInfoTest.java
index 0fcb384..8fba956 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ImsiEncryptionInfoTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ImsiEncryptionInfoTest.java
@@ -20,9 +20,10 @@
import android.os.Parcel;
import android.telephony.ImsiEncryptionInfo;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.Base64;
+import androidx.test.filters.SmallTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/InboundSmsTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/InboundSmsTrackerTest.java
index d251cf5..08a1b9a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/InboundSmsTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/InboundSmsTrackerTest.java
@@ -22,7 +22,8 @@
import android.database.Cursor;
import android.database.MatrixCursor;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.util.HexDump;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/IntRangeManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/IntRangeManagerTest.java
index ee75826..663fd3e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/IntRangeManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/IntRangeManagerTest.java
@@ -17,7 +17,8 @@
package com.android.internal.telephony;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/LocaleTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/LocaleTrackerTest.java
index 03b1cfd..6e50d88 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/LocaleTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/LocaleTrackerTest.java
@@ -22,8 +22,10 @@
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.content.Intent;
import android.os.AsyncResult;
@@ -34,15 +36,18 @@
import android.telephony.CellInfoGsm;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.util.Arrays;
import java.util.Collections;
@@ -65,13 +70,18 @@
private LocaleTracker mLocaleTracker;
private CellInfoGsm mCellInfo;
+ @Mock TelephonyCountryDetector mCountryDetector;
@Before
public void setUp() throws Exception {
- logd("LocaleTrackerTest +Setup!");
super.setUp(getClass().getSimpleName());
+ MockitoAnnotations.initMocks(this);
+ logd(TAG + " Setup!");
- mLocaleTracker = new LocaleTracker(mPhone, mNitzStateMachine, Looper.myLooper());
+ mLocaleTracker =
+ new LocaleTracker(mPhone, mNitzStateMachine, Looper.myLooper(), mFeatureFlags);
+ replaceInstance(TelephonyCountryDetector.class, "sInstance", null,
+ mCountryDetector);
// This is a workaround to bypass setting system properties, which causes access violation.
doReturn(-1).when(mPhone).getPhoneId();
@@ -334,4 +344,31 @@
sendServiceState(ServiceState.STATE_IN_SERVICE);
assertEquals(COUNTRY_CODE_UNAVAILABLE, mLocaleTracker.getCurrentCountry());
}
+
+ @Test
+ public void testNotifyCountryCodeChangedToTelephonyCountryDetector_featureFlagEnabled() {
+ testNotifyCountryCodeChangedToTelephonyCountryDetector(true);
+ }
+
+ @Test
+ public void testNotifyCountryCodeChangedToTelephonyCountryDetector_featureFlagDisabled() {
+ testNotifyCountryCodeChangedToTelephonyCountryDetector(false);
+ }
+
+ private void testNotifyCountryCodeChangedToTelephonyCountryDetector(
+ boolean oemEnabledSatelliteFlag) {
+ reset(mCountryDetector);
+ when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(oemEnabledSatelliteFlag);
+ doReturn(true).when(mPhone).isRadioOn();
+ sendServiceState(ServiceState.STATE_IN_SERVICE);
+ mLocaleTracker.updateOperatorNumeric(US_MCC + FAKE_MNC);
+ assertEquals(US_COUNTRY_CODE, mLocaleTracker.getCurrentCountry());
+ assertEquals(US_COUNTRY_CODE, mLocaleTracker.getLastKnownCountryIso());
+ verifyCountryCodeNotified(new String[]{COUNTRY_CODE_UNAVAILABLE, US_COUNTRY_CODE});
+ assertFalse(mLocaleTracker.isTracking());
+
+ int notifiedCount = oemEnabledSatelliteFlag ? 1 : 0;
+ verify(mCountryDetector, times(notifiedCount))
+ .onNetworkCountryCodeChanged(mPhone, US_COUNTRY_CODE);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java b/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java
index fcffa96..658935f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java
@@ -19,9 +19,9 @@
import static org.junit.Assert.assertEquals;
import android.content.Context;
-import android.test.suitebuilder.annotation.SmallTest;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.MccTable.MccMnc;
import com.android.internal.telephony.util.LocaleUtils;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/MissedIncomingCallSmsFilterTest.java b/tests/telephonytests/src/com/android/internal/telephony/MissedIncomingCallSmsFilterTest.java
index 510103c..d6dd573 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/MissedIncomingCallSmsFilterTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/MissedIncomingCallSmsFilterTest.java
@@ -27,7 +27,8 @@
import android.os.PersistableBundle;
import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.uicc.IccUtils;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ModemInfoTest.java b/tests/telephonytests/src/com/android/internal/telephony/ModemInfoTest.java
index 6e646d5..dc57a23 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ModemInfoTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ModemInfoTest.java
@@ -21,7 +21,8 @@
import android.os.Parcel;
import android.telephony.ModemInfo;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
index 7893e78..4c68e26 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
@@ -52,11 +52,11 @@
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.data.DataSettingsManager;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
@@ -247,6 +247,10 @@
return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}).when(mPhoneMock2).getSubId();
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
+ doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
+
replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
// Capture listener to emulate the carrier config change notification used later
ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
@@ -885,6 +889,13 @@
doReturn(true).when(mPhoneMock2).isUserDataEnabled();
mMultiSimSettingControllerUT.notifyAllSubscriptionLoaded();
processAllMessages();
+
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
+ doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(eq(1));
+ PersistableBundle bundle2 = new PersistableBundle();
+ doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(eq(2));
+
sendCarrierConfigChanged(0, 1);
// Notify carrier config change on phone1 without specifying subId.
sendCarrierConfigChanged(1, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
@@ -893,13 +904,9 @@
verify(mDataSettingsManagerMock2, never()).setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, false, PHONE_PACKAGE);
- // Still notify carrier config without specifying subId2, but this time subController
- // and CarrierConfigManager have subId 2 active and ready.
- doReturn(2).when(mSubscriptionManagerService).getSubId(1);
- CarrierConfigManager cm = (CarrierConfigManager) mContext.getSystemService(
- mContext.CARRIER_CONFIG_SERVICE);
- doReturn(new PersistableBundle()).when(cm).getConfigForSubId(2);
- sendCarrierConfigChanged(1, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ logd("Sending the correct phone id and sub id");
+ bundle2.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
+ sendCarrierConfigChanged(1, 2);
processAllMessages();
// This time user data should be disabled on phone1.
verify(mDataSettingsManagerMock2).setDataEnabled(
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NeighboringCellInfoTest.java b/tests/telephonytests/src/com/android/internal/telephony/NeighboringCellInfoTest.java
index f49fffd..e0e0aa1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NeighboringCellInfoTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NeighboringCellInfoTest.java
@@ -15,15 +15,16 @@
*/
package com.android.internal.telephony;
-import android.os.Parcel;
-import android.test.AndroidTestCase;
-import android.telephony.NeighboringCellInfo;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
import static android.telephony.TelephonyManager.NETWORK_TYPE_EDGE;
import static android.telephony.TelephonyManager.NETWORK_TYPE_GPRS;
import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
+
+import android.os.Parcel;
+import android.telephony.NeighboringCellInfo;
+import android.test.AndroidTestCase;
+
+import androidx.test.filters.SmallTest;
public class NeighboringCellInfoTest extends AndroidTestCase {
@SmallTest
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
index 7f15af8..0869bab 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
@@ -107,7 +107,8 @@
// Capture listener to emulate the carrier config change notification used later
ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
- mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
processAllMessages();
verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
listenerArgumentCaptor.capture());
@@ -277,7 +278,8 @@
public void testTransitionToCurrentStateIdleSupportPhysicalChannelConfig1_6() throws Exception {
doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
- mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
processAllMessages();
assertEquals("DefaultState", getCurrentState().getName());
@@ -295,7 +297,8 @@
CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL, true);
doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
- mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
sendCarrierConfigChanged();
processAllMessages();
assertEquals("DefaultState", getCurrentState().getName());
@@ -324,7 +327,8 @@
throws Exception {
doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
- mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
sendCarrierConfigChanged();
processAllMessages();
assertEquals("DefaultState", getCurrentState().getName());
@@ -344,7 +348,8 @@
CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL, true);
doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
- mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
sendCarrierConfigChanged();
processAllMessages();
assertEquals("DefaultState", getCurrentState().getName());
@@ -358,6 +363,19 @@
}
@Test
+ public void testTransitionToCurrentStateNrConnectedIdle() throws Exception {
+ assertEquals("DefaultState", getCurrentState().getName());
+ doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ doReturn(new ArrayList<>()).when(mSST).getPhysicalChannelConfigList();
+ sendCarrierConfigChanged();
+
+ mNetworkTypeController.sendMessage(3 /* EVENT_SERVICE_STATE_CHANGED */);
+ processAllMessages();
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ }
+
+ @Test
public void testTransitionToCurrentStateNrConnected() throws Exception {
assertEquals("DefaultState", getCurrentState().getName());
doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
@@ -745,7 +763,8 @@
throws Exception {
doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
- mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
processAllMessages();
testTransitionToCurrentStateNrConnectedMmwave();
doReturn(NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED).when(mServiceState).getNrState();
@@ -764,7 +783,8 @@
CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL, true);
doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
- mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
sendCarrierConfigChanged();
processAllMessages();
testTransitionToCurrentStateNrConnectedMmwave();
@@ -865,7 +885,8 @@
throws Exception {
doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
- mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
processAllMessages();
testTransitionToCurrentStateLteConnectedSupportPhysicalChannelConfig1_6();
doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
@@ -883,7 +904,8 @@
CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL, true);
doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
- mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
sendCarrierConfigChanged();
processAllMessages();
testTransitionToCurrentStateLteConnected_usingUserDataForRrcDetection();
@@ -1317,6 +1339,229 @@
}
@Test
+ public void testSecondaryTimerExpireNrIdle() throws Exception {
+ doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ ArrayList<PhysicalChannelConfig> physicalChannelConfigs = new ArrayList<>();
+ physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(1)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .setBand(41)
+ .build());
+ doReturn(physicalChannelConfigs).when(mSST).getPhysicalChannelConfigList();
+ mBundle.putIntArray(CarrierConfigManager.KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY,
+ new int[]{41});
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,10");
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,30");
+ sendCarrierConfigChanged();
+
+ assertEquals("connected_mmwave", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // should trigger 10 second primary timer
+ physicalChannelConfigs.clear();
+ physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(1)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .build());
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */);
+ processAllMessages();
+
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // switch to connected_rrc_idle
+ physicalChannelConfigs.clear();
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */);
+ processAllMessages();
+
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // primary timer expires
+ moveTimeForward(10 * 1000);
+ processAllMessages();
+
+ // should trigger 30 second secondary timer
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // secondary timer expires
+ moveTimeForward(30 * 1000);
+ processAllMessages();
+
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertFalse(mNetworkTypeController.areAnyTimersActive());
+ }
+
+ @Test
+ public void testSecondaryTimerResetNrIdle() throws Exception {
+ doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ ArrayList<PhysicalChannelConfig> physicalChannelConfigs = new ArrayList<>();
+ physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(1)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .setBand(41)
+ .build());
+ doReturn(physicalChannelConfigs).when(mSST).getPhysicalChannelConfigList();
+ mBundle.putIntArray(CarrierConfigManager.KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY,
+ new int[]{41});
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,10");
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,30");
+ sendCarrierConfigChanged();
+
+ assertEquals("connected_mmwave", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // should trigger 10 second primary timer
+ physicalChannelConfigs.clear();
+ physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(1)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .build());
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */);
+ processAllMessages();
+
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // switch to connected_rrc_idle
+ physicalChannelConfigs.clear();
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */);
+ processAllMessages();
+
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // primary timer expires
+ moveTimeForward(10 * 1000);
+ processAllMessages();
+
+ // should trigger 30 second secondary timer
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // reconnect to NR in the middle of the timer
+ physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(1)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .setBand(41)
+ .build());
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */);
+
+ // secondary timer expires
+ moveTimeForward(30 * 1000);
+ processAllMessages();
+
+ // timer should not have gone off
+ assertEquals("connected_mmwave", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertFalse(mNetworkTypeController.areAnyTimersActive());
+ }
+
+ @Test
+ public void testSecondaryTimerPrimaryCellChangeNrIdle() throws Exception {
+ doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ ArrayList<PhysicalChannelConfig> physicalChannelConfigs = new ArrayList<>();
+ physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(1)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .setBand(41)
+ .build());
+ doReturn(physicalChannelConfigs).when(mSST).getPhysicalChannelConfigList();
+ mBundle.putIntArray(CarrierConfigManager.KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY,
+ new int[]{41});
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,10");
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,30");
+ sendCarrierConfigChanged();
+
+ assertEquals("connected_mmwave", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // should trigger 10 second primary timer
+ physicalChannelConfigs.clear();
+ physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(1)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .build());
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */);
+ processAllMessages();
+
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // switch to connected_rrc_idle
+ physicalChannelConfigs.clear();
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */);
+ processAllMessages();
+
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // primary timer expires
+ moveTimeForward(10 * 1000);
+ processAllMessages();
+
+ // should trigger 30 second secondary timer
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // primary cell changes
+ physicalChannelConfigs.clear();
+ physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(2)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .build());
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */);
+ processAllMessages();
+
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+ }
+
+ @Test
public void testNrTimerResetIn3g() throws Exception {
doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneCapabilityTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneCapabilityTest.java
index 2410625..ca9d94a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneCapabilityTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneCapabilityTest.java
@@ -23,7 +23,8 @@
import android.os.Parcel;
import android.telephony.ModemInfo;
import android.telephony.PhoneCapability;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
index 4f2d8db..6743d1c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
@@ -20,6 +20,7 @@
import static android.telephony.TelephonyManager.EXTRA_ACTIVE_SIM_SUPPORTED_COUNT;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -37,12 +38,15 @@
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
+import android.telephony.ModemInfo;
import android.telephony.PhoneCapability;
import android.telephony.SubscriptionManager;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.telephony.TelephonyRegistryManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.flags.FeatureFlags;
import org.junit.After;
@@ -52,6 +56,13 @@
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class PhoneConfigurationManagerTest extends TelephonyTest {
@@ -63,8 +74,23 @@
PhoneConfigurationManager.MockableInterface mMi;
private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 1;
+ private static final PhoneCapability STATIC_DSDA_CAPABILITY;
PhoneConfigurationManager mPcm;
private FeatureFlags mFeatureFlags;
+ private TelephonyRegistryManager mMockRegistryManager;
+
+ static {
+ ModemInfo modemInfo1 = new ModemInfo(0, 0, true, true);
+ ModemInfo modemInfo2 = new ModemInfo(1, 0, true, true);
+
+ List<ModemInfo> logicalModemList = new ArrayList<>();
+ logicalModemList.add(modemInfo1);
+ logicalModemList.add(modemInfo2);
+ int[] deviceNrCapabilities = new int[0];
+
+ STATIC_DSDA_CAPABILITY = new PhoneCapability(2, 1, logicalModemList, false,
+ deviceNrCapabilities);
+ }
@Before
public void setUp() throws Exception {
@@ -78,6 +104,8 @@
mPhone.mCi = mMockCi0;
mCT.mCi = mMockCi0;
mPhone1.mCi = mMockCi1;
+ doReturn(RIL.RADIO_HAL_VERSION_2_2).when(mMockRadioConfigProxy).getVersion();
+ mMockRegistryManager = mContext.getSystemService(TelephonyRegistryManager.class);
}
@After
@@ -129,15 +157,7 @@
init(1);
assertEquals(PhoneCapability.DEFAULT_SSSS_CAPABILITY, mPcm.getStaticPhoneCapability());
- ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
- verify(mMockRadioConfig).getPhoneCapability(captor.capture());
- Message msg = captor.getValue();
- AsyncResult.forMessage(msg, PhoneCapability.DEFAULT_DSDS_CAPABILITY, null);
- msg.sendToTarget();
- processAllMessages();
-
- // Not static capability should indicate DSDS capable.
- assertEquals(PhoneCapability.DEFAULT_DSDS_CAPABILITY, mPcm.getStaticPhoneCapability());
+ setAndVerifyStaticCapability(PhoneCapability.DEFAULT_DSDS_CAPABILITY);
}
@Test
@@ -163,6 +183,209 @@
@Test
@SmallTest
+ public void testUpdateSimultaneousCallingSupport() throws Exception {
+ doReturn(false).when(mFeatureFlags).simultaneousCallingIndications();
+ init(2);
+ mPcm.updateSimultaneousCallingSupport();
+
+ int[] enabledLogicalSlots = {0, 1};
+ ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
+ verify(mMockRadioConfig).updateSimultaneousCallingSupport(captor.capture());
+ Message msg = captor.getValue();
+ AsyncResult.forMessage(msg, enabledLogicalSlots, null);
+ msg.sendToTarget();
+ processAllMessages();
+
+ HashSet<Integer> expectedSlots = new HashSet<>();
+ for (int i : enabledLogicalSlots) { expectedSlots.add(i); }
+ assertEquals(expectedSlots, mPcm.getSlotsSupportingSimultaneousCellularCalls());
+ }
+
+ @Test
+ @SmallTest
+ public void testUpdateSimultaneousCallingSupport_invalidResponse_shouldFail() throws Exception {
+ doReturn(false).when(mFeatureFlags).simultaneousCallingIndications();
+ init(2);
+ mPcm.updateSimultaneousCallingSupport();
+
+ // Have the modem send invalid phone slots -1 and 5:
+ int[] invalidEnabledLogicalSlots = {-1, 5};
+ ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
+ verify(mMockRadioConfig).updateSimultaneousCallingSupport(captor.capture());
+ Message msg = captor.getValue();
+ AsyncResult.forMessage(msg, invalidEnabledLogicalSlots, null);
+ msg.sendToTarget();
+ processAllMessages();
+
+ // We would expect to DSDA to be disabled and mSlotsSupportingSimultaneousCellularCalls to
+ // have been cleared:
+ assertTrue(mPcm.getSlotsSupportingSimultaneousCellularCalls().isEmpty());
+ }
+
+ /**
+ * If the device uses the older "dsda" multi_sim_config setting, ensure that DSDA is set
+ * statically for that device and subId updates work.
+ */
+ @Test
+ @SmallTest
+ public void testBkwdsCompatSimultaneousCallingDsda() throws Exception {
+ doReturn(true).when(mFeatureFlags).simultaneousCallingIndications();
+ doReturn(RIL.RADIO_HAL_VERSION_2_1).when(mMockRadioConfigProxy).getVersion();
+ doReturn(Optional.of("dsda")).when(mMi).getMultiSimProperty();
+ final int phone0SubId = 2;
+ final int phone1SubId = 3;
+ mPhones = new Phone[]{mPhone, mPhone1};
+ doReturn(0).when(mPhone).getPhoneId();
+ doReturn(1).when(mPhone1).getPhoneId();
+ replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
+ init(2);
+ doReturn(phone0SubId).when(mPhone).getSubId();
+ doReturn(phone1SubId).when(mPhone1).getSubId();
+ Set<Integer>[] cachedSimultaneousCallingSlots = new Set[]{Collections.emptySet()};
+ mPcm.registerForSimultaneousCellularCallingSlotsChanged(newSlots ->
+ cachedSimultaneousCallingSlots[0] = newSlots);
+
+ mPcm.getStaticPhoneCapability();
+ setAndVerifyStaticCapability(STATIC_DSDA_CAPABILITY);
+ ArgumentCaptor<SubscriptionManager.OnSubscriptionsChangedListener> cBCaptor =
+ ArgumentCaptor.forClass(SubscriptionManager.OnSubscriptionsChangedListener.class);
+ verify(mMockRegistryManager).addOnSubscriptionsChangedListener(cBCaptor.capture(), any());
+ processAllMessages();
+
+ int[] enabledLogicalSlots = {0, 1};
+ HashSet<Integer> expectedSlots = new HashSet<>(2);
+ for (int i : enabledLogicalSlots) {
+ expectedSlots.add(i);
+ }
+ HashSet<Integer> expectedSubIds = new HashSet<>(2);
+ expectedSubIds.add(phone0SubId);
+ expectedSubIds.add(phone1SubId);
+ assertEquals(expectedSlots, mPcm.getSlotsSupportingSimultaneousCellularCalls());
+ verify(mMockRegistryManager).notifySimultaneousCellularCallingSubscriptionsChanged(
+ eq(expectedSubIds));
+ assertEquals(expectedSlots, cachedSimultaneousCallingSlots[0]);
+
+ // Change sub ID mapping
+ final int phone1SubIdV2 = 4;
+ expectedSubIds.clear();
+ expectedSubIds.add(phone0SubId);
+ expectedSubIds.add(phone1SubIdV2);
+ doReturn(phone1SubIdV2).when(mPhone1).getSubId();
+ cBCaptor.getValue().onSubscriptionsChanged();
+ processAllMessages();
+ verify(mMockRegistryManager, times(2))
+ .notifySimultaneousCellularCallingSubscriptionsChanged(eq(expectedSubIds));
+ }
+
+ @Test
+ @SmallTest
+ public void testUpdateSimultaneousCallingSupportNotifications() throws Exception {
+ // retry simultaneous calling tests, but with notifications enabled this time
+ doReturn(true).when(mFeatureFlags).simultaneousCallingIndications();
+
+ final int phone0SubId = 2;
+ final int phone1SubId = 3;
+ mPhones = new Phone[]{mPhone, mPhone1};
+ replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
+ init(2);
+ doReturn(phone0SubId).when(mPhone).getSubId();
+ doReturn(phone1SubId).when(mPhone1).getSubId();
+ Set<Integer>[] cachedSimultaneousCallingSlots = new Set[]{Collections.emptySet()};
+ mPcm.registerForSimultaneousCellularCallingSlotsChanged(newSlots ->
+ cachedSimultaneousCallingSlots[0] = newSlots);
+
+ // Simultaneous calling enabled
+ mPcm.updateSimultaneousCallingSupport();
+ int[] enabledLogicalSlots = {0, 1};
+ ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
+ verify(mMockRadioConfig).updateSimultaneousCallingSupport(captor.capture());
+ Message msg = captor.getValue();
+ AsyncResult.forMessage(msg, enabledLogicalSlots, null);
+ msg.sendToTarget();
+ processAllMessages();
+
+ HashSet<Integer> expectedSlots = new HashSet<>(2);
+ for (int i : enabledLogicalSlots) {
+ expectedSlots.add(i);
+ }
+ HashSet<Integer> expectedSubIds = new HashSet<>(2);
+ expectedSubIds.add(phone0SubId);
+ expectedSubIds.add(phone1SubId);
+ assertEquals(expectedSlots, mPcm.getSlotsSupportingSimultaneousCellularCalls());
+ verify(mMockRegistryManager).notifySimultaneousCellularCallingSubscriptionsChanged(
+ eq(expectedSubIds));
+ assertEquals(expectedSlots, cachedSimultaneousCallingSlots[0]);
+
+ // Simultaneous Calling Disabled
+ mPcm.updateSimultaneousCallingSupport();
+ int[] disabled = {};
+ captor = ArgumentCaptor.forClass(Message.class);
+ verify(mMockRadioConfig, times(2)).updateSimultaneousCallingSupport(captor.capture());
+ msg = captor.getAllValues().get(1);
+ AsyncResult.forMessage(msg, disabled, null);
+ msg.sendToTarget();
+ processAllMessages();
+
+ assertEquals(Collections.emptySet(), mPcm.getSlotsSupportingSimultaneousCellularCalls());
+ verify(mMockRegistryManager, times(2))
+ .notifySimultaneousCellularCallingSubscriptionsChanged(eq(Collections.emptySet()));
+ assertEquals(Collections.emptySet(), cachedSimultaneousCallingSlots[0]);
+ }
+
+ @Test
+ @SmallTest
+ public void testSimultaneousCallingSubIdMappingChanges() throws Exception {
+ doReturn(true).when(mFeatureFlags).simultaneousCallingIndications();
+ final int phone0SubId = 2;
+ final int phone1SubId = 3;
+ mPhones = new Phone[]{mPhone, mPhone1};
+ replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
+ init(2);
+ doReturn(phone0SubId).when(mPhone).getSubId();
+ doReturn(phone1SubId).when(mPhone1).getSubId();
+
+ // Set the capability to DSDA mode to register listener, which will also trigger
+ // simultaneous calling evaluation
+ mPcm.getCurrentPhoneCapability();
+ setAndVerifyStaticCapability(STATIC_DSDA_CAPABILITY);
+ ArgumentCaptor<SubscriptionManager.OnSubscriptionsChangedListener> cBCaptor =
+ ArgumentCaptor.forClass(SubscriptionManager.OnSubscriptionsChangedListener.class);
+ verify(mMockRegistryManager).addOnSubscriptionsChangedListener(cBCaptor.capture(), any());
+
+ int[] enabledLogicalSlots = {0, 1};
+ ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
+ verify(mMockRadioConfig).updateSimultaneousCallingSupport(captor.capture());
+ Message msg = captor.getValue();
+ // Simultaneous calling enabled
+ AsyncResult.forMessage(msg, enabledLogicalSlots, null);
+ msg.sendToTarget();
+ processAllMessages();
+
+ HashSet<Integer> expectedSlots = new HashSet<>(2);
+ for (int i : enabledLogicalSlots) {
+ expectedSlots.add(i);
+ }
+ HashSet<Integer> expectedSubIds = new HashSet<>(2);
+ expectedSubIds.add(phone0SubId);
+ expectedSubIds.add(phone1SubId);
+ assertEquals(expectedSlots, mPcm.getSlotsSupportingSimultaneousCellularCalls());
+ verify(mMockRegistryManager).notifySimultaneousCellularCallingSubscriptionsChanged(
+ eq(expectedSubIds));
+
+ // Change sub ID mapping
+ final int phone1SubIdV2 = 4;
+ expectedSubIds.clear();
+ expectedSubIds.add(phone0SubId);
+ expectedSubIds.add(phone1SubIdV2);
+ doReturn(phone1SubIdV2).when(mPhone1).getSubId();
+ cBCaptor.getValue().onSubscriptionsChanged();
+ processAllMessages();
+ verify(mMockRegistryManager, times(2))
+ .notifySimultaneousCellularCallingSubscriptionsChanged(eq(expectedSubIds));
+ }
+
+ @Test
+ @SmallTest
public void testSwitchMultiSimConfig_notDsdsCapable_shouldFail() throws Exception {
init(1);
assertEquals(PhoneCapability.DEFAULT_SSSS_CAPABILITY, mPcm.getStaticPhoneCapability());
@@ -339,4 +562,15 @@
verify(mMockCi1, times(1)).registerForAvailable(any(), anyInt(), any());
verify(mMockCi1, times(1)).onSlotActiveStatusChange(anyBoolean());
}
+
+ private void setAndVerifyStaticCapability(PhoneCapability capability) {
+ ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
+ verify(mMockRadioConfig).getPhoneCapability(captor.capture());
+ Message msg = captor.getValue();
+ AsyncResult.forMessage(msg, capability, null);
+ msg.sendToTarget();
+ processAllMessages();
+
+ assertEquals(capability, mPcm.getStaticPhoneCapability());
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
index 3c7e0b6..1c4e43d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
@@ -23,11 +23,11 @@
import android.net.Uri;
import android.telephony.PhoneNumberUtils;
-import android.test.suitebuilder.annotation.SmallTest;
import android.text.SpannableStringBuilder;
import android.text.style.TtsSpan;
import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
import org.junit.After;
import org.junit.Before;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberWatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberWatcherTest.java
index c10dea9..e04507c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberWatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberWatcherTest.java
@@ -18,12 +18,14 @@
import static org.junit.Assert.assertEquals;
import android.telephony.PhoneNumberFormattingTextWatcher;
-import android.test.suitebuilder.annotation.SmallTest;
import android.text.Editable;
import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.text.TextWatcher;
import android.text.style.TtsSpan;
+
+import androidx.test.filters.SmallTest;
+
import org.junit.Ignore;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneStateListenerExecutorTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneStateListenerExecutorTest.java
index 5cd54c1..afc6f4a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneStateListenerExecutorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneStateListenerExecutorTest.java
@@ -21,7 +21,8 @@
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import org.junit.After;
import org.junit.Before;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneStateListenerTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneStateListenerTest.java
index 48b49d1..730e20f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneStateListenerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneStateListenerTest.java
@@ -24,10 +24,11 @@
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.emergency.EmergencyNumber;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
index 00634a0..1af4a76 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
@@ -23,8 +23,10 @@
import static org.junit.Assert.assertEquals;
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.anyString;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doReturn;
@@ -33,12 +35,14 @@
import android.app.AppOpsManager;
import android.app.PropertyInvalidatedCache;
+import android.compat.testing.PlatformCompatChangeRule;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.RemoteException;
+import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.internal.telephony.uicc.IsimUiccRecords;
@@ -47,10 +51,14 @@
import com.android.internal.telephony.uicc.UiccPort;
import com.android.internal.telephony.uicc.UiccProfile;
+import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
+
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.mockito.Mockito;
import java.util.List;
@@ -62,6 +70,9 @@
private static final String PSI_SMSC_TEL2 = "tel:+91987654321";
private static final String PSI_SMSC_SIP2 = "sip:+19876543210@dcf.pc.operetor2.com;user=phone";
+ @Rule
+ public TestRule compatChangeRule = new PlatformCompatChangeRule();
+
private PhoneSubInfoController mPhoneSubInfoControllerUT;
private AppOpsManager mAppOsMgr;
private PackageManager mPm;
@@ -91,7 +102,7 @@
mPm = mContext.getPackageManager();
replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[]{mPhone, mSecondPhone});
- mPhoneSubInfoControllerUT = new PhoneSubInfoController(mContext);
+ mPhoneSubInfoControllerUT = new PhoneSubInfoController(mContext, mFeatureFlags);
setupMocksForTelephonyPermissions();
// TelephonyPermissions will query the READ_DEVICE_IDENTIFIERS op from AppOpManager to
@@ -104,6 +115,12 @@
// Bypass calling package check.
doReturn(Binder.getCallingUid()).when(mPm).getPackageUid(eq(TAG), anyInt());
+
+ // In order not to affect the existing implementation, define a telephony features
+ // and disabled enforce_telephony_feature_mapping_for_public_apis feature flag
+ doReturn(false).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
+ doReturn(true).when(mPm).hasSystemFeature(anyString());
+ doReturn(new String[] {TAG}).when(mPm).getPackagesForUid(anyInt());
}
@After
@@ -156,7 +173,7 @@
//case 2: no READ_PRIVILEGED_PHONE_STATE & appOsMgr READ_PHONE_PERMISSION
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
try {
@@ -178,7 +195,7 @@
//case 3: no READ_PRIVILEGED_PHONE_STATE
// The READ_PRIVILEGED_PHONE_STATE permission is now required to get device identifiers.
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
try {
@@ -212,6 +229,31 @@
@Test
@SmallTest
+ @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
+ public void testGetNai_EnabledEnforceTelephonyFeatureMappingForPublicApis() {
+ // FeatureFlags enabled, System has required feature
+ doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
+ doReturn(true).when(mPm).hasSystemFeature(
+ eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
+ doReturn("bbb@example.com").when(mSecondPhone).getNai();
+
+ // Enabled FeatureFlags and ENABLE_FEATURE_MAPPING, telephony features are defined
+ try {
+ assertEquals("bbb@example.com",
+ mPhoneSubInfoControllerUT.getNaiForSubscriber(1, TAG, FEATURE_ID));
+ } catch (UnsupportedOperationException e) {
+ fail("Not expect exception " + e.getMessage());
+ }
+
+ // Telephony features is not defined, expect UnsupportedOperationException.
+ doReturn(false).when(mPm).hasSystemFeature(
+ eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
+ assertThrows(UnsupportedOperationException.class,
+ () -> mPhoneSubInfoControllerUT.getNaiForSubscriber(1, TAG, FEATURE_ID));
+ }
+
+ @Test
+ @SmallTest
public void testGetNaiWithOutPermission() {
// The READ_PRIVILEGED_PHONE_STATE permission, carrier privileges, or passing a device /
// profile owner access check is required to access subscriber identifiers. Since none of
@@ -240,7 +282,7 @@
//case 2: no READ_PRIVILEGED_PHONE_STATE & appOsMgr READ_PHONE_PERMISSION
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
try {
@@ -261,7 +303,7 @@
//case 3: no READ_PRIVILEGED_PHONE_STATE
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
try {
@@ -323,7 +365,7 @@
//case 2: no READ_PRIVILEGED_PHONE_STATE & appOsMgr READ_PHONE_PERMISSION
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
try {
@@ -344,7 +386,7 @@
//case 3: no READ_PRIVILEGED_PHONE_STATE
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
try {
@@ -400,7 +442,7 @@
//case 2: no READ_PRIVILEGED_PHONE_STATE & appOsMgr READ_PHONE_PERMISSION
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
@@ -409,7 +451,7 @@
//case 3: no READ_PRIVILEGED_PHONE_STATE
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
assertEquals("00", mPhoneSubInfoControllerUT.getDeviceSvnUsingSubId(0, TAG, FEATURE_ID));
@@ -466,7 +508,7 @@
//case 2: no READ_PRIVILEGED_PHONE_STATE & appOsMgr READ_PHONE_PERMISSION
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
try {
@@ -488,7 +530,7 @@
//case 3: no READ_PRIVILEGED_PHONE_STATE
// The READ_PRIVILEGED_PHONE_STATE permission is now required to get device identifiers.
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
try {
@@ -551,7 +593,7 @@
//case 2: no READ_PRIVILEGED_PHONE_STATE & appOsMgr READ_PHONE_PERMISSION
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
try {
@@ -572,7 +614,7 @@
//case 3: no READ_PRIVILEGED_PHONE_STATE
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
try {
@@ -718,7 +760,7 @@
//case 2: no READ_PRIVILEGED_PHONE_STATE & appOsMgr READ_PHONE_PERMISSION
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
@@ -727,7 +769,7 @@
//case 3: no READ_PRIVILEGED_PHONE_STATE
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
assertEquals("LINE1_SIM_0", mPhoneSubInfoControllerUT
@@ -865,7 +907,7 @@
//case 2: no READ_PRIVILEGED_PHONE_STATE & appOsMgr READ_PHONE_PERMISSION
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
@@ -874,7 +916,7 @@
//case 3: no READ_PRIVILEGED_PHONE_STATE
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
assertEquals("+18051234567", mPhoneSubInfoControllerUT
@@ -921,7 +963,7 @@
//case 2: no READ_PRIVILEGED_PHONE_STATE & appOsMgr READ_PHONE_PERMISSION
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ERRORED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
@@ -930,7 +972,7 @@
//case 3: no READ_PRIVILEGED_PHONE_STATE
mContextFixture.addCallingOrSelfPermission(READ_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
assertEquals("VM_SIM_0", mPhoneSubInfoControllerUT
@@ -1058,7 +1100,7 @@
//case 2: no READ_PRIVILEGED_PHONE_STATE
mContextFixture.addCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE);
- doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOp(
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOsMgr).noteOpNoThrow(
eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(), eq(TAG), eq(FEATURE_ID),
nullable(String.class));
@@ -1086,7 +1128,7 @@
doReturn(refSst).when(mSimRecords).getSimServiceTable();
- String resultSst = mPhoneSubInfoControllerUT.getSimServiceTable(anyInt(), anyInt());
+ String resultSst = mPhoneSubInfoControllerUT.getSimServiceTable(0, 0);
assertEquals(refSst, resultSst);
}
@@ -1100,22 +1142,22 @@
doReturn(refSst).when(mSimRecords).getSimServiceTable();
- String resultSst = mPhoneSubInfoControllerUT.getSimServiceTable(anyInt(), anyInt());
+ String resultSst = mPhoneSubInfoControllerUT.getSimServiceTable(0, 0);
assertEquals(refSst, resultSst);
}
@Test
public void testGetSstWhenNoUiccPort() throws RemoteException {
- String refSst = "1234567";
- doReturn(null).when(mPhone).getUiccPort();
- doReturn(mUiccProfile).when(mUiccPort).getUiccProfile();
- doReturn(mUiccCardApplicationIms).when(mUiccProfile).getApplicationByType(anyInt());
- doReturn(mSimRecords).when(mUiccCardApplicationIms).getIccRecords();
+ String refSst = "1234567";
+ doReturn(null).when(mPhone).getUiccPort();
+ doReturn(mUiccProfile).when(mUiccPort).getUiccProfile();
+ doReturn(mUiccCardApplicationIms).when(mUiccProfile).getApplicationByType(anyInt());
+ doReturn(mSimRecords).when(mUiccCardApplicationIms).getIccRecords();
- doReturn(refSst).when(mSimRecords).getSimServiceTable();
+ doReturn(refSst).when(mSimRecords).getSimServiceTable();
- String resultSst = mPhoneSubInfoControllerUT.getSimServiceTable(anyInt(), anyInt());
- assertEquals(null, resultSst);
+ String resultSst = mPhoneSubInfoControllerUT.getSimServiceTable(0, 0);
+ assertEquals(null, resultSst);
}
@Test
@@ -1128,7 +1170,7 @@
doReturn(refSst).when(mSimRecords).getSimServiceTable();
- String resultSst = mPhoneSubInfoControllerUT.getSimServiceTable(anyInt(), anyInt());
+ String resultSst = mPhoneSubInfoControllerUT.getSimServiceTable(0, 0);
assertEquals(null, resultSst);
}
@@ -1142,7 +1184,7 @@
doReturn(refSst).when(mSimRecords).getSimServiceTable();
- String resultSst = mPhoneSubInfoControllerUT.getSimServiceTable(anyInt(), anyInt());
+ String resultSst = mPhoneSubInfoControllerUT.getSimServiceTable(0, 0);
assertEquals(null, resultSst);
}
@@ -1158,7 +1200,7 @@
mContextFixture.removeCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL);
try {
- mPhoneSubInfoControllerUT.getSimServiceTable(anyInt(), anyInt());
+ mPhoneSubInfoControllerUT.getSimServiceTable(0, 0);
Assert.fail("expected Security Exception Thrown");
} catch (Exception ex) {
assertTrue(ex instanceof SecurityException);
@@ -1166,7 +1208,7 @@
}
mContextFixture.addCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE);
- assertEquals(refSst, mPhoneSubInfoControllerUT.getSimServiceTable(anyInt(), anyInt()));
+ assertEquals(refSst, mPhoneSubInfoControllerUT.getSimServiceTable(0, 0));
}
@Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PlmnActRecordTest.java b/tests/telephonytests/src/com/android/internal/telephony/PlmnActRecordTest.java
index 6769105..57a49d2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PlmnActRecordTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PlmnActRecordTest.java
@@ -20,7 +20,8 @@
import android.os.Parcel;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import java.util.Arrays;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ProxyControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ProxyControllerTest.java
index 65ab664..50061c6 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ProxyControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ProxyControllerTest.java
@@ -35,10 +35,11 @@
import android.os.Handler;
import android.os.Message;
import android.telephony.RadioAccessFamily;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -55,7 +56,7 @@
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
replaceInstance(ProxyController.class, "sProxyController", null, null);
- mProxyController = ProxyController.getInstance(mContext);
+ mProxyController = new ProxyController(mContext, mFeatureFlags);
}
@After
diff --git a/tests/telephonytests/src/com/android/internal/telephony/RadioAccessFamilyTest.java b/tests/telephonytests/src/com/android/internal/telephony/RadioAccessFamilyTest.java
index 97d4a06..722fb96 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/RadioAccessFamilyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/RadioAccessFamilyTest.java
@@ -21,9 +21,10 @@
import android.telephony.RadioAccessFamily;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
+import androidx.test.filters.SmallTest;
+
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTest.java
index 7efb886..4c42e2e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTest.java
@@ -28,9 +28,10 @@
import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.Pair;
+import androidx.test.filters.SmallTest;
+
import junit.framework.TestCase;
import java.util.ArrayList;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index c542857..1a6557b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
@@ -88,12 +88,12 @@
import android.telephony.cdma.CdmaCellLocation;
import android.telephony.gsm.GsmCellLocation;
import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
import android.text.TextUtils;
import android.util.Pair;
import androidx.test.filters.FlakyTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
import com.android.internal.R;
import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
@@ -260,7 +260,8 @@
mSatelliteController = Mockito.mock(SatelliteController.class);
replaceInstance(SatelliteController.class, "sInstance", null,
mSatelliteController);
- doReturn(new ArrayList<>()).when(mSatelliteController).getSatellitePlmnList(anyInt());
+ doReturn(new ArrayList<>()).when(mSatelliteController).getSatellitePlmnsForCarrier(
+ anyInt());
mContextFixture.putResource(R.string.kg_text_message_separator, " \u2014 ");
@@ -3386,7 +3387,8 @@
CellIdentityGsm cellIdentity =
new CellIdentityGsm(0, 1, 900, 5, "101", "23", "test", "tst",
Collections.emptyList());
- doReturn(Arrays.asList("10123")).when(mSatelliteController).getSatellitePlmnList(anyInt());
+ doReturn(Arrays.asList("10123")).when(mSatelliteController).getSatellitePlmnsForCarrier(
+ anyInt());
doReturn(satelliteSupportedServiceList).when(mSatelliteController)
.getSupportedSatelliteServices(sst.mSubId, "10123");
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthControllerTest.java
index fa89082..7e4cb08 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthControllerTest.java
@@ -59,10 +59,11 @@
import android.telephony.SignalStrengthUpdateRequest;
import android.telephony.SignalThresholdInfo;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.MediumTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.MediumTest;
+
import com.android.internal.util.ArrayUtils;
import org.junit.After;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SignalToneUtilTest.java b/tests/telephonytests/src/com/android/internal/telephony/SignalToneUtilTest.java
index d7eef36..599b549 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SignalToneUtilTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SignalToneUtilTest.java
@@ -15,12 +15,16 @@
*/
package com.android.internal.telephony;
-import android.media.ToneGenerator;
-import android.test.suitebuilder.annotation.SmallTest;
-import com.android.internal.telephony.cdma.SignalToneUtil;
-import org.junit.Test;
import static org.junit.Assert.assertEquals;
+import android.media.ToneGenerator;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.telephony.cdma.SignalToneUtil;
+
+import org.junit.Test;
+
public class SignalToneUtilTest {
/* no need to initialization, everything is static */
@Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimPhoneBookTest.java b/tests/telephonytests/src/com/android/internal/telephony/SimPhoneBookTest.java
index ea6f19d..7c8c7ec 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SimPhoneBookTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimPhoneBookTest.java
@@ -19,9 +19,9 @@
import android.content.ContentValues;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
-import android.test.suitebuilder.annotation.Suppress;
-import com.android.internal.telephony.IccProvider;
+import androidx.test.filters.Suppress;
+
import com.android.internal.telephony.uicc.AdnRecord;
import com.android.internal.telephony.uicc.IccConstants;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimSmsTest.java b/tests/telephonytests/src/com/android/internal/telephony/SimSmsTest.java
index 48406de..35a61fc 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SimSmsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimSmsTest.java
@@ -18,8 +18,9 @@
import android.app.ActivityThread;
import android.telephony.TelephonyFrameworkInitializer;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.Suppress;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
import junit.framework.TestCase;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java
index c79f17f..77612d2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimUtilsTest.java
@@ -16,12 +16,11 @@
package com.android.internal.telephony;
-import com.android.internal.telephony.gsm.SimTlv;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.uicc.IccUtils;
import junit.framework.TestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
public class SimUtilsTest extends TestCase {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/Sms7BitEncodingTranslatorTest.java b/tests/telephonytests/src/com/android/internal/telephony/Sms7BitEncodingTranslatorTest.java
index cc0eb94..3295640 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/Sms7BitEncodingTranslatorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/Sms7BitEncodingTranslatorTest.java
@@ -22,7 +22,7 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import org.junit.After;
import org.junit.Before;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsControllerTest.java
index 09c4173..f8d1bec 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsControllerTest.java
@@ -16,7 +16,10 @@
package com.android.internal.telephony;
+import static junit.framework.Assert.assertEquals;
+
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.anyInt;
@@ -26,7 +29,9 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import android.compat.testing.PlatformCompatChangeRule;
import android.content.pm.PackageManager;
+import android.telephony.TelephonyManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -34,17 +39,25 @@
import com.android.internal.telephony.uicc.AdnRecordCache;
import com.android.internal.telephony.uicc.IccConstants;
+import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
+
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.NoSuchElementException;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class SmsControllerTest extends TelephonyTest {
+ @Rule
+ public TestRule compatChangeRule = new PlatformCompatChangeRule();
// Mocked classes
private AdnRecordCache mAdnRecordCache;
@@ -58,13 +71,17 @@
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
mAdnRecordCache = Mockito.mock(AdnRecordCache.class);
- mSmsControllerUT = new SmsController(mContext);
+ mSmsControllerUT = new SmsController(mContext, mFeatureFlags);
mCallingPackage = mContext.getOpPackageName();
+
+ doReturn(true).when(mPackageManager).hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_MESSAGING);
}
@After
public void tearDown() throws Exception {
mAdnRecordCache = null;
+ WapPushCache.clear();
super.tearDown();
}
@@ -239,4 +256,65 @@
verify(mIccSmsInterfaceManager, Mockito.times(0))
.sendText(mCallingPackage, "1234", null, "text", null, null, false, 0L, true);
}
+
+ @Test
+ public void testGetWapMessageSize() {
+ long expectedSize = 100L;
+ String location = "content://mms";
+ byte[] locationBytes = location.getBytes(StandardCharsets.ISO_8859_1);
+ byte[] transactionId = "123".getBytes(StandardCharsets.ISO_8859_1);
+
+ WapPushCache.putWapMessageSize(locationBytes, transactionId, expectedSize);
+ long size = mSmsControllerUT.getWapMessageSize(location);
+
+ assertEquals(expectedSize, size);
+ }
+
+ @Test
+ public void testGetWapMessageSize_withTransactionIdAppended() {
+ long expectedSize = 100L;
+ byte[] location = "content://mms".getBytes(StandardCharsets.ISO_8859_1);
+ byte[] transactionId = "123".getBytes(StandardCharsets.ISO_8859_1);
+ byte[] joinedKey = new byte[location.length + transactionId.length];
+ System.arraycopy(location, 0, joinedKey, 0, location.length);
+ System.arraycopy(transactionId, 0, joinedKey, location.length, transactionId.length);
+ String joinedKeyString = new String(joinedKey, StandardCharsets.ISO_8859_1);
+
+ WapPushCache.putWapMessageSize(location, transactionId, expectedSize);
+ long size = mSmsControllerUT.getWapMessageSize(joinedKeyString);
+
+ assertEquals(expectedSize, size);
+ }
+
+ @Test
+ public void testGetWapMessageSize_nonexistentThrows() {
+ assertThrows(NoSuchElementException.class, () ->
+ mSmsControllerUT.getWapMessageSize("content://mms")
+ );
+ }
+
+ @Test
+ @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
+ public void sendTextForSubscriberTestEnabledTelephonyFeature() {
+ int subId = 1;
+ doReturn(true).when(mSubscriptionManager)
+ .isSubscriptionAssociatedWithUser(eq(subId), any());
+
+ // Feature enabled, device does not have required telephony feature.
+ doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
+ doReturn(false).when(mPackageManager).hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_MESSAGING);
+
+ assertThrows(UnsupportedOperationException.class,
+ () -> mSmsControllerUT.sendTextForSubscriber(subId, mCallingPackage, null, "1234",
+ null, "text", null, null, false, 0L, true, true));
+
+ // Device has required telephony feature.
+ doReturn(true).when(mPackageManager).hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_MESSAGING);
+ mSmsControllerUT.sendTextForSubscriber(subId, mCallingPackage, null, "1234",
+ null, "text", null, null, false, 0L, true, true);
+ verify(mIccSmsInterfaceManager, Mockito.times(1))
+ .sendText(mCallingPackage, "1234", null, "text", null, null, false, 0L, true);
+ }
}
\ 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 dc63932..3fa4fd1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
@@ -52,11 +52,12 @@
import android.telephony.PhoneNumberUtils;
import android.telephony.SmsManager;
import android.test.FlakyTest;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.Singleton;
+import androidx.test.filters.SmallTest;
+
import com.android.ims.ImsManager;
import com.android.internal.telephony.domainselection.DomainSelectionConnection;
import com.android.internal.telephony.domainselection.EmergencySmsDomainSelectionConnection;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java
index bd963ef..dc1ee63 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java
@@ -18,7 +18,8 @@
import android.telephony.TelephonyManager;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.telephony.Rlog;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsNumberUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsNumberUtilsTest.java
index 3c1cec1..90cc0fe 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsNumberUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsNumberUtilsTest.java
@@ -26,7 +26,8 @@
import android.telephony.TelephonyManager;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import org.junit.After;
import org.junit.Before;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsStorageMonitorTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsStorageMonitorTest.java
index b6775eb..4483c61 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsStorageMonitorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsStorageMonitorTest.java
@@ -27,11 +27,12 @@
import android.content.res.Resources;
import android.os.Message;
import android.provider.Telephony;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -39,7 +40,6 @@
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
-
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class SmsStorageMonitorTest extends TelephonyTest {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java
index 9fa88e2..4afdfe9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java
@@ -17,7 +17,10 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
+
import android.os.Parcel;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -25,12 +28,18 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import java.util.Set;
+
public class SubscriptionInfoTest {
private SubscriptionInfo mSubscriptionInfoUT;
- private static final String[] EHPLMNS = new String[] {"310999", "310998"};
- private static final String[] HPLMNS = new String[] {"310001"};
+ private static final String[] EHPLMNS = new String[]{"310999", "310998"};
+ private static final String[] HPLMNS = new String[]{"310001"};
+
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@After
public void tearDown() throws Exception {
@@ -39,6 +48,8 @@
@Before
public void setUp() throws Exception {
+ mSetFlagsRule.enableFlags(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE);
+ mSetFlagsRule.enableFlags(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG);
mSubscriptionInfoUT = new SubscriptionInfo.Builder()
.setId(1)
.setIccId("890126042XXXXXXXXXXX")
@@ -55,6 +66,8 @@
.setHplmns(HPLMNS)
.setCountryIso("us")
.setOnlyNonTerrestrialNetwork(true)
+ .setServiceCapabilities(SubscriptionManager.getServiceCapabilitiesSet(
+ SubscriptionManager.SERVICE_CAPABILITY_DATA_BITMASK))
.build();
}
@@ -77,6 +90,8 @@
if (Flags.oemEnabledSatelliteFlag()) {
assertThat(mSubscriptionInfoUT.isOnlyNonTerrestrialNetwork()).isTrue();
}
+ assertThat(mSubscriptionInfoUT.getServiceCapabilities()).isEqualTo(
+ Set.of(SubscriptionManager.SERVICE_CAPABILITY_DATA));
}
@Test
@@ -101,5 +116,32 @@
assertThat(mSubscriptionInfoUT).isEqualTo(copiedInfo);
assertThat(mSubscriptionInfoUT).isNotEqualTo(differentDisplayName);
assertThat(mSubscriptionInfoUT).isNotEqualTo(differentSubId);
+
+ SubscriptionInfo differentServiceCapabilities =
+ new SubscriptionInfo.Builder(mSubscriptionInfoUT)
+ .setServiceCapabilities(SubscriptionManager.getServiceCapabilitiesSet(
+ SubscriptionManager.SERVICE_CAPABILITY_SMS_BITMASK))
+ .build();
+ assertThat(mSubscriptionInfoUT).isNotEqualTo(differentServiceCapabilities);
+ }
+
+ @Test
+ public void testInvalidServiceCapability_tooLarge() {
+ assertThrows("IllegalArgumentException should throw when set invalid service capability.",
+ IllegalArgumentException.class,
+ () -> new SubscriptionInfo.Builder()
+ .setServiceCapabilities(
+ Set.of(SubscriptionManager.SERVICE_CAPABILITY_MAX + 1))
+ .build());
+ }
+
+ @Test
+ public void testInvalidServiceCapability_tooSmall() {
+ assertThrows("IllegalArgumentException should throw when set invalid service capability.",
+ IllegalArgumentException.class,
+ () -> new SubscriptionInfo.Builder()
+ .setServiceCapabilities(
+ Set.of(SubscriptionManager.SERVICE_CAPABILITY_VOICE - 1))
+ .build());
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyCountryDetectorTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyCountryDetectorTest.java
new file mode 100644
index 0000000..a2763fe
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyCountryDetectorTest.java
@@ -0,0 +1,378 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.location.Geocoder;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.testing.TestableLooper;
+import android.util.Log;
+import android.util.Pair;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+
+/** Test for {@link TelephonyCountryDetector} */
+@RunWith(AndroidJUnit4.class)
+public class TelephonyCountryDetectorTest extends TelephonyTest {
+ private static final String TAG = "TelephonyCountryDetectorTest";
+
+ @Mock
+ ServiceStateTracker mSST2;
+ @Mock
+ LocaleTracker mMockLocaleTracker;
+ @Mock
+ LocaleTracker mMockLocaleTracker2;
+ @Mock Location mMockLocation;
+ @Mock Network mMockNetwork;
+
+ @Captor
+ private ArgumentCaptor<LocationListener> mLocationListenerCaptor;
+ @Captor
+ private ArgumentCaptor<ConnectivityManager.NetworkCallback> mNetworkCallbackCaptor;
+
+ private LocaleTracker[] mLocaleTrackers;
+ private Looper mLooper;
+ private NetworkCapabilities mNetworkCapabilities;
+ private TestTelephonyCountryDetector mCountryDetectorUT;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp(getClass().getSimpleName());
+ MockitoAnnotations.initMocks(this);
+ logd(TAG + " Setup!");
+
+ HandlerThread handlerThread = new HandlerThread("CountryDetectorTest");
+ handlerThread.start();
+ mLooper = handlerThread.getLooper();
+ mTestableLooper = new TestableLooper(mLooper);
+
+ mLocaleTrackers = new LocaleTracker[]{mMockLocaleTracker, mMockLocaleTracker2};
+ replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[] {mPhone, mPhone2});
+ when(mPhone.getServiceStateTracker()).thenReturn(mSST);
+ when(mPhone.getPhoneId()).thenReturn(0);
+ when(mSST.getLocaleTracker()).thenReturn(mMockLocaleTracker);
+ when(mMockLocaleTracker.getCurrentCountry()).thenReturn("");
+ when(mPhone2.getServiceStateTracker()).thenReturn(mSST2);
+ when(mPhone2.getPhoneId()).thenReturn(1);
+ when(mSST2.getLocaleTracker()).thenReturn(mMockLocaleTracker2);
+ when(mMockLocaleTracker2.getCurrentCountry()).thenReturn("");
+
+ when(mConnectivityManager.getActiveNetwork()).thenReturn(mMockNetwork);
+ mNetworkCapabilities = new NetworkCapabilities();
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, true);
+ when(mConnectivityManager.getNetworkCapabilities(any(Network.class)))
+ .thenReturn(mNetworkCapabilities);
+
+ when(mLocationManager.getProviders(true)).thenReturn(Arrays.asList("TEST_PROVIDER"));
+
+ mCountryDetectorUT = new TestTelephonyCountryDetector(
+ mLooper, mContext, mLocationManager, mConnectivityManager);
+ if (isGeoCoderImplemented()) {
+ verify(mLocationManager).requestLocationUpdates(anyString(), anyLong(), anyFloat(),
+ mLocationListenerCaptor.capture());
+ verify(mLocationManager).getProviders(true);
+ verify(mLocationManager).getLastKnownLocation(anyString());
+ }
+ verify(mConnectivityManager).registerNetworkCallback(
+ any(NetworkRequest.class), mNetworkCallbackCaptor.capture());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ Log.d(TAG, "tearDown");
+ }
+
+ @Test
+ public void testGetInstance() {
+ clearInvocations(mLocationManager);
+ clearInvocations(mConnectivityManager);
+ when(mMockLocaleTracker.getCurrentCountry()).thenReturn("US");
+ TelephonyCountryDetector inst1 = TelephonyCountryDetector.getInstance(mContext);
+ TelephonyCountryDetector inst2 = TelephonyCountryDetector.getInstance(mContext);
+ assertEquals(inst1, inst2);
+ if (isGeoCoderImplemented()) {
+ verify(mLocationManager, never()).requestLocationUpdates(anyString(), anyLong(),
+ anyFloat(), any(LocationListener.class));
+ }
+ verify(mConnectivityManager).registerNetworkCallback(
+ any(NetworkRequest.class), any(ConnectivityManager.NetworkCallback.class));
+ }
+
+ @Test
+ public void testGetCurrentNetworkCountryIso() {
+ // No ServiceStateTracker
+ when(mPhone.getServiceStateTracker()).thenReturn(null);
+ when(mPhone2.getServiceStateTracker()).thenReturn(null);
+ assertTrue(mCountryDetectorUT.getCurrentNetworkCountryIso().isEmpty());
+
+ // No LocaleTracker
+ when(mPhone.getServiceStateTracker()).thenReturn(mSST);
+ when(mSST.getLocaleTracker()).thenReturn(null);
+ when(mPhone2.getServiceStateTracker()).thenReturn(mSST2);
+ when(mSST2.getLocaleTracker()).thenReturn(null);
+ assertTrue(mCountryDetectorUT.getCurrentNetworkCountryIso().isEmpty());
+
+ // LocaleTracker returns invalid country
+ when(mSST.getLocaleTracker()).thenReturn(mMockLocaleTracker);
+ when(mMockLocaleTracker.getCurrentCountry()).thenReturn("1234");
+ when(mSST2.getLocaleTracker()).thenReturn(mMockLocaleTracker2);
+ when(mMockLocaleTracker2.getCurrentCountry()).thenReturn("");
+ assertTrue(mCountryDetectorUT.getCurrentNetworkCountryIso().isEmpty());
+
+ // LocaleTracker of phone 2 returns valid country
+ when(mMockLocaleTracker2.getCurrentCountry()).thenReturn("US");
+ assertEquals(1, mCountryDetectorUT.getCurrentNetworkCountryIso().size());
+ assertTrue(mCountryDetectorUT.getCurrentNetworkCountryIso().contains("US"));
+
+ // Phone 1 is also in US
+ when(mMockLocaleTracker.getCurrentCountry()).thenReturn("US");
+ assertEquals(1, mCountryDetectorUT.getCurrentNetworkCountryIso().size());
+ assertTrue(mCountryDetectorUT.getCurrentNetworkCountryIso().contains("US"));
+
+ // Phone 1 is in US and Phone 2 is in CA
+ when(mMockLocaleTracker.getCurrentCountry()).thenReturn("CA");
+ assertEquals(2, mCountryDetectorUT.getCurrentNetworkCountryIso().size());
+ assertTrue(mCountryDetectorUT.getCurrentNetworkCountryIso().contains("US"));
+ assertTrue(mCountryDetectorUT.getCurrentNetworkCountryIso().contains("CA"));
+ }
+
+ @Test
+ public void testCachedNetworkCountryCodeUpdate() {
+ assertTrue(mCountryDetectorUT.getCachedNetworkCountryIsoInfo().isEmpty());
+
+ // Update network country code of Phone 1
+ sendNetworkCountryCodeChanged("US", mPhone);
+ assertEquals(1, mCountryDetectorUT.getCachedNetworkCountryIsoInfo().size());
+ assertTrue(mCountryDetectorUT.getCachedNetworkCountryIsoInfo().containsKey("US"));
+ assertEquals(0, (long) mCountryDetectorUT.getCachedNetworkCountryIsoInfo().get("US"));
+
+ // Move time forwards and update network country code of Phone 2
+ mCountryDetectorUT.elapsedRealtimeNanos = 2;
+ sendNetworkCountryCodeChanged("US", mPhone2);
+ assertEquals(1, mCountryDetectorUT.getCachedNetworkCountryIsoInfo().size());
+ assertTrue(mCountryDetectorUT.getCachedNetworkCountryIsoInfo().containsKey("US"));
+ assertEquals(2, (long) mCountryDetectorUT.getCachedNetworkCountryIsoInfo().get("US"));
+
+ // Move time forwards and update network country code of Phone 1
+ mCountryDetectorUT.elapsedRealtimeNanos = 3;
+ sendNetworkCountryCodeChanged("CA", mPhone);
+ assertEquals(2, mCountryDetectorUT.getCachedNetworkCountryIsoInfo().size());
+ assertTrue(mCountryDetectorUT.getCachedNetworkCountryIsoInfo().containsKey("US"));
+ assertEquals(2, (long) mCountryDetectorUT.getCachedNetworkCountryIsoInfo().get("US"));
+ assertTrue(mCountryDetectorUT.getCachedNetworkCountryIsoInfo().containsKey("CA"));
+ assertEquals(3, (long) mCountryDetectorUT.getCachedNetworkCountryIsoInfo().get("CA"));
+
+ // Move time forwards and update network country code of Phone 2
+ mCountryDetectorUT.elapsedRealtimeNanos = 4;
+ sendNetworkCountryCodeChanged("CA", mPhone2);
+ assertEquals(1, mCountryDetectorUT.getCachedNetworkCountryIsoInfo().size());
+ assertTrue(mCountryDetectorUT.getCachedNetworkCountryIsoInfo().containsKey("CA"));
+ assertEquals(4, (long) mCountryDetectorUT.getCachedNetworkCountryIsoInfo().get("CA"));
+
+ // Move time forwards and update network country code of Phone 1
+ mCountryDetectorUT.elapsedRealtimeNanos = 5;
+ sendNetworkCountryCodeChanged("", mPhone);
+ assertEquals(1, mCountryDetectorUT.getCachedNetworkCountryIsoInfo().size());
+ assertTrue(mCountryDetectorUT.getCachedNetworkCountryIsoInfo().containsKey("CA"));
+ assertEquals(5, (long) mCountryDetectorUT.getCachedNetworkCountryIsoInfo().get("CA"));
+
+ // Move time forwards and update network country code of Phone 2
+ mCountryDetectorUT.elapsedRealtimeNanos = 6;
+ sendNetworkCountryCodeChanged("", mPhone2);
+ assertEquals(1, mCountryDetectorUT.getCachedNetworkCountryIsoInfo().size());
+ assertTrue(mCountryDetectorUT.getCachedNetworkCountryIsoInfo().containsKey("CA"));
+ assertEquals(6, (long) mCountryDetectorUT.getCachedNetworkCountryIsoInfo().get("CA"));
+ }
+
+ @Test
+ public void testCachedLocationCountryCodeUpdate() {
+ if (!isGeoCoderImplemented()) {
+ logd("Skip the test because GeoCoder is not implemented on the device");
+ return;
+ }
+ assertNull(mCountryDetectorUT.getCachedLocationCountryIsoInfo().first);
+ assertEquals(0, (long) mCountryDetectorUT.getCachedLocationCountryIsoInfo().second);
+ assertFalse(mCountryDetectorUT.queryCountryCodeForLocationTriggered);
+
+ // Move time forwards and update location-based country code
+ mCountryDetectorUT.elapsedRealtimeNanos = 2;
+ mCountryDetectorUT.queryCountryCodeForLocationTriggered = false;
+ sendLocationUpdate();
+ assertTrue(mCountryDetectorUT.queryCountryCodeForLocationTriggered);
+ sendLocationBasedCountryCodeChanged("CA", 1);
+ mTestableLooper.processAllMessages();
+ assertEquals("CA", mCountryDetectorUT.getCachedLocationCountryIsoInfo().first);
+ assertEquals(1, (long) mCountryDetectorUT.getCachedLocationCountryIsoInfo().second);
+ }
+
+ @Test
+ public void testRegisterForLocationUpdates() {
+ if (!isGeoCoderImplemented()) {
+ logd("Skip the test because GeoCoder is not implemented on the device");
+ return;
+ }
+
+ // Network country code is available
+ clearInvocations(mLocationManager);
+ sendNetworkCountryCodeChanged("US", mPhone);
+ verify(mLocationManager).removeUpdates(any(LocationListener.class));
+
+ // Network country code is not available and Wi-fi is available
+ clearInvocations(mLocationManager);
+ sendNetworkCountryCodeChanged("", mPhone);
+ verify(mLocationManager).requestLocationUpdates(anyString(), anyLong(), anyFloat(),
+ any(LocationListener.class));
+
+ // Wi-fi is not available
+ clearInvocations(mLocationManager);
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, false);
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
+ mTestableLooper.processAllMessages();
+ verify(mLocationManager, never()).removeUpdates(any(LocationListener.class));
+
+ // Wi-fi becomes available
+ clearInvocations(mLocationManager);
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
+ mNetworkCallbackCaptor.getValue().onAvailable(mMockNetwork);
+ mTestableLooper.processAllMessages();
+ // Location updates were already requested
+ verify(mLocationManager, never()).requestLocationUpdates(anyString(), anyLong(), anyFloat(),
+ any(LocationListener.class));
+
+ // Make Wi-fi not available and reset the quota
+ clearInvocations(mLocationManager);
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, false);
+ mTestableLooper.moveTimeForward(
+ TestTelephonyCountryDetector.getLocationUpdateRequestQuotaResetTimeoutMillis());
+ mTestableLooper.processAllMessages();
+ verify(mLocationManager).removeUpdates(any(LocationListener.class));
+
+ // Wi-fi becomes available
+ clearInvocations(mLocationManager);
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
+ mNetworkCallbackCaptor.getValue().onAvailable(mMockNetwork);
+ mTestableLooper.processAllMessages();
+ verify(mLocationManager).requestLocationUpdates(anyString(), anyLong(), anyFloat(),
+ any(LocationListener.class));
+
+ // Reset the quota
+ clearInvocations(mLocationManager);
+ mTestableLooper.moveTimeForward(
+ TestTelephonyCountryDetector.getLocationUpdateRequestQuotaResetTimeoutMillis());
+ mTestableLooper.processAllMessages();
+ verify(mLocationManager, never()).removeUpdates(any(LocationListener.class));
+ verify(mLocationManager, never()).requestLocationUpdates(anyString(), anyLong(), anyFloat(),
+ any(LocationListener.class));
+
+ // Wi-fi becomes not available
+ clearInvocations(mLocationManager);
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, false);
+ mNetworkCallbackCaptor.getValue().onUnavailable();
+ mTestableLooper.processAllMessages();
+ verify(mLocationManager).removeUpdates(any(LocationListener.class));
+ }
+
+ private static boolean isGeoCoderImplemented() {
+ return Geocoder.isPresent();
+ }
+
+ private void sendLocationUpdate() {
+ mLocationListenerCaptor.getValue().onLocationChanged(mMockLocation);
+ mTestableLooper.processAllMessages();
+ }
+
+ private void sendLocationBasedCountryCodeChanged(String countryCode, long locationUpdatedTime) {
+ Message message = mCountryDetectorUT.obtainMessage(
+ 2 /* EVENT_LOCATION_COUNTRY_CODE_CHANGED */,
+ new Pair<>(countryCode, locationUpdatedTime));
+ message.sendToTarget();
+ mTestableLooper.processAllMessages();
+ }
+
+ private void sendNetworkCountryCodeChanged(String countryCode, @NonNull Phone phone) {
+ when(mLocaleTrackers[phone.getPhoneId()].getCurrentCountry()).thenReturn(countryCode);
+ mCountryDetectorUT.onNetworkCountryCodeChanged(phone, countryCode);
+ mTestableLooper.processAllMessages();
+ }
+
+ private static class TestTelephonyCountryDetector extends TelephonyCountryDetector {
+ public boolean queryCountryCodeForLocationTriggered = false;
+ public long elapsedRealtimeNanos = 0;
+
+ /**
+ * Create the singleton instance of {@link TelephonyCountryDetector}.
+ *
+ * @param looper The looper to run the {@link TelephonyCountryDetector} instance.
+ * @param context The context associated with the instance.
+ * @param locationManager The LocationManager instance.
+ */
+ TestTelephonyCountryDetector(Looper looper, Context context,
+ LocationManager locationManager, ConnectivityManager connectivityManager) {
+ super(looper, context, locationManager, connectivityManager);
+ }
+
+ @Override
+ protected void queryCountryCodeForLocation(@NonNull Location location) {
+ queryCountryCodeForLocationTriggered = true;
+ }
+
+ @Override
+ protected long getElapsedRealtimeNanos() {
+ return elapsedRealtimeNanos;
+ }
+
+ public static long getLocationUpdateRequestQuotaResetTimeoutMillis() {
+ return WAIT_FOR_LOCATION_UPDATE_REQUEST_QUOTA_RESET_TIMEOUT_MILLIS;
+ }
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyHistogramTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyHistogramTest.java
index c65ce91..3111e7b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyHistogramTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyHistogramTest.java
@@ -15,15 +15,16 @@
*/
package com.android.internal.telephony;
+import static org.junit.Assert.*;
+
import android.telephony.TelephonyHistogram;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import org.junit.After;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import org.junit.Assert;
-
-import static org.junit.Assert.*;
public class TelephonyHistogramTest {
private TelephonyHistogram mHistogram = null;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
index ad66b55..6369825 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
@@ -46,7 +46,8 @@
import android.telephony.TelephonyManager;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.util.test.FakeSettingsProvider;
@@ -58,6 +59,7 @@
import java.lang.reflect.Field;
import java.util.Map;
+
@SmallTest
public class TelephonyPermissionsTest {
@@ -168,8 +170,10 @@
public void testCheckReadPhoneState_hasPermissionAndAppOp() {
doNothing().when(mMockContext).enforcePermission(
android.Manifest.permission.READ_PHONE_STATE, PID, UID, MSG);
- when(mMockAppOps.noteOp(eq(AppOpsManager.OPSTR_READ_PHONE_STATE), eq(UID), eq(PACKAGE),
- eq(FEATURE), nullable(String.class))).thenReturn(AppOpsManager.MODE_ALLOWED);
+ when(mMockAppOps
+ .noteOpNoThrow(eq(AppOpsManager.OPSTR_READ_PHONE_STATE), eq(UID), eq(PACKAGE),
+ eq(FEATURE), nullable(String.class)))
+ .thenReturn(AppOpsManager.MODE_ALLOWED);
assertTrue(TelephonyPermissions.checkReadPhoneState(
mMockContext, SUB_ID, PID, UID, PACKAGE, FEATURE, MSG));
}
@@ -210,8 +214,10 @@
public void testCheckReadPhoneStateOnAnyActiveSub_hasPermissionAndAppOp() {
doNothing().when(mMockContext).enforcePermission(
android.Manifest.permission.READ_PHONE_STATE, PID, UID, MSG);
- when(mMockAppOps.noteOp(eq(AppOpsManager.OPSTR_READ_PHONE_STATE), eq(UID), eq(PACKAGE),
- eq(FEATURE), nullable(String.class))).thenReturn(AppOpsManager.MODE_ALLOWED);
+ when(mMockAppOps
+ .noteOpNoThrow(eq(AppOpsManager.OPSTR_READ_PHONE_STATE), eq(UID), eq(PACKAGE),
+ eq(FEATURE), nullable(String.class)))
+ .thenReturn(AppOpsManager.MODE_ALLOWED);
assertTrue(TelephonyPermissions.checkReadPhoneStateOnAnyActiveSub(
mMockContext, PID, UID, PACKAGE, FEATURE, MSG));
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
index 5a5e11f..6050b18 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
@@ -66,13 +66,14 @@
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.SparseArray;
import androidx.annotation.NonNull;
+import androidx.test.filters.SmallTest;
import com.android.server.TelephonyRegistry;
@@ -115,6 +116,7 @@
private BarringInfo mBarringInfo = null;
private CellIdentity mCellIdentityForRegiFail;
private int mRegistrationFailReason;
+ private Set<Integer> mSimultaneousCallingSubscriptions;
// All events contribute to TelephonyRegistry#isPhoneStatePermissionRequired
private static final Set<Integer> READ_PHONE_STATE_EVENTS;
@@ -160,6 +162,8 @@
TelephonyCallback.EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED);
READ_PRIVILEGED_PHONE_STATE_EVENTS.add(
TelephonyCallback.EVENT_EMERGENCY_CALLBACK_MODE_CHANGED);
+ READ_PRIVILEGED_PHONE_STATE_EVENTS.add(
+ TelephonyCallback.EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED);
}
// All events contribute to TelephonyRegistry#isActiveEmergencySessionPermissionRequired
@@ -187,7 +191,8 @@
TelephonyCallback.CellInfoListener,
TelephonyCallback.BarringInfoListener,
TelephonyCallback.RegistrationFailedListener,
- TelephonyCallback.DataActivityListener {
+ TelephonyCallback.DataActivityListener,
+ TelephonyCallback.SimultaneousCellularCallingSupportListener {
// This class isn't mockable to get invocation counts because the IBinder is null and
// crashes the TelephonyRegistry. Make a cheesy verify(times()) alternative.
public AtomicInteger invocationCount = new AtomicInteger(0);
@@ -275,6 +280,13 @@
invocationCount.incrementAndGet();
mDataActivity = direction;
}
+
+ @Override
+ public void onSimultaneousCellularCallingSubscriptionsChanged(
+ @NonNull Set<Integer> simultaneousCallingSubscriptionIds) {
+ invocationCount.incrementAndGet();
+ mSimultaneousCallingSubscriptions = simultaneousCallingSubscriptionIds;
+ }
}
private void addTelephonyRegistryService() {
@@ -1531,4 +1543,23 @@
processAllMessages();
assertEquals(TelephonyManager.DATA_ACTIVITY_OUT, mDataActivity);
}
+
+ @Test
+ public void testSimultaneousCellularCallingSubscriptionsChanged() {
+ final int subId = INVALID_SUBSCRIPTION_ID;
+ int[] events = {TelephonyCallback
+ .EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED};
+
+ int[] subIds = {0, 1, 2};
+ Set<Integer> subIdSet = new ArraySet<>(3);
+ for (Integer s : subIds) {
+ subIdSet.add(s);
+ }
+ mTelephonyRegistry.listenWithEventList(false, false, subId, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), mTelephonyCallback.callback, events, true);
+
+ mTelephonyRegistry.notifySimultaneousCellularCallingSubscriptionsChanged(subIds);
+ processAllMessages();
+ assertEquals(subIdSet, mSimultaneousCallingSubscriptions);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index 9212567..78b5e8c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -115,6 +115,7 @@
import com.android.internal.telephony.imsphone.ImsNrSaModeHandler;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
+import com.android.internal.telephony.metrics.DefaultNetworkMonitor;
import com.android.internal.telephony.metrics.DeviceStateHelper;
import com.android.internal.telephony.metrics.ImsStats;
import com.android.internal.telephony.metrics.MetricsCollector;
@@ -124,6 +125,7 @@
import com.android.internal.telephony.metrics.VoiceCallSessionStats;
import com.android.internal.telephony.satellite.SatelliteController;
import com.android.internal.telephony.security.CellularIdentifierDisclosureNotifier;
+import com.android.internal.telephony.security.NullCipherNotifier;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.test.SimulatedCommands;
import com.android.internal.telephony.test.SimulatedCommandsVerifier;
@@ -252,6 +254,7 @@
protected IntentBroadcaster mIntentBroadcaster;
protected NitzStateMachine mNitzStateMachine;
protected RadioConfig mMockRadioConfig;
+ protected RadioConfigProxy mMockRadioConfigProxy;
protected LocaleTracker mLocaleTracker;
protected RestrictedState mRestrictedState;
protected PhoneConfigurationManager mPhoneConfigurationManager;
@@ -264,6 +267,7 @@
protected CarrierPrivilegesTracker mCarrierPrivilegesTracker;
protected VoiceCallSessionStats mVoiceCallSessionStats;
protected PersistAtomsStorage mPersistAtomsStorage;
+ protected DefaultNetworkMonitor mDefaultNetworkMonitor;
protected MetricsCollector mMetricsCollector;
protected SmsStats mSmsStats;
protected TelephonyAnalytics mTelephonyAnalytics;
@@ -283,6 +287,7 @@
protected DeviceStateHelper mDeviceStateHelper;
protected CellularIdentifierDisclosureNotifier mIdentifierDisclosureNotifier;
protected DomainSelectionResolver mDomainSelectionResolver;
+ protected NullCipherNotifier mNullCipherNotifier;
// Initialized classes
protected ActivityManager mActivityManager;
@@ -524,6 +529,7 @@
mIntentBroadcaster = Mockito.mock(IntentBroadcaster.class);
mNitzStateMachine = Mockito.mock(NitzStateMachine.class);
mMockRadioConfig = Mockito.mock(RadioConfig.class);
+ mMockRadioConfigProxy = Mockito.mock(RadioConfigProxy.class);
mLocaleTracker = Mockito.mock(LocaleTracker.class);
mRestrictedState = Mockito.mock(RestrictedState.class);
mPhoneConfigurationManager = Mockito.mock(PhoneConfigurationManager.class);
@@ -536,6 +542,7 @@
mCarrierPrivilegesTracker = Mockito.mock(CarrierPrivilegesTracker.class);
mVoiceCallSessionStats = Mockito.mock(VoiceCallSessionStats.class);
mPersistAtomsStorage = Mockito.mock(PersistAtomsStorage.class);
+ mDefaultNetworkMonitor = Mockito.mock(DefaultNetworkMonitor.class);
mMetricsCollector = Mockito.mock(MetricsCollector.class);
mSmsStats = Mockito.mock(SmsStats.class);
mTelephonyAnalytics = Mockito.mock(TelephonyAnalytics.class);
@@ -555,6 +562,7 @@
mDeviceStateHelper = Mockito.mock(DeviceStateHelper.class);
mIdentifierDisclosureNotifier = Mockito.mock(CellularIdentifierDisclosureNotifier.class);
mDomainSelectionResolver = Mockito.mock(DomainSelectionResolver.class);
+ mNullCipherNotifier = Mockito.mock(NullCipherNotifier.class);
TelephonyManager.disableServiceHandleCaching();
PropertyInvalidatedCache.disableForTestMode();
@@ -625,9 +633,9 @@
doReturn(mUiccProfile).when(mTelephonyComponentFactory)
.makeUiccProfile(nullable(Context.class), nullable(CommandsInterface.class),
nullable(IccCardStatus.class), anyInt(), nullable(UiccCard.class),
- nullable(Object.class));
+ nullable(Object.class), any(FeatureFlags.class));
doReturn(mCT).when(mTelephonyComponentFactory)
- .makeGsmCdmaCallTracker(nullable(GsmCdmaPhone.class));
+ .makeGsmCdmaCallTracker(nullable(GsmCdmaPhone.class), any(FeatureFlags.class));
doReturn(mIccPhoneBookIntManager).when(mTelephonyComponentFactory)
.makeIccPhoneBookInterfaceManager(nullable(Phone.class));
doReturn(mDisplayInfoController).when(mTelephonyComponentFactory)
@@ -658,7 +666,7 @@
.makeNitzStateMachine(nullable(GsmCdmaPhone.class));
doReturn(mLocaleTracker).when(mTelephonyComponentFactory)
.makeLocaleTracker(nullable(Phone.class), nullable(NitzStateMachine.class),
- nullable(Looper.class));
+ nullable(Looper.class), any(FeatureFlags.class));
doReturn(mEriManager).when(mTelephonyComponentFactory)
.makeEriManager(nullable(Phone.class), anyInt());
doReturn(mLinkBandwidthEstimator).when(mTelephonyComponentFactory)
@@ -671,6 +679,9 @@
doReturn(mIdentifierDisclosureNotifier)
.when(mTelephonyComponentFactory)
.makeIdentifierDisclosureNotifier();
+ doReturn(mNullCipherNotifier)
+ .when(mTelephonyComponentFactory)
+ .makeNullCipherNotifier();
//mPhone
doReturn(mContext).when(mPhone).getContext();
@@ -812,6 +823,7 @@
anyInt(), anyInt());
doReturn(RIL.RADIO_HAL_VERSION_2_0).when(mPhone).getHalVersion(anyInt());
doReturn(2).when(mSignalStrength).getLevel();
+ doReturn(mMockRadioConfigProxy).when(mMockRadioConfig).getRadioConfigProxy(any());
// WiFi
doReturn(mWifiInfo).when(mWifiManager).getConnectionInfo();
@@ -884,6 +896,7 @@
// Metrics
doReturn(null).when(mContext).getFileStreamPath(anyString());
doReturn(mPersistAtomsStorage).when(mMetricsCollector).getAtomsStorage();
+ doReturn(mDefaultNetworkMonitor).when(mMetricsCollector).getDefaultNetworkMonitor();
doReturn(mWifiManager).when(mContext).getSystemService(eq(Context.WIFI_SERVICE));
doReturn(mDeviceStateHelper).when(mMetricsCollector).getDeviceStateHelper();
doReturn(CELLULAR_SERVICE_STATE__FOLD_STATE__STATE_UNKNOWN)
diff --git a/tests/telephonytests/src/com/android/internal/telephony/VisualVoicemailSmsParserTest.java b/tests/telephonytests/src/com/android/internal/telephony/VisualVoicemailSmsParserTest.java
index 13fa2d6..77ca1ca 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/VisualVoicemailSmsParserTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/VisualVoicemailSmsParserTest.java
@@ -15,7 +15,7 @@
*/
package com.android.internal.telephony;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.VisualVoicemailSmsParser.WrappedMessageData;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/VoLteServiceStateTest.java b/tests/telephonytests/src/com/android/internal/telephony/VoLteServiceStateTest.java
index 9d2b8a0..7b5297f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/VoLteServiceStateTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/VoLteServiceStateTest.java
@@ -19,11 +19,11 @@
import android.os.Bundle;
import android.os.Parcel;
import android.telephony.VoLteServiceState;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import junit.framework.TestCase;
-
public class VoLteServiceStateTest extends TestCase {
@SmallTest
diff --git a/tests/telephonytests/src/com/android/internal/telephony/WapPushCacheTest.java b/tests/telephonytests/src/com/android/internal/telephony/WapPushCacheTest.java
new file mode 100644
index 0000000..f572c08
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/WapPushCacheTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.time.Clock;
+import java.util.NoSuchElementException;
+import java.util.concurrent.TimeUnit;
+
+public class WapPushCacheTest extends TelephonyTest {
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp(getClass().getSimpleName());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ WapPushCache.clear();
+ WapPushCache.sTelephonyFacade = new TelephonyFacade();
+ super.tearDown();
+ }
+
+ @Test
+ public void testGetWapMessageSize() {
+ long expectedSize = 100L;
+ byte[] location = "content://mms".getBytes();
+ byte[] transactionId = "123".getBytes();
+
+ WapPushCache.putWapMessageSize(location, transactionId, expectedSize);
+ long size = WapPushCache.getWapMessageSize(location);
+
+ assertEquals(expectedSize, size);
+ }
+
+ @Test
+ public void testGetWapMessageSize_withTransactionIdAppended() {
+ long expectedSize = 100L;
+ byte[] location = "content://mms".getBytes();
+ byte[] transactionId = "123".getBytes();
+ byte[] joinedKey = new byte[location.length + transactionId.length];
+ System.arraycopy(location, 0, joinedKey, 0, location.length);
+ System.arraycopy(transactionId, 0, joinedKey, location.length, transactionId.length);
+
+ WapPushCache.putWapMessageSize(location, transactionId, expectedSize);
+ long size = WapPushCache.getWapMessageSize(joinedKey);
+
+ assertEquals(expectedSize, size);
+ }
+
+ @Test
+ public void testGetWapMessageSize_nonexistentThrows() {
+ assertThrows(NoSuchElementException.class, () ->
+ WapPushCache.getWapMessageSize("content://mms".getBytes())
+ );
+ }
+ @Test
+ public void testGetWapMessageSize_emptyLocationUrlThrows() {
+ assertThrows(IllegalArgumentException.class, () ->
+ WapPushCache.getWapMessageSize(new byte[0])
+ );
+ }
+
+ @Test
+ public void testPutWapMessageSize_invalidValuePreventsInsert() {
+ long expectedSize = 0L;
+ byte[] location = "content://mms".getBytes();
+ byte[] transactionId = "123".getBytes();
+
+ WapPushCache.putWapMessageSize(location, transactionId, expectedSize);
+
+ assertEquals(0, WapPushCache.size());
+ }
+
+ @Test
+ public void testPutWapMessageSize_sizeLimitExceeded_oldestEntryRemoved() {
+ long expectedSize = 100L;
+ for (int i = 0; i < 251; i++) {
+ byte[] location = ("" + i).getBytes();
+ byte[] transactionId = "abc".getBytes();
+ WapPushCache.putWapMessageSize(location, transactionId, expectedSize);
+ }
+
+ // assert one of the entries inserted above has been removed
+ assertEquals(500, WapPushCache.size());
+ // assert last entry added exists
+ assertEquals(expectedSize, WapPushCache.getWapMessageSize("250".getBytes()));
+ // assert the first entry added was removed
+ assertThrows(NoSuchElementException.class, () ->
+ WapPushCache.getWapMessageSize("0".getBytes())
+ );
+ }
+
+ @Test
+ public void testPutWapMessageSize_expiryExceeded_entryRemoved() {
+ long currentTime = Clock.systemUTC().millis();
+ TelephonyFacade facade = mock(TelephonyFacade.class);
+ when(facade.getElapsedSinceBootMillis()).thenReturn(currentTime);
+ WapPushCache.sTelephonyFacade = facade;
+
+ long expectedSize = 100L;
+ byte[] transactionId = "abc".getBytes();
+ byte[] location1 = "old".getBytes();
+ byte[] location2 = "new".getBytes();
+
+ WapPushCache.putWapMessageSize(location1, transactionId, expectedSize);
+ assertEquals(2, WapPushCache.size());
+
+ // advance time
+ when(facade.getElapsedSinceBootMillis())
+ .thenReturn(currentTime + TimeUnit.DAYS.toMillis(14) + 1);
+
+ WapPushCache.putWapMessageSize(location2, transactionId, expectedSize);
+
+ assertEquals(2, WapPushCache.size());
+ assertEquals(expectedSize, WapPushCache.getWapMessageSize(location2));
+ assertThrows(NoSuchElementException.class, () ->
+ WapPushCache.getWapMessageSize(location1)
+ );
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java b/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java
index 8e40271..c3db35c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java
@@ -34,7 +34,8 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Telephony;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import org.junit.After;
import org.junit.Before;
@@ -62,6 +63,7 @@
@After
public void tearDown() throws Exception {
+ WapPushCache.clear();
mWapPushOverSmsUT = null;
super.tearDown();
}
@@ -150,4 +152,29 @@
any(UserHandle.class),
anyInt());
}
+
+ @Test @SmallTest
+ public void testDispatchWapPdu_notificationIndInsertedToCache() throws Exception {
+ assertEquals(0, WapPushCache.size());
+ when(mISmsStub.getCarrierConfigValuesForSubscriber(anyInt())).thenReturn(new Bundle());
+
+ doReturn(true).when(mWspTypeDecoder).decodeUintvarInteger(anyInt());
+ doReturn(true).when(mWspTypeDecoder).decodeContentType(anyInt());
+ doReturn((long) 2).when(mWspTypeDecoder).getValue32();
+ doReturn(2).when(mWspTypeDecoder).getDecodedDataLength();
+ doReturn(WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO).when(mWspTypeDecoder).getValueString();
+
+ byte[] pdu = {1, 6, 0, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47,
+ 118, 110, 100, 46, 119, 97, 112, 46, 109, 109, 115, 45, 109, 101, 115, 115,
+ 97, 103, 101, 0, -116, -126, -104, 77, 109, 115, 84, 114, 97, 110, 115, 97,
+ 99, 116, 105, 111, 110, 73, 68, 0, -115, 18, -119, 8, -128, 49, 54, 49, 55,
+ 56, 50, 54, 57, 49, 54, 56, 47, 84, 89, 80, 69, 61, 80, 76, 77, 78, 0, -118,
+ -128, -114, 2, 3, -24, -120, 3, -127, 3, 3, -12, -128, -106, 84, 101, 115,
+ 116, 32, 77, 109, 115, 32, 83, 117, 98, 106, 101, 99, 116, 0, -125, 104, 116,
+ 116, 112, 58, 47, 47, 119, 119, 119, 46, 103, 111, 111, 103, 108, 101, 46, 99,
+ 111, 109, 47, 115, 97, 100, 102, 100, 100, 0};
+
+ mWapPushOverSmsUT.dispatchWapPdu(pdu, null, mInboundSmsHandler, null, 0, 0L);
+ assertEquals(2, WapPushCache.size());
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cat/CATServiceTest.java b/tests/telephonytests/src/com/android/internal/telephony/cat/CATServiceTest.java
index f2c1870..a07ddbe 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/cat/CATServiceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/cat/CATServiceTest.java
@@ -144,7 +144,7 @@
mSimulatedCommands = mock(SimulatedCommands.class);
mSimulatedCommands.setIccIoResultForApduLogicalChannel(mIccIoResult);
mUiccProfile = new UiccProfile(mContext, mSimulatedCommands, mIccCardStatus,
- 0 /* phoneId */, mUiccCard, new Object());
+ 0 /* phoneId */, mUiccCard, new Object(), mFeatureFlags);
processAllMessages();
logd("Created UiccProfile");
processAllMessages();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaInboundSmsHandlerTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaInboundSmsHandlerTest.java
index 3445939..24f7d2c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaInboundSmsHandlerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaInboundSmsHandlerTest.java
@@ -42,11 +42,11 @@
import android.os.UserManager;
import android.provider.Telephony;
import android.test.mock.MockContentResolver;
-import android.test.suitebuilder.annotation.MediumTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.FlakyTest;
+import androidx.test.filters.MediumTest;
import com.android.internal.telephony.FakeSmsContentProvider;
import com.android.internal.telephony.InboundSmsHandler;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java
index c9a16f5..100c391 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java
@@ -21,9 +21,9 @@
import android.telephony.SmsCbMessage;
import android.telephony.cdma.CdmaSmsCbProgramData;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.RILUtils;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsDispatcherTest.java
index 0315776..1f52cea 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsDispatcherTest.java
@@ -16,16 +16,17 @@
package com.android.internal.telephony.cdma;
+import static org.mockito.Mockito.*;
+
import android.os.HandlerThread;
import android.os.Message;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.SMSDispatcher;
import com.android.internal.telephony.SmsDispatchersController;
import com.android.internal.telephony.TelephonyTest;
-import static org.mockito.Mockito.*;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java
index 0e0f113..d2a6922 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java
@@ -18,7 +18,8 @@
import android.telephony.TelephonyManager;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
import com.android.internal.telephony.SmsHeader;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/d2d/CommunicatorTest.java b/tests/telephonytests/src/com/android/internal/telephony/d2d/CommunicatorTest.java
index 4681dbc..9008e16 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/d2d/CommunicatorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/d2d/CommunicatorTest.java
@@ -25,9 +25,9 @@
import static org.mockito.Mockito.verify;
import android.telecom.Connection;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/d2d/DtmfTransportConversionTest.java b/tests/telephonytests/src/com/android/internal/telephony/d2d/DtmfTransportConversionTest.java
index 5bc382f..c2c2a61 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/d2d/DtmfTransportConversionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/d2d/DtmfTransportConversionTest.java
@@ -21,9 +21,10 @@
import static org.junit.Assert.assertArrayEquals;
import static org.mockito.Mockito.mock;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.Pair;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.TestExecutorService;
import org.junit.After;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/d2d/DtmfTransportTest.java b/tests/telephonytests/src/com/android/internal/telephony/d2d/DtmfTransportTest.java
index 68ddd23..e1525d0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/d2d/DtmfTransportTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/d2d/DtmfTransportTest.java
@@ -26,9 +26,9 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.telephony.TestExecutorService;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/d2d/RtpTransportConversionTest.java b/tests/telephonytests/src/com/android/internal/telephony/d2d/RtpTransportConversionTest.java
index 545507b..3cdab56 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/d2d/RtpTransportConversionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/d2d/RtpTransportConversionTest.java
@@ -27,9 +27,10 @@
import android.os.Handler;
import android.telephony.ims.RtpHeaderExtension;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
+import androidx.test.filters.SmallTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/d2d/RtpTransportTest.java b/tests/telephonytests/src/com/android/internal/telephony/d2d/RtpTransportTest.java
index 55559eb..fe78c8d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/d2d/RtpTransportTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/d2d/RtpTransportTest.java
@@ -25,12 +25,11 @@
import android.os.Handler;
import android.telephony.ims.RtpHeaderExtension;
import android.telephony.ims.RtpHeaderExtensionType;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java
index 6462d73..5b91aee 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java
@@ -76,6 +76,7 @@
private static final int SCORE_TOLERANCE = 100;
private static final int GOOD_RAT_SIGNAL_SCORE = 200;
private static final int BAD_RAT_SIGNAL_SCORE = 50;
+ private boolean mIsNonTerrestrialNetwork = false;
// Mocked
private AutoDataSwitchController.AutoDataSwitchControllerCallback mMockedPhoneSwitcherCallback;
@@ -105,6 +106,17 @@
mPhones = new Phone[]{mPhone, mPhone2};
for (Phone phone : mPhones) {
+ ServiceState ss = new ServiceState();
+
+ ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .setRegistrationState(
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setIsNonTerrestrialNetwork(mIsNonTerrestrialNetwork)
+ .build());
+
+ doReturn(ss).when(phone).getServiceState();
doReturn(mSST).when(phone).getServiceStateTracker();
doReturn(mDisplayInfoController).when(phone).getDisplayInfoController();
doReturn(mSignalStrengthController).when(phone).getSignalStrengthController();
@@ -155,6 +167,7 @@
mPhoneSwitcher, mFeatureFlags, mMockedPhoneSwitcherCallback);
doReturn(true).when(mFeatureFlags).autoSwitchAllowRoaming();
+ doReturn(true).when(mFeatureFlags).carrierEnabledSatelliteFlag();
}
@After
@@ -246,6 +259,31 @@
}
@Test
+ public void testRoaming_prefer_roam_over_nonTerrestrial() {
+ // DDS -> nDDS: Prefer Roaming over non-terrestrial
+ prepareIdealUsesNonDdsCondition();
+ mIsNonTerrestrialNetwork = true;
+ serviceStateChanged(PHONE_1, NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+ mIsNonTerrestrialNetwork = false;
+ serviceStateChanged(PHONE_2, NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+ processAllFutureMessages();
+
+ verify(mMockedPhoneSwitcherCallback).onRequireValidation(PHONE_2, true/*needValidation*/);
+
+ // nDDS -> DDS: Prefer Roaming over non-terrestrial
+ doReturn(PHONE_2).when(mPhoneSwitcher).getPreferredDataPhoneId();
+ mIsNonTerrestrialNetwork = false;
+ serviceStateChanged(PHONE_1, NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+ mIsNonTerrestrialNetwork = true;
+ serviceStateChanged(PHONE_2, NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+ processAllFutureMessages();
+
+ verify(mMockedPhoneSwitcherCallback).onRequireValidation(DEFAULT_PHONE_INDEX,
+ true/*needValidation*/);
+ mIsNonTerrestrialNetwork = false;
+ }
+
+ @Test
public void testRoaming_roaming_but_roam_disabled() {
// Disable RAT + signalStrength base switching.
doReturn(-1).when(mDataConfigManager).getAutoDataSwitchScoreTolerance();
@@ -677,6 +715,7 @@
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setRegistrationState(dataRegState)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setIsNonTerrestrialNetwork(mIsNonTerrestrialNetwork)
.build());
ss.setDataRoamingFromRegistration(dataRegState
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/CellularNetworkValidatorTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/CellularNetworkValidatorTest.java
index 428699f..bbfd7a9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/CellularNetworkValidatorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/CellularNetworkValidatorTest.java
@@ -43,10 +43,11 @@
import android.telephony.PhoneCapability;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataCallResponseTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataCallResponseTest.java
index c8ab063..c0a9211 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataCallResponseTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataCallResponseTest.java
@@ -28,7 +28,8 @@
import android.telephony.data.Qos;
import android.telephony.data.TrafficDescriptor;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import java.util.ArrayList;
import java.util.Arrays;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataFailCauseTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataFailCauseTest.java
index 3590ae6..980762a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataFailCauseTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataFailCauseTest.java
@@ -26,7 +26,8 @@
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.DataFailCause;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.TelephonyTest;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
index a2c9724..fa4f8e4 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -775,9 +775,10 @@
"capabilities=eims, retry_interval=1000, maximum_retries=20",
"permanent_fail_causes=8|27|28|29|30|32|33|35|50|51|111|-5|-6|65537|65538|"
+ "-3|65543|65547|2252|2253|2254, retry_interval=2500",
- "capabilities=mms|supl|cbs, retry_interval=2000",
- "capabilities=internet|enterprise|dun|ims|fota, retry_interval=2500|3000|"
- + "5000|10000|15000|20000|40000|60000|120000|240000|"
+ "capabilities=mms|supl|cbs|rcs, retry_interval=2000",
+ "capabilities=internet|enterprise|dun|ims|fota|xcap|mcx|"
+ + "prioritize_bandwidth|prioritize_latency, retry_interval="
+ + "2500|3000|5000|10000|15000|20000|40000|60000|120000|240000|"
+ "600000|1200000|1800000, maximum_retries=20"
});
mCarrierConfig.putStringArray(
@@ -3947,6 +3948,50 @@
}
@Test
+ public void testNoGracefulTearDownForEmergencyDataNetwork() throws Exception {
+ setImsRegistered(true);
+
+ mCarrierConfig.putStringArray(CarrierConfigManager.KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY,
+ new String[]{"source=EUTRAN, target=IWLAN, type=disallowed, capabilities=EIMS|IMS",
+ "source=IWLAN, target=EUTRAN, type=disallowed, capabilities=MMS"});
+ // Force data config manager to reload the carrier config.
+ carrierConfigChanged();
+ processAllMessages();
+
+ // setup emergency data network.
+ NetworkCapabilities netCaps = new NetworkCapabilities();
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS);
+ netCaps.setRequestorPackageName(FAKE_MMTEL_PACKAGE);
+
+ NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
+ ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST);
+ TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest(
+ nativeNetworkRequest, mPhone);
+
+ mDataNetworkControllerUT.addNetworkRequest(networkRequest);
+ processAllMessages();
+
+ verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_EIMS);
+
+ updateTransport(NetworkCapabilities.NET_CAPABILITY_EIMS,
+ AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
+
+ // Verify all data disconnected.
+ verify(mMockedDataNetworkControllerCallback).onAnyDataNetworkExistingChanged(eq(false));
+ verify(mMockedDataNetworkControllerCallback).onPhysicalLinkStatusChanged(
+ eq(DataCallResponse.LINK_STATUS_INACTIVE));
+
+ // A new data network should be connected on IWLAN
+ List<DataNetwork> dataNetworkList = getDataNetworks();
+ assertThat(dataNetworkList).hasSize(1);
+ assertThat(dataNetworkList.get(0).isConnected()).isTrue();
+ assertThat(dataNetworkList.get(0).getNetworkCapabilities().hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_EIMS)).isTrue();
+ assertThat(dataNetworkList.get(0).getTransport())
+ .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
+ }
+
+ @Test
public void testNetworkRequestRemovedBeforeRetry() {
setFailedSetupDataResponse(mMockedWwanDataServiceManager, DataFailCause.CONGESTION,
DataCallResponse.RETRY_DURATION_UNDEFINED, false);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
index 5dd83bf..ad1ba61 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
@@ -76,6 +76,7 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.data.AccessNetworksManager.AccessNetworksManagerCallback;
import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback;
import com.android.internal.telephony.data.DataEvaluation.DataAllowedReason;
import com.android.internal.telephony.data.DataNetwork.DataNetworkCallback;
@@ -123,7 +124,7 @@
.setApnName("fake_apn")
.setUser("user")
.setPassword("passwd")
- .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_SUPL)
+ .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_SUPL | ApnSetting.TYPE_MMS)
.setProtocol(ApnSetting.PROTOCOL_IPV6)
.setRoamingProtocol(ApnSetting.PROTOCOL_IP)
.setCarrierEnabled(true)
@@ -134,6 +135,18 @@
.setMaxConnsTime(789)
.build();
+ private final ApnSetting mMmsApnSetting = new ApnSetting.Builder()
+ .setId(2164)
+ .setOperatorNumeric("12345")
+ .setEntryName("fake_mms_apn")
+ .setApnName("fake_mms_apn")
+ .setApnTypeBitmask(ApnSetting.TYPE_MMS)
+ .setProtocol(ApnSetting.PROTOCOL_IPV6)
+ .setRoamingProtocol(ApnSetting.PROTOCOL_IP)
+ .setCarrierEnabled(true)
+ .setNetworkTypeBitmask((int) TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN)
+ .build();
+
private final ApnSetting mImsApnSetting = new ApnSetting.Builder()
.setId(2163)
.setOperatorNumeric("12345")
@@ -157,6 +170,11 @@
.setTrafficDescriptor(new TrafficDescriptor("fake_apn", null))
.build();
+ private final DataProfile mMmsDataProfile = new DataProfile.Builder()
+ .setApnSetting(mMmsApnSetting)
+ .setTrafficDescriptor(new TrafficDescriptor("fake_apn", null))
+ .build();
+
private final DataProfile mImsDataProfile = new DataProfile.Builder()
.setApnSetting(mImsApnSetting)
.setTrafficDescriptor(new TrafficDescriptor("fake_apn", null))
@@ -2028,13 +2046,13 @@
// First Request
mDataNetworkUT.requestNetworkValidation(mIntegerConsumer);
processAllMessages();
- verify(mMockedWlanDataServiceManager).requestValidation(eq(123 /*cid*/),
+ verify(mMockedWlanDataServiceManager).requestNetworkValidation(eq(123 /*cid*/),
any(Message.class));
// Duplicate Request
mDataNetworkUT.requestNetworkValidation(mIntegerConsumer);
processAllMessages();
- verify(mMockedWlanDataServiceManager).requestValidation(eq(123 /*cid*/),
+ verify(mMockedWlanDataServiceManager).requestNetworkValidation(eq(123 /*cid*/),
any(Message.class));
assertThat(waitForIntegerConsumerResponse(1 /*numOfEvents*/)).isTrue();
assertThat(mIntegerConsumerResult).isEqualTo(DataServiceCallback.RESULT_ERROR_BUSY);
@@ -2107,7 +2125,7 @@
// Request Network Validation
mDataNetworkUT.requestNetworkValidation(mIntegerConsumer);
processAllMessages();
- verify(mMockedWlanDataServiceManager).requestValidation(eq(123 /*cid*/),
+ verify(mMockedWlanDataServiceManager).requestNetworkValidation(eq(123 /*cid*/),
any(Message.class));
// data state updated with network validation status
@@ -2203,4 +2221,43 @@
mDataNetworkUT, mDataCallSessionStats);
processAllMessages();
}
+
+ @Test
+ public void testMmsCapabilityRemovedWhenMmsPreferredOnIwlan() throws Exception {
+ doReturn(true).when(mFeatureFlags).forceIwlanMms();
+ setupDataNetwork();
+
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)).isTrue();
+
+ ArgumentCaptor<AccessNetworksManagerCallback> accessNetworksManagerCallbackArgumentCaptor =
+ ArgumentCaptor.forClass(AccessNetworksManagerCallback.class);
+ verify(mAccessNetworksManager).registerCallback(
+ accessNetworksManagerCallbackArgumentCaptor.capture());
+
+ // Now QNS prefers MMS on IWLAN
+ doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager)
+ .getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
+ doReturn(mMmsDataProfile).when(mDataProfileManager).getDataProfileForNetworkRequest(
+ any(TelephonyNetworkRequest.class),
+ eq(TelephonyManager.NETWORK_TYPE_IWLAN), eq(false), eq(false), eq(false));
+ accessNetworksManagerCallbackArgumentCaptor.getValue()
+ .onPreferredTransportChanged(NetworkCapabilities.NET_CAPABILITY_MMS);
+ processAllMessages();
+
+ // Check if MMS capability is removed.
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)).isFalse();
+
+ // Now QNS prefers MMS on IWLAN
+ doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mAccessNetworksManager)
+ .getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
+ accessNetworksManagerCallbackArgumentCaptor.getValue()
+ .onPreferredTransportChanged(NetworkCapabilities.NET_CAPABILITY_MMS);
+ processAllMessages();
+
+ // Check if MMS capability is added back.
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)).isTrue();
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataServiceManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataServiceManagerTest.java
index 2ceca0e..30f49ad 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataServiceManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataServiceManagerTest.java
@@ -269,18 +269,18 @@
}
@Test
- public void testRequestValidation_ServiceNotBound() throws Exception {
+ public void testRequestNetworkValidation_ServiceNotBound() throws Exception {
createDataServiceManager(false);
Message message = mHandler.obtainMessage(1234);
- mDataServiceManagerUT.requestValidation(123, message);
+ mDataServiceManagerUT.requestNetworkValidation(123, message);
waitAndVerifyResult(message, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
}
@Test
- public void testRequestValidation_ServiceBound() throws Exception {
+ public void testRequestNetworkValidation_ServiceBound() throws Exception {
createDataServiceManager(true);
Message message = mHandler.obtainMessage(1234);
- mDataServiceManagerUT.requestValidation(123, message);
+ mDataServiceManagerUT.requestNetworkValidation(123, message);
waitAndVerifyResult(message, DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataStallRecoveryManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataStallRecoveryManagerTest.java
index e1e238e..e508e5b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataStallRecoveryManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataStallRecoveryManagerTest.java
@@ -43,6 +43,7 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback;
+import com.android.internal.telephony.data.DataSettingsManager.DataSettingsManagerCallback;
import com.android.internal.telephony.data.DataStallRecoveryManager.DataStallRecoveryManagerCallback;
import org.junit.After;
@@ -107,7 +108,7 @@
doReturn(dataStallRecoveryStepsArray)
.when(mDataConfigManager)
.getDataStallRecoveryShouldSkipArray();
- doReturn(true).when(mDataNetworkController).isInternetDataAllowed();
+ doReturn(true).when(mDataNetworkController).isInternetDataAllowed(true);
doAnswer(invocation -> {
((Runnable) invocation.getArguments()[0]).run();
@@ -145,6 +146,17 @@
dataNetworkControllerCallback.onInternetDataNetworkValidationStatusChanged(status);
}
+ private void sendDataEabledCallback(boolean isEnabled) {
+ ArgumentCaptor<DataSettingsManagerCallback> dataSettingsManagerCallbackCaptor =
+ ArgumentCaptor.forClass(DataSettingsManagerCallback.class);
+ verify(mDataSettingsManager).registerCallback(dataSettingsManagerCallbackCaptor.capture());
+
+ // Data enabled
+ doReturn(isEnabled).when(mDataSettingsManager).isDataEnabled();
+ dataSettingsManagerCallbackCaptor.getValue().onDataEnabledChanged(isEnabled,
+ TelephonyManager.DATA_ENABLED_REASON_USER, "");
+ }
+
private void sendOnInternetDataNetworkCallback(boolean isConnected) {
ArgumentCaptor<DataNetworkControllerCallback> dataNetworkControllerCallbackCaptor =
ArgumentCaptor.forClass(DataNetworkControllerCallback.class);
@@ -257,7 +269,8 @@
moveTimeForward(15000);
processAllMessages();
- assertThat(mDataStallRecoveryManager.getRecoveryAction()).isEqualTo(3);
+ // should not change the recovery action due to there is an active call.
+ assertThat(mDataStallRecoveryManager.getRecoveryAction()).isEqualTo(1);
}
@Test
@@ -347,7 +360,7 @@
mDataStallRecoveryManager.setRecoveryAction(1);
doReturn(mSignalStrength).when(mPhone).getSignalStrength();
doReturn(PhoneConstants.State.IDLE).when(mPhone).getState();
- doReturn(false).when(mDataNetworkController).isInternetDataAllowed();
+ doReturn(false).when(mDataNetworkController).isInternetDataAllowed(true);
logd("Sending validation failed callback");
sendValidationStatusCallback(NetworkAgent.VALIDATION_STATUS_NOT_VALID);
@@ -510,4 +523,59 @@
// Check if predict waiting millis is 0
assertThat(field.get(mDataStallRecoveryManager)).isEqualTo(0L);
}
+
+ @Test
+ public void testRecoveryActionAfterDataEnabled() throws Exception {
+ sendDataEabledCallback(true);
+ sendOnInternetDataNetworkCallback(true);
+ sendValidationStatusCallback(NetworkAgent.VALIDATION_STATUS_VALID);
+ mDataStallRecoveryManager.setRecoveryAction(0);
+ doReturn(PhoneConstants.State.IDLE).when(mPhone).getState();
+ doReturn(3).when(mSignalStrength).getLevel();
+ doReturn(mSignalStrength).when(mPhone).getSignalStrength();
+ logd("Sending validation failed callback");
+
+ assertThat(mDataStallRecoveryManager.getRecoveryAction()).isEqualTo(0);
+ sendValidationStatusCallback(NetworkAgent.VALIDATION_STATUS_NOT_VALID);
+ processAllMessages();
+ moveTimeForward(101);
+ assertThat(mDataStallRecoveryManager.getRecoveryAction()).isEqualTo(1);
+
+ // test mobile data off/on
+ sendDataEabledCallback(false);
+ sendDataEabledCallback(true);
+
+ // recovery action will jump to next action if user doing the mobile data off/on.
+ assertThat(mDataStallRecoveryManager.getRecoveryAction()).isEqualTo(3);
+ }
+
+ @Test
+ public void testJumpToRecoveryActionRadioRestart() throws Exception {
+ sendDataEabledCallback(true);
+ sendOnInternetDataNetworkCallback(true);
+ sendValidationStatusCallback(NetworkAgent.VALIDATION_STATUS_VALID);
+ mDataStallRecoveryManager.setRecoveryAction(0);
+
+ doReturn(PhoneConstants.State.IDLE).when(mPhone).getState();
+ doReturn(3).when(mSignalStrength).getLevel();
+ doReturn(mSignalStrength).when(mPhone).getSignalStrength();
+ doReturn(TelephonyManager.RADIO_POWER_ON).when(mPhone).getRadioPowerState();
+ assertThat(mDataStallRecoveryManager.getRecoveryAction()).isEqualTo(0);
+
+ sendValidationStatusCallback(NetworkAgent.VALIDATION_STATUS_NOT_VALID);
+ moveTimeForward(200);
+ processAllMessages();
+ moveTimeForward(200);
+ mDataStallRecoveryManager.sendMessageDelayed(
+ mDataStallRecoveryManager.obtainMessage(3), 1000);
+ processAllMessages();
+ sendValidationStatusCallback(NetworkAgent.VALIDATION_STATUS_NOT_VALID);
+ moveTimeForward(200);
+ sendValidationStatusCallback(NetworkAgent.VALIDATION_STATUS_NOT_VALID);
+ processAllMessages();
+ moveTimeForward(200);
+
+ // recovery action will jump to modem reset action if user doing the radio restart.
+ assertThat(mDataStallRecoveryManager.getRecoveryAction()).isEqualTo(4);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
index 719862a..e011a60 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
@@ -68,10 +68,11 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
@@ -1935,6 +1936,17 @@
}
replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
+ for (Phone phone : mPhones) {
+ ServiceState ss = new ServiceState();
+
+ ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .setRegistrationState(
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .build());
+ doReturn(ss).when(phone).getServiceState();
+ }
}
private void initializeCommandInterfacesMock() {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkFactoryTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkFactoryTest.java
index 5941f06..ad99eaf 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkFactoryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkFactoryTest.java
@@ -35,12 +35,12 @@
import android.net.TelephonyNetworkSpecifier;
import android.os.Looper;
import android.os.Message;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArraySet;
import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.ISub;
import com.android.internal.telephony.RadioConfig;
@@ -190,7 +190,8 @@
private void createMockedTelephonyComponents() throws Exception {
replaceInstance(PhoneSwitcher.class, "sPhoneSwitcher", null, mPhoneSwitcher);
- mTelephonyNetworkFactoryUT = new TelephonyNetworkFactory(Looper.myLooper(), mPhone);
+ mTelephonyNetworkFactoryUT = new TelephonyNetworkFactory(Looper.myLooper(), mPhone,
+ mFeatureFlags);
final ArgumentCaptor<NetworkProvider> providerCaptor =
ArgumentCaptor.forClass(NetworkProvider.class);
verify(mConnectivityManager).registerNetworkProvider(providerCaptor.capture());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java
index 1734244..cd7aadc 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java
@@ -24,29 +24,36 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.os.AsyncResult;
-import android.os.CancellationSignal;
import android.os.Handler;
+import android.os.RemoteException;
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.DomainSelectionService;
-import android.telephony.DomainSelector;
import android.telephony.EmergencyRegResult;
-import android.telephony.TransportSelectorCallback;
-import android.telephony.WwanSelectorCallback;
import android.telephony.data.ApnSetting;
import android.telephony.ims.ImsReasonInfo;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.CallFailCause;
+import com.android.internal.telephony.IDomainSelector;
+import com.android.internal.telephony.ITransportSelectorCallback;
+import com.android.internal.telephony.ITransportSelectorResultCallback;
+import com.android.internal.telephony.IWwanSelectorCallback;
+import com.android.internal.telephony.IWwanSelectorResultCallback;
+import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.data.AccessNetworksManager.QualifiedNetworks;
@@ -56,12 +63,12 @@
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Executor;
-import java.util.function.Consumer;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -78,102 +85,93 @@
super.setUp(this.getClass().getSimpleName());
mDomainSelectionController = Mockito.mock(DomainSelectionController.class);
+ doReturn(true).when(mDomainSelectionController).selectDomain(any(), any());
mConnectionCallback =
Mockito.mock(DomainSelectionConnection.DomainSelectionConnectionCallback.class);
}
@After
public void tearDown() throws Exception {
+ mDsc.finishSelection();
mDsc = null;
super.tearDown();
}
@Test
@SmallTest
- public void testTransportSelectorCallback() {
- mDsc = new DomainSelectionConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ public void testTransportSelectorCallback() throws Exception {
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
mDomainSelectionController);
- TransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
assertNotNull(transportCallback);
}
@Test
@SmallTest
- public void testSelectDomain() {
- mDsc = new DomainSelectionConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ public void testSelectDomain() throws Exception {
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
mDomainSelectionController);
- TransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
- false, 0, null, null, null, null);
+ false, 0, TELECOM_CALL_ID1, null, null, null);
mDsc.selectDomain(attr);
- verify(mDomainSelectionController).selectDomain(any(), eq(transportCallback));
- }
-
- @Test
- @SmallTest
- public void testWwanSelectorCallback() throws Exception {
- mDsc = new DomainSelectionConnection(mPhone, SELECTOR_TYPE_CALLING, true,
- mDomainSelectionController);
-
- TransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
-
- assertNotNull(transportCallback);
-
- WwanSelectorCallback wwanCallback = null;
- wwanCallback = transportCallback.onWwanSelected();
-
- assertNotNull(wwanCallback);
+ verify(mDomainSelectionController).selectDomain(eq(attr), eq(transportCallback));
}
@Test
@SmallTest
public void testWwanSelectorCallbackAsync() throws Exception {
- mDsc = new DomainSelectionConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
mDomainSelectionController);
- TransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
assertNotNull(transportCallback);
- replaceInstance(DomainSelectionConnection.class, "mLooper",
- mDsc, mTestableLooper.getLooper());
- Consumer<WwanSelectorCallback> consumer = Mockito.mock(Consumer.class);
- transportCallback.onWwanSelected(consumer);
- processAllMessages();
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
+ transportCallback.onCreated(domainSelector);
- verify(consumer).accept(any());
+ IWwanSelectorCallback wwanCallback = onWwanSelected(transportCallback);
+
+ assertNotNull(wwanCallback);
}
@Test
@SmallTest
public void testWwanSelectorCallbackOnRequestEmergencyNetworkScan() throws Exception {
- mDsc = new DomainSelectionConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
mDomainSelectionController);
- TransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
assertNotNull(transportCallback);
- WwanSelectorCallback wwanCallback = transportCallback.onWwanSelected();
+ DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
+ mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
+ false, 0, TELECOM_CALL_ID1, null, null, null);
+
+ mDsc.selectDomain(attr);
+
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
+ transportCallback.onCreated(domainSelector);
+
+ IWwanSelectorCallback wwanCallback = onWwanSelected(transportCallback);
assertNotNull(wwanCallback);
- replaceInstance(DomainSelectionConnection.class, "mLooper",
- mDsc, mTestableLooper.getLooper());
- List<Integer> preferredNetworks = new ArrayList<>();
- preferredNetworks.add(EUTRAN);
- preferredNetworks.add(UTRAN);
+ int[] preferredNetworks = new int[] { EUTRAN, UTRAN };
int scanType = SCAN_TYPE_NO_PREFERENCE;
- Consumer<EmergencyRegResult> consumer = Mockito.mock(Consumer.class);
+ IWwanSelectorResultCallback resultCallback =
+ Mockito.mock(IWwanSelectorResultCallback.class);
- wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType, null, consumer);
+ wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType, resultCallback);
processAllMessages();
ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
@@ -192,44 +190,45 @@
assertNotNull(handler);
- doReturn(new Executor() {
- public void execute(Runnable r) {
- r.run();
- }
- }).when(mDomainSelectionController).getDomainSelectionServiceExecutor();
EmergencyRegResult regResult =
new EmergencyRegResult(UTRAN, 0, 0, true, false, 0, 0, "", "", "");
handler.sendMessage(handler.obtainMessage(event, new AsyncResult(null, regResult, null)));
processAllMessages();
- verify(consumer).accept(eq(regResult));
+ verify(resultCallback).onComplete(eq(regResult));
}
@Test
@SmallTest
public void testWwanSelectorCallbackOnRequestEmergencyNetworkScanAndCancel() throws Exception {
- mDsc = new DomainSelectionConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
mDomainSelectionController);
- TransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
assertNotNull(transportCallback);
- WwanSelectorCallback wwanCallback = transportCallback.onWwanSelected();
+ DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
+ mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
+ false, 0, null, null, null, null);
+
+ mDsc.selectDomain(attr);
+
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
+ transportCallback.onCreated(domainSelector);
+
+ IWwanSelectorCallback wwanCallback = onWwanSelected(transportCallback);
assertNotNull(wwanCallback);
- replaceInstance(DomainSelectionConnection.class, "mLooper",
- mDsc, mTestableLooper.getLooper());
- CancellationSignal signal = new CancellationSignal();
- wwanCallback.onRequestEmergencyNetworkScan(new ArrayList<>(),
- SCAN_TYPE_NO_PREFERENCE, signal, Mockito.mock(Consumer.class));
+ wwanCallback.onRequestEmergencyNetworkScan(new int[] { },
+ SCAN_TYPE_NO_PREFERENCE, Mockito.mock(IWwanSelectorResultCallback.class));
processAllMessages();
verify(mPhone).registerForEmergencyNetworkScan(any(), anyInt(), any());
verify(mPhone).triggerEmergencyNetworkScan(any(), anyInt(), any());
- signal.cancel();
+ wwanCallback.onCancel();
processAllMessages();
verify(mPhone).cancelEmergencyNetworkScan(eq(false), any());
@@ -238,14 +237,20 @@
@Test
@SmallTest
public void testDomainSelectorCancelSelection() throws Exception {
- mDsc = new DomainSelectionConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
mDomainSelectionController);
- TransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
assertNotNull(transportCallback);
- DomainSelector domainSelector = Mockito.mock(DomainSelector.class);
+ DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
+ mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
+ false, 0, TELECOM_CALL_ID1, null, null, null);
+
+ mDsc.selectDomain(attr);
+
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
transportCallback.onCreated(domainSelector);
mDsc.cancelSelection();
@@ -256,39 +261,45 @@
@Test
@SmallTest
public void testDomainSelectorReselectDomain() throws Exception {
- mDsc = new DomainSelectionConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
mDomainSelectionController);
- TransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
assertNotNull(transportCallback);
- DomainSelector domainSelector = Mockito.mock(DomainSelector.class);
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
transportCallback.onCreated(domainSelector);
DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
- false, CallFailCause.ERROR_UNSPECIFIED, null, null, null, null);
+ false, CallFailCause.ERROR_UNSPECIFIED, TELECOM_CALL_ID1, null, null, null);
CompletableFuture<Integer> future = mDsc.reselectDomain(attr);
assertNotNull(future);
assertFalse(future.isDone());
- verify(domainSelector).reselectDomain(any());
+ verify(domainSelector).reselectDomain(eq(attr));
}
@Test
@SmallTest
public void testDomainSelectorFinishSelection() throws Exception {
- mDsc = new DomainSelectionConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
mDomainSelectionController);
- TransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
assertNotNull(transportCallback);
- DomainSelector domainSelector = Mockito.mock(DomainSelector.class);
+ DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
+ mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
+ false, 0, TELECOM_CALL_ID1, null, null, null);
+
+ mDsc.selectDomain(attr);
+
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
transportCallback.onCreated(domainSelector);
mDsc.finishSelection();
@@ -299,7 +310,7 @@
@Test
@SmallTest
public void testQualifiedNetworkTypesChanged() throws Exception {
- mDsc = new DomainSelectionConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
mDomainSelectionController);
List<QualifiedNetworks> networksList = new ArrayList<>();
@@ -321,6 +332,256 @@
.isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
}
+ @Test
+ @SmallTest
+ public void testRemoteDomainSelectorRebindingService() throws Exception {
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDomainSelectionController);
+
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+
+ assertNotNull(transportCallback);
+
+ DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
+ mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
+ false, 0, null, null, null, null);
+
+ mDsc.selectDomain(attr);
+
+ verify(mDomainSelectionController, times(1)).selectDomain(eq(attr), eq(transportCallback));
+
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
+ transportCallback.onCreated(domainSelector);
+
+ // Detect failure
+ mDsc.onServiceDisconnected();
+
+ verify(mDomainSelectionController, times(1)).selectDomain(any(), eq(transportCallback));
+
+ // Waiting for timeout
+ processAllFutureMessages();
+
+ verify(mDomainSelectionController).removeConnection(eq(mDsc));
+ }
+
+ @Test
+ @SmallTest
+ public void testRemoteDomainSelectorRebindingServiceWhenScanning() throws Exception {
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDomainSelectionController);
+
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+
+ assertNotNull(transportCallback);
+
+ DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
+ mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
+ false, 0, TELECOM_CALL_ID1, null, null, null);
+
+ mDsc.selectDomain(attr);
+
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
+ transportCallback.onCreated(domainSelector);
+
+ IWwanSelectorCallback wwanCallback = onWwanSelected(transportCallback);
+
+ assertNotNull(wwanCallback);
+
+ int[] preferredNetworks = new int[] { EUTRAN, UTRAN };
+ int scanType = SCAN_TYPE_NO_PREFERENCE;
+ IWwanSelectorResultCallback resultCallback =
+ Mockito.mock(IWwanSelectorResultCallback.class);
+
+ // 1st scan request from remote service
+ wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType, resultCallback);
+ processAllMessages();
+
+ ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
+ ArgumentCaptor<Integer> eventCaptor = ArgumentCaptor.forClass(Integer.class);
+
+ verify(mPhone).registerForEmergencyNetworkScan(
+ handlerCaptor.capture(), eventCaptor.capture(), any());
+
+ int[] expectedPreferredNetworks = new int[] { EUTRAN, UTRAN };
+
+ verify(mPhone, times(1)).triggerEmergencyNetworkScan(eq(expectedPreferredNetworks),
+ eq(scanType), any());
+ verify(mPhone, times(1)).triggerEmergencyNetworkScan(any(), anyInt(), any());
+
+ Handler handler = handlerCaptor.getValue();
+ int event = eventCaptor.getValue();
+
+ assertNotNull(handler);
+
+ mDsc.onServiceDisconnected();
+
+ assertTrue(mDsc.isWaitingForServiceBinding());
+
+ verify(mDomainSelectionController, times(1)).selectDomain(eq(attr), eq(transportCallback));
+
+ // reconnected to service
+ transportCallback.onCreated(domainSelector);
+
+ wwanCallback = onWwanSelected(transportCallback);
+
+ assertNotNull(wwanCallback);
+
+ // 2nd scan request
+ IWwanSelectorResultCallback resultCallback2 =
+ Mockito.mock(IWwanSelectorResultCallback.class);
+ wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType, resultCallback2);
+ processAllMessages();
+
+ // Verify that triggerEmergencyNetworkScan isn't called
+ verify(mPhone, times(1)).triggerEmergencyNetworkScan(any(), anyInt(), any());
+
+ // Result received
+ EmergencyRegResult regResult =
+ new EmergencyRegResult(UTRAN, 0, 0, true, false, 0, 0, "", "", "");
+ handler.sendMessage(handler.obtainMessage(event, new AsyncResult(null, regResult, null)));
+ processAllMessages();
+
+ // Verify that triggerEmergencyNetworkScan isn't called
+ verify(mPhone, times(1)).triggerEmergencyNetworkScan(any(), anyInt(), any());
+ verify(resultCallback, times(0)).onComplete(any());
+ verify(resultCallback2, times(1)).onComplete(eq(regResult));
+ }
+
+ @Test
+ @SmallTest
+ public void testRemoteDomainSelectorRebindingServiceAfterScanCompleted() throws Exception {
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDomainSelectionController);
+
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+
+ assertNotNull(transportCallback);
+
+ DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
+ mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
+ false, 0, null, null, null, null);
+
+ mDsc.selectDomain(attr);
+
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
+ transportCallback.onCreated(domainSelector);
+
+ IWwanSelectorCallback wwanCallback = onWwanSelected(transportCallback);
+
+ assertNotNull(wwanCallback);
+
+ int[] preferredNetworks = new int[] { EUTRAN, UTRAN };
+ int scanType = SCAN_TYPE_NO_PREFERENCE;
+ IWwanSelectorResultCallback resultCallback =
+ Mockito.mock(IWwanSelectorResultCallback.class);
+
+ // 1st scan request from remote service
+ wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType, resultCallback);
+ processAllMessages();
+
+ ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
+ ArgumentCaptor<Integer> eventCaptor = ArgumentCaptor.forClass(Integer.class);
+
+ verify(mPhone).registerForEmergencyNetworkScan(
+ handlerCaptor.capture(), eventCaptor.capture(), any());
+
+ int[] expectedPreferredNetworks = new int[] { EUTRAN, UTRAN };
+
+ verify(mPhone, times(1)).triggerEmergencyNetworkScan(eq(expectedPreferredNetworks),
+ eq(scanType), any());
+
+ Handler handler = handlerCaptor.getValue();
+ int event = eventCaptor.getValue();
+
+ assertNotNull(handler);
+
+ mDsc.onServiceDisconnected();
+
+ verify(mDomainSelectionController, times(1)).selectDomain(eq(attr), eq(transportCallback));
+
+ // Result received
+ EmergencyRegResult regResult =
+ new EmergencyRegResult(UTRAN, 0, 0, true, false, 0, 0, "", "", "");
+ handler.sendMessage(handler.obtainMessage(event, new AsyncResult(null, regResult, null)));
+ processAllMessages();
+
+ verify(resultCallback, times(0)).onComplete(any());
+
+ // reconnected to service
+ transportCallback.onCreated(domainSelector);
+
+ wwanCallback = onWwanSelected(transportCallback);
+
+ assertNotNull(wwanCallback);
+
+ // 2nd scan request
+ IWwanSelectorResultCallback resultCallback2 =
+ Mockito.mock(IWwanSelectorResultCallback.class);
+ wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType, resultCallback2);
+ processAllMessages();
+
+ // Verify that triggerEmergencyNetworkScan is called
+ verify(mPhone, times(2)).triggerEmergencyNetworkScan(any(), anyInt(), any());
+
+ // Result received
+ regResult =
+ new EmergencyRegResult(EUTRAN, 0, 0, true, false, 0, 0, "", "", "");
+ handler.sendMessage(handler.obtainMessage(event, new AsyncResult(null, regResult, null)));
+ processAllMessages();
+
+ verify(resultCallback, times(0)).onComplete(any());
+ verify(resultCallback2, times(1)).onComplete(eq(regResult));
+ }
+
+ @Test
+ @SmallTest
+ public void testRemoteDomainSelectorRebindServiceWhenReselect() throws Exception {
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDomainSelectionController);
+
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+
+ assertNotNull(transportCallback);
+
+ DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
+ mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
+ false, 0, null, null, null, null);
+
+ mDsc.selectDomain(attr);
+
+ verify(mDomainSelectionController, times(1)).selectDomain(eq(attr), eq(transportCallback));
+
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ throw new RemoteException();
+ }
+ }).when(domainSelector).reselectDomain(any());
+ transportCallback.onCreated(domainSelector);
+
+ attr = getSelectionAttributes(
+ mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
+ false, CallFailCause.ERROR_UNSPECIFIED, null, null, null, null);
+
+ CompletableFuture<Integer> future = mDsc.reselectDomain(attr);
+
+ assertNotNull(future);
+ assertFalse(future.isDone());
+
+ verify(domainSelector).reselectDomain(eq(attr));
+ verify(mDomainSelectionController, times(1)).selectDomain(any(), eq(transportCallback));
+ }
+
+ private DomainSelectionConnection createConnection(Phone phone, int selectorType,
+ boolean isEmergency, DomainSelectionController controller) throws Exception {
+ DomainSelectionConnection dsc = new DomainSelectionConnection(phone,
+ selectorType, isEmergency, controller);
+ replaceInstance(DomainSelectionConnection.class, "mLooper",
+ dsc, mTestableLooper.getLooper());
+ return dsc;
+ }
+
private DomainSelectionService.SelectionAttributes getSelectionAttributes(
int slotId, int subId, int selectorType, boolean isEmergency,
boolean exited, int callFailCause, String callId, String number,
@@ -339,4 +600,18 @@
return builder.build();
}
+
+ private IWwanSelectorCallback onWwanSelected(ITransportSelectorCallback transportCallback)
+ throws Exception {
+ ITransportSelectorResultCallback cb = Mockito.mock(ITransportSelectorResultCallback.class);
+ transportCallback.onWwanSelectedAsync(cb);
+ processAllMessages();
+
+ ArgumentCaptor<IWwanSelectorCallback> callbackCaptor =
+ ArgumentCaptor.forClass(IWwanSelectorCallback.class);
+
+ verify(cb).onCompleted(callbackCaptor.capture());
+
+ return callbackCaptor.getValue();
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionControllerTest.java
new file mode 100644
index 0000000..f5ccdd6
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionControllerTest.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.domainselection;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.telephony.DomainSelectionService;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.telephony.IDomainSelectionServiceController;
+import com.android.internal.telephony.TelephonyTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Unit tests for DomainSelectionController
+ */
+@RunWith(AndroidJUnit4.class)
+public class DomainSelectionControllerTest extends TelephonyTest {
+
+ private static final DomainSelectionController.BindRetry BIND_RETRY =
+ new DomainSelectionController.BindRetry() {
+ @Override
+ public long getStartDelay() {
+ return 50;
+ }
+
+ @Override
+ public long getMaximumDelay() {
+ return 1000;
+ }
+ };
+
+ // Mocked classes
+ IDomainSelectionServiceController mMockServiceControllerBinder;
+ Context mMockContext;
+
+ private final ComponentName mTestComponentName = new ComponentName("TestPkg",
+ "DomainSelectionControllerTest");
+ private Handler mHandler;
+ private DomainSelectionController mTestController;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp(this.getClass().getSimpleName());
+
+ mMockContext = mock(Context.class);
+ mMockServiceControllerBinder = mock(IDomainSelectionServiceController.class);
+ mTestController = new DomainSelectionController(mMockContext,
+ Looper.getMainLooper(), BIND_RETRY);
+ mHandler = mTestController.getHandlerForTest();
+
+ when(mMockContext.bindService(any(), any(), anyInt())).thenReturn(true);
+ }
+
+
+ @After
+ public void tearDown() throws Exception {
+ mTestController.stopBackoffTimer();
+ waitForHandlerAction(mHandler, 1000);
+ mTestController = null;
+ super.tearDown();
+ }
+
+ /**
+ * Tests that Context.bindService is called with the correct parameters when we call bind.
+ */
+ @SmallTest
+ @Test
+ public void testBindService() {
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+
+ assertTrue(mTestController.bind(mTestComponentName));
+
+ int expectedFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
+ | Context.BIND_IMPORTANT;
+
+ verify(mMockContext).bindService(intentCaptor.capture(), any(), eq(expectedFlags));
+
+ Intent testIntent = intentCaptor.getValue();
+
+ assertEquals(DomainSelectionService.SERVICE_INTERFACE, testIntent.getAction());
+ assertEquals(mTestComponentName, testIntent.getComponent());
+ }
+
+ /**
+ * Verify that if bind is called multiple times, we only call bindService once.
+ */
+ @SmallTest
+ @Test
+ public void testBindFailureWhenBound() {
+ bindAndConnectService();
+
+ // already bound, should return false
+ assertFalse(mTestController.bind(mTestComponentName));
+
+ verify(mMockContext, times(1)).bindService(any(), any(), anyInt());
+ }
+
+ /**
+ * Tests that when unbind is called while the DomainSelectionService is disconnected,
+ * we still handle unbinding to the service correctly.
+ */
+ @SmallTest
+ @Test
+ public void testBindServiceAndConnectedDisconnectedUnbind() throws RemoteException {
+ ServiceConnection conn = bindAndConnectService();
+
+ conn.onServiceDisconnected(mTestComponentName);
+
+ long delay = mTestController.getBindDelay();
+ waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
+
+ mTestController.unbind();
+ verify(mMockContext).unbindService(eq(conn));
+ }
+
+ /**
+ * Tests DomainSelectionController callbacks are properly called when a DomainSelectionService
+ * is bound and subsequently unbound.
+ */
+ @SmallTest
+ @Test
+ public void testBindServiceBindUnbind() throws RemoteException {
+ ServiceConnection conn = bindAndConnectService();
+
+ mTestController.unbind();
+
+ verify(mMockContext).unbindService(eq(conn));
+ }
+
+ /**
+ * Ensures that imsServiceFeatureRemoved is called when the binder dies in another process.
+ */
+ @SmallTest
+ @Test
+ public void testBindServiceAndBinderDied() throws RemoteException {
+ ServiceConnection conn = bindAndConnectService();
+
+ conn.onBindingDied(null /*null*/);
+
+ long delay = BIND_RETRY.getStartDelay();
+ waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
+ verify(mMockContext).unbindService(eq(conn));
+ }
+
+ /**
+ * Ensures that imsServiceBindPermanentError is called when the binder returns null.
+ */
+ @SmallTest
+ @Test
+ public void testBindServiceAndReturnedNull() throws RemoteException {
+ bindAndNullServiceError();
+
+ long delay = mTestController.getBindDelay();
+ waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
+ }
+
+ /**
+ * Verifies that the DomainSelectionController automatically tries to bind again after
+ * an untimely binder death.
+ */
+ @SmallTest
+ @Test
+ public void testAutoBindAfterBinderDied() throws RemoteException {
+ ServiceConnection conn = bindAndConnectService();
+
+ conn.onBindingDied(null /*null*/);
+
+ long delay = BIND_RETRY.getStartDelay();
+ waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
+ // The service should autobind after rebind event occurs
+ verify(mMockContext, times(2)).bindService(any(), any(), anyInt());
+ }
+
+ /**
+ * Due to a bug in ServiceConnection, we will sometimes receive a null binding after the binding
+ * dies. Ignore null binding in this case.
+ */
+ @SmallTest
+ @Test
+ public void testAutoBindAfterBinderDiedIgnoreNullBinding() throws RemoteException {
+ ServiceConnection conn = bindAndConnectService();
+
+ conn.onBindingDied(null);
+ // null binding should be ignored in this case.
+ conn.onNullBinding(null);
+
+ long delay = BIND_RETRY.getStartDelay();
+ waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
+ // The service should autobind after rebind event occurs
+ verify(mMockContext, times(2)).bindService(any(), any(), anyInt());
+ }
+
+ /**
+ * Ensure that bindService has only been called once before automatic rebind occurs.
+ */
+ @SmallTest
+ @Test
+ public void testNoAutoBindBeforeTimeout() throws RemoteException {
+ ServiceConnection conn = bindAndConnectService();
+
+ conn.onBindingDied(null /*null*/);
+
+ // Be sure that there are no binds before the RETRY_TIMEOUT expires
+ verify(mMockContext, times(1)).bindService(any(), any(), anyInt());
+ }
+
+ /**
+ * Ensure that calling unbind stops automatic rebind from occurring.
+ */
+ @SmallTest
+ @Test
+ public void testUnbindCauseAutoBindCancelAfterBinderDied() throws RemoteException {
+ ServiceConnection conn = bindAndConnectService();
+
+ conn.onBindingDied(null /*null*/);
+ mTestController.unbind();
+
+ long delay = mTestController.getBindDelay();
+ waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
+
+ // Unbind should stop the autobind from occurring.
+ verify(mMockContext, times(1)).bindService(any(), any(), anyInt());
+ }
+
+ private void bindAndNullServiceError() {
+ ServiceConnection connection = bindService(mTestComponentName);
+ connection.onNullBinding(mTestComponentName);
+ }
+
+ private ServiceConnection bindAndConnectService() {
+ ServiceConnection connection = bindService(mTestComponentName);
+ IDomainSelectionServiceController.Stub controllerStub =
+ mock(IDomainSelectionServiceController.Stub.class);
+ when(controllerStub.queryLocalInterface(any())).thenReturn(mMockServiceControllerBinder);
+ connection.onServiceConnected(mTestComponentName, controllerStub);
+
+ long delay = mTestController.getBindDelay();
+ waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
+ return connection;
+ }
+
+ private ServiceConnection bindService(ComponentName testComponentName) {
+ ArgumentCaptor<ServiceConnection> serviceCaptor =
+ ArgumentCaptor.forClass(ServiceConnection.class);
+ assertTrue(mTestController.bind(testComponentName));
+ verify(mMockContext).bindService(any(), serviceCaptor.capture(), anyInt());
+ return serviceCaptor.getValue();
+ }
+
+ private void waitForHandlerActionDelayed(Handler h, long timeoutMillis, long delayMs) {
+ final CountDownLatch lock = new CountDownLatch(1);
+ h.postDelayed(lock::countDown, delayMs);
+ while (lock.getCount() > 0) {
+ try {
+ lock.await(timeoutMillis, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ // do nothing
+ }
+ }
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionResolverTest.java b/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionResolverTest.java
index eaf11a4..e0fb0bd 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionResolverTest.java
@@ -31,14 +31,18 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.ComponentName;
import android.content.Context;
-import android.telephony.DomainSelectionService;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.HalVersion;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyTest;
@@ -55,10 +59,24 @@
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class DomainSelectionResolverTest extends TelephonyTest {
+ private static final String COMPONENT_NAME_STRING =
+ "com.android.dss/.TelephonyDomainSelectionService";
+ private static final ComponentName DSS_COMPONENT_NAME =
+ ComponentName.unflattenFromString(COMPONENT_NAME_STRING);
+ private static final String CLASS_NAME = "com.android.dss.TelephonyDomainSelectionService";
+ private static final String EMPTY_COMPONENT_NAME_STRING = "/" + CLASS_NAME;
+ private static final ComponentName EMPTY_COMPONENT_NAME =
+ ComponentName.unflattenFromString(EMPTY_COMPONENT_NAME_STRING);
+ private static final String NONE_COMPONENT_NAME_STRING =
+ DomainSelectionResolver.PACKAGE_NAME_NONE + "/" + CLASS_NAME;
+ private static final ComponentName NONE_COMPONENT_NAME =
+ ComponentName.unflattenFromString(NONE_COMPONENT_NAME_STRING);
+ private static final String OVERRIDDEN_COMPONENT_NAME_STRING = "test/" + CLASS_NAME;
+ private static final ComponentName OVERRIDDEN_COMPONENT_NAME =
+ ComponentName.unflattenFromString(OVERRIDDEN_COMPONENT_NAME_STRING);
// Mock classes
private DomainSelectionController mDsController;
private DomainSelectionConnection mDsConnection;
- private DomainSelectionService mDsService;
private DomainSelectionResolver mDsResolver;
@@ -68,13 +86,11 @@
mDsController = Mockito.mock(DomainSelectionController.class);
mDsConnection = Mockito.mock(DomainSelectionConnection.class);
- mDsService = Mockito.mock(DomainSelectionService.class);
}
@After
public void tearDown() throws Exception {
mDsResolver = null;
- mDsService = null;
mDsConnection = null;
mDsController = null;
super.tearDown();
@@ -89,7 +105,7 @@
DomainSelectionResolver.getInstance();
});
- DomainSelectionResolver.make(mContext, true);
+ DomainSelectionResolver.make(mContext, COMPONENT_NAME_STRING);
DomainSelectionResolver resolver = DomainSelectionResolver.getInstance();
assertNotNull(resolver);
@@ -97,8 +113,8 @@
@Test
@SmallTest
- public void testIsDomainSelectionSupportedWhenDeviceConfigDisabled() {
- setUpResolver(false, RADIO_HAL_VERSION_2_1);
+ public void testIsDomainSelectionSupportedWhenComponentNameNotConfigured() {
+ setUpResolver(null, RADIO_HAL_VERSION_2_1);
assertFalse(mDsResolver.isDomainSelectionSupported());
}
@@ -106,7 +122,7 @@
@Test
@SmallTest
public void testIsDomainSelectionSupportedWhenHalVersionLessThan20() {
- setUpResolver(true, RADIO_HAL_VERSION_2_0);
+ setUpResolver(COMPONENT_NAME_STRING, RADIO_HAL_VERSION_2_0);
assertFalse(mDsResolver.isDomainSelectionSupported());
}
@@ -114,7 +130,7 @@
@Test
@SmallTest
public void testIsDomainSelectionSupported() {
- setUpResolver(true, RADIO_HAL_VERSION_2_1);
+ setUpResolver(COMPONENT_NAME_STRING, RADIO_HAL_VERSION_2_1);
assertTrue(mDsResolver.isDomainSelectionSupported());
}
@@ -122,7 +138,7 @@
@Test
@SmallTest
public void testGetDomainSelectionConnectionWhenNotInitialized() throws Exception {
- setUpResolver(true, RADIO_HAL_VERSION_2_1);
+ setUpResolver(COMPONENT_NAME_STRING, RADIO_HAL_VERSION_2_1);
assertThrows(IllegalStateException.class, () -> {
mDsResolver.getDomainSelectionConnection(mPhone, SELECTOR_TYPE_CALLING, true);
@@ -132,29 +148,36 @@
@Test
@SmallTest
public void testGetDomainSelectionConnectionWhenPhoneNull() throws Exception {
- setUpResolver(true, RADIO_HAL_VERSION_2_1);
- mDsResolver.initialize(mDsService);
+ setUpResolver(COMPONENT_NAME_STRING, RADIO_HAL_VERSION_2_1);
+ setUpController();
+ mDsResolver.initialize();
+ verify(mDsController).bind(eq(DSS_COMPONENT_NAME));
+
assertNull(mDsResolver.getDomainSelectionConnection(null, SELECTOR_TYPE_CALLING, true));
}
@Test
@SmallTest
public void testGetDomainSelectionConnectionWhenImsPhoneNull() throws Exception {
- setUpResolver(true, RADIO_HAL_VERSION_2_1);
- mDsResolver.initialize(mDsService);
- when(mPhone.getImsPhone()).thenReturn(null);
+ setUpResolver(COMPONENT_NAME_STRING, RADIO_HAL_VERSION_2_1);
+ setUpController();
+ mDsResolver.initialize();
+ verify(mDsController).bind(eq(DSS_COMPONENT_NAME));
+ when(mPhone.getImsPhone()).thenReturn(null);
assertNull(mDsResolver.getDomainSelectionConnection(mPhone, SELECTOR_TYPE_CALLING, true));
}
@Test
@SmallTest
public void testGetDomainSelectionConnectionWhenImsNotAvailable() throws Exception {
- setUpResolver(true, RADIO_HAL_VERSION_2_1);
- mDsResolver.initialize(mDsService);
+ setUpResolver(COMPONENT_NAME_STRING, RADIO_HAL_VERSION_2_1);
+ setUpController();
+ mDsResolver.initialize();
+ verify(mDsController).bind(eq(DSS_COMPONENT_NAME));
+
when(mPhone.isImsAvailable()).thenReturn(false);
when(mPhone.getImsPhone()).thenReturn(mImsPhone);
-
assertNull(mDsResolver.getDomainSelectionConnection(mPhone, SELECTOR_TYPE_CALLING, false));
}
@@ -162,12 +185,13 @@
@SmallTest
public void testGetDomainSelectionConnectionWhenImsNotAvailableForEmergencyCall()
throws Exception {
- setUpResolver(true, RADIO_HAL_VERSION_2_1);
+ setUpResolver(COMPONENT_NAME_STRING, RADIO_HAL_VERSION_2_1);
setUpController();
- mDsResolver.initialize(mDsService);
+ mDsResolver.initialize();
+ verify(mDsController).bind(eq(DSS_COMPONENT_NAME));
+
when(mPhone.isImsAvailable()).thenReturn(false);
when(mPhone.getImsPhone()).thenReturn(mImsPhone);
-
assertNotNull(mDsResolver.getDomainSelectionConnection(mPhone,
SELECTOR_TYPE_CALLING, true));
}
@@ -175,18 +199,81 @@
@Test
@SmallTest
public void testGetDomainSelectionConnection() throws Exception {
- setUpResolver(true, RADIO_HAL_VERSION_2_1);
+ setUpResolver(COMPONENT_NAME_STRING, RADIO_HAL_VERSION_2_1);
setUpController();
- mDsResolver.initialize(mDsService);
+ mDsResolver.initialize();
+ verify(mDsController).bind(eq(DSS_COMPONENT_NAME));
+
when(mPhone.isImsAvailable()).thenReturn(true);
when(mPhone.getImsPhone()).thenReturn(mImsPhone);
-
assertNotNull(mDsResolver.getDomainSelectionConnection(
mPhone, SELECTOR_TYPE_CALLING, true));
}
- private void setUpResolver(boolean deviceConfigEnabled, HalVersion halVersion) {
- mDsResolver = new DomainSelectionResolver(mContext, deviceConfigEnabled);
+ @Test
+ @SmallTest
+ public void testSetDomainSelectionServiceOverride() throws Exception {
+ setUpResolver(COMPONENT_NAME_STRING, RADIO_HAL_VERSION_2_1);
+ setUpController();
+ mDsResolver.initialize();
+ mDsResolver.setDomainSelectionServiceOverride(OVERRIDDEN_COMPONENT_NAME);
+ verify(mDsController, never()).unbind();
+ verify(mDsController).bind(eq(OVERRIDDEN_COMPONENT_NAME));
+ }
+
+ @Test
+ @SmallTest
+ public void testSetDomainSelectionServiceOverrideWithoutInitialize() throws Exception {
+ setUpResolver(COMPONENT_NAME_STRING, RADIO_HAL_VERSION_2_1);
+ setUpController();
+ assertFalse(mDsResolver.setDomainSelectionServiceOverride(OVERRIDDEN_COMPONENT_NAME));
+ verify(mDsController, never()).bind(eq(OVERRIDDEN_COMPONENT_NAME));
+ }
+
+ @Test
+ @SmallTest
+ public void testSetDomainSelectionServiceOverrideWithEmptyComponentName() throws Exception {
+ setUpResolver(COMPONENT_NAME_STRING, RADIO_HAL_VERSION_2_1);
+ setUpController();
+ mDsResolver.initialize();
+ assertTrue(mDsResolver.setDomainSelectionServiceOverride(EMPTY_COMPONENT_NAME));
+ verify(mDsController).unbind();
+ verify(mDsController, never()).bind(eq(EMPTY_COMPONENT_NAME));
+ }
+
+ @Test
+ @SmallTest
+ public void testSetDomainSelectionServiceOverrideWithNoneComponentName() throws Exception {
+ setUpResolver(COMPONENT_NAME_STRING, RADIO_HAL_VERSION_2_1);
+ setUpController();
+ mDsResolver.initialize();
+ assertTrue(mDsResolver.setDomainSelectionServiceOverride(NONE_COMPONENT_NAME));
+ verify(mDsController).unbind();
+ verify(mDsController, never()).bind(eq(NONE_COMPONENT_NAME));
+ }
+
+ @Test
+ @SmallTest
+ public void testClearDomainSelectionServiceOverride() throws Exception {
+ setUpResolver(COMPONENT_NAME_STRING, RADIO_HAL_VERSION_2_1);
+ setUpController();
+ mDsResolver.initialize();
+ mDsResolver.clearDomainSelectionServiceOverride();
+ verify(mDsController).unbind();
+ verify(mDsController, times(2)).bind(eq(DSS_COMPONENT_NAME));
+ }
+
+ @Test
+ @SmallTest
+ public void testClearDomainSelectionServiceOverrideWithoutInitialize() throws Exception {
+ setUpResolver(COMPONENT_NAME_STRING, RADIO_HAL_VERSION_2_1);
+ setUpController();
+ assertFalse(mDsResolver.clearDomainSelectionServiceOverride());
+ verify(mDsController, never()).unbind();
+ }
+
+ private void setUpResolver(String flattenedComponentName, HalVersion halVersion) {
+ mDsResolver = new DomainSelectionResolver(mContext, flattenedComponentName);
when(mPhone.getHalVersion(eq(HAL_SERVICE_NETWORK))).thenReturn(halVersion);
}
@@ -194,8 +281,7 @@
mDsResolver.setDomainSelectionControllerFactory(
new DomainSelectionResolver.DomainSelectionControllerFactory() {
@Override
- public DomainSelectionController create(Context context,
- DomainSelectionService service) {
+ public DomainSelectionController create(Context context) {
return mDsController;
}
});
diff --git a/tests/telephonytests/src/com/android/internal/telephony/domainselection/EmergencyCallDomainSelectionConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/domainselection/EmergencyCallDomainSelectionConnectionTest.java
index d0b2fce..76de9c9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/domainselection/EmergencyCallDomainSelectionConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/domainselection/EmergencyCallDomainSelectionConnectionTest.java
@@ -44,13 +44,15 @@
import android.telephony.DomainSelectionService;
import android.telephony.EmergencyRegResult;
import android.telephony.NetworkRegistrationInfo;
-import android.telephony.TransportSelectorCallback;
-import android.telephony.WwanSelectorCallback;
import android.telephony.data.ApnSetting;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.telephony.ITransportSelectorCallback;
+import com.android.internal.telephony.ITransportSelectorResultCallback;
+import com.android.internal.telephony.IWwanSelectorCallback;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.data.AccessNetworksManager;
import com.android.internal.telephony.data.AccessNetworksManager.QualifiedNetworks;
@@ -77,7 +79,7 @@
private DomainSelectionConnection.DomainSelectionConnectionCallback mConnectionCallback;
private EmergencyCallDomainSelectionConnection mEcDsc;
private AccessNetworksManager mAnm;
- private TransportSelectorCallback mTransportCallback;
+ private ITransportSelectorCallback mTransportCallback;
private EmergencyStateTracker mEmergencyStateTracker;
@Before
@@ -85,6 +87,7 @@
super.setUp(this.getClass().getSimpleName());
mDomainSelectionController = Mockito.mock(DomainSelectionController.class);
+ doReturn(true).when(mDomainSelectionController).selectDomain(any(), any());
mConnectionCallback =
Mockito.mock(DomainSelectionConnection.DomainSelectionConnectionCallback.class);
mEmergencyStateTracker = Mockito.mock(EmergencyStateTracker.class);
@@ -92,6 +95,8 @@
doReturn(mAnm).when(mPhone).getAccessNetworksManager();
mEcDsc = new EmergencyCallDomainSelectionConnection(mPhone,
mDomainSelectionController, mEmergencyStateTracker);
+ replaceInstance(DomainSelectionConnection.class, "mLooper",
+ mEcDsc, mTestableLooper.getLooper());
mTransportCallback = mEcDsc.getTransportSelectorCallback();
}
@@ -124,7 +129,8 @@
assertNotNull(future);
assertFalse(future.isDone());
- verify(mDomainSelectionController).selectDomain(any(), any());
+ verify(mDomainSelectionController).selectDomain(any(),
+ any(ITransportSelectorCallback.class));
mTransportCallback.onWlanSelected(true);
@@ -172,10 +178,10 @@
assertNotNull(future);
assertFalse(future.isDone());
- verify(mDomainSelectionController).selectDomain(any(), any());
+ verify(mDomainSelectionController).selectDomain(any(),
+ any(ITransportSelectorCallback.class));
- WwanSelectorCallback wwanCallback = null;
- wwanCallback = mTransportCallback.onWwanSelected();
+ IWwanSelectorCallback wwanCallback = onWwanSelected(mTransportCallback);
assertFalse(future.isDone());
verify(mEmergencyStateTracker).onEmergencyTransportChanged(
@@ -210,10 +216,10 @@
assertNotNull(future);
assertFalse(future.isDone());
- verify(mDomainSelectionController).selectDomain(any(), any());
+ verify(mDomainSelectionController).selectDomain(any(),
+ any(ITransportSelectorCallback.class));
- WwanSelectorCallback wwanCallback = null;
- wwanCallback = mTransportCallback.onWwanSelected();
+ IWwanSelectorCallback wwanCallback = onWwanSelected(mTransportCallback);
assertFalse(future.isDone());
verify(mEmergencyStateTracker).onEmergencyTransportChanged(
@@ -250,4 +256,18 @@
mEcDsc.cancelSelection();
verify(mAnm).unregisterForQualifiedNetworksChanged(any());
}
+
+ private IWwanSelectorCallback onWwanSelected(ITransportSelectorCallback transportCallback)
+ throws Exception {
+ ITransportSelectorResultCallback cb = Mockito.mock(ITransportSelectorResultCallback.class);
+ transportCallback.onWwanSelectedAsync(cb);
+ processAllMessages();
+
+ ArgumentCaptor<IWwanSelectorCallback> callbackCaptor =
+ ArgumentCaptor.forClass(IWwanSelectorCallback.class);
+
+ verify(cb).onCompleted(callbackCaptor.capture());
+
+ return callbackCaptor.getValue();
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/domainselection/EmergencySmsDomainSelectionConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/domainselection/EmergencySmsDomainSelectionConnectionTest.java
index 3b6d0c3..c25aeb9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/domainselection/EmergencySmsDomainSelectionConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/domainselection/EmergencySmsDomainSelectionConnectionTest.java
@@ -25,6 +25,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -36,13 +37,14 @@
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.DomainSelectionService;
-import android.telephony.DomainSelector;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.data.ApnSetting;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.telephony.IDomainSelector;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.data.AccessNetworksManager;
import com.android.internal.telephony.data.AccessNetworksManager.QualifiedNetworks;
@@ -67,7 +69,7 @@
public class EmergencySmsDomainSelectionConnectionTest extends TelephonyTest {
private DomainSelectionController mDsController;
private DomainSelectionConnection.DomainSelectionConnectionCallback mDscCallback;
- private DomainSelector mDomainSelector;
+ private IDomainSelector mDomainSelector;
private EmergencyStateTracker mEmergencyStateTracker;
private Handler mHandler;
@@ -85,9 +87,10 @@
mHandler = new Handler(Looper.myLooper());
mDsController = Mockito.mock(DomainSelectionController.class);
+ doReturn(true).when(mDsController).selectDomain(any(), any());
mDscCallback = Mockito.mock(
DomainSelectionConnection.DomainSelectionConnectionCallback.class);
- mDomainSelector = Mockito.mock(DomainSelector.class);
+ mDomainSelector = Mockito.mock(IDomainSelector.class);
mEmergencyStateTracker = Mockito.mock(EmergencyStateTracker.class);
mAnm = Mockito.mock(AccessNetworksManager.class);
when(mPhone.getAccessNetworksManager()).thenReturn(mAnm);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/domainselection/NormalCallDomainSelectionConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/domainselection/NormalCallDomainSelectionConnectionTest.java
index 0403232..f05943f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/domainselection/NormalCallDomainSelectionConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/domainselection/NormalCallDomainSelectionConnectionTest.java
@@ -31,24 +31,25 @@
import static org.mockito.Mockito.verify;
import android.telephony.DomainSelectionService;
-import android.telephony.TransportSelectorCallback;
-import android.telephony.WwanSelectorCallback;
import android.telephony.ims.ImsReasonInfo;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.telephony.ITransportSelectorCallback;
+import com.android.internal.telephony.ITransportSelectorResultCallback;
+import com.android.internal.telephony.IWwanSelectorCallback;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.data.AccessNetworksManager;
-import com.android.internal.telephony.domainselection.DomainSelectionConnection;
-import com.android.internal.telephony.domainselection.DomainSelectionController;
-import com.android.internal.telephony.domainselection.NormalCallDomainSelectionConnection;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.concurrent.CompletableFuture;
@@ -58,6 +59,7 @@
public class NormalCallDomainSelectionConnectionTest extends TelephonyTest {
private static final String TELECOM_CALL_ID1 = "TC1";
+ private static final int TEST_PHONE_ID = 111;
@Mock
private DomainSelectionController mMockDomainSelectionController;
@@ -66,7 +68,7 @@
@Mock
private AccessNetworksManager mMockAccessNetworksManager;
- private TransportSelectorCallback mTransportCallback;
+ private ITransportSelectorCallback mTransportCallback;
private NormalCallDomainSelectionConnection mNormalCallDomainSelectionConnection;
@Before
@@ -74,8 +76,12 @@
super.setUp(this.getClass().getSimpleName());
MockitoAnnotations.initMocks(this);
doReturn(mMockAccessNetworksManager).when(mPhone).getAccessNetworksManager();
+ doReturn(TEST_PHONE_ID).when(mPhone).getPhoneId();
+ doReturn(true).when(mMockDomainSelectionController).selectDomain(any(), any());
mNormalCallDomainSelectionConnection =
new NormalCallDomainSelectionConnection(mPhone, mMockDomainSelectionController);
+ replaceInstance(DomainSelectionConnection.class, "mLooper",
+ mNormalCallDomainSelectionConnection, mTestableLooper.getLooper());
mTransportCallback = mNormalCallDomainSelectionConnection.getTransportSelectorCallback();
}
@@ -99,7 +105,8 @@
assertNotNull(future);
assertFalse(future.isDone());
- verify(mMockDomainSelectionController).selectDomain(any(), any());
+ verify(mMockDomainSelectionController).selectDomain(any(),
+ any(ITransportSelectorCallback.class));
mTransportCallback.onWlanSelected(false);
@@ -121,9 +128,10 @@
assertNotNull(future);
assertFalse(future.isDone());
- verify(mMockDomainSelectionController).selectDomain(any(), any());
+ verify(mMockDomainSelectionController).selectDomain(any(),
+ any(ITransportSelectorCallback.class));
- WwanSelectorCallback wwanCallback = mTransportCallback.onWwanSelected();
+ IWwanSelectorCallback wwanCallback = onWwanSelected(mTransportCallback);
assertFalse(future.isDone());
wwanCallback.onDomainSelected(DOMAIN_CS, false);
@@ -146,9 +154,10 @@
assertNotNull(future);
assertFalse(future.isDone());
- verify(mMockDomainSelectionController).selectDomain(any(), any());
+ verify(mMockDomainSelectionController).selectDomain(any(),
+ any(ITransportSelectorCallback.class));
- WwanSelectorCallback wwanCallback = mTransportCallback.onWwanSelected();
+ IWwanSelectorCallback wwanCallback = onWwanSelected(mTransportCallback);
assertFalse(future.isDone());
wwanCallback.onDomainSelected(DOMAIN_PS, false);
@@ -189,4 +198,38 @@
assertEquals(10, attributes.getCsDisconnectCause());
assertEquals(imsReasonInfo, attributes.getPsDisconnectCause());
}
+
+ @Test
+ public void testGetSetMethods() throws Exception {
+ ImsReasonInfo imsReasonInfo = new ImsReasonInfo();
+ DomainSelectionService.SelectionAttributes attributes =
+ NormalCallDomainSelectionConnection.getSelectionAttributes(1, 2,
+ TELECOM_CALL_ID1, "123", false, 0, imsReasonInfo);
+
+ mNormalCallDomainSelectionConnection
+ .createNormalConnection(attributes, mMockConnectionCallback);
+
+ mNormalCallDomainSelectionConnection.setDisconnectCause(100, 101,
+ "Test disconnect cause");
+ assertEquals(100, mNormalCallDomainSelectionConnection.getDisconnectCause());
+ assertEquals(101, mNormalCallDomainSelectionConnection.getPreciseDisconnectCause());
+ assertEquals("Test disconnect cause",
+ mNormalCallDomainSelectionConnection.getReasonMessage());
+ assertEquals(imsReasonInfo, mNormalCallDomainSelectionConnection.getImsReasonInfo());
+ assertEquals(TEST_PHONE_ID, mNormalCallDomainSelectionConnection.getPhoneId());
+ }
+
+ private IWwanSelectorCallback onWwanSelected(ITransportSelectorCallback transportCallback)
+ throws Exception {
+ ITransportSelectorResultCallback cb = Mockito.mock(ITransportSelectorResultCallback.class);
+ transportCallback.onWwanSelectedAsync(cb);
+ processAllMessages();
+
+ ArgumentCaptor<IWwanSelectorCallback> callbackCaptor =
+ ArgumentCaptor.forClass(IWwanSelectorCallback.class);
+
+ verify(cb).onCompleted(callbackCaptor.capture());
+
+ return callbackCaptor.getValue();
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/domainselection/SmsDomainSelectionConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/domainselection/SmsDomainSelectionConnectionTest.java
index e4afa79..05291e2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/domainselection/SmsDomainSelectionConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/domainselection/SmsDomainSelectionConnectionTest.java
@@ -22,20 +22,21 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
import android.os.Handler;
import android.os.HandlerThread;
import android.telephony.DisconnectCause;
import android.telephony.DomainSelectionService;
-import android.telephony.DomainSelector;
import android.telephony.NetworkRegistrationInfo;
-import android.telephony.TransportSelectorCallback;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.telephony.IDomainSelector;
+import com.android.internal.telephony.ITransportSelectorCallback;
import com.android.internal.telephony.Phone;
import org.junit.After;
@@ -58,7 +59,7 @@
@Mock private Phone mPhone;
@Mock private DomainSelectionController mDsController;
@Mock private DomainSelectionConnection.DomainSelectionConnectionCallback mDscCallback;
- @Mock private DomainSelector mDomainSelector;
+ @Mock private IDomainSelector mDomainSelector;
private Handler mHandler;
private TestableLooper mTestableLooper;
@@ -69,6 +70,8 @@
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ doReturn(true).when(mDsController).selectDomain(any(), any());
+
HandlerThread handlerThread = new HandlerThread(
SmsDomainSelectionConnectionTest.class.getSimpleName());
handlerThread.start();
@@ -107,7 +110,7 @@
mDsConnection.requestDomainSelection(mDsAttr, mDscCallback);
assertNotNull(future);
- verify(mDsController).selectDomain(eq(mDsAttr), any(TransportSelectorCallback.class));
+ verify(mDsController).selectDomain(eq(mDsAttr), any(ITransportSelectorCallback.class));
}
@Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
index fff1b68..7704218 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
@@ -23,6 +23,7 @@
import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_CALLBACK;
import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_WLAN;
import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_WWAN;
+import static com.android.internal.telephony.emergency.EmergencyStateTracker.DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -52,17 +53,20 @@
import android.os.Message;
import android.os.UserHandle;
import android.provider.Settings;
+import android.telephony.AccessNetworkConstants;
import android.telephony.CarrierConfigManager;
import android.telephony.DisconnectCause;
import android.telephony.EmergencyRegResult;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.Call;
import com.android.internal.telephony.GsmCdmaPhone;
import com.android.internal.telephony.Phone;
@@ -150,6 +154,13 @@
false /* isRadioOn */);
setConfigForDdsSwitch(testPhone, null,
CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY, "150");
+ ServiceState ss = mock(ServiceState.class);
+ doReturn(ss).when(mSST).getServiceState();
+ NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .build();
+ doReturn(nri).when(ss).getNetworkRegistrationInfo(anyInt(), anyInt());
// Spy is used to capture consumer in delayDialForDdsSwitch
EmergencyStateTracker spyEst = spy(emergencyStateTracker);
CompletableFuture<Integer> unused = spyEst.startEmergencyCall(testPhone, TEST_CALL_ID,
@@ -159,13 +170,77 @@
ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor
.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone),
- eq(false), eq(0));
- // isOkToCall() should return true once radio is on
+ eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS));
+ // isOkToCall() should return true when IN_SERVICE state
assertFalse(callback.getValue()
.isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
when(mSST.isRadioOn()).thenReturn(true);
- assertTrue(callback.getValue()
+ assertFalse(callback.getValue()
.isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
+
+ nri = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .setRegistrationState(REGISTRATION_STATE_HOME)
+ .build();
+ doReturn(nri).when(ss).getNetworkRegistrationInfo(anyInt(), anyInt());
+
+ assertTrue(callback.getValue()
+ .isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, false));
+ // Once radio on is complete, trigger delay dial
+ callback.getValue().onComplete(null, true);
+ ArgumentCaptor<Consumer<Boolean>> completeConsumer = ArgumentCaptor
+ .forClass(Consumer.class);
+ verify(spyEst).switchDdsDelayed(eq(testPhone), completeConsumer.capture());
+ verify(mPhoneSwitcher).overrideDefaultDataForEmergency(eq(testPhone.getPhoneId()),
+ eq(150) /* extensionTime */, any());
+ // After dds switch completes successfully, set emergency mode
+ completeConsumer.getValue().accept(true);
+ verify(testPhone).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any());
+ }
+
+ /**
+ * Test that the EmergencyStateTracker turns on radio, performs a DDS switch and sets emergency
+ * mode switch when we are not roaming and the carrier only supports SUPL over the data plane.
+ */
+ @Test
+ @SmallTest
+ public void startEmergencyCall_radioOff_turnOnRadioTimeoutSwitchDdsAndSetEmergencyMode() {
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ true /* isSuplDdsSwitchRequiredForEmergencyCall */);
+ // Create test Phones and set radio off
+ Phone testPhone = setupTestPhoneForEmergencyCall(false /* isRoaming */,
+ false /* isRadioOn */);
+ setConfigForDdsSwitch(testPhone, null,
+ CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY, "150");
+ ServiceState ss = mock(ServiceState.class);
+ doReturn(ss).when(mSST).getServiceState();
+ NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .build();
+ doReturn(nri).when(ss).getNetworkRegistrationInfo(anyInt(), anyInt());
+ // Spy is used to capture consumer in delayDialForDdsSwitch
+ EmergencyStateTracker spyEst = spy(emergencyStateTracker);
+ CompletableFuture<Integer> unused = spyEst.startEmergencyCall(testPhone, TEST_CALL_ID,
+ false);
+
+ // startEmergencyCall should trigger radio on
+ ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor
+ .forClass(RadioOnStateListener.Callback.class);
+ verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone),
+ eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS));
+ // onTimeout should return true when radion on
+ assertFalse(callback.getValue()
+ .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
+ assertFalse(callback.getValue()
+ .onTimeout(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
+ when(mSST.isRadioOn()).thenReturn(true);
+
+ assertFalse(callback.getValue()
+ .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
+ assertTrue(callback.getValue()
+ .onTimeout(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
// Once radio on is complete, trigger delay dial
callback.getValue().onComplete(null, true);
ArgumentCaptor<Consumer<Boolean>> completeConsumer = ArgumentCaptor
@@ -198,7 +273,7 @@
ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor
.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone),
- eq(false), eq(0));
+ eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS));
// Verify future completes with DisconnectCause.POWER_OFF if radio not ready
CompletableFuture<Void> unused = future.thenAccept((result) -> {
assertEquals((Integer) result, (Integer) DisconnectCause.POWER_OFF);
@@ -1956,6 +2031,168 @@
assertFalse(testEst.isEmergencyCallbackModeSupported());
}
+ /**
+ * Test that new emergency call is dialed while in emergency callback mode and completes.
+ */
+ @Test
+ @SmallTest
+ public void exitEmergencyCallbackMode_NewEmergencyCallDialedAndCompletes() {
+ // Setup EmergencyStateTracker
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+ // Create test Phone
+ GsmCdmaPhone testPhone = (GsmCdmaPhone) setupTestPhoneForEmergencyCall(
+ /* isRoaming= */ true, /* isRadioOn= */ true);
+ setUpAsyncResultForSetEmergencyMode(testPhone, E_REG_RESULT);
+ setUpAsyncResultForExitEmergencyMode(testPhone);
+ // Start emergency call then enter ECM
+ CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(testPhone,
+ TEST_CALL_ID, false);
+ processAllMessages();
+
+ // Set call to ACTIVE
+ emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, TEST_CALL_ID);
+ emergencyStateTracker.onEmergencyCallDomainUpdated(
+ PhoneConstants.PHONE_TYPE_IMS, TEST_CALL_ID);
+ // Set ecm as supported
+ setEcmSupportedConfig(testPhone, /* ecmSupported= */ true);
+ // End call to enter ECM
+ emergencyStateTracker.endCall(TEST_CALL_ID);
+ processAllMessages();
+
+ // verify ecbm states are correct
+ assertTrue(emergencyStateTracker.isInEcm());
+ assertTrue(emergencyStateTracker.isInImsEcm());
+ assertFalse(emergencyStateTracker.isInCdmaEcm());
+
+ // 2nd call while in emergency callback mode
+ unused = emergencyStateTracker.startEmergencyCall(testPhone,
+ TEST_CALL_ID, false);
+ emergencyStateTracker.onEmergencyTransportChanged(
+ EmergencyStateTracker.EMERGENCY_TYPE_CALL, MODE_EMERGENCY_WWAN);
+ processAllMessages();
+ processAllFutureMessages();
+
+ // verify ecbm states are not changed.
+ assertTrue(emergencyStateTracker.isInEcm());
+ assertTrue(emergencyStateTracker.isInImsEcm());
+ assertFalse(emergencyStateTracker.isInCdmaEcm());
+
+ // Verify exitEmergencyMode() is not called.
+ verify(testPhone, never()).exitEmergencyMode(any(Message.class));
+
+ // Verify ECBM timer cancel.
+ verify(testPhone).notifyEcbmTimerReset(eq(Boolean.TRUE));
+
+ // Set call to ACTIVE
+ emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, TEST_CALL_ID);
+ emergencyStateTracker.onEmergencyCallDomainUpdated(
+ PhoneConstants.PHONE_TYPE_IMS, TEST_CALL_ID);
+ // End call to enter ECM
+ emergencyStateTracker.endCall(TEST_CALL_ID);
+ processAllMessages();
+
+ // verify ecbm states are correct
+ assertTrue(emergencyStateTracker.isInEcm());
+ assertTrue(emergencyStateTracker.isInImsEcm());
+ assertFalse(emergencyStateTracker.isInCdmaEcm());
+
+ // Verify ECBM timer reset.
+ verify(testPhone).notifyEcbmTimerReset(eq(Boolean.FALSE));
+
+ // Verify exitEmergencyMode() is not called.
+ verify(testPhone, never()).exitEmergencyMode(any(Message.class));
+
+ processAllFutureMessages();
+
+ // Ensure ECBM states are all correctly false after we exit.
+ assertFalse(emergencyStateTracker.isInEcm());
+ assertFalse(emergencyStateTracker.isInImsEcm());
+ assertFalse(emergencyStateTracker.isInCdmaEcm());
+
+ // Verify exitEmergencyMode() is called.
+ verify(testPhone).exitEmergencyMode(any(Message.class));
+ }
+
+ /**
+ * Test that new emergency call is dialed while in emergency callback mode and it fails.
+ */
+ @Test
+ @SmallTest
+ public void exitEmergencyCallbackMode_NewEmergencyCallDialedAndFails() {
+ // Setup EmergencyStateTracker
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+ // Create test Phone
+ GsmCdmaPhone testPhone = (GsmCdmaPhone) setupTestPhoneForEmergencyCall(
+ /* isRoaming= */ true, /* isRadioOn= */ true);
+ setUpAsyncResultForSetEmergencyMode(testPhone, E_REG_RESULT);
+ setUpAsyncResultForExitEmergencyMode(testPhone);
+ // Start emergency call then enter ECM
+ CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(testPhone,
+ TEST_CALL_ID, false);
+ processAllMessages();
+
+ // Set call to ACTIVE
+ emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, TEST_CALL_ID);
+ emergencyStateTracker.onEmergencyCallDomainUpdated(
+ PhoneConstants.PHONE_TYPE_IMS, TEST_CALL_ID);
+ // Set ecm as supported
+ setEcmSupportedConfig(testPhone, /* ecmSupported= */ true);
+ // End call to enter ECM
+ emergencyStateTracker.endCall(TEST_CALL_ID);
+ processAllMessages();
+
+ // verify ecbm states are correct
+ assertTrue(emergencyStateTracker.isInEcm());
+ assertTrue(emergencyStateTracker.isInImsEcm());
+ assertFalse(emergencyStateTracker.isInCdmaEcm());
+
+ // 2nd call while in emergency callback mode
+ unused = emergencyStateTracker.startEmergencyCall(testPhone,
+ TEST_CALL_ID, false);
+ emergencyStateTracker.onEmergencyTransportChanged(
+ EmergencyStateTracker.EMERGENCY_TYPE_CALL, MODE_EMERGENCY_WWAN);
+ processAllMessages();
+ processAllFutureMessages();
+
+ // verify ecbm states are not changed.
+ assertTrue(emergencyStateTracker.isInEcm());
+ assertTrue(emergencyStateTracker.isInImsEcm());
+ assertFalse(emergencyStateTracker.isInCdmaEcm());
+
+ // Verify exitEmergencyMode() is not called.
+ verify(testPhone, never()).exitEmergencyMode(any(Message.class));
+
+ // Verify ECBM timer cancel.
+ verify(testPhone).notifyEcbmTimerReset(eq(Boolean.TRUE));
+
+ // End call to return to ECM
+ emergencyStateTracker.endCall(TEST_CALL_ID);
+ processAllMessages();
+
+ // verify ecbm states are correct
+ assertTrue(emergencyStateTracker.isInEcm());
+ assertTrue(emergencyStateTracker.isInImsEcm());
+ assertFalse(emergencyStateTracker.isInCdmaEcm());
+
+ // Verify ECBM timer reset.
+ verify(testPhone).notifyEcbmTimerReset(eq(Boolean.FALSE));
+
+ // Verify exitEmergencyMode() is not called.
+ verify(testPhone, never()).exitEmergencyMode(any(Message.class));
+
+ processAllFutureMessages();
+
+ // Ensure ECBM states are all correctly false after we exit.
+ assertFalse(emergencyStateTracker.isInEcm());
+ assertFalse(emergencyStateTracker.isInImsEcm());
+ assertFalse(emergencyStateTracker.isInCdmaEcm());
+
+ // Verify exitEmergencyMode() is called.
+ verify(testPhone).exitEmergencyMode(any(Message.class));
+ }
+
private EmergencyStateTracker setupEmergencyStateTracker(
boolean isSuplDdsSwitchRequiredForEmergencyCall) {
doReturn(mPhoneSwitcher).when(mPhoneSwitcherProxy).getPhoneSwitcher();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/emergency/RadioOnStateListenerTest.java b/tests/telephonytests/src/com/android/internal/telephony/emergency/RadioOnStateListenerTest.java
index 2c5a873..5a6fdc2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/RadioOnStateListenerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/RadioOnStateListenerTest.java
@@ -90,7 +90,7 @@
waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
verify(mMockPhone).unregisterForServiceStateChanged(any(Handler.class));
- verify(mSatelliteController).unregisterForSatelliteModemStateChanged(anyInt(), any());
+ verify(mSatelliteController).unregisterForModemStateChanged(anyInt(), any());
verify(mMockPhone).registerForServiceStateChanged(any(Handler.class),
eq(RadioOnStateListener.MSG_SERVICE_STATE_CHANGED), isNull());
verify(mSatelliteController, never()).registerForSatelliteModemStateChanged(
@@ -110,7 +110,7 @@
waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
- verify(mSatelliteController).unregisterForSatelliteModemStateChanged(anyInt(), any());
+ verify(mSatelliteController).unregisterForModemStateChanged(anyInt(), any());
verify(mSatelliteController).registerForSatelliteModemStateChanged(anyInt(), any());
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccCardControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccCardControllerTest.java
index 242c9f8..11d3f14 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccCardControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccCardControllerTest.java
@@ -146,8 +146,8 @@
@Test
public void testIsEmbeddedSlotActivated() {
- mEuiccCardController =
- new EuiccCardController(mContext, null, mEuiccController, mUiccController);
+ mEuiccCardController = new EuiccCardController(mContext, null, mEuiccController,
+ mUiccController, mFeatureFlags);
when(mUiccController.getUiccSlots())
.thenReturn(new UiccSlot[] {mActivatedRemovableSlot});
assertFalse(mEuiccCardController.isEmbeddedSlotActivated());
@@ -173,8 +173,8 @@
@Test
public void testIsEmbeddedCardPresent() {
- mEuiccCardController =
- new EuiccCardController(mContext, null, mEuiccController, mUiccController);
+ mEuiccCardController = new EuiccCardController(mContext, null, mEuiccController,
+ mUiccController, mFeatureFlags);
when(mUiccController.getUiccSlots())
.thenReturn(new UiccSlot[] {mActivatedRemovableSlot});
assertFalse(mEuiccCardController.isEmbeddedCardPresent());
@@ -204,8 +204,8 @@
mSp.edit().remove(KEY_LAST_BOOT_COUNT);
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 0);
when(mUiccController.getUiccSlots()).thenReturn(new UiccSlot[] {mActivatedEsimSlot});
- mEuiccCardController =
- new EuiccCardController(mContext, null, mEuiccController, mUiccController);
+ mEuiccCardController = new EuiccCardController(mContext, null, mEuiccController,
+ mUiccController, mFeatureFlags);
mContext.sendBroadcast(new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
processAllMessages();
@@ -218,8 +218,8 @@
mSp.edit().remove(KEY_LAST_BOOT_COUNT);
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 0);
when(mUiccController.getUiccSlots()).thenReturn(new UiccSlot[] {mNotPresentEsimSlot});
- mEuiccCardController =
- new EuiccCardController(mContext, null, mEuiccController, mUiccController);
+ mEuiccCardController = new EuiccCardController(mContext, null, mEuiccController,
+ mUiccController, mFeatureFlags);
mContext.sendBroadcast(new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
processAllMessages();
@@ -232,8 +232,8 @@
mSp.edit().putInt(KEY_LAST_BOOT_COUNT, 1).apply();
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 1);
when(mUiccController.getUiccSlots()).thenReturn(new UiccSlot[] {mActivatedEsimSlot});
- mEuiccCardController =
- new EuiccCardController(mContext, null, mEuiccController, mUiccController);
+ mEuiccCardController = new EuiccCardController(mContext, null, mEuiccController,
+ mUiccController, mFeatureFlags);
mContext.sendBroadcast(new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
processAllMessages();
@@ -247,8 +247,8 @@
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 0);
when(mUiccController.getUiccSlots())
.thenReturn(new UiccSlot[] {mActivatedRemovableSlot, mInactivatedEsimSlot});
- mEuiccCardController =
- new EuiccCardController(mContext, null, mEuiccController, mUiccController);
+ mEuiccCardController = new EuiccCardController(mContext, null, mEuiccController,
+ mUiccController, mFeatureFlags);
mContext.sendBroadcast(new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
processAllMessages();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
index fc8dfbf..a493247 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
@@ -23,6 +23,7 @@
import static org.junit.Assert.assertFalse;
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.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -70,6 +71,7 @@
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.euicc.EuiccConnector.GetOtaStatusCommandCallback;
import com.android.internal.telephony.euicc.EuiccConnector.OtaStatusChangedCallback;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.uicc.UiccSlot;
import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
@@ -156,8 +158,8 @@
// Number of OTA status changed.
private int mNumOtaStatusChanged;
- TestEuiccController(Context context, EuiccConnector connector) {
- super(context, connector);
+ TestEuiccController(Context context, EuiccConnector connector, FeatureFlags featureFlags) {
+ super(context, connector, featureFlags);
mNumOtaStatusChanged = 0;
}
@@ -196,7 +198,7 @@
super.setUp(getClass().getSimpleName());
mMockConnector = Mockito.mock(EuiccConnector.class);
mUiccSlot = Mockito.mock(UiccSlot.class);
- mController = new TestEuiccController(mContext, mMockConnector);
+ mController = new TestEuiccController(mContext, mMockConnector, mFeatureFlags);
PackageInfo pi = new PackageInfo();
pi.packageName = PACKAGE_NAME;
@@ -1295,6 +1297,30 @@
}
@Test
+ @EnableCompatChanges({EuiccManager.INACTIVE_PORT_AVAILABILITY_CHECK,
+ TelephonyManager.ENABLE_FEATURE_MAPPING})
+ public void testIsSimPortAvailable_WithTelephonyFeatureMapping() {
+ // Feature flag enabled, device has required telephony feature.
+ doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
+ doReturn(true).when(mPackageManager).hasSystemFeature(
+ eq(PackageManager.FEATURE_TELEPHONY_EUICC));
+
+ setUiccCardInfos(false, true, true);
+
+ // assert non euicc card id
+ assertFalse(mController.isSimPortAvailable(REMOVABLE_CARD_ID, 0, TEST_PACKAGE_NAME));
+
+ // assert invalid port index
+ assertFalse(mController.isSimPortAvailable(CARD_ID, 5 /* portIndex */, TEST_PACKAGE_NAME));
+
+ // Device does not have required telephony feature.
+ doReturn(false).when(mPackageManager).hasSystemFeature(
+ eq(PackageManager.FEATURE_TELEPHONY_EUICC));
+ assertThrows(UnsupportedOperationException.class,
+ () -> mController.isSimPortAvailable(REMOVABLE_CARD_ID, 0, TEST_PACKAGE_NAME));
+ }
+
+ @Test
@EnableCompatChanges({EuiccManager.INACTIVE_PORT_AVAILABILITY_CHECK})
public void testIsSimPortAvailable_invalidCase() {
setUiccCardInfos(false, true, true);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimServiceTableTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimServiceTableTest.java
index a2965c6..f128f65 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimServiceTableTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimServiceTableTest.java
@@ -17,7 +17,8 @@
package com.android.internal.telephony.gsm;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.uicc.UsimServiceTable;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsCallProfileTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsCallProfileTest.java
index 48148ba..66a18b0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsCallProfileTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsCallProfileTest.java
@@ -27,8 +27,8 @@
import android.os.Parcelable;
import android.telecom.DisconnectCause;
import android.telephony.ims.ImsCallProfile;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsEnablementTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsEnablementTrackerTest.java
index c6f45d9..270960c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsEnablementTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsEnablementTrackerTest.java
@@ -33,8 +33,8 @@
import android.os.Looper;
import android.os.RemoteException;
import android.telephony.ims.aidl.IImsServiceController;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
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 abc231a..7e65048 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
@@ -52,13 +52,14 @@
import android.telephony.ims.ImsService;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.stub.ImsFeatureConfiguration;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.SparseIntArray;
+import androidx.test.filters.SmallTest;
+
import com.android.ims.ImsFeatureBinderRepository;
import com.android.internal.telephony.PhoneConfigurationManager;
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 4a3ceaa..2544fc1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerCompatTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerCompatTest.java
@@ -38,9 +38,9 @@
import android.os.RemoteException;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.stub.ImsFeatureConfiguration;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.SparseIntArray;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.ims.ImsFeatureBinderRepository;
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 adfc4a3..0b6aa9f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
@@ -48,9 +48,9 @@
import android.telephony.ims.aidl.IImsServiceController;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.stub.ImsFeatureConfiguration;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.SparseIntArray;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.ims.ImsFeatureBinderRepository;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsCallTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsCallTest.java
index b869c9b..47e780e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsCallTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsCallTest.java
@@ -36,7 +36,8 @@
import android.telephony.ims.ImsCallProfile;
import android.telephony.ims.ImsCallSession;
import android.telephony.ims.ImsStreamMediaProfile;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.ims.ImsCall;
import com.android.internal.telephony.TelephonyTest;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsNrSaModeHandlerTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsNrSaModeHandlerTest.java
index 7d6557d..3b362b1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsNrSaModeHandlerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsNrSaModeHandlerTest.java
@@ -41,6 +41,9 @@
import android.util.ArraySet;
import com.android.internal.telephony.Call;
+import com.android.internal.telephony.GsmCdmaPhone;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyTest;
import org.junit.After;
@@ -66,6 +69,8 @@
private CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener;
private Handler mPreciseCallStateHandler;
+ private Phone mPassthroughPhone;
+
@Mock private ImsPhoneCall mForegroundCall;
@Mock private ImsPhoneCall mBackgroundCall;
private Call.State mActiveState = ImsPhoneCall.State.ACTIVE;
@@ -90,7 +95,13 @@
doReturn(mAnyInt).when(mImsPhone).getSubId();
doReturn(mContextFixture.getCarrierConfigBundle()).when(mCarrierConfigManager)
.getConfigForSubId(anyInt(), any());
- doReturn(mPhone).when(mImsPhone).getDefaultPhone();
+
+ mPassthroughPhone = new GsmCdmaPhone(
+ mContext, mSimulatedCommands, mNotifier, true, 0,
+ PhoneConstants.PHONE_TYPE_GSM, mTelephonyComponentFactory,
+ (c, p) -> mImsManager, mFeatureFlags);
+
+ doReturn(mPassthroughPhone).when(mImsPhone).getDefaultPhone();
doReturn(mForegroundCall).when(mImsPhone).getForegroundCall();
doReturn(mBackgroundCall).when(mImsPhone).getBackgroundCall();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTest.java
index c4bb864..f0ae0f1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTest.java
@@ -31,9 +31,9 @@
import android.telephony.ims.ImsCallProfile;
import android.telephony.ims.ImsCallSession;
import android.telephony.ims.ImsStreamMediaProfile;
-import android.test.suitebuilder.annotation.SmallTest;
import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
import com.android.ims.ImsCall;
import com.android.ims.ImsException;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
index bfa702c..79b1ada 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
@@ -102,12 +102,12 @@
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.FlakyTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
import com.android.ims.FeatureConnector;
import com.android.ims.ImsCall;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneConnectionTest.java
index 396466c..6c4493b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneConnectionTest.java
@@ -46,11 +46,12 @@
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsCallProfile;
import android.telephony.ims.ImsStreamMediaProfile;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
+
import com.android.ims.ImsCall;
import com.android.ims.ImsException;
import com.android.internal.telephony.Call;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneFactoryTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneFactoryTest.java
index 21d79a9..6937469 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneFactoryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneFactoryTest.java
@@ -24,7 +24,8 @@
import static org.mockito.Mockito.verify;
import android.os.HandlerThread;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.PhoneNotifier;
import com.android.internal.telephony.TelephonyTest;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
index a833da0..3c1b045 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
@@ -29,10 +29,11 @@
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.ServiceState;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.flags.FeatureFlags;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
index f491041..6496efb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
@@ -22,10 +22,10 @@
import static android.telephony.CarrierConfigManager.USSD_OVER_IMS_ONLY;
import static android.telephony.CarrierConfigManager.USSD_OVER_IMS_PREFERRED;
import static android.telephony.ims.RegistrationManager.SUGGESTED_ACTION_NONE;
+import static android.telephony.ims.RegistrationManager.SUGGESTED_ACTION_TRIGGER_CLEAR_RAT_BLOCKS;
import static android.telephony.ims.RegistrationManager.SUGGESTED_ACTION_TRIGGER_PLMN_BLOCK;
import static android.telephony.ims.RegistrationManager.SUGGESTED_ACTION_TRIGGER_PLMN_BLOCK_WITH_TIMEOUT;
import static android.telephony.ims.RegistrationManager.SUGGESTED_ACTION_TRIGGER_RAT_BLOCK;
-import static android.telephony.ims.RegistrationManager.SUGGESTED_ACTION_TRIGGER_CLEAR_RAT_BLOCK;
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_3G;
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN;
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_LTE;
@@ -63,6 +63,7 @@
import android.app.Activity;
import android.content.BroadcastReceiver;
+import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
@@ -82,11 +83,11 @@
import android.telephony.ims.RegistrationManager;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.telephony.ims.stub.ImsUtImplBase;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
import com.android.ims.ImsEcbmStateListener;
import com.android.ims.ImsUtInterface;
@@ -819,6 +820,37 @@
}
@Test
+ @SmallTest
+ public void testSetWfcModeInRoaming() throws Exception {
+ doReturn(true).when(mFeatureFlags).updateRoamingStateToSetWfcMode();
+ doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState();
+ doReturn(true).when(mPhone).isRadioOn();
+
+ // Set CarrierConfigManager to be invalid
+ doReturn(null).when(mContext).getSystemService(Context.CARRIER_CONFIG_SERVICE);
+
+ //Roaming - data registration only on LTE
+ Message m = getServiceStateChangedMessage(getServiceStateDataOnly(
+ ServiceState.RIL_RADIO_TECHNOLOGY_LTE, ServiceState.STATE_IN_SERVICE, true));
+ // Inject the message synchronously instead of waiting for the thread to do it.
+ mImsPhoneUT.handleMessage(m);
+ m.recycle();
+
+ verify(mImsManager, never()).setWfcMode(anyInt(), eq(true));
+
+ // Set CarrierConfigManager to be valid
+ doReturn(mCarrierConfigManager).when(mContext)
+ .getSystemService(Context.CARRIER_CONFIG_SERVICE);
+
+ m = getServiceStateChangedMessage(getServiceStateDataOnly(
+ ServiceState.RIL_RADIO_TECHNOLOGY_LTE, ServiceState.STATE_IN_SERVICE, true));
+ mImsPhoneUT.handleMessage(m);
+ m.recycle();
+
+ verify(mImsManager, times(1)).setWfcMode(anyInt(), eq(true));
+ }
+
+ @Test
public void testNonNullTrackersInImsPhone() throws Exception {
assertNotNull(mImsPhoneUT.getEmergencyNumberTracker());
assertNotNull(mImsPhoneUT.getServiceStateTracker());
@@ -1531,13 +1563,13 @@
// unregistered with rat block clear
registrationCallback.onUnregistered(reasonInfo,
- SUGGESTED_ACTION_TRIGGER_CLEAR_RAT_BLOCK,
+ SUGGESTED_ACTION_TRIGGER_CLEAR_RAT_BLOCKS,
REGISTRATION_TECH_LTE);
regInfo = mSimulatedCommands.getImsRegistrationInfo();
assertTrue(regInfo[0] == RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED
&& regInfo[1] == REGISTRATION_TECH_LTE
- && regInfo[2] == SUGGESTED_ACTION_TRIGGER_CLEAR_RAT_BLOCK);
+ && regInfo[2] == SUGGESTED_ACTION_TRIGGER_CLEAR_RAT_BLOCKS);
// reset the registration info saved in the SimulatedCommands
mSimulatedCommands.updateImsRegistrationInfo(0, 0, 0, 0, null);
@@ -1547,13 +1579,13 @@
// verfies that duplicated notification with the same suggested action is invoked
registrationCallback.onUnregistered(reasonInfo,
- SUGGESTED_ACTION_TRIGGER_CLEAR_RAT_BLOCK,
+ SUGGESTED_ACTION_TRIGGER_CLEAR_RAT_BLOCKS,
REGISTRATION_TECH_LTE);
regInfo = mSimulatedCommands.getImsRegistrationInfo();
assertTrue(regInfo[0] == RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED
&& regInfo[1] == REGISTRATION_TECH_LTE
- && regInfo[2] == SUGGESTED_ACTION_TRIGGER_CLEAR_RAT_BLOCK);
+ && regInfo[2] == SUGGESTED_ACTION_TRIGGER_CLEAR_RAT_BLOCKS);
}
@Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsRegistrationCallbackHelperTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsRegistrationCallbackHelperTest.java
index 93fbfdc..451c315 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsRegistrationCallbackHelperTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsRegistrationCallbackHelperTest.java
@@ -37,7 +37,8 @@
import android.telephony.ims.RegistrationManager;
import android.telephony.ims.RegistrationManager.RegistrationCallback;
import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.imsphone.ImsRegistrationCallbackHelper.ImsRegistrationUpdate;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/DataCallSessionStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/DataCallSessionStatsTest.java
new file mode 100644
index 0000000..d63dc3c
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/DataCallSessionStatsTest.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.metrics;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.net.NetworkCapabilities;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.telephony.DataFailCause;
+import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
+import android.telephony.data.ApnSetting;
+import android.telephony.data.DataCallResponse;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+public class DataCallSessionStatsTest extends TelephonyTest {
+
+ private DataCallResponse mDefaultImsResponse = buildDataCallResponse("ims", 0);
+ private static class TestableDataCallSessionStats extends DataCallSessionStats {
+ private long mTimeMillis = 0L;
+
+ TestableDataCallSessionStats(Phone phone) {
+ super(phone);
+ }
+
+ @Override
+ protected long getTimeMillis() {
+ return mTimeMillis;
+ }
+
+ private void setTimeMillis(long timeMillis) {
+ mTimeMillis = timeMillis;
+ }
+ }
+
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule =
+ DeviceFlagsValueProvider.createCheckFlagsRule();
+ private TestableDataCallSessionStats mDataCallSessionStats;
+ private NetworkCapabilities mCellularNetworkCapabilities = new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build();
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp(getClass().getSimpleName());
+ when(mServiceState.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ mDataCallSessionStats = new TestableDataCallSessionStats(mPhone);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mDataCallSessionStats = null;
+ super.tearDown();
+ }
+
+ private DataCallResponse buildDataCallResponse(String apn, long retryDurationMillis) {
+ return new DataCallResponse.Builder()
+ .setId(apn.hashCode())
+ .setRetryDurationMillis(retryDurationMillis)
+ .build();
+ }
+
+ @Test
+ @SmallTest
+ public void testSetupDataCallOnCellularIms_success() {
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS);
+ mDataCallSessionStats.onSetupDataCallResponse(
+ mDefaultImsResponse,
+ TelephonyManager.NETWORK_TYPE_LTE,
+ ApnSetting.TYPE_IMS,
+ ApnSetting.PROTOCOL_IP,
+ DataFailCause.NONE);
+
+ mDataCallSessionStats.setTimeMillis(60000L);
+ mDataCallSessionStats.conclude();
+
+ ArgumentCaptor<DataCallSession> callCaptor =
+ ArgumentCaptor.forClass(DataCallSession.class);
+ verify(mPersistAtomsStorage, times(1)).addDataCallSession(
+ callCaptor.capture());
+ DataCallSession stats = callCaptor.getValue();
+
+ assertEquals(ApnSetting.TYPE_IMS, stats.apnTypeBitmask);
+ assertEquals(1, stats.durationMinutes);
+ assertEquals(TelephonyManager.NETWORK_TYPE_LTE, stats.ratAtEnd);
+ assertTrue(stats.ongoing);
+ }
+
+ @Test
+ @SmallTest
+ public void testSetupDataCallOnIwlan_success() {
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS);
+ mDataCallSessionStats.onSetupDataCallResponse(
+ mDefaultImsResponse,
+ TelephonyManager.NETWORK_TYPE_IWLAN,
+ ApnSetting.TYPE_IMS,
+ ApnSetting.PROTOCOL_IP,
+ DataFailCause.NONE);
+
+ mDataCallSessionStats.setTimeMillis(120000L);
+ mDataCallSessionStats.conclude();
+
+ ArgumentCaptor<DataCallSession> callCaptor =
+ ArgumentCaptor.forClass(DataCallSession.class);
+ verify(mPersistAtomsStorage, times(1)).addDataCallSession(
+ callCaptor.capture());
+ DataCallSession stats = callCaptor.getValue();
+
+ assertEquals(ApnSetting.TYPE_IMS, stats.apnTypeBitmask);
+ assertEquals(2, stats.durationMinutes);
+ assertEquals(TelephonyManager.NETWORK_TYPE_IWLAN, stats.ratAtEnd);
+ assertFalse(stats.isIwlanCrossSim);
+ assertTrue(stats.ongoing);
+ }
+
+ @Test
+ @SmallTest
+ public void testSetupDataCallOnCrossSimCalling_success() {
+ doReturn(mCellularNetworkCapabilities)
+ .when(mDefaultNetworkMonitor).getNetworkCapabilities();
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS);
+ mDataCallSessionStats.onSetupDataCallResponse(
+ mDefaultImsResponse,
+ TelephonyManager.NETWORK_TYPE_IWLAN,
+ ApnSetting.TYPE_IMS,
+ ApnSetting.PROTOCOL_IP,
+ DataFailCause.NONE);
+
+ mDataCallSessionStats.setTimeMillis(60000L);
+ mDataCallSessionStats.conclude();
+
+ ArgumentCaptor<DataCallSession> callCaptor =
+ ArgumentCaptor.forClass(DataCallSession.class);
+ verify(mPersistAtomsStorage, times(1)).addDataCallSession(
+ callCaptor.capture());
+ DataCallSession stats = callCaptor.getValue();
+
+ assertEquals(ApnSetting.TYPE_IMS, stats.apnTypeBitmask);
+ assertEquals(1, stats.durationMinutes);
+ assertEquals(TelephonyManager.NETWORK_TYPE_IWLAN, stats.ratAtEnd);
+ assertTrue(stats.isIwlanCrossSim);
+ assertTrue(stats.ongoing);
+ }
+
+ @Test
+ @SmallTest
+ public void testSetupDataCallOnCellularIms_failure() {
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS);
+ mDataCallSessionStats.onSetupDataCallResponse(
+ mDefaultImsResponse,
+ TelephonyManager.NETWORK_TYPE_LTE,
+ ApnSetting.TYPE_IMS,
+ ApnSetting.PROTOCOL_IP,
+ DataFailCause.NETWORK_FAILURE);
+
+ ArgumentCaptor<DataCallSession> callCaptor =
+ ArgumentCaptor.forClass(DataCallSession.class);
+ verify(mPersistAtomsStorage, times(1)).addDataCallSession(
+ callCaptor.capture());
+ DataCallSession stats = callCaptor.getValue();
+
+ assertEquals(ApnSetting.TYPE_IMS, stats.apnTypeBitmask);
+ assertEquals(0, stats.durationMinutes);
+ assertEquals(TelephonyManager.NETWORK_TYPE_LTE, stats.ratAtEnd);
+ assertFalse(stats.ongoing);
+ }
+
+ @Test
+ @SmallTest
+ public void testHandoverFromCellularToIwlan_success() {
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS);
+ mDataCallSessionStats.onSetupDataCallResponse(
+ mDefaultImsResponse,
+ TelephonyManager.NETWORK_TYPE_LTE,
+ ApnSetting.TYPE_IMS,
+ ApnSetting.PROTOCOL_IP,
+ DataFailCause.NONE);
+
+ mDataCallSessionStats.onDrsOrRatChanged(TelephonyManager.NETWORK_TYPE_IWLAN);
+ mDataCallSessionStats.conclude();
+
+ ArgumentCaptor<DataCallSession> callCaptor =
+ ArgumentCaptor.forClass(DataCallSession.class);
+ verify(mPersistAtomsStorage, times(1)).addDataCallSession(
+ callCaptor.capture());
+ DataCallSession stats = callCaptor.getValue();
+
+ assertEquals(ApnSetting.TYPE_IMS, stats.apnTypeBitmask);
+ assertEquals(TelephonyManager.NETWORK_TYPE_IWLAN, stats.ratAtEnd);
+ assertEquals(1, stats.ratSwitchCount);
+ assertTrue(stats.ongoing);
+ }
+
+ @Test
+ @SmallTest
+ public void testHandoverFromCellularToCrossSimCalling_success() {
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS);
+ mDataCallSessionStats.onSetupDataCallResponse(
+ mDefaultImsResponse,
+ TelephonyManager.NETWORK_TYPE_LTE,
+ ApnSetting.TYPE_IMS,
+ ApnSetting.PROTOCOL_IP,
+ DataFailCause.NONE);
+
+ doReturn(mCellularNetworkCapabilities)
+ .when(mDefaultNetworkMonitor).getNetworkCapabilities();
+ mDataCallSessionStats.onDrsOrRatChanged(TelephonyManager.NETWORK_TYPE_IWLAN);
+ mDataCallSessionStats.conclude();
+
+ ArgumentCaptor<DataCallSession> callCaptor =
+ ArgumentCaptor.forClass(DataCallSession.class);
+ verify(mPersistAtomsStorage, times(1)).addDataCallSession(
+ callCaptor.capture());
+ DataCallSession stats = callCaptor.getValue();
+
+ assertEquals(ApnSetting.TYPE_IMS, stats.apnTypeBitmask);
+ assertEquals(TelephonyManager.NETWORK_TYPE_IWLAN, stats.ratAtEnd);
+ assertEquals(1, stats.ratSwitchCount);
+ assertTrue(stats.isIwlanCrossSim);
+ assertTrue(stats.ongoing);
+ }
+
+ @Test
+ @SmallTest
+ public void testHandoverFromCellularToIwlan_failure() {
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS);
+ mDataCallSessionStats.onSetupDataCallResponse(
+ mDefaultImsResponse,
+ TelephonyManager.NETWORK_TYPE_LTE,
+ ApnSetting.TYPE_IMS,
+ ApnSetting.PROTOCOL_IP,
+ DataFailCause.NONE);
+
+ mDataCallSessionStats.onHandoverFailure(DataFailCause.IWLAN_DNS_RESOLUTION_TIMEOUT,
+ TelephonyManager.NETWORK_TYPE_LTE, TelephonyManager.NETWORK_TYPE_IWLAN);
+ mDataCallSessionStats.conclude();
+
+ ArgumentCaptor<DataCallSession> callCaptor =
+ ArgumentCaptor.forClass(DataCallSession.class);
+ verify(mPersistAtomsStorage, times(1)).addDataCallSession(
+ callCaptor.capture());
+ DataCallSession stats = callCaptor.getValue();
+
+ assertEquals(ApnSetting.TYPE_IMS, stats.apnTypeBitmask);
+ assertEquals(TelephonyManager.NETWORK_TYPE_LTE, stats.ratAtEnd);
+ assertTrue(stats.ongoing);
+ assertEquals(DataFailCause.IWLAN_DNS_RESOLUTION_TIMEOUT,
+ stats.handoverFailureCauses[0]);
+
+ int cellularToIwlanFailureDirection = TelephonyManager.NETWORK_TYPE_LTE
+ | (TelephonyManager.NETWORK_TYPE_IWLAN << 16);
+ assertEquals(cellularToIwlanFailureDirection, stats.handoverFailureRat[0]);
+ }
+
+ @Test
+ @SmallTest
+ public void testSetupDataCallOnIwlan_success_thenOOS() {
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS);
+ mDataCallSessionStats.onSetupDataCallResponse(
+ mDefaultImsResponse,
+ TelephonyManager.NETWORK_TYPE_IWLAN,
+ ApnSetting.TYPE_IMS,
+ ApnSetting.PROTOCOL_IP,
+ DataFailCause.NONE);
+ when(mServiceState.getDataRegistrationState())
+ .thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ mDataCallSessionStats.onDataCallDisconnected(DataFailCause.IWLAN_IKE_DPD_TIMEOUT);
+
+ ArgumentCaptor<DataCallSession> callCaptor =
+ ArgumentCaptor.forClass(DataCallSession.class);
+ verify(mPersistAtomsStorage, times(1)).addDataCallSession(
+ callCaptor.capture());
+ DataCallSession stats = callCaptor.getValue();
+
+ assertEquals(ApnSetting.TYPE_IMS, stats.apnTypeBitmask);
+ assertEquals(TelephonyManager.NETWORK_TYPE_IWLAN, stats.ratAtEnd);
+ assertTrue(stats.oosAtEnd);
+ assertFalse(stats.ongoing);
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/ImsStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/ImsStatsTest.java
index df8bd85..f831c98 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/ImsStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/ImsStatsTest.java
@@ -45,7 +45,8 @@
import android.telephony.ims.ProvisioningManager;
import android.telephony.ims.feature.MmTelFeature.MmTelCapabilities;
import android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyTest;
@@ -197,6 +198,7 @@
assertEquals(2000L, stats.utAvailableMillis);
assertEquals(2000L, stats.smsCapableMillis);
assertEquals(2000L, stats.smsAvailableMillis);
+ assertEquals(1, stats.registeredTimes);
verifyNoMoreInteractions(mPersistAtomsStorage);
}
@@ -291,6 +293,7 @@
assertEquals(0L, stats.utAvailableMillis);
assertEquals(0L, stats.smsCapableMillis);
assertEquals(0L, stats.smsAvailableMillis);
+ assertEquals(1, stats.registeredTimes);
verifyNoMoreInteractions(mPersistAtomsStorage);
}
@@ -320,6 +323,7 @@
assertEquals(2000L, stats.registeredMillis);
assertEquals(2000L, stats.voiceCapableMillis);
assertEquals(2000L, stats.voiceAvailableMillis);
+ assertEquals(1, stats.registeredTimes);
verifyNoMoreInteractions(mPersistAtomsStorage);
}
@@ -373,6 +377,7 @@
assertEquals(0, stats.simSlotIndex);
assertEquals(TelephonyManager.NETWORK_TYPE_LTE, stats.rat);
assertEquals(2000L, stats.unregisteredMillis);
+ assertEquals(0, stats.registeredTimes);
verifyNoMoreInteractions(mPersistAtomsStorage);
}
@@ -413,6 +418,7 @@
assertEquals(0, stats.simSlotIndex);
assertEquals(TelephonyManager.NETWORK_TYPE_IWLAN, stats.rat);
assertEquals(2000L, stats.registeringMillis);
+ assertEquals(0, stats.registeredTimes);
verifyNoMoreInteractions(mPersistAtomsStorage);
}
@@ -563,6 +569,7 @@
assertEquals(0L, stats.utAvailableMillis);
assertEquals(0L, stats.smsCapableMillis);
assertEquals(0L, stats.smsAvailableMillis);
+ assertEquals(1, stats.registeredTimes);
verifyNoMoreInteractions(mPersistAtomsStorage);
// ServiceStateStats should be notified
verify(mServiceStateStats).onImsVoiceRegistrationChanged();
@@ -602,6 +609,7 @@
assertEquals(0L, stats.utAvailableMillis);
assertEquals(0L, stats.smsCapableMillis);
assertEquals(0L, stats.smsAvailableMillis);
+ assertEquals(1, stats.registeredTimes);
verifyNoMoreInteractions(mPersistAtomsStorage);
// ServiceStateStats should be notified
verify(mServiceStateStats, times(2)).onImsVoiceRegistrationChanged();
@@ -641,6 +649,7 @@
assertEquals(0L, stats.utAvailableMillis);
assertEquals(2000L, stats.smsCapableMillis);
assertEquals(2000L, stats.smsAvailableMillis);
+ assertEquals(1, stats.registeredTimes);
verifyNoMoreInteractions(mPersistAtomsStorage);
// ServiceStateStats should not be notified
verify(mServiceStateStats, never()).onImsVoiceRegistrationChanged();
@@ -678,6 +687,7 @@
assertEquals(0L, stats.utAvailableMillis);
assertEquals(0L, stats.smsCapableMillis);
assertEquals(0L, stats.smsAvailableMillis);
+ assertEquals(1, stats.registeredTimes);
verifyNoMoreInteractions(mPersistAtomsStorage);
}
@@ -708,6 +718,7 @@
assertEquals(0L, statsLte.utAvailableMillis);
assertEquals(0L, statsLte.smsCapableMillis);
assertEquals(0L, statsLte.smsAvailableMillis);
+ assertEquals(1, statsLte.registeredTimes);
ImsRegistrationStats statsWifi = captor.getAllValues().get(1);
assertEquals(CARRIER1_ID, statsWifi.carrierId);
assertEquals(0, statsWifi.simSlotIndex);
@@ -721,6 +732,7 @@
assertEquals(0L, statsWifi.utAvailableMillis);
assertEquals(0L, statsWifi.smsCapableMillis);
assertEquals(0L, statsWifi.smsAvailableMillis);
+ assertEquals(0, statsWifi.registeredTimes);
verifyNoMoreInteractions(mPersistAtomsStorage);
}
@@ -741,6 +753,7 @@
assertEquals(TelephonyManager.NETWORK_TYPE_LTE, stats.rat);
assertEquals(0L, stats.registeredMillis);
assertEquals(2000L, stats.registeringMillis);
+ assertEquals(1, stats.registeredTimes);
}
@Test
@@ -777,6 +790,7 @@
assertEquals(0, stats.simSlotIndex);
assertEquals(TelephonyManager.NETWORK_TYPE_LTE, stats.rat);
assertEquals(2000L, stats.unregisteredMillis);
+ assertEquals(0, stats.registeredTimes);
verifyNoMoreInteractions(mPersistAtomsStorage);
}
@@ -859,6 +873,7 @@
assertEquals(0L, stats.utAvailableMillis);
assertEquals(0L, stats.smsCapableMillis);
assertEquals(0L, stats.smsAvailableMillis);
+ assertEquals(1, stats.registeredTimes);
ArgumentCaptor<ImsRegistrationTermination> terminationCaptor =
ArgumentCaptor.forClass(ImsRegistrationTermination.class);
verify(mPersistAtomsStorage).addImsRegistrationTermination(terminationCaptor.capture());
@@ -1085,6 +1100,7 @@
assertEquals(0L, stats.utAvailableMillis);
assertEquals(0L, stats.smsCapableMillis);
assertEquals(0L, stats.smsAvailableMillis);
+ assertEquals(1, stats.registeredTimes);
ArgumentCaptor<ImsRegistrationTermination> terminationCaptor =
ArgumentCaptor.forClass(ImsRegistrationTermination.class);
verify(mPersistAtomsStorage).addImsRegistrationTermination(terminationCaptor.capture());
@@ -1119,6 +1135,7 @@
assertEquals(TelephonyManager.NETWORK_TYPE_IWLAN, stats.rat);
assertEquals(true, stats.isIwlanCrossSim);
assertEquals(2000L, stats.registeredMillis);
+ assertEquals(1, stats.registeredTimes);
ArgumentCaptor<ImsRegistrationTermination> terminationCaptor =
ArgumentCaptor.forClass(ImsRegistrationTermination.class);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/InProgressCallSessionTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/InProgressCallSessionTest.java
index 116293c..3ad2d18 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/InProgressCallSessionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/InProgressCallSessionTest.java
@@ -20,7 +20,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.nano.TelephonyProto;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/InProgressSmsSessionTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/InProgressSmsSessionTest.java
index a8ac50a..4f52513 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/InProgressSmsSessionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/InProgressSmsSessionTest.java
@@ -20,7 +20,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.nano.TelephonyProto;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java
index 0e1135e..0426737 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java
@@ -37,12 +37,14 @@
import android.app.StatsManager;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.StatsEvent;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch;
import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingShortCodeSms;
@@ -96,6 +98,7 @@
private UiccPort mActivePort;
private ServiceStateStats mServiceStateStats;
private VonrHelper mVonrHelper;
+ private FeatureFlags mFeatureFlags;
private MetricsCollector mMetricsCollector;
@@ -109,9 +112,10 @@
mActivePort = mock(UiccPort.class);
mServiceStateStats = mock(ServiceStateStats.class);
mVonrHelper = mock(VonrHelper.class);
+ mFeatureFlags = mock(FeatureFlags.class);
mMetricsCollector =
new MetricsCollector(mContext, mPersistAtomsStorage,
- mDeviceStateHelper, mVonrHelper);
+ mDeviceStateHelper, mVonrHelper, mFeatureFlags);
doReturn(mSST).when(mSecondPhone).getServiceStateTracker();
doReturn(mServiceStateStats).when(mSST).getServiceStateStats();
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/PerSimStatusTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/PerSimStatusTest.java
index e03dfe4..5ca73e5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/PerSimStatusTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/PerSimStatusTest.java
@@ -38,7 +38,8 @@
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsMmTelManager;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.Phone;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
index 0cbb0f6..c992f4d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
@@ -55,7 +55,8 @@
import android.telephony.TelephonyProtoEnums;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.SipDelegateManager;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.TelephonyStatsLog;
import com.android.internal.telephony.TelephonyTest;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/RcsStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/RcsStatsTest.java
index 3a941e3..d417214 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/RcsStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/RcsStatsTest.java
@@ -30,10 +30,11 @@
import android.telephony.ims.DelegateRegistrationState;
import android.telephony.ims.FeatureTagState;
import android.telephony.ims.SipDelegateManager;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
import android.util.Log;
+import androidx.test.filters.SmallTest;
+
import com.android.ims.rcs.uce.util.FeatureTags;
import com.android.internal.telephony.TelephonyStatsLog;
import com.android.internal.telephony.TelephonyTest;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/ServiceStateStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/ServiceStateStatsTest.java
index c66cfa7..16dab44 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/ServiceStateStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/ServiceStateStatsTest.java
@@ -45,7 +45,8 @@
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyTest;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/SimSlotStateTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/SimSlotStateTest.java
index c5c672c..4ab85f1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/SimSlotStateTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/SimSlotStateTest.java
@@ -23,7 +23,7 @@
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.uicc.IccCardStatus.CardState;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java
index c26dd22..71b975a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java
@@ -46,9 +46,10 @@
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.Base64;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CarrierResolver;
import com.android.internal.telephony.GsmCdmaConnection;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
index 1498eb4..58cc516 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
@@ -58,7 +58,8 @@
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ImsStreamMediaProfile;
import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.DriverCall;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/VonrHelperTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/VonrHelperTest.java
index 04cd925..ddc29de 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/VonrHelperTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/VonrHelperTest.java
@@ -21,7 +21,8 @@
import static org.mockito.Mockito.doReturn;
import android.annotation.NonNull;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.flags.FeatureFlags;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java
index 0944c6c..f8827be 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java
@@ -76,7 +76,7 @@
replaceInstance(SatelliteController.class, "sInstance", null,
mMockSatelliteController);
doReturn(Arrays.asList(SATELLITE_PLMN_ARRAY))
- .when(mMockSatelliteController).getSatellitePlmnList(anyInt());
+ .when(mMockSatelliteController).getSatellitePlmnsForCarrier(anyInt());
doReturn(mSatelliteSupportedServiceList).when(mMockSatelliteController)
.getSupportedSatelliteServices(SUB_ID, SATELLITE_PLMN);
}
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 55532cc..f7483d9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -34,6 +34,7 @@
import static android.telephony.satellite.SatelliteManager.NT_RADIO_TECHNOLOGY_NB_IOT_NTN;
import static android.telephony.satellite.SatelliteManager.NT_RADIO_TECHNOLOGY_NR_NTN;
import static android.telephony.satellite.SatelliteManager.NT_RADIO_TECHNOLOGY_PROPRIETARY;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT;
import static android.telephony.satellite.SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION;
import static android.telephony.satellite.SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
@@ -94,15 +95,14 @@
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.ResultReceiver;
-import android.os.ServiceSpecificException;
import android.telephony.CarrierConfigManager;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.satellite.INtnSignalStrengthCallback;
import android.telephony.satellite.ISatelliteCapabilitiesCallback;
import android.telephony.satellite.ISatelliteDatagramCallback;
+import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.ISatelliteProvisionStateCallback;
-import android.telephony.satellite.ISatelliteStateCallback;
import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.SatelliteCapabilities;
@@ -112,6 +112,8 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.Pair;
+import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import com.android.internal.R;
import com.android.internal.telephony.IIntegerConsumer;
@@ -212,6 +214,7 @@
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
mQueriedSatelliteCapabilitiesResultCode = resultCode;
+ logd("mSatelliteCapabilitiesReceiver: resultCode=" + resultCode);
if (resultCode == SATELLITE_RESULT_SUCCESS) {
if (resultData.containsKey(KEY_SATELLITE_CAPABILITIES)) {
mQueriedSatelliteCapabilities = resultData.getParcelable(
@@ -221,13 +224,13 @@
mQueriedSatelliteCapabilities = null;
}
} else {
- logd("mSatelliteSupportReceiver: resultCode=" + resultCode);
mQueriedSatelliteCapabilities = null;
}
try {
mSatelliteCapabilitiesSemaphore.release();
} catch (Exception ex) {
- loge("mSatelliteSupportReceiver: Got exception in releasing semaphore, ex=" + ex);
+ loge("mSatelliteCapabilitiesReceiver: Got exception in releasing semaphore, ex="
+ + ex);
}
}
};
@@ -239,6 +242,7 @@
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
mQueriedSatelliteSupportedResultCode = resultCode;
+ logd("mSatelliteSupportReceiver: resultCode=" + resultCode);
if (resultCode == SATELLITE_RESULT_SUCCESS) {
if (resultData.containsKey(KEY_SATELLITE_SUPPORTED)) {
mQueriedSatelliteSupported = resultData.getBoolean(KEY_SATELLITE_SUPPORTED);
@@ -247,7 +251,6 @@
mQueriedSatelliteSupported = false;
}
} else {
- logd("mSatelliteSupportReceiver: resultCode=" + resultCode);
mQueriedSatelliteSupported = false;
}
try {
@@ -279,7 +282,7 @@
try {
mIsSatelliteEnabledSemaphore.release();
} catch (Exception ex) {
- loge("mIsSatelliteEnableReceiver: Got exception in releasing semaphore, ex=" + ex);
+ loge("mIsSatelliteEnabledReceiver: Got exception in releasing semaphore, ex=" + ex);
}
}
};
@@ -291,6 +294,7 @@
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
mQueriedIsDemoModeEnabledResultCode = resultCode;
+ logd("mIsDemoModeEnabledReceiver: resultCode=" + resultCode);
if (resultCode == SATELLITE_RESULT_SUCCESS) {
if (resultData.containsKey(KEY_DEMO_MODE_ENABLED)) {
mQueriedIsDemoModeEnabled = resultData.getBoolean(KEY_DEMO_MODE_ENABLED);
@@ -299,7 +303,6 @@
mQueriedIsDemoModeEnabled = false;
}
} else {
- logd("mIsSatelliteEnableReceiver: resultCode=" + resultCode);
mQueriedIsDemoModeEnabled = false;
}
try {
@@ -317,6 +320,7 @@
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
mQueriedIsSatelliteProvisionedResultCode = resultCode;
+ logd("mIsSatelliteProvisionedReceiver: resultCode=" + resultCode);
if (resultCode == SATELLITE_RESULT_SUCCESS) {
if (resultData.containsKey(KEY_SATELLITE_PROVISIONED)) {
mQueriedIsSatelliteProvisioned =
@@ -344,6 +348,7 @@
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
mQueriedSatelliteAllowedResultCode = resultCode;
+ logd("mSatelliteAllowedReceiver: resultCode=" + resultCode);
if (resultCode == SATELLITE_RESULT_SUCCESS) {
if (resultData.containsKey(KEY_SATELLITE_COMMUNICATION_ALLOWED)) {
mQueriedSatelliteAllowed = resultData.getBoolean(
@@ -353,7 +358,6 @@
mQueriedSatelliteAllowed = false;
}
} else {
- logd("mSatelliteAllowedReceiver: resultCode=" + resultCode);
mQueriedSatelliteAllowed = false;
}
try {
@@ -372,6 +376,7 @@
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
mQueriedSatelliteVisibilityTimeResultCode = resultCode;
+ logd("mSatelliteVisibilityTimeReceiver: resultCode=" + resultCode);
if (resultCode == SATELLITE_RESULT_SUCCESS) {
if (resultData.containsKey(KEY_SATELLITE_NEXT_VISIBILITY)) {
mQueriedSatelliteVisibilityTime = resultData.getInt(
@@ -381,13 +386,13 @@
mQueriedSatelliteVisibilityTime = -1;
}
} else {
- logd("mSatelliteSupportReceiver: resultCode=" + resultCode);
mQueriedSatelliteVisibilityTime = -1;
}
try {
mSatelliteVisibilityTimeSemaphore.release();
} catch (Exception ex) {
- loge("mSatelliteAllowedReceiver: Got exception in releasing semaphore, ex=" + ex);
+ loge("mSatelliteVisibilityTimeReceiver: Got exception in releasing semaphore, ex="
+ + ex);
}
}
};
@@ -400,6 +405,7 @@
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
mQueriedNtnSignalStrengthResultCode = resultCode;
+ logd("KEY_NTN_SIGNAL_STRENGTH: resultCode=" + resultCode);
if (resultCode == SATELLITE_RESULT_SUCCESS) {
if (resultData.containsKey(KEY_NTN_SIGNAL_STRENGTH)) {
NtnSignalStrength result = resultData.getParcelable(KEY_NTN_SIGNAL_STRENGTH);
@@ -410,7 +416,6 @@
mQueriedNtnSignalStrengthLevel = NTN_SIGNAL_STRENGTH_NONE;
}
} else {
- logd("KEY_NTN_SIGNAL_STRENGTH: resultCode=" + resultCode);
mQueriedNtnSignalStrengthLevel = NTN_SIGNAL_STRENGTH_NONE;
}
try {
@@ -619,10 +624,7 @@
mQueriedSatelliteVisibilityTimeResultCode);
resetSatelliteControllerUT();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ provisionSatelliteService();
setUpResponseForRequestTimeForNextSatelliteVisibility(mSatelliteNextVisibilityTime,
SATELLITE_RESULT_SUCCESS);
mSatelliteControllerUT.requestTimeForNextSatelliteVisibility(SUB_ID,
@@ -633,10 +635,7 @@
assertEquals(mSatelliteNextVisibilityTime, mQueriedSatelliteVisibilityTime);
resetSatelliteControllerUT();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ provisionSatelliteService();
setUpNullResponseForRequestTimeForNextSatelliteVisibility(
SATELLITE_RESULT_SUCCESS);
mSatelliteControllerUT.requestTimeForNextSatelliteVisibility(SUB_ID,
@@ -647,10 +646,7 @@
mQueriedSatelliteVisibilityTimeResultCode);
resetSatelliteControllerUT();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ provisionSatelliteService();
setUpNullResponseForRequestTimeForNextSatelliteVisibility(
SATELLITE_RESULT_INVALID_MODEM_STATE);
mSatelliteControllerUT.requestTimeForNextSatelliteVisibility(SUB_ID,
@@ -662,6 +658,55 @@
}
@Test
+ public void testRadioStateChanged() {
+ mIsSatelliteEnabledSemaphore.drainPermits();
+
+ when(mMockSatelliteModemInterface.isSatelliteServiceConnected()).thenReturn(false);
+ setRadioPower(false);
+ processAllMessages();
+ verify(mMockSatelliteModemInterface, never())
+ .requestIsSatelliteSupported(any(Message.class));
+
+ setRadioPower(true);
+ processAllMessages();
+ verify(mMockSatelliteModemInterface, never())
+ .requestIsSatelliteSupported(any(Message.class));
+
+ when(mMockSatelliteModemInterface.isSatelliteServiceConnected()).thenReturn(true);
+ setRadioPower(false);
+ processAllMessages();
+ verify(mMockSatelliteModemInterface, times(1))
+ .requestIsSatelliteSupported(any(Message.class));
+
+ setRadioPower(true);
+ processAllMessages();
+ verify(mMockSatelliteModemInterface, times(2))
+ .requestIsSatelliteSupported(any(Message.class));
+
+ setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
+ setRadioPower(false);
+ processAllMessages();
+ verify(mMockSatelliteModemInterface, times(3))
+ .requestIsSatelliteSupported(any(Message.class));
+
+ setRadioPower(true);
+ processAllMessages();
+ verify(mMockSatelliteModemInterface, times(4))
+ .requestIsSatelliteSupported(any(Message.class));
+
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ setRadioPower(false);
+ processAllMessages();
+ verify(mMockSatelliteModemInterface, times(5))
+ .requestIsSatelliteSupported(any(Message.class));
+
+ setRadioPower(true);
+ processAllMessages();
+ verify(mMockSatelliteModemInterface, times(5))
+ .requestIsSatelliteSupported(any(Message.class));
+ }
+
+ @Test
public void testRequestSatelliteEnabled() {
mIsSatelliteEnabledSemaphore.drainPermits();
@@ -717,7 +762,6 @@
verify(mMockSatelliteSessionController, times(1)).onSatelliteEnabledStateChanged(eq(true));
verify(mMockSatelliteSessionController, times(2)).setDemoMode(eq(false));
verify(mMockDatagramController, times(2)).setDemoMode(eq(false));
- verify(mMockPointingAppController).startPointingUI(eq(false));
verify(mMockControllerMetricsStats, times(1)).onSatelliteEnabled();
verify(mMockControllerMetricsStats, times(1)).reportServiceEnablementSuccessCount();
@@ -776,7 +820,6 @@
verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
assertEquals(SATELLITE_MODE_ENABLED_TRUE, mSatelliteControllerUT.satelliteModeSettingValue);
- verify(mMockPointingAppController).startPointingUI(eq(false));
verify(mMockSatelliteSessionController, times(2)).onSatelliteEnabledStateChanged(eq(true));
verify(mMockSatelliteSessionController, times(4)).setDemoMode(eq(false));
verify(mMockDatagramController, times(4)).setDemoMode(eq(false));
@@ -1009,11 +1052,8 @@
(long) mIIntegerConsumerResults.get(0));
resetSatelliteControllerUT();
+ provisionSatelliteService();
mIIntegerConsumerResults.clear();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForStartSatelliteTransmissionUpdates(SATELLITE_RESULT_SUCCESS);
mSatelliteControllerUT.startSatelliteTransmissionUpdates(SUB_ID, mIIntegerConsumer,
mStartTransmissionUpdateCallback);
@@ -1026,11 +1066,8 @@
verify(mMockPointingAppController).setStartedSatelliteTransmissionUpdates(eq(true));
resetSatelliteControllerUT();
+ provisionSatelliteService();
mIIntegerConsumerResults.clear();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForStartSatelliteTransmissionUpdates(SATELLITE_RESULT_INVALID_TELEPHONY_STATE);
mSatelliteControllerUT.startSatelliteTransmissionUpdates(SUB_ID, mIIntegerConsumer,
mStartTransmissionUpdateCallback);
@@ -1090,10 +1127,7 @@
resetSatelliteControllerUT();
mIIntegerConsumerResults.clear();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ provisionSatelliteService();
setUpResponseForStopSatelliteTransmissionUpdates(SATELLITE_RESULT_SUCCESS);
mSatelliteControllerUT.stopSatelliteTransmissionUpdates(SUB_ID, mIIntegerConsumer,
mStopTransmissionUpdateCallback);
@@ -1105,11 +1139,8 @@
verify(mMockPointingAppController).stopSatelliteTransmissionUpdates(any(Message.class));
resetSatelliteControllerUT();
+ provisionSatelliteService();
mIIntegerConsumerResults.clear();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForStopSatelliteTransmissionUpdates(SATELLITE_RESULT_INVALID_TELEPHONY_STATE);
mSatelliteControllerUT.stopSatelliteTransmissionUpdates(SUB_ID, mIIntegerConsumer,
mStopTransmissionUpdateCallback);
@@ -1156,10 +1187,7 @@
resetSatelliteControllerUT();
boolean isDemoModeEnabled = mSatelliteControllerUT.isDemoModeEnabled();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ provisionSatelliteService();
mSatelliteControllerUT.requestIsDemoModeEnabled(SUB_ID, mIsDemoModeEnabledReceiver);
assertTrue(waitForRequestIsDemoModeEnabledResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedIsDemoModeEnabledResultCode);
@@ -1168,12 +1196,21 @@
@Test
public void testIsSatelliteEnabled() {
- assertFalse(mSatelliteControllerUT.isSatelliteEnabled());
setUpResponseForRequestIsSatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+ assertFalse(mSatelliteControllerUT.isSatelliteEnabled());
mIsSatelliteEnabledSemaphore.drainPermits();
mSatelliteControllerUT.requestIsSatelliteEnabled(SUB_ID, mIsSatelliteEnabledReceiver);
processAllMessages();
assertTrue(waitForRequestIsSatelliteEnabledResult(1));
+ assertEquals(
+ SATELLITE_RESULT_INVALID_TELEPHONY_STATE, mQueriedIsSatelliteEnabledResultCode);
+
+
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestIsSatelliteEnabled(SUB_ID, mIsSatelliteEnabledReceiver);
+ processAllMessages();
+ assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedIsSatelliteEnabledResultCode);
assertEquals(mSatelliteControllerUT.isSatelliteEnabled(), mQueriedIsSatelliteEnabled);
}
@@ -1187,17 +1224,18 @@
setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForRequestSatelliteEnabled(false, false, SATELLITE_RESULT_SUCCESS);
+ setUpResponseForRequestIsSatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
mSatelliteControllerUT.onSatelliteServiceConnected();
processAllMessages();
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
}
@Test
public void testRegisterForSatelliteModemStateChanged() {
- ISatelliteStateCallback callback = new ISatelliteStateCallback.Stub() {
+ ISatelliteModemStateCallback callback = new ISatelliteModemStateCallback.Stub() {
@Override
public void onSatelliteModemStateChanged(int state) {
logd("onSatelliteModemStateChanged: state=" + state);
@@ -1219,19 +1257,19 @@
@Test
public void testUnregisterForSatelliteModemStateChanged() {
- ISatelliteStateCallback callback = new ISatelliteStateCallback.Stub() {
+ ISatelliteModemStateCallback callback = new ISatelliteModemStateCallback.Stub() {
@Override
public void onSatelliteModemStateChanged(int state) {
logd("onSatelliteModemStateChanged: state=" + state);
}
};
- mSatelliteControllerUT.unregisterForSatelliteModemStateChanged(SUB_ID, callback);
+ mSatelliteControllerUT.unregisterForModemStateChanged(SUB_ID, callback);
verify(mMockSatelliteSessionController, never())
.unregisterForSatelliteModemStateChanged(callback);
resetSatelliteControllerUTToSupportedAndProvisionedState();
- mSatelliteControllerUT.unregisterForSatelliteModemStateChanged(SUB_ID, callback);
+ mSatelliteControllerUT.unregisterForModemStateChanged(SUB_ID, callback);
verify(mMockSatelliteSessionController).unregisterForSatelliteModemStateChanged(callback);
}
@@ -1293,7 +1331,7 @@
};
when(mMockDatagramController.registerForSatelliteDatagram(eq(SUB_ID), eq(callback)))
.thenReturn(SATELLITE_RESULT_SUCCESS);
- int errorCode = mSatelliteControllerUT.registerForSatelliteDatagram(SUB_ID, callback);
+ int errorCode = mSatelliteControllerUT.registerForIncomingDatagram(SUB_ID, callback);
assertEquals(SATELLITE_RESULT_SUCCESS, errorCode);
verify(mMockDatagramController).registerForSatelliteDatagram(eq(SUB_ID), eq(callback));
}
@@ -1311,7 +1349,7 @@
};
doNothing().when(mMockDatagramController)
.unregisterForSatelliteDatagram(eq(SUB_ID), eq(callback));
- mSatelliteControllerUT.unregisterForSatelliteDatagram(SUB_ID, callback);
+ mSatelliteControllerUT.unregisterForIncomingDatagram(SUB_ID, callback);
verify(mMockDatagramController).unregisterForSatelliteDatagram(eq(SUB_ID), eq(callback));
}
@@ -1321,7 +1359,7 @@
SatelliteDatagram datagram = new SatelliteDatagram(mText.getBytes());
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.sendSatelliteDatagram(SUB_ID,
+ mSatelliteControllerUT.sendDatagram(SUB_ID,
SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE, datagram, true, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -1337,7 +1375,7 @@
sendProvisionedStateChangedEvent(false, null);
processAllMessages();
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.sendSatelliteDatagram(SUB_ID,
+ mSatelliteControllerUT.sendDatagram(SUB_ID,
SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE, datagram, true, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -1351,7 +1389,7 @@
sendProvisionedStateChangedEvent(true, null);
processAllMessages();
verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.sendSatelliteDatagram(SUB_ID,
+ mSatelliteControllerUT.sendDatagram(SUB_ID,
SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE, datagram, true, mIIntegerConsumer);
processAllMessages();
assertFalse(waitForIIntegerConsumerResult(1));
@@ -1364,7 +1402,7 @@
@Test
public void testPollPendingSatelliteDatagrams() {
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.pollPendingSatelliteDatagrams(SUB_ID, mIIntegerConsumer);
+ mSatelliteControllerUT.pollPendingDatagrams(SUB_ID, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
@@ -1377,7 +1415,7 @@
sendProvisionedStateChangedEvent(false, null);
processAllMessages();
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.pollPendingSatelliteDatagrams(SUB_ID, mIIntegerConsumer);
+ mSatelliteControllerUT.pollPendingDatagrams(SUB_ID, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED,
@@ -1388,7 +1426,7 @@
sendProvisionedStateChangedEvent(true, null);
processAllMessages();
verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.pollPendingSatelliteDatagrams(SUB_ID, mIIntegerConsumer);
+ mSatelliteControllerUT.pollPendingDatagrams(SUB_ID, mIIntegerConsumer);
processAllMessages();
assertFalse(waitForIIntegerConsumerResult(1));
verify(mMockDatagramController, times(1)).pollPendingSatelliteDatagrams(anyInt(), any());
@@ -1425,20 +1463,6 @@
resetSatelliteControllerUT();
mIIntegerConsumerResults.clear();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- cancelRemote = mSatelliteControllerUT.provisionSatelliteService(SUB_ID,
- TEST_SATELLITE_TOKEN,
- testProvisionData, mIIntegerConsumer);
- processAllMessages();
- assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
- assertNull(cancelRemote);
-
- resetSatelliteControllerUT();
- mIIntegerConsumerResults.clear();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForRequestIsSatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
@@ -1451,6 +1475,47 @@
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
assertNotNull(cancelRemote);
+ verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+
+ // Send provision request again after the device is successfully provisioned
+ cancelRemote = mSatelliteControllerUT.provisionSatelliteService(SUB_ID,
+ TEST_SATELLITE_TOKEN,
+ testProvisionData, mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ assertNull(cancelRemote);
+
+ // Vendor service does not support the request requestIsSatelliteProvisioned. Telephony will
+ // make decision itself
+ resetSatelliteControllerUT();
+ mIIntegerConsumerResults.clear();
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ setUpResponseForRequestIsSatelliteProvisioned(
+ false, SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+
+ // Vendor service does not support the requests requestIsSatelliteProvisioned and
+ // provisionSatelliteService. Telephony will make decision itself
+ deprovisionSatelliteService();
+ resetSatelliteControllerUT();
+ mIIntegerConsumerResults.clear();
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ setUpResponseForRequestIsSatelliteProvisioned(
+ false, SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
+ setUpResponseForProvisionSatelliteService(TEST_SATELLITE_TOKEN, testProvisionData,
+ SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
+ cancelRemote = mSatelliteControllerUT.provisionSatelliteService(SUB_ID,
+ TEST_SATELLITE_TOKEN,
+ testProvisionData, mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ assertNotNull(cancelRemote);
+ verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
resetSatelliteControllerUT();
mIIntegerConsumerResults.clear();
@@ -1554,24 +1619,32 @@
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
resetSatelliteControllerUT();
+ provisionSatelliteService();
mIIntegerConsumerResults.clear();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForDeprovisionSatelliteService(TEST_SATELLITE_TOKEN, SATELLITE_RESULT_SUCCESS);
mSatelliteControllerUT.deprovisionSatelliteService(SUB_ID,
TEST_SATELLITE_TOKEN, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
+
+ // Vendor service does not support deprovisionSatelliteService
+ resetSatelliteControllerUT();
+ provisionSatelliteService();
+ mIIntegerConsumerResults.clear();
+ setUpResponseForDeprovisionSatelliteService(
+ TEST_SATELLITE_TOKEN, SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
+ mSatelliteControllerUT.deprovisionSatelliteService(SUB_ID,
+ TEST_SATELLITE_TOKEN, mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
resetSatelliteControllerUT();
+ provisionSatelliteService();
mIIntegerConsumerResults.clear();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForDeprovisionSatelliteService(TEST_SATELLITE_TOKEN,
SATELLITE_RESULT_INVALID_MODEM_STATE);
mSatelliteControllerUT.deprovisionSatelliteService(SUB_ID,
@@ -1579,12 +1652,14 @@
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_INVALID_MODEM_STATE, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
}
@Test
public void testSupportedSatelliteServices() {
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
- List<String> satellitePlmnList = mSatelliteControllerUT.getSatellitePlmnList(SUB_ID);
+ List<String> satellitePlmnList = mSatelliteControllerUT.getSatellitePlmnsForCarrier(
+ SUB_ID);
assertEquals(EMPTY_STRING_ARRAY.length, satellitePlmnList.size());
List<Integer> supportedSatelliteServices =
mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00101");
@@ -1607,7 +1682,7 @@
TestSatelliteController testSatelliteController =
new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
- satellitePlmnList = testSatelliteController.getSatellitePlmnList(SUB_ID);
+ satellitePlmnList = testSatelliteController.getSatellitePlmnsForCarrier(SUB_ID);
assertTrue(satellitePlmnList.isEmpty());
supportedSatelliteServices =
testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00101");
@@ -1639,7 +1714,7 @@
}
processAllMessages();
- satellitePlmnList = testSatelliteController.getSatellitePlmnList(SUB_ID);
+ satellitePlmnList = testSatelliteController.getSatellitePlmnsForCarrier(SUB_ID);
assertTrue(Arrays.equals(
expectedSupportedSatellitePlmns, satellitePlmnList.stream().toArray()));
supportedSatelliteServices =
@@ -1666,7 +1741,7 @@
}
processAllMessages();
- satellitePlmnList = testSatelliteController.getSatellitePlmnList(SUB_ID);
+ satellitePlmnList = testSatelliteController.getSatellitePlmnsForCarrier(SUB_ID);
assertTrue(satellitePlmnList.isEmpty());
supportedSatelliteServices =
testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00102");
@@ -1711,7 +1786,8 @@
TestSatelliteController testSatelliteController =
new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
processAllMessages();
- List<String> carrierPlmnList = testSatelliteController.getSatellitePlmnList(SUB_ID);
+ List<String> carrierPlmnList = testSatelliteController.getSatellitePlmnsForCarrier(
+ SUB_ID);
verify(mMockSatelliteModemInterface, never()).setSatellitePlmn(
anyInt(), anyList(), anyList(), any(Message.class));
assertTrue(carrierPlmnList.isEmpty());
@@ -1738,7 +1814,7 @@
);
}
processAllMessages();
- carrierPlmnList = testSatelliteController.getSatellitePlmnList(SUB_ID);
+ carrierPlmnList = testSatelliteController.getSatellitePlmnsForCarrier(SUB_ID);
verify(mMockSatelliteModemInterface, never()).setSatellitePlmn(
anyInt(), anyList(), anyList(), any(Message.class));
assertTrue(carrierPlmnList.isEmpty());
@@ -1764,7 +1840,7 @@
}
processAllMessages();
- carrierPlmnList = testSatelliteController.getSatellitePlmnList(SUB_ID);
+ carrierPlmnList = testSatelliteController.getSatellitePlmnsForCarrier(SUB_ID);
assertTrue(carrierPlmnList.isEmpty());
List<String> allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
carrierPlmnList, satellitePlmnListFromOverlayConfig);
@@ -1784,7 +1860,7 @@
);
}
processAllMessages();
- carrierPlmnList = testSatelliteController.getSatellitePlmnList(SUB_ID);
+ carrierPlmnList = testSatelliteController.getSatellitePlmnsForCarrier(SUB_ID);
allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
carrierPlmnList, satellitePlmnListFromOverlayConfig);
assertEquals(expectedCarrierPlmnList, carrierPlmnList);
@@ -1823,7 +1899,7 @@
);
}
processAllMessages();
- carrierPlmnList = testSatelliteController.getSatellitePlmnList(SUB_ID);
+ carrierPlmnList = testSatelliteController.getSatellitePlmnsForCarrier(SUB_ID);
assertTrue(carrierPlmnList.isEmpty());
verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
eq(EMPTY_STRING_LIST), eq(EMPTY_STRING_LIST), any(Message.class));
@@ -1849,9 +1925,9 @@
setUpResponseForRequestSetSatelliteEnabledForCarrier(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForRequestSetSatelliteEnabledForCarrier(false, SATELLITE_RESULT_SUCCESS);
doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
- mSatelliteControllerUT.removeSatelliteAttachRestrictionForCarrier(SUB_ID,
+ mSatelliteControllerUT.removeAttachRestrictionForCarrier(SUB_ID,
SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, mIIntegerConsumer);
- mSatelliteControllerUT.removeSatelliteAttachRestrictionForCarrier(SUB_ID,
+ mSatelliteControllerUT.removeAttachRestrictionForCarrier(SUB_ID,
SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(2));
@@ -1860,7 +1936,7 @@
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(1));
Set<Integer> restrictionSet =
- mSatelliteControllerUT.getSatelliteAttachRestrictionReasonsForCarrier(SUB_ID);
+ mSatelliteControllerUT.getAttachRestrictionReasonsForCarrier(SUB_ID);
assertTrue(!restrictionSet.contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER));
assertTrue(!restrictionSet.contains(
SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION));
@@ -1870,7 +1946,7 @@
reset(mMockSatelliteModemInterface);
setUpResponseForRequestSetSatelliteEnabledForCarrier(false, SATELLITE_RESULT_SUCCESS);
doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
- mSatelliteControllerUT.addSatelliteAttachRestrictionForCarrier(SUB_ID,
+ mSatelliteControllerUT.addAttachRestrictionForCarrier(SUB_ID,
SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, mIIntegerConsumer);
processAllMessages();
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -1878,7 +1954,7 @@
.requestSetSatelliteEnabledForCarrier(anyInt(), anyBoolean(), any(Message.class));
assertTrue(waitForIIntegerConsumerResult(1));
restrictionSet =
- mSatelliteControllerUT.getSatelliteAttachRestrictionReasonsForCarrier(SUB_ID);
+ mSatelliteControllerUT.getAttachRestrictionReasonsForCarrier(SUB_ID);
assertTrue(restrictionSet.contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER));
// remove satellite restriction reason by user
@@ -1886,13 +1962,13 @@
reset(mMockSatelliteModemInterface);
setUpResponseForRequestSetSatelliteEnabledForCarrier(true, SATELLITE_RESULT_SUCCESS);
doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
- mSatelliteControllerUT.removeSatelliteAttachRestrictionForCarrier(SUB_ID,
+ mSatelliteControllerUT.removeAttachRestrictionForCarrier(SUB_ID,
SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
restrictionSet =
- mSatelliteControllerUT.getSatelliteAttachRestrictionReasonsForCarrier(SUB_ID);
+ mSatelliteControllerUT.getAttachRestrictionReasonsForCarrier(SUB_ID);
assertTrue(!restrictionSet.contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER));
verify(mMockSatelliteModemInterface, times(1))
.requestSetSatelliteEnabledForCarrier(anyInt(), anyBoolean(), any(Message.class));
@@ -1902,13 +1978,13 @@
reset(mMockSatelliteModemInterface);
setUpResponseForRequestSetSatelliteEnabledForCarrier(false, SATELLITE_RESULT_SUCCESS);
doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
- mSatelliteControllerUT.addSatelliteAttachRestrictionForCarrier(SUB_ID,
+ mSatelliteControllerUT.addAttachRestrictionForCarrier(SUB_ID,
SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
restrictionSet =
- mSatelliteControllerUT.getSatelliteAttachRestrictionReasonsForCarrier(SUB_ID);
+ mSatelliteControllerUT.getAttachRestrictionReasonsForCarrier(SUB_ID);
assertTrue(restrictionSet.contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER));
verify(mMockSatelliteModemInterface, times(1))
.requestSetSatelliteEnabledForCarrier(anyInt(), eq(false), any(Message.class));
@@ -1917,14 +1993,14 @@
mIIntegerConsumerResults.clear();
reset(mMockSatelliteModemInterface);
setUpResponseForRequestSetSatelliteEnabledForCarrier(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.addSatelliteAttachRestrictionForCarrier(SUB_ID,
+ mSatelliteControllerUT.addAttachRestrictionForCarrier(SUB_ID,
SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION, mIIntegerConsumer);
doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
restrictionSet =
- mSatelliteControllerUT.getSatelliteAttachRestrictionReasonsForCarrier(SUB_ID);
+ mSatelliteControllerUT.getAttachRestrictionReasonsForCarrier(SUB_ID);
assertTrue(restrictionSet.contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION));
verify(mMockSatelliteModemInterface, never())
.requestSetSatelliteEnabledForCarrier(anyInt(), anyBoolean(), any(Message.class));
@@ -1933,14 +2009,14 @@
mIIntegerConsumerResults.clear();
reset(mMockSatelliteModemInterface);
setUpResponseForRequestSetSatelliteEnabledForCarrier(true, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.removeSatelliteAttachRestrictionForCarrier(SUB_ID,
+ mSatelliteControllerUT.removeAttachRestrictionForCarrier(SUB_ID,
SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION, mIIntegerConsumer);
doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
restrictionSet =
- mSatelliteControllerUT.getSatelliteAttachRestrictionReasonsForCarrier(SUB_ID);
+ mSatelliteControllerUT.getAttachRestrictionReasonsForCarrier(SUB_ID);
assertTrue(!restrictionSet.contains(
SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION));
verify(mMockSatelliteModemInterface, never())
@@ -1950,14 +2026,14 @@
mIIntegerConsumerResults.clear();
reset(mMockSatelliteModemInterface);
setUpResponseForRequestSetSatelliteEnabledForCarrier(true, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.removeSatelliteAttachRestrictionForCarrier(SUB_ID,
+ mSatelliteControllerUT.removeAttachRestrictionForCarrier(SUB_ID,
SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, mIIntegerConsumer);
doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
restrictionSet =
- mSatelliteControllerUT.getSatelliteAttachRestrictionReasonsForCarrier(SUB_ID);
+ mSatelliteControllerUT.getAttachRestrictionReasonsForCarrier(SUB_ID);
assertTrue(!restrictionSet.contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER));
verify(mMockSatelliteModemInterface, times(1))
.requestSetSatelliteEnabledForCarrier(anyInt(), eq(true), any(Message.class));
@@ -1966,7 +2042,7 @@
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.removeSatelliteAttachRestrictionForCarrier(SUB_ID,
+ mSatelliteControllerUT.removeAttachRestrictionForCarrier(SUB_ID,
SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -1975,7 +2051,7 @@
verifyZeroInteractions(mMockSatelliteModemInterface);
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.addSatelliteAttachRestrictionForCarrier(SUB_ID,
+ mSatelliteControllerUT.addAttachRestrictionForCarrier(SUB_ID,
SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -1984,15 +2060,15 @@
verifyZeroInteractions(mMockSatelliteModemInterface);
Set<Integer> satelliteRestrictionReasons =
- mSatelliteControllerUT.getSatelliteAttachRestrictionReasonsForCarrier(SUB_ID);
+ mSatelliteControllerUT.getAttachRestrictionReasonsForCarrier(SUB_ID);
assertTrue(satelliteRestrictionReasons.isEmpty());
}
@Test
public void testIsSatelliteAttachRequired() {
- mSatelliteCapabilitiesSemaphore.drainPermits();
TestSatelliteController satelliteController =
new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
+ mSatelliteCapabilitiesSemaphore.drainPermits();
satelliteController.requestSatelliteCapabilities(SUB_ID, mSatelliteCapabilitiesReceiver);
processAllMessages();
assertTrue(waitForRequestSatelliteCapabilitiesResult(1));
@@ -2002,12 +2078,11 @@
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForRequestSatelliteCapabilities(
- mSatelliteCapabilities, SATELLITE_RESULT_MODEM_ERROR);
+ mEmptySatelliteCapabilities, SATELLITE_RESULT_SUCCESS);
satelliteController =
new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestSatelliteCapabilities(
- mEmptySatelliteCapabilities, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteSupported(satelliteController, true, SATELLITE_RESULT_SUCCESS);
+ mSatelliteCapabilitiesSemaphore.drainPermits();
satelliteController.requestSatelliteCapabilities(SUB_ID, mSatelliteCapabilitiesReceiver);
processAllMessages();
assertTrue(waitForRequestSatelliteCapabilitiesResult(1));
@@ -2020,12 +2095,11 @@
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForRequestSatelliteCapabilities(
- mSatelliteCapabilities, SATELLITE_RESULT_MODEM_ERROR);
+ mSatelliteCapabilities, SATELLITE_RESULT_SUCCESS);
satelliteController =
new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestSatelliteCapabilities(
- mSatelliteCapabilities, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteSupported(satelliteController, true, SATELLITE_RESULT_SUCCESS);
+ mSatelliteCapabilitiesSemaphore.drainPermits();
satelliteController.requestSatelliteCapabilities(SUB_ID, mSatelliteCapabilitiesReceiver);
processAllMessages();
assertTrue(waitForRequestSatelliteCapabilitiesResult(1));
@@ -2082,9 +2156,7 @@
verifyRequestNtnSignalStrength(NTN_SIGNAL_STRENGTH_NONE, SATELLITE_RESULT_NOT_SUPPORTED);
resetSatelliteControllerUT();
- setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ provisionSatelliteService();
doReturn(false).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
setUpResponseForRequestNtnSignalStrength(expectedLevel, SATELLITE_RESULT_SUCCESS);
@@ -2096,8 +2168,7 @@
verifyRequestNtnSignalStrength(expectedLevel, SATELLITE_RESULT_SUCCESS);
resetSatelliteControllerUT();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ provisionSatelliteService();
doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
// reset cache to NTN_SIGNAL_STRENGTH_NONE
sendNtnSignalStrengthChangedEvent(NTN_SIGNAL_STRENGTH_NONE, null);
@@ -2172,10 +2243,8 @@
verifyRequestNtnSignalStrength(expectedLevel, SATELLITE_RESULT_NOT_SUPPORTED);
resetSatelliteControllerUT();
- setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForRequestNtnSignalStrength(expectedLevel, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ provisionSatelliteService();
verifyRegisterForNtnSignalStrengthChanged(SUB_ID, callback,
SATELLITE_RESULT_SUCCESS);
verifyRequestNtnSignalStrength(expectedLevel, SATELLITE_RESULT_SUCCESS);
@@ -2265,10 +2334,7 @@
// startSendingNtnSignalStrength() is requested when screen on event comes.
reset(mMockSatelliteModemInterface);
doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
- setUpResponseForRequestIsSatelliteSupported(true, expectedResult);
- setUpResponseForRequestIsSatelliteProvisioned(true, expectedResult);
- verifySatelliteSupported(true, expectedResult);
- verifySatelliteProvisioned(true, expectedResult);
+ provisionSatelliteService();
setUpResponseForStartSendingNtnSignalStrength(expectedResult);
sendCmdStartSendingNtnSignalStrengthChangedEvent(true);
processAllMessages();
@@ -2462,23 +2528,20 @@
}
};
- int errorCode = mSatelliteControllerUT.registerForSatelliteCapabilitiesChanged(SUB_ID,
+ int errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(SUB_ID,
callback);
assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, errorCode);
setUpResponseForRequestIsSatelliteSupported(false,
SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- errorCode = mSatelliteControllerUT.registerForSatelliteCapabilitiesChanged(SUB_ID,
+ errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(SUB_ID,
callback);
assertEquals(SATELLITE_RESULT_NOT_SUPPORTED, errorCode);
resetSatelliteControllerUT();
- setUpResponseForRequestIsSatelliteProvisioned(true,
- SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- errorCode = mSatelliteControllerUT.registerForSatelliteCapabilitiesChanged(SUB_ID,
+ provisionSatelliteService();
+ errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(SUB_ID,
callback);
assertEquals(SATELLITE_RESULT_SUCCESS, errorCode);
SatelliteCapabilities expectedCapabilities = mSatelliteCapabilities;
@@ -2495,7 +2558,7 @@
semaphore, 1, "testRegisterForSatelliteCapabilitiesChanged"));
assertTrue(expectedCapabilities.equals(satelliteCapabilities[0]));
- mSatelliteControllerUT.unregisterForSatelliteCapabilitiesChanged(SUB_ID, callback);
+ mSatelliteControllerUT.unregisterForCapabilitiesChanged(SUB_ID, callback);
expectedCapabilities = mSatelliteCapabilities;
sendSatelliteCapabilitiesChangedEvent(expectedCapabilities, null);
processAllMessages();
@@ -2524,21 +2587,21 @@
}
};
- int errorCode = mSatelliteControllerUT.registerForSatelliteCapabilitiesChanged(SUB_ID,
+ int errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(SUB_ID,
callback);
assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, errorCode);
setUpResponseForRequestIsSatelliteSupported(false,
SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(false, SATELLITE_RESULT_NOT_SUPPORTED);
- errorCode = mSatelliteControllerUT.registerForSatelliteCapabilitiesChanged(SUB_ID,
+ errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(SUB_ID,
callback);
assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, errorCode);
resetSatelliteControllerUT();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(false, SATELLITE_RESULT_NOT_SUPPORTED);
- errorCode = mSatelliteControllerUT.registerForSatelliteCapabilitiesChanged(SUB_ID,
+ errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(SUB_ID,
callback);
assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, errorCode);
@@ -2549,6 +2612,263 @@
semaphore, 0, "testRegisterForSatelliteCapabilitiesChanged"));
}
+ @Test
+ public void testSatelliteCommunicationRestrictionForEntitlement() throws Exception {
+ logd("testSatelliteCommunicationRestrictionForEntitlement");
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+
+ mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ true);
+ SparseBooleanArray satelliteEnabledPerCarrier = new SparseBooleanArray();
+ replaceInstance(SatelliteController.class, "mSatelliteEntitlementStatusPerCarrier",
+ mSatelliteControllerUT, satelliteEnabledPerCarrier);
+
+ mIIntegerConsumerResults.clear();
+ reset(mMockSatelliteModemInterface);
+ setUpResponseForRequestSetSatelliteEnabledForCarrier(true, SATELLITE_RESULT_SUCCESS);
+ doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+ Map<Integer, Set<Integer>> satelliteAttachRestrictionForCarrierArray = new HashMap<>();
+ satelliteAttachRestrictionForCarrierArray.put(SUB_ID, new HashSet<>());
+ satelliteAttachRestrictionForCarrierArray.get(SUB_ID).add(
+ SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT);
+ replaceInstance(SatelliteController.class, "mSatelliteAttachRestrictionForCarrierArray",
+ mSatelliteControllerUT, satelliteAttachRestrictionForCarrierArray);
+
+ // Verify call the requestSetSatelliteEnabledForCarrier to enable the satellite when
+ // satellite service is enabled by entitlement server.
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, true, new ArrayList<>(),
+ mIIntegerConsumer);
+ processAllMessages();
+
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verify(mMockSatelliteModemInterface, times(1))
+ .requestSetSatelliteEnabledForCarrier(anyInt(), eq(true), any(Message.class));
+
+ // Verify call the requestSetSatelliteEnabledForCarrier to disable the satellite when
+ // satellite service is disabled by entitlement server.
+ mIIntegerConsumerResults.clear();
+ reset(mMockSatelliteModemInterface);
+ Map<Integer, Boolean> enabledForCarrierArrayPerSub = new HashMap<>();
+ enabledForCarrierArrayPerSub.put(SUB_ID, true);
+ replaceInstance(SatelliteController.class, "mIsSatelliteAttachEnabledForCarrierArrayPerSub",
+ mSatelliteControllerUT, enabledForCarrierArrayPerSub);
+ doReturn(mIsSatelliteServiceSupported)
+ .when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+ setUpResponseForRequestSetSatelliteEnabledForCarrier(false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, new ArrayList<>(),
+ mIIntegerConsumer);
+ processAllMessages();
+
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verify(mMockSatelliteModemInterface, times(1))
+ .requestSetSatelliteEnabledForCarrier(anyInt(), eq(false), any(Message.class));
+ }
+
+ @Test
+ public void testPassSatellitePlmnToModemAfterUpdateSatelliteEntitlementStatus()
+ throws Exception {
+ logd("testPassSatellitePlmnToModemAfterUpdateSatelliteEntitlementStatus");
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
+ mSatelliteControllerUT, new SparseArray<>());
+ List<String> overlayConfigPlmnList = new ArrayList<>();
+ replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+ mSatelliteControllerUT, overlayConfigPlmnList);
+
+ // If the PlmnListPerCarrier and the overlay config plmn list are empty verify passing to
+ // the modem.
+ List<String> entitlementPlmnList = new ArrayList<>();
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+ entitlementPlmnList, mIIntegerConsumer);
+
+ List<String> plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(
+ SUB_ID);
+ List<String> allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
+ plmnListPerCarrier, overlayConfigPlmnList);
+
+ assertEquals(new ArrayList<>(), plmnListPerCarrier);
+ assertEquals(new ArrayList<>(), allSatellitePlmnList);
+ verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
+ eq(plmnListPerCarrier), eq(allSatellitePlmnList), any(Message.class));
+
+ // If the PlmnListPerCarrier and the overlay config plmn list are exist verify passing
+ // the modem.
+ entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "00103"}).toList();
+ overlayConfigPlmnList =
+ Arrays.stream(new String[]{"00101", "00102", "00104"}).toList();
+ replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+ mSatelliteControllerUT, overlayConfigPlmnList);
+
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, true,
+ entitlementPlmnList, mIIntegerConsumer);
+
+ plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(SUB_ID);
+ allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
+ plmnListPerCarrier, overlayConfigPlmnList);
+
+ assertEquals(entitlementPlmnList, plmnListPerCarrier);
+ verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
+ eq(plmnListPerCarrier), eq(allSatellitePlmnList), any(Message.class));
+
+ // If the PlmnListPerCarrier and the overlay config plmn list are exist verify passing
+ // the modem.
+ reset(mMockSatelliteModemInterface);
+ entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "00103"}).toList();
+ Map<Integer, Map<String, Set<Integer>>>
+ satelliteServicesSupportedByCarriers = new HashMap<>();
+ List<String> carrierConfigPlmnList = Arrays.stream(new String[]{"00105", "00106"}).toList();
+ Map<String, Set<Integer>> plmnAndService = new HashMap<>();
+ plmnAndService.put(carrierConfigPlmnList.get(0), new HashSet<>(Arrays.asList(3, 5)));
+ plmnAndService.put(carrierConfigPlmnList.get(1), new HashSet<>(Arrays.asList(3)));
+ satelliteServicesSupportedByCarriers.put(SUB_ID, plmnAndService);
+ replaceInstance(SatelliteController.class, "mSatelliteServicesSupportedByCarriers",
+ mSatelliteControllerUT, satelliteServicesSupportedByCarriers);
+ overlayConfigPlmnList = Arrays.stream(new String[]{"00101", "00102", "00104"}).toList();
+ replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+ mSatelliteControllerUT, overlayConfigPlmnList);
+ List<String> mergedPlmnList = entitlementPlmnList;
+
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, true,
+ entitlementPlmnList, mIIntegerConsumer);
+
+ plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(SUB_ID);
+ allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
+ plmnListPerCarrier, overlayConfigPlmnList);
+
+ assertEquals(mergedPlmnList, plmnListPerCarrier);
+ verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
+ eq(plmnListPerCarrier), eq(allSatellitePlmnList), any(Message.class));
+ }
+
+ @Test
+ public void testUpdatePlmnListPerCarrier() throws Exception {
+ logd("testUpdatePlmnListPerCarrier");
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
+ mSatelliteControllerUT, new SparseArray<>());
+ replaceInstance(SatelliteController.class, "mSatelliteServicesSupportedByCarriers",
+ mSatelliteControllerUT, new HashMap<>());
+ SparseArray<List<String>> entitlementPlmnListPerCarrier = new SparseArray<>();
+ replaceInstance(SatelliteController.class, "mEntitlementPlmnListPerCarrier",
+ mSatelliteControllerUT, entitlementPlmnListPerCarrier);
+
+ // If the carrier config and the entitlement plmn list are empty, verify whether an empty
+ // list is returned.
+ mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+ .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+ new PersistableBundle());
+ for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+ : mCarrierConfigChangedListenerList) {
+ pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+ /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+ );
+ }
+ processAllMessages();
+
+ List<String> plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(
+ SUB_ID);
+ assertEquals(new ArrayList<>(), plmnListPerCarrier);
+
+ // If the carrier config list is empty and the entitlement plmn list is exists, verify
+ // whether the entitlement list is returned.
+ entitlementPlmnListPerCarrier.clear();
+ List<String> entitlementPlmnList = Arrays.asList("00101", "00102", "00104");
+ entitlementPlmnListPerCarrier.put(SUB_ID, entitlementPlmnList);
+ List<String> expectedPlmnListPerCarrier = entitlementPlmnList;
+ for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+ : mCarrierConfigChangedListenerList) {
+ pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+ /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+ );
+ }
+ processAllMessages();
+
+ plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(SUB_ID);
+ assertEquals(expectedPlmnListPerCarrier, plmnListPerCarrier);
+
+ // If the carrier config list is exists and the entitlement plmn list is empty, verify
+ // whether the carrier config list is returned.
+ entitlementPlmnListPerCarrier.clear();
+ entitlementPlmnList = new ArrayList<>();
+ entitlementPlmnListPerCarrier.put(SUB_ID, entitlementPlmnList);
+ mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ true);
+ PersistableBundle carrierSupportedSatelliteServicesPerProvider = new PersistableBundle();
+ List<String> carrierConfigPlmnList = Arrays.asList("00102", "00103", "00105");
+ carrierSupportedSatelliteServicesPerProvider.putIntArray(
+ carrierConfigPlmnList.get(0), new int[]{2});
+ carrierSupportedSatelliteServicesPerProvider.putIntArray(
+ carrierConfigPlmnList.get(1), new int[]{1, 3});
+ carrierSupportedSatelliteServicesPerProvider.putIntArray(
+ carrierConfigPlmnList.get(2), new int[]{2});
+ mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+ .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+ carrierSupportedSatelliteServicesPerProvider);
+ for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+ : mCarrierConfigChangedListenerList) {
+ pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+ /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+ );
+ }
+ processAllMessages();
+
+ expectedPlmnListPerCarrier = carrierConfigPlmnList;
+ plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(SUB_ID);
+ assertEquals(expectedPlmnListPerCarrier.stream().sorted().toList(),
+ plmnListPerCarrier.stream().sorted().toList());
+
+
+ // If the carrier config and the entitlement plmn list are exist, verify whether the
+ // entitlement list is returned.
+ entitlementPlmnList = Arrays.asList("00101", "00102", "00104");
+ entitlementPlmnListPerCarrier.put(SUB_ID, entitlementPlmnList);
+ for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+ : mCarrierConfigChangedListenerList) {
+ pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+ /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+ );
+ }
+ processAllMessages();
+
+ expectedPlmnListPerCarrier = entitlementPlmnList;
+ plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(
+ SUB_ID);
+ assertEquals(expectedPlmnListPerCarrier.stream().sorted().toList(),
+ plmnListPerCarrier.stream().sorted().toList());
+ }
+
+ @Test
+ public void testEntitlementStatus() throws Exception {
+ logd("testEntitlementStatus");
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ SparseBooleanArray satelliteEnabledPerCarrier = new SparseBooleanArray();
+ replaceInstance(SatelliteController.class, "mSatelliteEntitlementStatusPerCarrier",
+ mSatelliteControllerUT, satelliteEnabledPerCarrier);
+
+ // Change SUB_ID's EntitlementStatus to true
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, true, new ArrayList<>(),
+ mIIntegerConsumer);
+
+ assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID));
+ assertEquals(false, satelliteEnabledPerCarrier.get(SUB_ID1));
+
+ // Change SUB_ID1's EntitlementStatus to true
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID1, true, new ArrayList<>(),
+ mIIntegerConsumer);
+
+ assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID));
+ assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID1));
+
+ // Change SUB_ID's EntitlementStatus to false
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, new ArrayList<>(),
+ mIIntegerConsumer);
+
+ assertEquals(false, satelliteEnabledPerCarrier.get(SUB_ID));
+ assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID1));
+ }
+
private void resetSatelliteControllerUTEnabledState() {
logd("resetSatelliteControllerUTEnabledState");
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
@@ -2614,7 +2934,8 @@
? null : new SatelliteException(error);
doAnswer(invocation -> {
Message message = (Message) invocation.getArguments()[0];
- AsyncResult.forMessage(message, isSatelliteEnabled, exception);
+ int[] enabled = new int[] {isSatelliteEnabled ? 1 : 0};
+ AsyncResult.forMessage(message, enabled, exception);
message.sendToTarget();
return null;
}).when(mMockSatelliteModemInterface).requestIsSatelliteEnabled(any(Message.class));
@@ -2887,7 +3208,7 @@
try {
if (!mSatelliteAllowedSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) {
loge("Timeout to receive "
- + "requestIsSatelliteCommunicationAllowedForCurrentLocation()"
+ + "requestIsCommunicationAllowedForCurrentLocation()"
+ " callback");
return false;
}
@@ -3016,6 +3337,16 @@
assertEquals(supported, mQueriedSatelliteSupported);
}
+ private void verifySatelliteSupported(TestSatelliteController satelliteController,
+ boolean supported, int expectedErrorCode) {
+ mSatelliteSupportSemaphore.drainPermits();
+ satelliteController.requestIsSatelliteSupported(SUB_ID, mSatelliteSupportReceiver);
+ processAllMessages();
+ assertTrue(waitForRequestIsSatelliteSupportedResult(1));
+ assertEquals(expectedErrorCode, mQueriedSatelliteSupportedResultCode);
+ assertEquals(supported, mQueriedSatelliteSupported);
+ }
+
private void verifySatelliteEnabled(boolean enabled, int expectedErrorCode) {
mIsSatelliteEnabledSemaphore.drainPermits();
mSatelliteControllerUT.requestIsSatelliteEnabled(SUB_ID, mIsSatelliteEnabledReceiver);
@@ -3112,13 +3443,45 @@
throw new AssertionError();
}
} else {
- ServiceSpecificException ex = assertThrows(ServiceSpecificException.class,
+ RemoteException ex = assertThrows(RemoteException.class,
() -> mSatelliteControllerUT.registerForNtnSignalStrengthChanged(subId,
callback));
- assertEquals(expectedError, ex.errorCode);
+ assertTrue("The cause is not IllegalStateException",
+ ex.getCause() instanceof IllegalStateException);
}
}
+ private void provisionSatelliteService() {
+ String mText = "This is test provision data.";
+ byte[] testProvisionData = mText.getBytes();
+ ICancellationSignal cancelRemote;
+ mIIntegerConsumerResults.clear();
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ setUpResponseForRequestIsSatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
+ setUpResponseForProvisionSatelliteService(TEST_SATELLITE_TOKEN, testProvisionData,
+ SATELLITE_RESULT_SUCCESS);
+ cancelRemote = mSatelliteControllerUT.provisionSatelliteService(SUB_ID,
+ TEST_SATELLITE_TOKEN,
+ testProvisionData, mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ assertNotNull(cancelRemote);
+ verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ }
+
+ private void deprovisionSatelliteService() {
+ mIIntegerConsumerResults.clear();
+ setUpResponseForDeprovisionSatelliteService(TEST_SATELLITE_TOKEN, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.deprovisionSatelliteService(SUB_ID,
+ TEST_SATELLITE_TOKEN, mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ }
+
private static void loge(String message) {
Rlog.e(TAG, message);
}
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 589f32b..20b33eb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
@@ -23,6 +23,8 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -38,8 +40,8 @@
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Looper;
+import android.os.OutcomeReceiver;
import android.os.RemoteException;
-import android.os.ResultReceiver;
import android.telecom.Connection;
import android.telephony.BinderCacheManager;
import android.telephony.ServiceState;
@@ -184,13 +186,22 @@
private void testTimeoutBeforeEmergencyCallEnd(int expectedHandoverType,
String expectedPackageName, String expectedClassName, String expectedAction) {
+ mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
processAllMessages();
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+ assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
+
+ // Move Location service to emergency mode
+ mTestSOSMessageRecommender.onEmergencyCallConnectionStateChanged(
+ mTestConnection.getTelecomCallId(), Connection.STATE_DIALING);
+ processAllMessages();
+ assertNotNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
// Wait for the timeout to expires
+ mTestSOSMessageRecommender.isSatelliteAllowedCallback.onResult(true);
moveTimeForward(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS);
processAllMessages();
if (TextUtils.isEmpty(expectedPackageName) || TextUtils.isEmpty(expectedClassName)) {
@@ -208,13 +219,22 @@
public void testTimeoutBeforeEmergencyCallEnd_EventDisplayEmergencyMessageNotSent() {
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
mTestSatelliteController.setIsSatelliteViaOemProvisioned(false);
+ mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
processAllMessages();
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+ assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
+
+ // Move Location service to emergency mode
+ mTestSOSMessageRecommender.onEmergencyCallConnectionStateChanged(
+ mTestConnection.getTelecomCallId(), Connection.STATE_DIALING);
+ processAllMessages();
+ assertNotNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
// Wait for the timeout to expires
+ mTestSOSMessageRecommender.isSatelliteAllowedCallback.onResult(true);
moveTimeForward(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS);
processAllMessages();
assertFalse(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE));
@@ -224,12 +244,21 @@
@Test
public void testTimeoutBeforeEmergencyCallEnd_T911_FromNotConnectedToConnected() {
+ mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
+ mTestSatelliteController.isOemEnabledSatelliteSupported = false;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
processAllMessages();
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+ assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
+
+ // Move Location service to emergency mode
+ mTestSOSMessageRecommender.onEmergencyCallConnectionStateChanged(
+ mTestConnection.getTelecomCallId(), Connection.STATE_DIALING);
+ processAllMessages();
+ assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
// Wait for the timeout to expires
@@ -241,6 +270,7 @@
DEFAULT_HANDOVER_INTENT_ACTION));
assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+ mTestSatelliteController.isOemEnabledSatelliteSupported = true;
}
@Test
@@ -255,13 +285,14 @@
@Test
public void testImsRegistrationStateChangedBeforeTimeout() {
+ mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
processAllMessages();
-
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+ assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
when(mPhone.isImsRegistered()).thenReturn(true);
mTestImsManager.sendImsRegistrationStateChangedEvent(0, true);
@@ -285,8 +316,16 @@
mTestImsManager.sendImsRegistrationStateChangedEvent(1, false);
processAllMessages();
assertEquals(2, mTestSOSMessageRecommender.getCountOfTimerStarted());
+ assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
+
+ // Move Location service to emergency mode
+ mTestSOSMessageRecommender.onEmergencyCallConnectionStateChanged(
+ mTestConnection.getTelecomCallId(), Connection.STATE_DIALING);
+ processAllMessages();
+ assertNotNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
// Wait for the timeout to expires
+ mTestSOSMessageRecommender.isSatelliteAllowedCallback.onResult(true);
moveTimeForward(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS);
processAllMessages();
@@ -324,10 +363,18 @@
assertRegisterForStateChangedEventsTriggered(mPhone, 2, 4, 2);
assertRegisterForStateChangedEventsTriggered(mPhone2, 2, 4, 2);
+ // Move Location service to emergency mode
+ mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
+ mTestSOSMessageRecommender.onEmergencyCallConnectionStateChanged(
+ mTestConnection.getTelecomCallId(), Connection.STATE_DIALING);
+ processAllMessages();
+ assertNotNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
+
mTestSatelliteController.sendProvisionStateChangedEvent(
SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, true);
// Wait for the timeout to expires
+ mTestSOSMessageRecommender.isSatelliteAllowedCallback.onResult(true);
moveTimeForward(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS);
processAllMessages();
@@ -342,23 +389,31 @@
@Test
public void testEmergencyCallRedialBeforeTimeout() {
+ mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
processAllMessages();
+ assertTrue(mTestSOSMessageRecommender.isTimerStarted());
+ assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
+ assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
+ assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+ assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ processAllMessages();
+ assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ // Move Location service to emergency mode
+ mTestSOSMessageRecommender.onEmergencyCallConnectionStateChanged(
+ mTestConnection.getTelecomCallId(), Connection.STATE_DIALING);
processAllMessages();
+ assertNotNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
- assertTrue(mTestSOSMessageRecommender.isTimerStarted());
- assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
- assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
- assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
-
- // Wait for the timeout to expires
+ // Wait for the timeout to expires and satellite access restriction checking result
+ mTestSOSMessageRecommender.isSatelliteAllowedCallback.onResult(true);
moveTimeForward(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS);
processAllMessages();
@@ -418,16 +473,23 @@
@Test
public void testSatelliteNotAllowedInCurrentLocation() {
- mTestSatelliteController.setIsSatelliteCommunicationAllowed(false);
+ mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
processAllMessages();
+ assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
+ assertTrue(mTestSOSMessageRecommender.isTimerStarted());
+ assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
- /**
- * We should have registered for the state change events and started the timer when
- * receiving the event onEmergencyCallStarted. After getting the callback for the result of
- * the request requestIsSatelliteCommunicationAllowedForCurrentLocation, the resources
- * should be cleaned up.
- */
+ // Move Location service to emergency mode
+ mTestSOSMessageRecommender.onEmergencyCallConnectionStateChanged(
+ mTestConnection.getTelecomCallId(), Connection.STATE_DIALING);
+ processAllMessages();
+ assertNotNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
+
+ mTestSOSMessageRecommender.isSatelliteAllowedCallback.onResult(false);
+ moveTimeForward(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS);
+ processAllMessages();
+
assertFalse(mTestSOSMessageRecommender.isTimerStarted());
assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
@@ -475,9 +537,10 @@
private void testCellularServiceStateChangedBeforeTimeout(
@ServiceState.RegState int availableServiceState,
@ServiceState.RegState int unavailableServiceState) {
+ mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
processAllMessages();
-
+ assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
@@ -505,7 +568,14 @@
assertEquals(2, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
+ // Move Location service to emergency mode
+ mTestSOSMessageRecommender.onEmergencyCallConnectionStateChanged(
+ mTestConnection.getTelecomCallId(), Connection.STATE_DIALING);
+ processAllMessages();
+ assertNotNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
+
// Wait for the timeout to expires
+ mTestSOSMessageRecommender.isSatelliteAllowedCallback.onResult(true);
moveTimeForward(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS);
processAllMessages();
@@ -545,8 +615,9 @@
private int mRegisterForSatelliteProvisionStateChangedCalls = 0;
private int mUnregisterForSatelliteProvisionStateChangedCalls = 0;
private boolean mIsSatelliteViaOemProvisioned = true;
- private boolean mIsSatelliteCommunicationAllowed = true;
private boolean mIsSatelliteConnectedViaCarrierWithinHysteresisTime = true;
+ public boolean isOemEnabledSatelliteSupported = true;
+ public boolean isCarrierEnabledSatelliteSupported = true;
/**
* Create a SatelliteController to act as a backend service of
@@ -567,7 +638,12 @@
@Override
public boolean isSatelliteSupportedViaOem() {
- return true;
+ return isOemEnabledSatelliteSupported;
+ }
+
+ @Override
+ public boolean isSatelliteSupportedViaCarrier() {
+ return isCarrierEnabledSatelliteSupported;
}
@Override
@@ -593,15 +669,6 @@
}
@Override
- public void requestIsSatelliteCommunicationAllowedForCurrentLocation(int subId,
- @NonNull ResultReceiver result) {
- Bundle bundle = new Bundle();
- bundle.putBoolean(SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED,
- mIsSatelliteCommunicationAllowed);
- result.send(SatelliteManager.SATELLITE_RESULT_SUCCESS, bundle);
- }
-
- @Override
public boolean isSatelliteConnectedViaCarrierWithinHysteresisTime() {
return mIsSatelliteConnectedViaCarrierWithinHysteresisTime;
}
@@ -611,10 +678,6 @@
return INVALID_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE;
}
- public void setIsSatelliteCommunicationAllowed(boolean allowed) {
- mIsSatelliteCommunicationAllowed = allowed;
- }
-
public void setSatelliteConnectedViaCarrierWithinHysteresisTime(
boolean connectedViaCarrier) {
mIsSatelliteConnectedViaCarrierWithinHysteresisTime = connectedViaCarrier;
@@ -717,6 +780,8 @@
}
private static class TestSOSMessageRecommender extends SatelliteSOSMessageRecommender {
+ public OutcomeReceiver<Boolean, SatelliteManager.SatelliteException>
+ isSatelliteAllowedCallback = null;
private ComponentName mSmsAppComponent = new ComponentName(
DEFAULT_SATELLITE_MESSAGING_PACKAGE, DEFAULT_SATELLITE_MESSAGING_CLASS);
@@ -741,6 +806,14 @@
return mSmsAppComponent;
}
+ @Override
+ protected void requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ @NonNull OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> callback) {
+ logd("requestIsSatelliteCommunicationAllowedForCurrentLocation: callback="
+ + callback);
+ isSatelliteAllowedCallback = callback;
+ }
+
public boolean isTimerStarted() {
return hasMessages(EVENT_TIME_OUT);
}
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 50c6c24..6d3bb4e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
@@ -38,7 +38,7 @@
import android.content.res.Resources;
import android.os.Looper;
import android.os.Message;
-import android.telephony.satellite.ISatelliteStateCallback;
+import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.SatelliteManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -76,7 +76,7 @@
private TestSatelliteModemInterface mSatelliteModemInterface;
private TestSatelliteSessionController mTestSatelliteSessionController;
- private TestSatelliteStateCallback mTestSatelliteStateCallback;
+ private TestSatelliteModemStateCallback mTestSatelliteModemStateCallback;
@Mock private SatelliteController mMockSatelliteController;
@Mock private DatagramReceiver mMockDatagramReceiver;
@@ -107,11 +107,11 @@
Looper.myLooper(), true, mSatelliteModemInterface);
processAllMessages();
- mTestSatelliteStateCallback = new TestSatelliteStateCallback();
+ mTestSatelliteModemStateCallback = new TestSatelliteModemStateCallback();
mTestSatelliteSessionController.registerForSatelliteModemStateChanged(
- mTestSatelliteStateCallback);
+ mTestSatelliteModemStateCallback);
assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
}
@After
@@ -176,7 +176,7 @@
// SatelliteSessionController should move to IDLE state after the modem is powered on.
assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
assertFalse(mTestSatelliteSessionController.isSendingTriggeredDuringTransferringState());
@@ -186,7 +186,7 @@
// SatelliteSessionController should move back to POWER_OFF state.
assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
assertFalse(mTestSatelliteSessionController.isSendingTriggeredDuringTransferringState());
@@ -196,7 +196,7 @@
// SatelliteSessionController should move to IDLE state after radio is turned on.
assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
assertFalse(mTestSatelliteSessionController.isSendingTriggeredDuringTransferringState());
@@ -206,7 +206,7 @@
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
assertTrue(mTestSatelliteSessionController.isSendingTriggeredDuringTransferringState());
@@ -218,7 +218,7 @@
processAllMessages();
// SatelliteSessionController should move to IDLE state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
assertFalse(mTestSatelliteSessionController.isSendingTriggeredDuringTransferringState());
@@ -230,7 +230,7 @@
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
assertTrue(mTestSatelliteSessionController.isSendingTriggeredDuringTransferringState());
@@ -242,7 +242,7 @@
processAllMessages();
// SatelliteSessionController should move to LISTENING state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_LISTENING);
assertEquals(STATE_LISTENING, mTestSatelliteSessionController.getCurrentStateName());
assertEquals(1, mSatelliteModemInterface.getListeningEnabledCount());
@@ -255,7 +255,7 @@
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
assertEquals(1, mSatelliteModemInterface.getListeningDisabledCount());
@@ -267,7 +267,7 @@
processAllMessages();
// SatelliteSessionController should move to LISTENING state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_LISTENING);
assertEquals(STATE_LISTENING, mTestSatelliteSessionController.getCurrentStateName());
assertEquals(2, mSatelliteModemInterface.getListeningEnabledCount());
@@ -280,7 +280,7 @@
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
assertEquals(2, mSatelliteModemInterface.getListeningDisabledCount());
@@ -293,7 +293,7 @@
processAllMessages();
// SatelliteSessionController should move to IDLE state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
assertFalse(mTestSatelliteSessionController.isSendingTriggeredDuringTransferringState());
@@ -305,7 +305,7 @@
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
assertFalse(mTestSatelliteSessionController.isSendingTriggeredDuringTransferringState());
@@ -316,7 +316,7 @@
processAllMessages();
// SatelliteSessionController should move to LISTENING state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_LISTENING);
assertEquals(STATE_LISTENING, mTestSatelliteSessionController.getCurrentStateName());
assertEquals(3, mSatelliteModemInterface.getListeningEnabledCount());
@@ -327,7 +327,7 @@
processAllMessages();
// SatelliteSessionController should move to IDLE state after timeout
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
assertEquals(3, mSatelliteModemInterface.getListeningDisabledCount());
@@ -340,7 +340,7 @@
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
assertFalse(mTestSatelliteSessionController.isSendingTriggeredDuringTransferringState());
@@ -352,7 +352,7 @@
processAllMessages();
// SatelliteSessionController should stay at TRANSFERRING state.
- assertModemStateChangedCallbackNotCalled(mTestSatelliteStateCallback);
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
assertTrue(mTestSatelliteSessionController.isSendingTriggeredDuringTransferringState());
@@ -364,7 +364,7 @@
// SatelliteSessionController should stay at TRANSFERRING state instead of moving to IDLE
// state.
- assertModemStateChangedCallbackNotCalled(mTestSatelliteStateCallback);
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
assertTrue(mTestSatelliteSessionController.isSendingTriggeredDuringTransferringState());
@@ -375,7 +375,7 @@
processAllMessages();
// SatelliteSessionController should stay at TRANSFERRING state.
- assertModemStateChangedCallbackNotCalled(mTestSatelliteStateCallback);
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
assertTrue(mTestSatelliteSessionController.isSendingTriggeredDuringTransferringState());
@@ -387,7 +387,7 @@
// SatelliteSessionController should stay at TRANSFERRING state instead of moving to IDLE
// state.
- assertModemStateChangedCallbackNotCalled(mTestSatelliteStateCallback);
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
assertTrue(mTestSatelliteSessionController.isSendingTriggeredDuringTransferringState());
@@ -397,7 +397,7 @@
// SatelliteSessionController should move to POWER_OFF state.
assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
assertFalse(mTestSatelliteSessionController.isSendingTriggeredDuringTransferringState());
}
@@ -419,8 +419,8 @@
// SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
// is powered on.
- assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
verify(mMockDatagramController).onSatelliteModemStateChanged(
@@ -430,7 +430,7 @@
moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
processAllMessages();
// SatelliteSessionController should stay at NOT_CONNECTED state.
- assertModemStateChangedCallbackNotCalled(mTestSatelliteStateCallback);
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
setupDatagramTransferringState(true);
@@ -441,7 +441,7 @@
// SatelliteSessionController should move back to POWER_OFF state.
assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
verify(mMockDatagramController).onSatelliteModemStateChanged(
SatelliteManager.SATELLITE_MODEM_STATE_OFF);
@@ -452,8 +452,8 @@
processAllMessages();
// SatelliteSessionController should move to NOT_CONNECTED state after radio is turned on.
- assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
verify(mMockDatagramController).onSatelliteModemStateChanged(
@@ -466,7 +466,7 @@
processAllMessages();
// The datagram sending event should be ignored.
- assertModemStateChangedCallbackNotCalled(mTestSatelliteStateCallback);
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
// Satellite modem is connected to a satellite network.
@@ -476,7 +476,7 @@
// SatelliteSessionController should move to CONNECTED state
assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
verify(mMockDatagramController).onSatelliteModemStateChanged(
@@ -489,7 +489,7 @@
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
@@ -504,7 +504,7 @@
processAllMessages();
// SatelliteSessionController should move to CONNECTED state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
@@ -519,7 +519,7 @@
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
@@ -534,7 +534,7 @@
processAllMessages();
// SatelliteSessionController should move to CONNECTED state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
@@ -549,7 +549,7 @@
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
@@ -563,7 +563,7 @@
processAllMessages();
// SatelliteSessionController should move to CONNECTED state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
@@ -576,7 +576,7 @@
processAllMessages();
// SatelliteSessionController should move to IDLE state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
@@ -591,7 +591,7 @@
processAllMessages();
// SatelliteSessionController should move to NOT_CONNECTED state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
verify(mMockDatagramController).onSatelliteModemStateChanged(
@@ -605,7 +605,7 @@
// SatelliteSessionController should move to CONNECTED state
assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
verify(mMockDatagramController).onSatelliteModemStateChanged(
SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
@@ -617,8 +617,8 @@
processAllMessages();
// SatelliteSessionController should move to NOT_CONNECTED state
- assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
verify(mMockDatagramController).onSatelliteModemStateChanged(
SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
@@ -631,7 +631,7 @@
// SatelliteSessionController should move to CONNECTED state
assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
verify(mMockDatagramController).onSatelliteModemStateChanged(
SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
@@ -643,7 +643,7 @@
// SatelliteSessionController should move to POWER_OFF state.
assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
verify(mMockDatagramController).onSatelliteModemStateChanged(
SatelliteManager.SATELLITE_MODEM_STATE_OFF);
@@ -655,8 +655,8 @@
// SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
// is powered on.
- assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
verify(mMockDatagramController).onSatelliteModemStateChanged(
SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
@@ -669,7 +669,7 @@
// SatelliteSessionController should move to CONNECTED state
assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
// Wait for timeout
@@ -677,7 +677,7 @@
processAllMessages();
// SatelliteSessionController should move to IDLE state.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
@@ -692,7 +692,7 @@
// SatelliteSessionController should stay at IDLE state because it failed to disable
// cellular scanning.
- assertModemStateChangedCallbackNotCalled(mTestSatelliteStateCallback);
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
mSatelliteModemInterface.setErrorCode(SatelliteManager.SATELLITE_RESULT_SUCCESS);
@@ -703,7 +703,7 @@
// SatelliteSessionController should move to POWER_OFF
assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
// Power on the modem.
@@ -712,8 +712,8 @@
// SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
// is powered on.
- assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
@@ -721,7 +721,7 @@
// SatelliteSessionController should move to IDLE state because NB-IOT inactivity timer has
// timed out.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
@@ -731,7 +731,7 @@
// SatelliteSessionController should move to POWER_OFF
assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
// Power on the modem.
@@ -740,8 +740,8 @@
// SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
// is powered on.
- assertSuccessfulModemStateChangedCallback(
- mTestSatelliteStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
// Start sending datagrams and the NB-IOT inactivity timer should be stopped.
@@ -752,7 +752,7 @@
processAllMessages();
// SatelliteSessionController should stay at NOT_CONNECTED state because.
- assertModemStateChangedCallbackNotCalled(mTestSatelliteStateCallback);
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
// Transferring datagram failed because satellite failed to connect to a satellite network.
@@ -771,7 +771,7 @@
// SatelliteSessionController should move to IDLE state because NB-IOT inactivity timer has
// timed out.
- assertSuccessfulModemStateChangedCallback(mTestSatelliteStateCallback,
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
}
@@ -850,7 +850,7 @@
}
}
- private static class TestSatelliteStateCallback extends ISatelliteStateCallback.Stub {
+ private static class TestSatelliteModemStateCallback extends ISatelliteModemStateCallback.Stub {
private final AtomicInteger mModemState = new AtomicInteger(
SatelliteManager.SATELLITE_MODEM_STATE_OFF);
private final Semaphore mSemaphore = new Semaphore(0);
@@ -885,7 +885,7 @@
}
private static void assertSuccessfulModemStateChangedCallback(
- TestSatelliteStateCallback callback,
+ TestSatelliteModemStateCallback callback,
@SatelliteManager.SatelliteModemState int expectedModemState) {
boolean successful = callback.waitUntilResult();
assertTrue(successful);
@@ -893,7 +893,7 @@
}
private static void assertModemStateChangedCallbackNotCalled(
- TestSatelliteStateCallback callback) {
+ TestSatelliteModemStateCallback callback) {
boolean successful = callback.waitUntilResult();
assertFalse(successful);
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifierTest.java b/tests/telephonytests/src/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifierTest.java
new file mode 100644
index 0000000..582c658
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifierTest.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.security;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.telephony.CellularIdentifierDisclosure;
+
+import com.android.internal.telephony.TestExecutorService;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.concurrent.TimeUnit;
+
+public class CellularIdentifierDisclosureNotifierTest {
+
+ // 15 minutes and 100 milliseconds. Can be used to advance time in a test executor far enough
+ // to (hopefully, if the code is behaving) close a disclosure window.
+ private static final long WINDOW_CLOSE_ADVANCE_MILLIS = (15 * 60 * 1000) + 100;
+ private static final int SUB_ID_1 = 1;
+ private static final int SUB_ID_2 = 2;
+ private CellularIdentifierDisclosure mDislosure;
+
+ @Before
+ public void setUp() {
+ mDislosure =
+ new CellularIdentifierDisclosure(
+ CellularIdentifierDisclosure.NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST,
+ CellularIdentifierDisclosure.CELLULAR_IDENTIFIER_IMSI,
+ "001001",
+ false);
+ }
+
+ @Test
+ public void testInitializeDisabled() {
+ TestExecutorService executor = new TestExecutorService();
+ CellularIdentifierDisclosureNotifier notifier =
+ new CellularIdentifierDisclosureNotifier(executor, 15, TimeUnit.MINUTES);
+
+ assertFalse(notifier.isEnabled());
+ }
+
+ @Test
+ public void testDisableAddDisclosureNop() {
+ TestExecutorService executor = new TestExecutorService();
+ CellularIdentifierDisclosureNotifier notifier =
+ new CellularIdentifierDisclosureNotifier(executor, 15, TimeUnit.MINUTES);
+
+ assertFalse(notifier.isEnabled());
+ notifier.addDisclosure(SUB_ID_1, mDislosure);
+ assertEquals(0, notifier.getCurrentDisclosureCount(SUB_ID_1));
+ }
+
+ @Test
+ public void testAddDisclosureEmergencyNop() {
+ TestExecutorService executor = new TestExecutorService();
+ CellularIdentifierDisclosureNotifier notifier =
+ new CellularIdentifierDisclosureNotifier(executor, 15, TimeUnit.MINUTES);
+ CellularIdentifierDisclosure emergencyDisclosure =
+ new CellularIdentifierDisclosure(
+ CellularIdentifierDisclosure.NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST,
+ CellularIdentifierDisclosure.CELLULAR_IDENTIFIER_IMSI,
+ "001001",
+ true);
+
+ notifier.enable();
+ notifier.addDisclosure(SUB_ID_1, emergencyDisclosure);
+
+ assertEquals(0, notifier.getCurrentDisclosureCount(SUB_ID_1));
+ }
+
+ @Test
+ public void testAddDisclosureCountIncrements() {
+ TestExecutorService executor = new TestExecutorService();
+ CellularIdentifierDisclosureNotifier notifier =
+ new CellularIdentifierDisclosureNotifier(executor, 15, TimeUnit.MINUTES);
+
+ notifier.enable();
+
+ for (int i = 0; i < 3; i++) {
+ notifier.addDisclosure(SUB_ID_1, mDislosure);
+ }
+
+ assertEquals(3, notifier.getCurrentDisclosureCount(SUB_ID_1));
+ }
+
+ @Test
+ public void testSingleDisclosureStartAndEndTimesAreEqual() {
+ TestExecutorService executor = new TestExecutorService();
+ CellularIdentifierDisclosureNotifier notifier =
+ new CellularIdentifierDisclosureNotifier(executor, 15, TimeUnit.MINUTES);
+
+ notifier.enable();
+
+ notifier.addDisclosure(SUB_ID_1, mDislosure);
+
+ assertEquals(1, notifier.getCurrentDisclosureCount(SUB_ID_1));
+ assertTrue(notifier.getFirstOpen(SUB_ID_1).equals(notifier.getCurrentEnd(SUB_ID_1)));
+ }
+
+ @Test
+ public void testMultipleDisclosuresTimeWindows() {
+ TestExecutorService executor = new TestExecutorService();
+ CellularIdentifierDisclosureNotifier notifier =
+ new CellularIdentifierDisclosureNotifier(executor, 15, TimeUnit.MINUTES);
+
+ notifier.enable();
+
+ notifier.addDisclosure(SUB_ID_1, mDislosure);
+ try {
+ Thread.sleep(50);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ notifier.addDisclosure(SUB_ID_1, mDislosure);
+
+ assertEquals(2, notifier.getCurrentDisclosureCount(SUB_ID_1));
+ assertTrue(notifier.getFirstOpen(SUB_ID_1).isBefore(notifier.getCurrentEnd(SUB_ID_1)));
+ }
+
+ @Test
+ public void testAddDisclosureThenWindowClose() {
+ TestExecutorService executor = new TestExecutorService();
+ CellularIdentifierDisclosureNotifier notifier =
+ new CellularIdentifierDisclosureNotifier(executor, 15, TimeUnit.MINUTES);
+
+ // One round of disclosures
+ notifier.enable();
+ notifier.addDisclosure(SUB_ID_1, mDislosure);
+ notifier.addDisclosure(SUB_ID_1, mDislosure);
+ assertEquals(2, notifier.getCurrentDisclosureCount(SUB_ID_1));
+
+ // Window close should reset the counter
+ executor.advanceTime(WINDOW_CLOSE_ADVANCE_MILLIS);
+ assertEquals(0, notifier.getCurrentDisclosureCount(SUB_ID_1));
+
+ // A new disclosure should increment as normal
+ notifier.addDisclosure(SUB_ID_1, mDislosure);
+ assertEquals(1, notifier.getCurrentDisclosureCount(SUB_ID_1));
+ }
+
+ @Test
+ public void testDisableClosesWindow() {
+ TestExecutorService executor = new TestExecutorService();
+ CellularIdentifierDisclosureNotifier notifier =
+ new CellularIdentifierDisclosureNotifier(executor, 15, TimeUnit.MINUTES);
+
+ // One round of disclosures
+ notifier.enable();
+ notifier.addDisclosure(SUB_ID_1, mDislosure);
+ notifier.addDisclosure(SUB_ID_1, mDislosure);
+ assertEquals(2, notifier.getCurrentDisclosureCount(SUB_ID_1));
+
+ notifier.disable();
+ assertFalse(notifier.isEnabled());
+
+ // We're disabled now so no disclosures should open the disclosure window
+ notifier.addDisclosure(SUB_ID_1, mDislosure);
+ assertEquals(0, notifier.getCurrentDisclosureCount(SUB_ID_1));
+ }
+
+ @Test
+ public void testMultipleSubIdsTrackedIndependently() {
+ TestExecutorService executor = new TestExecutorService();
+ CellularIdentifierDisclosureNotifier notifier =
+ new CellularIdentifierDisclosureNotifier(executor, 15, TimeUnit.MINUTES);
+
+ notifier.enable();
+ for (int i = 0; i < 3; i++) {
+ notifier.addDisclosure(SUB_ID_1, mDislosure);
+ }
+
+ for (int i = 0; i < 4; i++) {
+ notifier.addDisclosure(SUB_ID_2, mDislosure);
+ }
+
+ assertEquals(3, notifier.getCurrentDisclosureCount(SUB_ID_1));
+ assertEquals(4, notifier.getCurrentDisclosureCount(SUB_ID_2));
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/security/SecurityAlgorithmUpdateTest.java b/tests/telephonytests/src/com/android/internal/telephony/security/SecurityAlgorithmUpdateTest.java
new file mode 100644
index 0000000..bd50151
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/security/SecurityAlgorithmUpdateTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.security;
+
+import static android.telephony.SecurityAlgorithmUpdate.CONNECTION_EVENT_PS_SIGNALLING_3G;
+import static android.telephony.SecurityAlgorithmUpdate.CONNECTION_EVENT_VOLTE_SIP;
+import static android.telephony.SecurityAlgorithmUpdate.SECURITY_ALGORITHM_AUTH_HMAC_SHA2_256_128;
+import static android.telephony.SecurityAlgorithmUpdate.SECURITY_ALGORITHM_EEA2;
+import static android.telephony.SecurityAlgorithmUpdate.SECURITY_ALGORITHM_HMAC_SHA1_96;
+import static android.telephony.SecurityAlgorithmUpdate.SECURITY_ALGORITHM_UEA1;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.hardware.radio.network.ConnectionEvent;
+import android.hardware.radio.network.SecurityAlgorithm;
+import android.os.Parcel;
+import android.telephony.SecurityAlgorithmUpdate;
+
+import com.android.internal.telephony.RILUtils;
+
+import org.junit.Test;
+
+public final class SecurityAlgorithmUpdateTest {
+
+ @Test
+ public void testEqualsAndHash() {
+ SecurityAlgorithmUpdate update = new SecurityAlgorithmUpdate(
+ CONNECTION_EVENT_VOLTE_SIP, SECURITY_ALGORITHM_EEA2,
+ SECURITY_ALGORITHM_HMAC_SHA1_96, false);
+ SecurityAlgorithmUpdate sameUpdate = new SecurityAlgorithmUpdate(
+ CONNECTION_EVENT_VOLTE_SIP, SECURITY_ALGORITHM_EEA2,
+ SECURITY_ALGORITHM_HMAC_SHA1_96, false);
+
+ assertThat(update).isEqualTo(sameUpdate);
+ assertThat(update.hashCode()).isEqualTo(sameUpdate.hashCode());
+ }
+
+ @Test
+ public void testNotEqualsAndHash() {
+ SecurityAlgorithmUpdate update = new SecurityAlgorithmUpdate(
+ CONNECTION_EVENT_VOLTE_SIP, SECURITY_ALGORITHM_EEA2,
+ SECURITY_ALGORITHM_HMAC_SHA1_96, false);
+ SecurityAlgorithmUpdate sameUpdate = new SecurityAlgorithmUpdate(
+ CONNECTION_EVENT_VOLTE_SIP, SECURITY_ALGORITHM_EEA2,
+ SECURITY_ALGORITHM_HMAC_SHA1_96, true);
+
+ assertThat(update).isNotEqualTo(sameUpdate);
+ assertThat(update.hashCode()).isNotEqualTo(sameUpdate.hashCode());
+ }
+
+ @Test
+ public void testGetters() {
+ SecurityAlgorithmUpdate update = new SecurityAlgorithmUpdate(
+ CONNECTION_EVENT_VOLTE_SIP, SECURITY_ALGORITHM_EEA2,
+ SECURITY_ALGORITHM_HMAC_SHA1_96, false);
+
+ assertThat(update.getConnectionEvent()).isEqualTo(CONNECTION_EVENT_VOLTE_SIP);
+ assertThat(update.getEncryption()).isEqualTo(SECURITY_ALGORITHM_EEA2);
+ assertThat(update.getIntegrity()).isEqualTo(SECURITY_ALGORITHM_HMAC_SHA1_96);
+ assertThat(update.isUnprotectedEmergency()).isFalse();
+ }
+
+ @Test
+ public void testParcel() {
+ SecurityAlgorithmUpdate update = new SecurityAlgorithmUpdate(
+ CONNECTION_EVENT_VOLTE_SIP, SECURITY_ALGORITHM_EEA2,
+ SECURITY_ALGORITHM_HMAC_SHA1_96, false);
+
+ Parcel p = Parcel.obtain();
+ update.writeToParcel(p, 0);
+ p.setDataPosition(0);
+
+ SecurityAlgorithmUpdate fromParcel = SecurityAlgorithmUpdate.CREATOR.createFromParcel(p);
+ assertThat(fromParcel).isEqualTo(update);
+ }
+
+ @Test
+ public void testConvertSecurityAlgorithmUpdate() {
+ android.hardware.radio.network.SecurityAlgorithmUpdate aidlUpdate =
+ new android.hardware.radio.network.SecurityAlgorithmUpdate();
+ aidlUpdate.connectionEvent = ConnectionEvent.PS_SIGNALLING_3G;
+ aidlUpdate.encryption = SecurityAlgorithm.UEA1;
+ aidlUpdate.integrity = SecurityAlgorithm.AUTH_HMAC_SHA2_256_128;
+ aidlUpdate.isUnprotectedEmergency = true;
+
+ assertThat(RILUtils.convertSecurityAlgorithmUpdate(aidlUpdate))
+ .isEqualTo(
+ new SecurityAlgorithmUpdate(
+ CONNECTION_EVENT_PS_SIGNALLING_3G,
+ SECURITY_ALGORITHM_UEA1,
+ SECURITY_ALGORITHM_AUTH_HMAC_SHA2_256_128,
+ true));
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
index b42e6d6..1a89c15 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
@@ -124,6 +124,10 @@
static final int FAKE_SATELLITE_ATTACH_FOR_CARRIER_DISABLED = 0;
static final int FAKE_SATELLITE_IS_NTN_ENABLED = 1;
static final int FAKE_SATELLITE_IS_NTN_DISABLED = 0;
+ static final int FAKE_SERVICE_CAPABILITIES_1 =
+ SubscriptionManager.SERVICE_CAPABILITY_DATA_BITMASK;
+ static final int FAKE_SERVICE_CAPABILITIES_2 =
+ SubscriptionManager.SERVICE_CAPABILITY_SMS_BITMASK;
static final String FAKE_MAC_ADDRESS1 = "DC:E5:5B:38:7D:40";
static final String FAKE_MAC_ADDRESS2 = "DC:B5:4F:47:F3:4C";
@@ -199,6 +203,7 @@
FAKE_SATELLITE_ATTACH_FOR_CARRIER_DISABLED)
.setOnlyNonTerrestrialNetwork(FAKE_SATELLITE_IS_NTN_DISABLED)
.setGroupDisabled(false)
+ .setServiceCapabilities(FAKE_SERVICE_CAPABILITIES_1)
.build();
static final SubscriptionInfoInternal FAKE_SUBSCRIPTION_INFO2 =
@@ -270,6 +275,7 @@
FAKE_SATELLITE_ATTACH_FOR_CARRIER_ENABLED)
.setOnlyNonTerrestrialNetwork(FAKE_SATELLITE_IS_NTN_ENABLED)
.setGroupDisabled(false)
+ .setServiceCapabilities(FAKE_SERVICE_CAPABILITIES_2)
.build();
private SubscriptionDatabaseManager mDatabaseManagerUT;
@@ -429,6 +435,7 @@
doReturn(1).when(mUiccController).convertToPublicCardId(eq(FAKE_ICCID1));
doReturn(2).when(mUiccController).convertToPublicCardId(eq(FAKE_ICCID2));
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+ when(mFeatureFlags.dataOnlyCellularService()).thenReturn(true);
mDatabaseManagerUT = new SubscriptionDatabaseManager(mContext, Looper.myLooper(),
mFeatureFlags, mSubscriptionDatabaseManagerCallback);
logd("SubscriptionDatabaseManagerTest -Setup!");
@@ -2011,6 +2018,36 @@
}
@Test
+ public void testSetGroupDisabled() throws Exception {
+ assertThrows(IllegalArgumentException.class,
+ () -> mDatabaseManagerUT.setGroupDisabled(
+ FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(), true));
+
+ insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO1);
+ mDatabaseManagerUT.setGroupDisabled(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(), true);
+ processAllMessages();
+
+ assertThat(mDatabaseManagerUT.getSubscriptionInfoInternal(
+ FAKE_SUBSCRIPTION_INFO1.getSubscriptionId()).isGroupDisabled()).isTrue();
+
+ verify(mSubscriptionDatabaseManagerCallback, times(2)).onSubscriptionChanged(eq(1));
+ Mockito.clearInvocations(mSubscriptionDatabaseManagerCallback);
+
+ mDatabaseManagerUT.setGroupDisabled(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(), true);
+ processAllMessages();
+ verify(mSubscriptionDatabaseManagerCallback, never()).onSubscriptionChanged(eq(1));
+
+ assertThat(mDatabaseManagerUT.getSubscriptionInfoInternal(
+ FAKE_SUBSCRIPTION_INFO1.getSubscriptionId()).isGroupDisabled()).isTrue();
+
+ mDatabaseManagerUT.setGroupDisabled(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(), false);
+ processAllMessages();
+ verify(mSubscriptionDatabaseManagerCallback, times(1)).onSubscriptionChanged(eq(1));
+ assertThat(mDatabaseManagerUT.getSubscriptionInfoInternal(
+ FAKE_SUBSCRIPTION_INFO1.getSubscriptionId()).isGroupDisabled()).isFalse();
+ }
+
+ @Test
public void testUpdateSatelliteNtnWithFeatureDisabled() throws Exception {
assertThrows(IllegalArgumentException.class,
() -> mDatabaseManagerUT.setSatelliteAttachEnabledForCarrier(
@@ -2174,4 +2211,32 @@
processAllMessages();
assertThat(latch.getCount()).isEqualTo(0);
}
+
+ @Test
+ public void testUpdateServiceCapabilities() throws Exception {
+ // exception is expected if there is nothing in the database.
+ assertThrows(IllegalArgumentException.class,
+ () -> mDatabaseManagerUT.setServiceCapabilities(1,
+ FAKE_SERVICE_CAPABILITIES_2));
+
+ SubscriptionInfoInternal subInfo = insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO1);
+ mDatabaseManagerUT.setServiceCapabilities(subInfo.getSubscriptionId(),
+ FAKE_SERVICE_CAPABILITIES_2);
+ processAllMessages();
+
+ subInfo = new SubscriptionInfoInternal.Builder(subInfo).setServiceCapabilities(
+ FAKE_SERVICE_CAPABILITIES_2).build();
+ verifySubscription(subInfo);
+ verify(mSubscriptionDatabaseManagerCallback, times(2)).onSubscriptionChanged(eq(1));
+
+ assertThat(mDatabaseManagerUT.getSubscriptionProperty(1,
+ SimInfo.COLUMN_SERVICE_CAPABILITIES))
+ .isEqualTo(FAKE_SERVICE_CAPABILITIES_2);
+ mDatabaseManagerUT.setSubscriptionProperty(
+ 1, SimInfo.COLUMN_SERVICE_CAPABILITIES,
+ FAKE_SERVICE_CAPABILITIES_1);
+ assertThat(
+ mDatabaseManagerUT.getSubscriptionInfoInternal(1).getServiceCapabilities())
+ .isEqualTo(FAKE_SERVICE_CAPABILITIES_1);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
index 2505f32..d9addd1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
@@ -18,16 +18,21 @@
import static com.google.common.truth.Truth.assertThat;
import android.os.ParcelUuid;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.UiccAccessRule;
import android.telephony.ims.ImsMmTelManager;
+import com.android.internal.telephony.flags.Flags;
+
+import org.junit.Rule;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Set;
public class SubscriptionInfoInternalTest {
private final SubscriptionInfoInternal mSubInfo =
@@ -108,6 +113,8 @@
SubscriptionDatabaseManagerTest.FAKE_SATELLITE_IS_NTN_ENABLED)
.setGroupDisabled(false)
.setOnlyNonTerrestrialNetwork(1)
+ .setServiceCapabilities(
+ SubscriptionManager.SERVICE_CAPABILITY_DATA_BITMASK)
.build();
private final SubscriptionInfoInternal mSubInfoNull =
@@ -136,8 +143,12 @@
.setDeviceToDeviceStatusSharingContacts("")
.build();
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
@Test
public void testSubscriptionInfoInternalSetAndGet() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE);
assertThat(mSubInfo.getSubscriptionId()).isEqualTo(1);
assertThat(mSubInfo.getIccId()).isEqualTo(SubscriptionDatabaseManagerTest.FAKE_ICCID1);
assertThat(mSubInfo.getSimSlotIndex()).isEqualTo(0);
@@ -224,6 +235,8 @@
SubscriptionDatabaseManagerTest.FAKE_SATELLITE_IS_NTN_ENABLED);
assertThat(mSubInfo.isGroupDisabled()).isFalse();
assertThat(mSubInfo.getOnlyNonTerrestrialNetwork()).isEqualTo(1);
+ assertThat(mSubInfo.getServiceCapabilities()).isEqualTo(
+ SubscriptionManager.SERVICE_CAPABILITY_DATA_BITMASK);
}
@Test
@@ -235,6 +248,7 @@
@Test
public void testConvertToSubscriptionInfo() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE);
SubscriptionInfo subInfo = mSubInfo.toSubscriptionInfo();
assertThat(subInfo.getSubscriptionId()).isEqualTo(1);
@@ -287,6 +301,8 @@
SubscriptionManager.USAGE_SETTING_DEFAULT);
assertThat(subInfo.isGroupDisabled()).isFalse();
assertThat(subInfo.isOnlyNonTerrestrialNetwork()).isTrue();
+ assertThat(subInfo.getServiceCapabilities()).isEqualTo(
+ Set.of(SubscriptionManager.SERVICE_CAPABILITY_DATA));
}
@Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
index eecaf90..0aeaad3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
@@ -97,6 +97,7 @@
import android.util.ArraySet;
import android.util.Base64;
+import com.android.internal.R;
import com.android.internal.telephony.ContextFixture;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
@@ -113,6 +114,7 @@
import com.android.internal.telephony.uicc.IccCardStatus;
import com.android.internal.telephony.uicc.UiccSlot;
+import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
import org.junit.After;
@@ -232,6 +234,11 @@
doReturn(true).when(mUserManager)
.isManagedProfile(eq(FAKE_MANAGED_PROFILE_USER_HANDLE.getIdentifier()));
+ // Due to affect exist implementation, bypass feature flag.
+ doReturn(false).when(mFlags).enforceTelephonyFeatureMappingForPublicApis();
+ doReturn(true).when(mPackageManager).hasSystemFeature(
+ eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
+
logd("SubscriptionManagerServiceTest -Setup!");
}
@@ -407,7 +414,12 @@
}
@Test
+ @DisableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
public void testSetPhoneNumber() {
+ doReturn(false).when(mFlags).enforceTelephonyFeatureMapping();
+ doReturn(true).when(mPackageManager).hasSystemFeature(
+ eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
+
mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1,
0, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
@@ -444,6 +456,41 @@
}
@Test
+ @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
+ public void testSetPhoneNumber_EnabledEnforceTelephonyFeatureMappingForPublicApis() {
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
+ mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1,
+ 0, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
+ processAllMessages();
+
+ verify(mMockedSubscriptionManagerServiceCallback).onSubscriptionChanged(eq(1));
+ Mockito.clearInvocations(mMockedSubscriptionManagerServiceCallback);
+
+ // Grant carrier privilege
+ setCarrierPrivilegesForSubId(true, 1);
+
+ // Enabled FeatureFlags and ENABLE_FEATURE_MAPPING, telephony features are defined
+ doReturn(true).when(mFlags).enforceTelephonyFeatureMappingForPublicApis();
+ doReturn(true).when(mPackageManager).hasSystemFeature(
+ eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
+ try {
+ mSubscriptionManagerServiceUT.setPhoneNumber(1,
+ SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER, FAKE_PHONE_NUMBER2,
+ CALLING_PACKAGE, CALLING_FEATURE);
+ } catch (UnsupportedOperationException e) {
+ fail("Not expect exception " + e.getMessage());
+ }
+
+ // Telephony features is not defined, expect UnsupportedOperationException.
+ doReturn(false).when(mPackageManager).hasSystemFeature(
+ eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
+ assertThrows(UnsupportedOperationException.class,
+ () -> mSubscriptionManagerServiceUT.setPhoneNumber(1,
+ SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER, FAKE_PHONE_NUMBER2,
+ CALLING_PACKAGE, CALLING_FEATURE));
+ }
+
+ @Test
public void testGetAllSubInfoList() {
mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
insertSubscription(FAKE_SUBSCRIPTION_INFO1);
@@ -481,6 +528,10 @@
// Grant READ_PHONE_STATE permission
mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE);
+ // Allow the application to perform.
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
+ .noteOpNoThrow(eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(),
+ nullable(String.class), nullable(String.class), nullable(String.class));
// Grant identifier access
setIdentifierAccess(true);
// Revoke carrier privileges.
@@ -538,6 +589,11 @@
// Grant READ_PHONE_STATE permission
mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE);
+ // Allow the application to perform.
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
+ .noteOpNoThrow(eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(),
+ nullable(String.class), nullable(String.class), nullable(String.class));
+
setIdentifierAccess(false);
setCarrierPrivilegesForSubId(false, 1);
setCarrierPrivilegesForSubId(false, 2);
@@ -770,6 +826,10 @@
// Grant READ_PHONE_STATE permission for insertion.
mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE);
+ // Allow the application to perform.
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
+ .noteOpNoThrow(eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(),
+ nullable(String.class), nullable(String.class), nullable(String.class));
List<SubscriptionInfo> subInfos = mSubscriptionManagerServiceUT
.getActiveSubscriptionInfoList(CALLING_PACKAGE, CALLING_FEATURE, true);
@@ -799,6 +859,11 @@
// Grant READ_PHONE_STATE permission for insertion.
mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE);
+ // Allow the application to perform.
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
+ .noteOpNoThrow(eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(),
+ nullable(String.class), nullable(String.class), nullable(String.class));
+
SubscriptionInfo subInfo = mSubscriptionManagerServiceUT
.getActiveSubscriptionInfoForSimSlotIndex(0, CALLING_PACKAGE,
CALLING_FEATURE);
@@ -893,6 +958,10 @@
public void testUpdateEmbeddedSubscriptionsNullResult() {
// Grant READ_PHONE_STATE permission.
mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE);
+ // Allow the application to perform.
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
+ .noteOpNoThrow(eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(),
+ nullable(String.class), nullable(String.class), nullable(String.class));
doReturn(null).when(mEuiccController).blockingGetEuiccProfileInfoList(anyInt());
@@ -914,6 +983,11 @@
// Grant READ_PHONE_STATE permission for insertion.
mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE);
+ // Allow the application to perform.
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
+ .noteOpNoThrow(eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(),
+ nullable(String.class), nullable(String.class), nullable(String.class));
+
SubscriptionInfo subInfo = mSubscriptionManagerServiceUT
.getActiveSubscriptionInfoForSimSlotIndex(0, CALLING_PACKAGE,
CALLING_FEATURE);
@@ -1161,6 +1235,7 @@
SubscriptionManagerService.FILTER_ACCESSIBLE_SUBS_BY_USER})
public void testIsSubscriptionAssociatedWithUserMultiSubs() {
doReturn(true).when(mFlags).workProfileApiSplit();
+ doReturn(true).when(mFlags).enforceSubscriptionUserFilter();
mContextFixture.addCallingOrSelfPermission(
Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
insertSubscription(FAKE_SUBSCRIPTION_INFO1);
@@ -1222,6 +1297,7 @@
public void testSubscriptionAssociationWorkProfileCallerVisibility() {
// Split mode is defined as when a profile owns a dedicated sub, it loses the visibility to
// the unassociated sub.
+ doReturn(true).when(mFlags).enforceSubscriptionUserFilter();
doReturn(true).when(mFlags).workProfileApiSplit();
mContextFixture.addCallingOrSelfPermission(
Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
@@ -1250,9 +1326,17 @@
// Test getActiveSubIdList, System
assertThat(mSubscriptionManagerServiceUT.getActiveSubIdList(false/*visible only*/))
.isEqualTo(new int[]{subId1, subId2});
- // Test get getActiveSubInfoCount
+ // Test get getActiveSubInfoCount - forAllProfiles: false
assertThat(mSubscriptionManagerServiceUT.getActiveSubInfoCount(
CALLING_PACKAGE, CALLING_FEATURE, false)).isEqualTo(1);
+ // Test get getActiveSubInfoCount - forAllProfiles: true
+ assertThrows(SecurityException.class,
+ () -> mSubscriptionManagerServiceUT.getActiveSubInfoCount(
+ CALLING_PACKAGE, CALLING_FEATURE, true));
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_PROFILES);
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubInfoCount(
+ CALLING_PACKAGE, CALLING_FEATURE, true)).isEqualTo(2);
+ mContextFixture.removeCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_PROFILES);
// Test getActiveSubscriptionInfo
assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfo(
subId1, CALLING_PACKAGE, CALLING_FEATURE).getSubscriptionId()).isEqualTo(subId1);
@@ -1272,11 +1356,21 @@
assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoForSimSlotIndex(
1, CALLING_PACKAGE, CALLING_FEATURE).getSubscriptionId())
.isEqualTo(subId2);
- // Test getActiveSubscriptionInfoList
+ // Test getActiveSubscriptionInfoList - forAllProfiles: false
assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoList(
CALLING_PACKAGE, CALLING_FEATURE, false)
.stream().map(SubscriptionInfo::getSubscriptionId)
.toList()).isEqualTo(List.of(subId1));
+ // Test getActiveSubscriptionInfoList - forAllProfiles: true
+ assertThrows(SecurityException.class,
+ () -> mSubscriptionManagerServiceUT.getActiveSubscriptionInfoList(
+ CALLING_PACKAGE, CALLING_FEATURE, true));
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_PROFILES);
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoList(
+ CALLING_PACKAGE, CALLING_FEATURE, true)
+ .stream().map(SubscriptionInfo::getSubscriptionId)
+ .toList()).isEqualTo(List.of(subId1, subId2));
+ mContextFixture.removeCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_PROFILES);
// Test getAllSubInfoList
assertThat(mSubscriptionManagerServiceUT.getAllSubInfoList(CALLING_PACKAGE,
CALLING_FEATURE).stream().map(SubscriptionInfo::getSubscriptionId).toList())
@@ -1339,6 +1433,7 @@
public void testSubscriptionAssociationPersonalCallerVisibility() {
// Split mode is defined as when a profile owns a dedicated sub, it loses the visibility to
// the unassociated sub.
+ doReturn(true).when(mFlags).enforceSubscriptionUserFilter();
doReturn(true).when(mFlags).workProfileApiSplit();
mContextFixture.addCallingOrSelfPermission(
Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
@@ -1367,9 +1462,17 @@
// Test getActiveSubIdList, System
assertThat(mSubscriptionManagerServiceUT.getActiveSubIdList(false/*visible only*/))
.isEqualTo(new int[]{subId1, subId2});
- // Test get getActiveSubInfoCount
+ // Test get getActiveSubInfoCount- forAllProfiles: false
assertThat(mSubscriptionManagerServiceUT.getActiveSubInfoCount(
CALLING_PACKAGE, CALLING_FEATURE, false)).isEqualTo(1);
+ // Test get getActiveSubInfoCount - forAllProfiles: true
+ assertThrows(SecurityException.class,
+ () -> mSubscriptionManagerServiceUT.getActiveSubInfoCount(
+ CALLING_PACKAGE, CALLING_FEATURE, true));
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_PROFILES);
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubInfoCount(
+ CALLING_PACKAGE, CALLING_FEATURE, true)).isEqualTo(2);
+ mContextFixture.removeCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_PROFILES);
// Test getActiveSubscriptionInfo
assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfo(
subId1, CALLING_PACKAGE, CALLING_FEATURE).getSubscriptionId()).isEqualTo(subId1);
@@ -1389,11 +1492,21 @@
assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoForSimSlotIndex(
1, CALLING_PACKAGE, CALLING_FEATURE).getSubscriptionId())
.isEqualTo(subId2);
- // Test getActiveSubscriptionInfoList
+ // Test getActiveSubscriptionInfoList - forAllProfiles: false
assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoList(
CALLING_PACKAGE, CALLING_FEATURE, false).stream()
.map(SubscriptionInfo::getSubscriptionId)
.toList()).isEqualTo(List.of(subId1));
+ // Test getActiveSubscriptionInfoList - forAllProfiles: true
+ assertThrows(SecurityException.class,
+ () -> mSubscriptionManagerServiceUT.getActiveSubscriptionInfoList(
+ CALLING_PACKAGE, CALLING_FEATURE, true));
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_PROFILES);
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoList(
+ CALLING_PACKAGE, CALLING_FEATURE, true)
+ .stream().map(SubscriptionInfo::getSubscriptionId)
+ .toList()).isEqualTo(List.of(subId1, subId2));
+ mContextFixture.removeCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_PROFILES);
// Test getAllSubInfoList
assertThat(mSubscriptionManagerServiceUT.getAllSubInfoList(CALLING_PACKAGE,
CALLING_FEATURE).stream().map(SubscriptionInfo::getSubscriptionId).toList())
@@ -1522,7 +1635,12 @@
assertThat(mSubscriptionManagerServiceUT.getOpportunisticSubscriptions(
CALLING_PACKAGE, CALLING_FEATURE)).isEmpty();
+ // Grant READ_PHONE_STATE permission
mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE);
+ // Allow the application to perform.
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
+ .noteOpNoThrow(eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(),
+ nullable(String.class), nullable(String.class), nullable(String.class));
setIdentifierAccess(true);
setPhoneNumberAccess(PackageManager.PERMISSION_GRANTED);
@@ -2271,6 +2389,7 @@
}
@Test
+ @DisableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
public void testGetPhoneNumber() {
mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
testSetPhoneNumber();
@@ -2874,4 +2993,156 @@
assertThat(subInfo.isRemovableEmbedded()).isFalse();
assertThat(subInfo.getNativeAccessRules()).isEqualTo(new byte[]{});
}
+
+ @Test
+ public void testGetActiveSubscriptionInfoListNoSecurityException() {
+ // Grant MODIFY_PHONE_STATE permission for insertion.
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
+ insertSubscription(FAKE_SUBSCRIPTION_INFO1);
+ insertSubscription(new SubscriptionInfoInternal.Builder(FAKE_SUBSCRIPTION_INFO2)
+ .setSimSlotIndex(SubscriptionManager.INVALID_SIM_SLOT_INDEX).build());
+ // Remove MODIFY_PHONE_STATE
+ mContextFixture.removeCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
+
+ // Should get an empty list without READ_PHONE_STATE.
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoList(
+ CALLING_PACKAGE, CALLING_FEATURE, true)).isEmpty();
+
+ // Grant READ_PHONE_STATE permission for insertion.
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE);
+ // Disallow the application to perform.
+ doReturn(AppOpsManager.MODE_ERRORED).when(mAppOpsManager)
+ .noteOpNoThrow(eq(AppOpsManager.OPSTR_READ_PHONE_STATE), anyInt(),
+ nullable(String.class), nullable(String.class), nullable(String.class));
+
+ // Should get an empty list if the application is not allowed to perform it.
+ assertThat(mSubscriptionManagerServiceUT.getActiveSubscriptionInfoList(
+ CALLING_PACKAGE, CALLING_FEATURE, true)).isEmpty();
+ }
+
+ @Test
+ public void testUpdateGroupDisabled() {
+ insertSubscription(FAKE_SUBSCRIPTION_INFO1);
+ insertSubscription(new SubscriptionInfoInternal
+ .Builder(FAKE_SUBSCRIPTION_INFO2).setGroupUuid(FAKE_UUID1).build());
+
+ mSubscriptionManagerServiceUT.updateGroupDisabled();
+
+ SubscriptionInfoInternal subInfo = mSubscriptionManagerServiceUT
+ .getSubscriptionInfoInternal(2);
+ assertThat(subInfo.isGroupDisabled()).isFalse();
+ }
+
+ @Test
+ public void testIsSatelliteSpn() {
+ mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
+ FAKE_CARRIER_NAME1);
+ System.setProperty("persist.radio.allow_mock_modem", "true");
+ doReturn(true).when(mFlags).oemEnabledSatelliteFlag();
+
+ EuiccProfileInfo profileInfo1 = new EuiccProfileInfo.Builder(FAKE_ICCID1)
+ .setIccid(FAKE_ICCID1)
+ .setNickname(FAKE_CARRIER_NAME1)
+ .setServiceProviderName(FAKE_CARRIER_NAME1)
+ .setProfileClass(SubscriptionManager.PROFILE_CLASS_OPERATIONAL)
+ .setCarrierIdentifier(new CarrierIdentifier(FAKE_MCC1, FAKE_MNC1,
+ FAKE_CARRIER_NAME1, null, null, null, FAKE_CARRIER_ID1, FAKE_CARRIER_ID1))
+ .setUiccAccessRule(Arrays.asList(UiccAccessRule.decodeRules(
+ FAKE_NATIVE_ACCESS_RULES1)))
+ .build();
+
+ GetEuiccProfileInfoListResult result = new GetEuiccProfileInfoListResult(
+ EuiccService.RESULT_OK, new EuiccProfileInfo[]{profileInfo1}, false);
+ doReturn(result).when(mEuiccController).blockingGetEuiccProfileInfoList(eq(1));
+ doReturn(TelephonyManager.INVALID_PORT_INDEX).when(mUiccSlot)
+ .getPortIndexFromIccId(anyString());
+ doReturn(FAKE_ICCID1).when(mUiccController).convertToCardString(eq(1));
+
+ mSubscriptionManagerServiceUT.updateEmbeddedSubscriptions(List.of(1), null);
+ processAllMessages();
+
+ SubscriptionInfoInternal subInfo = mSubscriptionManagerServiceUT
+ .getSubscriptionInfoInternal(1);
+ assertThat(subInfo.getOnlyNonTerrestrialNetwork()).isEqualTo(1);
+
+ mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
+ FAKE_CARRIER_NAME1);
+ System.setProperty("persist.radio.allow_mock_modem", "false");
+ doReturn(false).when(mFlags).oemEnabledSatelliteFlag();
+ }
+
+ @Test
+ public void testIsSatelliteSpnWithNullCarrierIdentifier() {
+ mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
+ FAKE_CARRIER_NAME1);
+ System.setProperty("persist.radio.allow_mock_modem", "true");
+ doReturn(true).when(mFlags).oemEnabledSatelliteFlag();
+
+ EuiccProfileInfo profileInfo1 = new EuiccProfileInfo.Builder(FAKE_ICCID1)
+ .setIccid(FAKE_ICCID1)
+ .setNickname(FAKE_CARRIER_NAME1)
+ .setServiceProviderName(FAKE_CARRIER_NAME1)
+ .setProfileClass(SubscriptionManager.PROFILE_CLASS_OPERATIONAL)
+ .setCarrierIdentifier(null)
+ .setUiccAccessRule(Arrays.asList(UiccAccessRule.decodeRules(
+ FAKE_NATIVE_ACCESS_RULES1)))
+ .build();
+
+ GetEuiccProfileInfoListResult result = new GetEuiccProfileInfoListResult(
+ EuiccService.RESULT_OK, new EuiccProfileInfo[]{profileInfo1}, false);
+ doReturn(result).when(mEuiccController).blockingGetEuiccProfileInfoList(eq(1));
+ doReturn(TelephonyManager.INVALID_PORT_INDEX).when(mUiccSlot)
+ .getPortIndexFromIccId(anyString());
+ doReturn(FAKE_ICCID1).when(mUiccController).convertToCardString(eq(1));
+
+ mSubscriptionManagerServiceUT.updateEmbeddedSubscriptions(List.of(1), null);
+ processAllMessages();
+
+ SubscriptionInfoInternal subInfo = mSubscriptionManagerServiceUT
+ .getSubscriptionInfoInternal(1);
+ assertThat(subInfo.getOnlyNonTerrestrialNetwork()).isEqualTo(1);
+
+ mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
+ FAKE_CARRIER_NAME1);
+ System.setProperty("persist.radio.allow_mock_modem", "false");
+ doReturn(false).when(mFlags).oemEnabledSatelliteFlag();
+ }
+
+ @Test
+ public void testIsSatelliteSpnWithWrongSpn() {
+ mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
+ FAKE_CARRIER_NAME1);
+ System.setProperty("persist.radio.allow_mock_modem", "true");
+ doReturn(true).when(mFlags).oemEnabledSatelliteFlag();
+
+ EuiccProfileInfo profileInfo1 = new EuiccProfileInfo.Builder(FAKE_ICCID1)
+ .setIccid(FAKE_ICCID1)
+ .setNickname(FAKE_CARRIER_NAME1)
+ .setServiceProviderName(FAKE_CARRIER_NAME2)
+ .setProfileClass(SubscriptionManager.PROFILE_CLASS_OPERATIONAL)
+ .setCarrierIdentifier(new CarrierIdentifier(FAKE_MCC1, FAKE_MNC1,
+ FAKE_CARRIER_NAME1, null, null, null, FAKE_CARRIER_ID1, FAKE_CARRIER_ID1))
+ .setUiccAccessRule(Arrays.asList(UiccAccessRule.decodeRules(
+ FAKE_NATIVE_ACCESS_RULES1)))
+ .build();
+
+ GetEuiccProfileInfoListResult result = new GetEuiccProfileInfoListResult(
+ EuiccService.RESULT_OK, new EuiccProfileInfo[]{profileInfo1}, false);
+ doReturn(result).when(mEuiccController).blockingGetEuiccProfileInfoList(eq(1));
+ doReturn(TelephonyManager.INVALID_PORT_INDEX).when(mUiccSlot)
+ .getPortIndexFromIccId(anyString());
+ doReturn(FAKE_ICCID1).when(mUiccController).convertToCardString(eq(1));
+
+ mSubscriptionManagerServiceUT.updateEmbeddedSubscriptions(List.of(1), null);
+ processAllMessages();
+
+ SubscriptionInfoInternal subInfo = mSubscriptionManagerServiceUT
+ .getSubscriptionInfoInternal(1);
+ assertThat(subInfo.getOnlyNonTerrestrialNetwork()).isEqualTo(0);
+
+ mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
+ FAKE_CARRIER_NAME1);
+ System.setProperty("persist.radio.allow_mock_modem", "false");
+ doReturn(false).when(mFlags).oemEnabledSatelliteFlag();
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/AnswerToResetTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/AnswerToResetTest.java
index 3dba439..2ae08ad 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/AnswerToResetTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/AnswerToResetTest.java
@@ -21,14 +21,13 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
-
public class AnswerToResetTest {
@Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/IccCardStatusTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/IccCardStatusTest.java
index 5d759c2..f035b77 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/IccCardStatusTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/IccCardStatusTest.java
@@ -18,9 +18,10 @@
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
+import androidx.test.filters.SmallTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/IccPhoneBookInterfaceManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/IccPhoneBookInterfaceManagerTest.java
index 143a530..53627ca 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/IccPhoneBookInterfaceManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/IccPhoneBookInterfaceManagerTest.java
@@ -29,7 +29,8 @@
import android.os.AsyncResult;
import android.os.HandlerThread;
import android.os.Message;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.IccPhoneBookInterfaceManager;
import com.android.internal.telephony.IccProvider;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardApplicationTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardApplicationTest.java
index 59bb239..d2490ef 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardApplicationTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardApplicationTest.java
@@ -28,10 +28,11 @@
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.test.SimulatedCommands;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardTest.java
index e4fabc5..33b195c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardTest.java
@@ -21,10 +21,11 @@
import static org.mockito.Mockito.mock;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.TelephonyTest;
import org.junit.After;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRulesTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRulesTest.java
index 15fb729..9a444d7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRulesTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRulesTest.java
@@ -28,10 +28,11 @@
import android.os.AsyncResult;
import android.os.Message;
import android.telephony.UiccAccessRule;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.TelephonyTest;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
index 14e95f1..1a846c4 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
@@ -26,10 +26,11 @@
import android.os.Binder;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telephony.IccLogicalChannelRequest;
import com.android.internal.telephony.TelephonyTest;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java
index a9034eb..ca322e0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java
@@ -129,7 +129,7 @@
ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
mUiccProfile = new UiccProfile(mContext, mSimulatedCommands, mIccCardStatus,
- 0 /* phoneId */, mUiccCard, new Object());
+ 0 /* phoneId */, mUiccCard, new Object(), mFeatureFlags);
verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
listenerArgumentCaptor.capture());
mCarrierConfigChangeListener = listenerArgumentCaptor.getAllValues().get(0);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
index 1d320a3..671f273 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
@@ -428,7 +428,7 @@
mUiccSlot.update(mSimulatedCommands, mIccCardStatus, phoneId, slotIndex);
verify(mTelephonyComponentFactory).makeUiccProfile(
anyObject(), eq(mSimulatedCommands), eq(mIccCardStatus), anyInt(), anyObject(),
- anyObject());
+ anyObject(), anyObject());
assertEquals(IccCardStatus.CardState.CARDSTATE_PRESENT, mUiccSlot.getCardState());
assertNotNull(mUiccSlot.getUiccCard());
@@ -451,7 +451,7 @@
mUiccSlot.update(mSimulatedCommands, mIccCardStatus, phoneId, slotIndex);
verify(mTelephonyComponentFactory).makeUiccProfile(
anyObject(), eq(mSimulatedCommands), eq(mIccCardStatus), anyInt(), anyObject(),
- anyObject());
+ anyObject(), anyObject());
assertEquals(IccCardStatus.CardState.CARDSTATE_PRESENT, mUiccSlot.getCardState());
assertNotNull(mUiccSlot.getUiccCard());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java
index d5b6ccb..8209dfa 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java
@@ -33,7 +33,8 @@
import android.os.Looper;
import android.os.Message;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.R;
import com.android.internal.telephony.TelephonyIntents;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/asn1/Asn1DecoderTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/asn1/Asn1DecoderTest.java
index cfd8b99..c02f965 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/asn1/Asn1DecoderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/asn1/Asn1DecoderTest.java
@@ -23,7 +23,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.uicc.asn1.Asn1Decoder;
import com.android.internal.telephony.uicc.asn1.Asn1Node;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/asn1/Asn1NodeTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/asn1/Asn1NodeTest.java
index e987a1f..27f8940 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/asn1/Asn1NodeTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/asn1/Asn1NodeTest.java
@@ -22,7 +22,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.telephony.uicc.asn1.Asn1Decoder;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/asn1/IccUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/asn1/IccUtilsTest.java
index 9c1dd20..d0b455a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/asn1/IccUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/asn1/IccUtilsTest.java
@@ -20,7 +20,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.uicc.IccUtils;