Merge "Update to check if the s2cellfile is null" into main
diff --git a/flags/calling.aconfig b/flags/calling.aconfig
index e67ebc6..f8de8b2 100644
--- a/flags/calling.aconfig
+++ b/flags/calling.aconfig
@@ -5,6 +5,7 @@
namespace: "telephony"
description: "APIs that are used to notify simultaneous calling changes to other applications."
bug: "297446980"
+ is_exported: true
}
flag {
diff --git a/flags/ims.aconfig b/flags/ims.aconfig
index d09259e..b2cc904 100644
--- a/flags/ims.aconfig
+++ b/flags/ims.aconfig
@@ -62,3 +62,10 @@
description: "This flag updates roaming state to set wfc mode"
bug:"317298331"
}
+
+flag {
+ name: "enable_sip_subscribe_retry"
+ namespace: "telephony"
+ description: "This flag controls whether framework supports SIP subscribe retry or not"
+ bug:"297023230"
+}
diff --git a/flags/telephony.aconfig b/flags/telephony.aconfig
index d59b249..9ef70b1 100644
--- a/flags/telephony.aconfig
+++ b/flags/telephony.aconfig
@@ -26,4 +26,18 @@
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
+}
+
+flag {
+ name: "minimal_telephony_cdm_check"
+ namespace: "telephony"
+ description: "This flag disables Calling/Data/Messaging features if their respective feature is missing"
+ bug: "310710841"
+}
+
+flag {
+ name: "minimal_telephony_managers_conditional_on_features"
+ namespace: "telephony"
+ description: "This flag enables checking for telephony features before initializing corresponding managers"
+ bug: "310710841"
+}
diff --git a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
index 5517bc6..9113514 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.os.AsyncResult;
import android.os.Build;
import android.os.Bundle;
@@ -159,6 +160,12 @@
public GsmCdmaCallTracker(GsmCdmaPhone phone, FeatureFlags featureFlags) {
super(featureFlags);
+ if (mFeatureFlags.minimalTelephonyCdmCheck()
+ && !phone.getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_CALLING)) {
+ throw new UnsupportedOperationException("GsmCdmaCallTracker requires calling");
+ }
+
this.mPhone = phone;
mCi = phone.mCi;
mCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
@@ -1492,7 +1499,7 @@
switch (msg.what) {
case EVENT_POLL_CALLS_RESULT:
- Rlog.d(LOG_TAG, "Event EVENT_POLL_CALLS_RESULT Received");
+ if (DBG_POLL) Rlog.d(LOG_TAG, "Event EVENT_POLL_CALLS_RESULT Received");
if (msg == mLastRelevantPoll) {
if (DBG_POLL) log(
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 911eee5..de7ebd6 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -42,6 +42,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
import android.database.SQLException;
import android.hardware.radio.modem.ImeiInfo;
import android.net.Uri;
@@ -370,9 +371,11 @@
SignalStrengthController.class.getName()).makeSignalStrengthController(this);
mSST = mTelephonyComponentFactory.inject(ServiceStateTracker.class.getName())
.makeServiceStateTracker(this, this.mCi, featureFlags);
- mEmergencyNumberTracker = mTelephonyComponentFactory
- .inject(EmergencyNumberTracker.class.getName()).makeEmergencyNumberTracker(
- this, this.mCi);
+ if (hasCalling()) {
+ mEmergencyNumberTracker = mTelephonyComponentFactory
+ .inject(EmergencyNumberTracker.class.getName()).makeEmergencyNumberTracker(
+ this, this.mCi, mFeatureFlags);
+ }
mDeviceStateMonitor = mTelephonyComponentFactory.inject(DeviceStateMonitor.class.getName())
.makeDeviceStateMonitor(this, mFeatureFlags);
@@ -412,9 +415,11 @@
mCallWaitingController = new CallWaitingController(this);
- loadTtyMode();
+ if (hasCalling()) {
+ loadTtyMode();
- CallManager.getInstance().registerPhone(this);
+ CallManager.getInstance().registerPhone(this);
+ }
mSubscriptionsChangedListener =
new SubscriptionManager.OnSubscriptionsChangedListener() {
@@ -464,13 +469,21 @@
}
};
+ private boolean hasCalling() {
+ if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true;
+ return mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_CALLING);
+ }
+
private void initOnce(CommandsInterface ci) {
if (ci instanceof SimulatedRadioControl) {
mSimulatedRadioControl = (SimulatedRadioControl) ci;
}
- mCT = mTelephonyComponentFactory.inject(GsmCdmaCallTracker.class.getName())
- .makeGsmCdmaCallTracker(this, mFeatureFlags);
+ if (hasCalling()) {
+ mCT = mTelephonyComponentFactory.inject(GsmCdmaCallTracker.class.getName())
+ .makeGsmCdmaCallTracker(this, mFeatureFlags);
+ }
mIccPhoneBookIntManager = mTelephonyComponentFactory
.inject(IccPhoneBookInterfaceManager.class.getName())
.makeIccPhoneBookInterfaceManager(this);
@@ -693,7 +706,7 @@
unregisterForIccRecordEvents();
registerForIccRecordEvents();
- mCT.updatePhoneType();
+ if (mCT != null) mCT.updatePhoneType();
int radioState = mCi.getRadioState();
if (radioState != TelephonyManager.RADIO_POWER_UNAVAILABLE) {
@@ -753,6 +766,8 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@Override
public PhoneConstants.State getState() {
+ if (!hasCalling()) return PhoneConstants.State.IDLE;
+
if (mImsPhone != null) {
PhoneConstants.State imsState = mImsPhone.getState();
if (imsState != PhoneConstants.State.IDLE) {
@@ -837,6 +852,7 @@
@Override
public boolean isDataSuspended() {
+ if (mCT == null) return false;
return mCT.mState != PhoneConstants.State.IDLE && !mSST.isConcurrentVoiceAndDataAllowed();
}
@@ -884,7 +900,7 @@
@Override
public boolean isInEmergencyCall() {
- if (isPhoneTypeGsm()) {
+ if (!hasCalling() || isPhoneTypeGsm()) {
return false;
} else {
return mCT.isInEmergencyCall();
@@ -893,7 +909,7 @@
@Override
protected void setIsInEmergencyCall() {
- if (!isPhoneTypeGsm()) {
+ if (!hasCalling() && !isPhoneTypeGsm()) {
mCT.setIsInEmergencyCall();
}
}
@@ -985,6 +1001,7 @@
@Override
public void acceptCall(int videoState) throws CallStateException {
+ if (!hasCalling()) throw new CallStateException();
Phone imsPhone = mImsPhone;
if ( imsPhone != null && imsPhone.getRingingCall().isRinging() ) {
imsPhone.acceptCall(videoState);
@@ -995,6 +1012,7 @@
@Override
public void rejectCall() throws CallStateException {
+ if (!hasCalling()) throw new CallStateException();
mCT.rejectCall();
}
@@ -1025,6 +1043,7 @@
@Override
public boolean canConference() {
+ if (!hasCalling()) return false;
if (mImsPhone != null && mImsPhone.canConference()) {
return true;
}
@@ -1075,12 +1094,13 @@
@Override
public void clearDisconnected() {
+ if (!hasCalling()) return;
mCT.clearDisconnected();
}
@Override
public boolean canTransfer() {
- if (isPhoneTypeGsm()) {
+ if (hasCalling() && isPhoneTypeGsm()) {
return mCT.canTransfer();
} else {
loge("canTransfer: not possible in CDMA");
@@ -1090,7 +1110,7 @@
@Override
public void explicitCallTransfer() {
- if (isPhoneTypeGsm()) {
+ if (hasCalling() && isPhoneTypeGsm()) {
mCT.explicitCallTransfer();
} else {
loge("explicitCallTransfer: not possible in CDMA");
@@ -1104,11 +1124,13 @@
@Override
public GsmCdmaCall getBackgroundCall() {
+ if (!hasCalling()) return null;
return mCT.mBackgroundCall;
}
@Override
public Call getRingingCall() {
+ if (!hasCalling()) return null;
Phone imsPhone = mImsPhone;
// It returns the ringing call of ImsPhone if the ringing call of GSMPhone isn't ringing.
// In CallManager.registerPhone(), it always registers ringing call of ImsPhone, because
@@ -1184,7 +1206,7 @@
private boolean handleCallDeflectionIncallSupplementaryService(
String dialString) {
- if (dialString.length() > 1) {
+ if (!hasCalling() || dialString.length() > 1) {
return false;
}
@@ -1209,7 +1231,7 @@
private boolean handleCallWaitingIncallSupplementaryService(String dialString) {
int len = dialString.length();
- if (len > 2) {
+ if (!hasCalling() || len > 2) {
return false;
}
@@ -1429,6 +1451,9 @@
@Override
public Connection dial(String dialString, @NonNull DialArgs dialArgs,
Consumer<Phone> chosenPhoneConsumer) throws CallStateException {
+ if (!hasCalling()) {
+ throw new CallStateException("Calling feature is not supported!");
+ }
if (!isPhoneTypeGsm() && dialArgs.uusInfo != null) {
throw new CallStateException("Sending UUS information NOT supported in CDMA!");
}
@@ -2148,7 +2173,9 @@
@Override
public int getEmergencyNumberDbVersion() {
- return getEmergencyNumberTracker().getEmergencyNumberDbVersion();
+ EmergencyNumberTracker tracker = getEmergencyNumberTracker();
+ if (tracker == null) return -1;
+ return tracker.getEmergencyNumberDbVersion();
}
@Override
@@ -3134,6 +3161,8 @@
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private void syncClirSetting() {
+ if (!hasCalling()) return;
+
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
migrateClirSettingIfNeeded(sp);
@@ -3339,8 +3368,10 @@
if (b != null) {
updateBroadcastEmergencyCallStateChangesAfterCarrierConfigChanged(b);
updateCdmaRoamingSettingsAfterCarrierConfigChanged(b);
- updateNrSettingsAfterCarrierConfigChanged(b);
- updateVoNrSettings(b);
+ if (hasCalling()) {
+ updateNrSettingsAfterCarrierConfigChanged(b);
+ updateVoNrSettings(b);
+ }
updateSsOverCdmaSupported(b);
updateCarrierN1ModeSupported(b);
} else {
@@ -4912,6 +4943,7 @@
* Handler of RIL Voice Radio Technology changed event.
*/
private void onVoiceRegStateOrRatChanged(int vrs, int vrat) {
+ if (!hasCalling()) return;
logd("onVoiceRegStateOrRatChanged");
mCT.dispatchCsCallRadioTech(getCsCallRadioTech(vrs, vrat));
}
@@ -5113,6 +5145,8 @@
* Load the current TTY mode in GsmCdmaPhone based on Telecom and UI settings.
*/
private void loadTtyMode() {
+ if (!hasCalling()) return;
+
int ttyMode = TelecomManager.TTY_MODE_OFF;
TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
if (telecomManager != null) {
diff --git a/src/java/com/android/internal/telephony/MultiSimSettingController.java b/src/java/com/android/internal/telephony/MultiSimSettingController.java
index 8488ab0..aaeba23 100644
--- a/src/java/com/android/internal/telephony/MultiSimSettingController.java
+++ b/src/java/com/android/internal/telephony/MultiSimSettingController.java
@@ -35,6 +35,7 @@
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Looper;
@@ -52,6 +53,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.data.DataSettingsManager.DataSettingsManagerCallback;
+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.util.ArrayUtils;
@@ -122,6 +124,7 @@
protected final Context mContext;
private final SubscriptionManagerService mSubscriptionManagerService;
+ private final @NonNull FeatureFlags mFeatureFlags;
// Keep a record of active primary (non-opportunistic) subscription list.
@NonNull private List<Integer> mPrimarySubList = new ArrayList<>();
@@ -201,10 +204,11 @@
/**
* Init instance of MultiSimSettingController.
*/
- public static MultiSimSettingController init(Context context) {
+ public static MultiSimSettingController init(Context context,
+ @NonNull FeatureFlags featureFlags) {
synchronized (MultiSimSettingController.class) {
if (sInstance == null) {
- sInstance = new MultiSimSettingController(context);
+ sInstance = new MultiSimSettingController(context, featureFlags);
} else {
Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
}
@@ -213,9 +217,10 @@
}
@VisibleForTesting
- public MultiSimSettingController(Context context) {
+ public MultiSimSettingController(Context context, @NonNull FeatureFlags featureFlags) {
mContext = context;
mSubscriptionManagerService = SubscriptionManagerService.getInstance();
+ mFeatureFlags = featureFlags;
// Initialize mCarrierConfigLoadedSubIds and register to listen to carrier config change.
TelephonyManager telephonyManager = ((TelephonyManager) mContext.getSystemService(
@@ -239,6 +244,24 @@
onCarrierConfigChanged(slotIndex, subId));
}
+ private boolean hasCalling() {
+ if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true;
+ return mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_CALLING);
+ }
+
+ private boolean hasData() {
+ if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true;
+ return mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_DATA);
+ }
+
+ private boolean hasMessaging() {
+ if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true;
+ return mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_MESSAGING);
+ }
+
/**
* Notify MOBILE_DATA of a subscription is changed.
*/
@@ -606,35 +629,43 @@
|| mActiveModemCount == 1)) {
int subId = mPrimarySubList.get(0);
if (DBG) log("updateDefaultValues: to only primary sub " + subId);
- mSubscriptionManagerService.setDefaultDataSubId(subId);
- mSubscriptionManagerService.setDefaultVoiceSubId(subId);
- mSubscriptionManagerService.setDefaultSmsSubId(subId);
+ if (hasData()) mSubscriptionManagerService.setDefaultDataSubId(subId);
+ if (hasCalling()) mSubscriptionManagerService.setDefaultVoiceSubId(subId);
+ if (hasMessaging()) mSubscriptionManagerService.setDefaultSmsSubId(subId);
sendDefaultSubConfirmedNotification(subId);
return;
}
if (DBG) log("updateDefaultValues: records: " + mPrimarySubList);
- boolean dataSelected, voiceSelected, smsSelected;
+ boolean dataSelected = false;
+ boolean voiceSelected = false;
+ boolean smsSelected = false;
- // Update default data subscription.
- if (DBG) log("updateDefaultValues: Update default data subscription");
- dataSelected = updateDefaultValue(mPrimarySubList,
- mSubscriptionManagerService.getDefaultDataSubId(),
- mSubscriptionManagerService::setDefaultDataSubId);
+ if (hasData()) {
+ // Update default data subscription.
+ if (DBG) log("updateDefaultValues: Update default data subscription");
+ dataSelected = updateDefaultValue(mPrimarySubList,
+ mSubscriptionManagerService.getDefaultDataSubId(),
+ mSubscriptionManagerService::setDefaultDataSubId);
+ }
- // Update default voice subscription.
- if (DBG) log("updateDefaultValues: Update default voice subscription");
- voiceSelected = updateDefaultValue(mPrimarySubList,
- mSubscriptionManagerService.getDefaultVoiceSubId(),
- mSubscriptionManagerService::setDefaultVoiceSubId);
+ if (hasCalling()) {
+ // Update default voice subscription.
+ if (DBG) log("updateDefaultValues: Update default voice subscription");
+ voiceSelected = updateDefaultValue(mPrimarySubList,
+ mSubscriptionManagerService.getDefaultVoiceSubId(),
+ mSubscriptionManagerService::setDefaultVoiceSubId);
+ }
- // Update default sms subscription.
- if (DBG) log("updateDefaultValues: Update default sms subscription");
- smsSelected = updateDefaultValue(mPrimarySubList,
- mSubscriptionManagerService.getDefaultSmsSubId(),
- mSubscriptionManagerService::setDefaultSmsSubId,
- mIsAskEverytimeSupportedForSms);
+ if (hasMessaging()) {
+ // Update default sms subscription.
+ if (DBG) log("updateDefaultValues: Update default sms subscription");
+ smsSelected = updateDefaultValue(mPrimarySubList,
+ mSubscriptionManagerService.getDefaultSmsSubId(),
+ mSubscriptionManagerService::setDefaultSmsSubId,
+ mIsAskEverytimeSupportedForSms);
+ }
boolean autoFallbackEnabled = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_voice_data_sms_auto_fallback);
@@ -1023,11 +1054,11 @@
int autoDefaultSubId = primarySubList.get(0);
- if ((primarySubList.size() == 1) && !smsSelected) {
+ if (hasMessaging() && (primarySubList.size() == 1) && !smsSelected) {
mSubscriptionManagerService.setDefaultSmsSubId(autoDefaultSubId);
}
- if ((primarySubList.size() == 1) && !voiceSelected) {
+ if (hasCalling() && (primarySubList.size() == 1) && !voiceSelected) {
mSubscriptionManagerService.setDefaultVoiceSubId(autoDefaultSubId);
}
@@ -1036,13 +1067,15 @@
log("User pref subId = " + userPrefDataSubId + " current dds " + defaultDataSubId
+ " next active subId " + autoDefaultSubId);
- // If earlier user selected DDS is now available, set that as DDS subId.
- if (primarySubList.contains(userPrefDataSubId)
- && SubscriptionManager.isValidSubscriptionId(userPrefDataSubId)
- && (defaultDataSubId != userPrefDataSubId)) {
- mSubscriptionManagerService.setDefaultDataSubId(userPrefDataSubId);
- } else if (!dataSelected) {
- mSubscriptionManagerService.setDefaultDataSubId(autoDefaultSubId);
+ if (hasData()) {
+ // If earlier user selected DDS is now available, set that as DDS subId.
+ if (primarySubList.contains(userPrefDataSubId)
+ && SubscriptionManager.isValidSubscriptionId(userPrefDataSubId)
+ && (defaultDataSubId != userPrefDataSubId)) {
+ mSubscriptionManagerService.setDefaultDataSubId(userPrefDataSubId);
+ } else if (!dataSelected) {
+ mSubscriptionManagerService.setDefaultDataSubId(autoDefaultSubId);
+ }
}
if (DBG) {
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index 68d24a2..67ca1e1 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -26,6 +26,7 @@
import android.os.Message;
import android.os.PersistableBundle;
import android.os.PowerManager;
+import android.os.SystemClock;
import android.telephony.AccessNetworkConstants;
import android.telephony.Annotation;
import android.telephony.CarrierConfigManager;
@@ -194,6 +195,7 @@
private boolean mIsPhysicalChannelConfigOn;
private boolean mIsPrimaryTimerActive;
private boolean mIsSecondaryTimerActive;
+ private long mSecondaryTimerExpireTimestamp;
private boolean mIsTimerResetEnabledForLegacyStateRrcIdle;
/** Carrier config to reset timers when mccmnc changes */
private boolean mIsTimerResetEnabledOnPlmnChanges;
@@ -220,6 +222,7 @@
// Cached copies below to prevent race conditions
@NonNull private ServiceState mServiceState;
+ /** Used to track link status to be DORMANT or ACTIVE */
@Nullable private List<PhysicalChannelConfig> mPhysicalChannelConfigs;
// Ratchet physical channel config fields to prevent 5G/5G+ flickering
@@ -666,6 +669,7 @@
case EVENT_SECONDARY_TIMER_EXPIRED:
if (DBG) log("Secondary timer expired for state: " + mSecondaryTimerState);
mIsSecondaryTimerActive = false;
+ mSecondaryTimerExpireTimestamp = 0;
mSecondaryTimerState = "";
updateTimers();
mLastShownNrDueToAdvancedBand = false;
@@ -1251,6 +1255,8 @@
private void updatePhysicalChannelConfigs(List<PhysicalChannelConfig> physicalChannelConfigs) {
boolean isPccListEmpty = physicalChannelConfigs == null || physicalChannelConfigs.isEmpty();
if (isPccListEmpty && isUsingPhysicalChannelConfigForRrcDetection()) {
+ // Clear mPrimaryCellChangedWhileIdle to allow later potential one-off PCI change.
+ // Update link status to be DORMANT, but keep ratcheted bands.
log("Physical channel configs updated: not updating PCC fields for empty PCC list "
+ "indicating RRC idle.");
mPrimaryCellChangedWhileIdle = false;
@@ -1310,6 +1316,7 @@
+ mLastAnchorNrCellId + " -> " + anchorNrCellId);
mPrimaryCellChangedWhileIdle = true;
mLastAnchorNrCellId = anchorNrCellId;
+ reduceSecondaryTimerIfNeeded();
return;
}
if (mRatchetPccFieldsForSameAnchorNrCell) {
@@ -1330,6 +1337,27 @@
}
}
+ /**
+ * Called when PCI change, specifically during idle state.
+ */
+ private void reduceSecondaryTimerIfNeeded() {
+ if (!mIsSecondaryTimerActive || mNrAdvancedBandsSecondaryTimer <= 0) return;
+ // Secondary timer is active, so we must have a valid secondary rule right now.
+ OverrideTimerRule secondaryRule = mOverrideTimerRules.get(mPrimaryTimerState);
+ if (secondaryRule != null) {
+ int secondaryDuration = secondaryRule.getSecondaryTimer(mSecondaryTimerState);
+ long durationMillis = secondaryDuration * 1000L;
+ if ((mSecondaryTimerExpireTimestamp - SystemClock.uptimeMillis()) > durationMillis) {
+ if (DBG) log("Due to PCI change, reduce the secondary timer to " + durationMillis);
+ removeMessages(EVENT_SECONDARY_TIMER_EXPIRED);
+ sendMessageDelayed(EVENT_SECONDARY_TIMER_EXPIRED, mSecondaryTimerState,
+ durationMillis);
+ }
+ } else {
+ loge("!! Secondary timer is active, but found no rule for " + mPrimaryTimerState);
+ }
+ }
+
private void transitionWithTimerTo(IState destState) {
String destName = destState.getName();
if (mIsPrimaryTimerActive) {
@@ -1369,7 +1397,9 @@
mSecondaryTimerState = currentName;
mPreviousState = currentName;
mIsSecondaryTimerActive = true;
- sendMessageDelayed(EVENT_SECONDARY_TIMER_EXPIRED, destState, duration * 1000L);
+ long durationMillis = duration * 1000L;
+ mSecondaryTimerExpireTimestamp = SystemClock.uptimeMillis() + durationMillis;
+ sendMessageDelayed(EVENT_SECONDARY_TIMER_EXPIRED, destState, durationMillis);
}
mIsPrimaryTimerActive = false;
transitionTo(getCurrentState());
@@ -1434,6 +1464,7 @@
}
removeMessages(EVENT_SECONDARY_TIMER_EXPIRED);
mIsSecondaryTimerActive = false;
+ mSecondaryTimerExpireTimestamp = 0;
mSecondaryTimerState = "";
transitionToCurrentState();
return;
@@ -1464,6 +1495,7 @@
removeMessages(EVENT_SECONDARY_TIMER_EXPIRED);
mIsPrimaryTimerActive = false;
mIsSecondaryTimerActive = false;
+ mSecondaryTimerExpireTimestamp = 0;
mPrimaryTimerState = "";
mSecondaryTimerState = "";
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index c5bc428..803fb19 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -212,7 +212,7 @@
Looper.myLooper(), featureFlags);
TelephonyComponentFactory.getInstance().inject(MultiSimSettingController.class.
- getName()).initMultiSimSettingController(context);
+ getName()).initMultiSimSettingController(context, featureFlags);
if (context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY_EUICC)) {
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 5177adb..8b3be1e 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -31,6 +31,7 @@
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.hardware.radio.V1_0.IRadio;
import android.hardware.radio.V1_0.RadioError;
import android.hardware.radio.V1_0.RadioIndicationType;
@@ -271,6 +272,13 @@
static final String[] HIDL_SERVICE_NAME = {"slot1", "slot2", "slot3"};
+ private static final Map<String, Integer> FEATURES_TO_SERVICES = Map.ofEntries(
+ Map.entry(PackageManager.FEATURE_TELEPHONY_CALLING, HAL_SERVICE_VOICE),
+ Map.entry(PackageManager.FEATURE_TELEPHONY_DATA, HAL_SERVICE_DATA),
+ Map.entry(PackageManager.FEATURE_TELEPHONY_MESSAGING, HAL_SERVICE_MESSAGING),
+ Map.entry(PackageManager.FEATURE_TELEPHONY_IMS, HAL_SERVICE_IMS)
+ );
+
public static List<TelephonyHistogram> getTelephonyRILTimingHistograms() {
List<TelephonyHistogram> list;
synchronized (sRilTimeHistograms) {
@@ -621,6 +629,7 @@
if (mDisabledRadioServices.get(HAL_SERVICE_RADIO).contains(mPhoneId)) {
riljLoge("getRadioProxy: mRadioProxy for " + HIDL_SERVICE_NAME[mPhoneId]
+ " is disabled");
+ return null;
} else {
try {
mRadioProxy = android.hardware.radio.V1_6.IRadio.getService(
@@ -662,6 +671,7 @@
mDisabledRadioServices.get(HAL_SERVICE_RADIO).add(mPhoneId);
riljLoge("getRadioProxy: set mRadioProxy for "
+ HIDL_SERVICE_NAME[mPhoneId] + " as disabled");
+ return null;
}
}
} catch (RemoteException e) {
@@ -718,6 +728,9 @@
public synchronized RadioServiceProxy getRadioServiceProxy(int service) {
if (!SubscriptionManager.isValidPhoneId(mPhoneId)) return mServiceProxies.get(service);
if ((service >= HAL_SERVICE_IMS) && !isRadioServiceSupported(service)) {
+ riljLogw("getRadioServiceProxy: " + serviceToString(service) + " for "
+ + HIDL_SERVICE_NAME[mPhoneId] + " is not supported\n"
+ + android.util.Log.getStackTraceString(new RuntimeException()));
return mServiceProxies.get(service);
}
if (!mIsCellularSupported) {
@@ -733,7 +746,9 @@
try {
if (mMockModem == null && mDisabledRadioServices.get(service).contains(mPhoneId)) {
riljLoge("getRadioServiceProxy: " + serviceToString(service) + " for "
- + HIDL_SERVICE_NAME[mPhoneId] + " is disabled");
+ + HIDL_SERVICE_NAME[mPhoneId] + " is disabled\n"
+ + android.util.Log.getStackTraceString(new RuntimeException()));
+ return null;
} else {
IBinder binder;
switch (service) {
@@ -944,7 +959,8 @@
mDisabledRadioServices.get(service).add(mPhoneId);
mHalVersion.put(service, RADIO_HAL_VERSION_UNKNOWN);
riljLoge("getRadioServiceProxy: set " + serviceToString(service) + " for "
- + HIDL_SERVICE_NAME[mPhoneId] + " as disabled");
+ + HIDL_SERVICE_NAME[mPhoneId] + " as disabled\n"
+ + android.util.Log.getStackTraceString(new RuntimeException()));
}
}
} catch (RemoteException e) {
@@ -1094,9 +1110,16 @@
tdc.registerRIL(this);
}
+ validateFeatureFlags();
+
// Set radio callback; needed to set RadioIndication callback (should be done after
// wakelock stuff is initialized above as callbacks are received on separate binder threads)
for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) {
+ if (!isRadioServiceSupported(service)) {
+ riljLog("Not initializing " + serviceToString(service) + " (not supported)");
+ continue;
+ }
+
if (service == HAL_SERVICE_RADIO) {
getRadioProxy();
} else {
@@ -1161,6 +1184,26 @@
return false;
}
+ private void validateFeatureFlags() {
+ PackageManager pm = mContext.getPackageManager();
+ for (var entry : FEATURES_TO_SERVICES.entrySet()) {
+ String feature = entry.getKey();
+ int service = entry.getValue();
+
+ boolean hasFeature = pm.hasSystemFeature(feature);
+ boolean hasService = isRadioServiceSupported(service);
+
+ if (hasFeature && !hasService) {
+ riljLoge("Feature " + feature + " is declared, but service "
+ + serviceToString(service) + " is missing");
+ }
+ if (!hasFeature && hasService) {
+ riljLoge("Service " + serviceToString(service) + " is available, but feature "
+ + feature + " is not declared");
+ }
+ }
+ }
+
private boolean isRadioBugDetectionEnabled() {
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.ENABLE_RADIO_BUG_DETECTION, 1) != 0;
diff --git a/src/java/com/android/internal/telephony/RadioInterfaceCapabilityController.java b/src/java/com/android/internal/telephony/RadioInterfaceCapabilityController.java
index bab4d12..4d9196e 100644
--- a/src/java/com/android/internal/telephony/RadioInterfaceCapabilityController.java
+++ b/src/java/com/android/internal/telephony/RadioInterfaceCapabilityController.java
@@ -86,6 +86,13 @@
register();
}
+ private void requestCapabilities() {
+ if (mRadioInterfaceCapabilities != null) return;
+
+ mRadioConfig.getHalDeviceCapabilities(obtainMessage(
+ EVENT_GET_HAL_DEVICE_CAPABILITIES_DONE));
+ }
+
/**
* Gets the radio interface capabilities for the device
*/
@@ -95,8 +102,7 @@
// Only incur cost of synchronization block if mRadioInterfaceCapabilities isn't null
synchronized (mLockRadioInterfaceCapabilities) {
if (mRadioInterfaceCapabilities == null) {
- mRadioConfig.getHalDeviceCapabilities(
- obtainMessage(EVENT_GET_HAL_DEVICE_CAPABILITIES_DONE));
+ requestCapabilities();
try {
if (Looper.myLooper() != getLooper()) {
mLockRadioInterfaceCapabilities.wait(2000);
@@ -158,7 +164,7 @@
switch (msg.what) {
case Phone.EVENT_RADIO_AVAILABLE:
case Phone.EVENT_RADIO_ON:
- getCapabilities();
+ requestCapabilities();
break;
case EVENT_GET_HAL_DEVICE_CAPABILITIES_DONE:
setupCapabilities((AsyncResult) msg.obj);
diff --git a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
index 04776b1..5da4b12 100644
--- a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
+++ b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
@@ -305,8 +305,9 @@
/**
* Create a new EmergencyNumberTracker.
*/
- public EmergencyNumberTracker makeEmergencyNumberTracker(Phone phone, CommandsInterface ci) {
- return new EmergencyNumberTracker(phone, ci);
+ public EmergencyNumberTracker makeEmergencyNumberTracker(Phone phone, CommandsInterface ci,
+ @NonNull FeatureFlags featureFlags) {
+ return new EmergencyNumberTracker(phone, ci, featureFlags);
}
private static final boolean USE_NEW_NITZ_STATE_MACHINE = true;
@@ -507,8 +508,9 @@
* @param c The context.
* @return The multi sim settings controller instance.
*/
- public MultiSimSettingController initMultiSimSettingController(Context c) {
- return MultiSimSettingController.init(c);
+ public MultiSimSettingController initMultiSimSettingController(Context c,
+ @NonNull FeatureFlags featureFlags) {
+ return MultiSimSettingController.init(c, featureFlags);
}
/**
@@ -571,9 +573,11 @@
* @return The data settings manager instance.
*/
public @NonNull DataSettingsManager makeDataSettingsManager(@NonNull Phone phone,
- @NonNull DataNetworkController dataNetworkController, @NonNull Looper looper,
+ @NonNull DataNetworkController dataNetworkController,
+ @NonNull FeatureFlags featureFlags, @NonNull Looper looper,
@NonNull DataSettingsManager.DataSettingsManagerCallback callback) {
- return new DataSettingsManager(phone, dataNetworkController, looper, callback);
+ return new DataSettingsManager(phone, dataNetworkController, featureFlags, looper,
+ callback);
}
/** Create CellularNetworkSecuritySafetySource. */
diff --git a/src/java/com/android/internal/telephony/data/DataNetwork.java b/src/java/com/android/internal/telephony/data/DataNetwork.java
index 97f8c5a..0dbbc5c 100644
--- a/src/java/com/android/internal/telephony/data/DataNetwork.java
+++ b/src/java/com/android/internal/telephony/data/DataNetwork.java
@@ -1180,12 +1180,14 @@
mPhone.getServiceStateTracker().registerForCssIndicatorChanged(
getHandler(), EVENT_CSS_INDICATOR_CHANGED, null);
- mPhone.getCallTracker().registerForVoiceCallStarted(
- getHandler(), EVENT_VOICE_CALL_STARTED, null);
- mPhone.getCallTracker().registerForVoiceCallEnded(
- getHandler(), EVENT_VOICE_CALL_ENDED, null);
+ if (mPhone.getCallTracker() != null) {
+ mPhone.getCallTracker().registerForVoiceCallStarted(
+ getHandler(), EVENT_VOICE_CALL_STARTED, null);
+ mPhone.getCallTracker().registerForVoiceCallEnded(
+ getHandler(), EVENT_VOICE_CALL_ENDED, null);
+ }
// Check null for devices not supporting FEATURE_TELEPHONY_IMS.
- if (mPhone.getImsPhone() != null) {
+ if (mPhone.getImsPhone() != null && mPhone.getImsPhone().getCallTracker() != null) {
mPhone.getImsPhone().getCallTracker().registerForVoiceCallStarted(
getHandler(), EVENT_VOICE_CALL_STARTED, null);
mPhone.getImsPhone().getCallTracker().registerForVoiceCallEnded(
@@ -1223,12 +1225,14 @@
}
// Check null for devices not supporting FEATURE_TELEPHONY_IMS.
- if (mPhone.getImsPhone() != null) {
+ if (mPhone.getImsPhone() != null && mPhone.getImsPhone().getCallTracker() != null) {
mPhone.getImsPhone().getCallTracker().unregisterForVoiceCallStarted(getHandler());
mPhone.getImsPhone().getCallTracker().unregisterForVoiceCallEnded(getHandler());
}
- mPhone.getCallTracker().unregisterForVoiceCallStarted(getHandler());
- mPhone.getCallTracker().unregisterForVoiceCallEnded(getHandler());
+ if (mPhone.getCallTracker() != null) {
+ mPhone.getCallTracker().unregisterForVoiceCallStarted(getHandler());
+ mPhone.getCallTracker().unregisterForVoiceCallEnded(getHandler());
+ }
mPhone.getServiceStateTracker().unregisterForCssIndicatorChanged(getHandler());
TelephonyManager tm = mPhone.getContext().getSystemService(TelephonyManager.class);
@@ -2514,7 +2518,8 @@
newSuspendedState = true;
// Check voice/data concurrency.
} else if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()
- && mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
+ && mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN
+ && mPhone.getCallTracker() != null) {
newSuspendedState = mPhone.getCallTracker().getState() != PhoneConstants.State.IDLE;
}
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index 1501b58..70d3b23 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -26,6 +26,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
import android.net.NetworkPolicyManager;
@@ -426,6 +427,12 @@
}
};
+ private boolean hasCalling() {
+ if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true;
+ return mPhone.getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_CALLING);
+ }
+
/**
* The sorted network request list by priority. The highest priority network request stays at
* the head of the list. The highest priority is 100, the lowest is 0.
@@ -861,7 +868,7 @@
mDataSettingsManager = TelephonyComponentFactory.getInstance().inject(
DataSettingsManager.class.getName())
- .makeDataSettingsManager(mPhone, this, looper,
+ .makeDataSettingsManager(mPhone, this, mFeatureFlags, looper,
new DataSettingsManagerCallback(this::post) {
@Override
public void onDataEnabledChanged(boolean enabled,
@@ -1045,16 +1052,18 @@
}
}, this::post);
- // Register for call ended event for voice/data concurrent not supported case. It is
- // intended to only listen for events from the same phone as most of the telephony modules
- // are designed as per-SIM basis. For DSDS call ended on non-DDS sub, the frameworks relies
- // on service state on DDS sub change from out-of-service to in-service to trigger data
- // retry.
- mPhone.getCallTracker().registerForVoiceCallEnded(this, EVENT_VOICE_CALL_ENDED, null);
- // Check null for devices not supporting FEATURE_TELEPHONY_IMS.
- if (mPhone.getImsPhone() != null) {
- mPhone.getImsPhone().getCallTracker().registerForVoiceCallEnded(
- this, EVENT_VOICE_CALL_ENDED, null);
+ if (hasCalling()) {
+ // Register for call ended event for voice/data concurrent not supported case. It is
+ // intended to only listen for events from the same phone as most of the telephony
+ // modules are designed as per-SIM basis. For DSDS call ended on non-DDS sub, the
+ // frameworks relies on service state on DDS sub change from out-of-service to
+ // in-service to trigger data retry.
+ mPhone.getCallTracker().registerForVoiceCallEnded(this, EVENT_VOICE_CALL_ENDED, null);
+ // Check null for devices not supporting FEATURE_TELEPHONY_IMS.
+ if (mPhone.getImsPhone() != null) {
+ mPhone.getImsPhone().getCallTracker().registerForVoiceCallEnded(
+ this, EVENT_VOICE_CALL_ENDED, null);
+ }
}
mPhone.mCi.registerForSlicingConfigChanged(this, EVENT_SLICE_CONFIG_CHANGED, null);
mPhone.mCi.registerForSrvccStateChanged(this, EVENT_SRVCC_STATE_CHANGED, null);
@@ -1569,7 +1578,7 @@
}
// Check CS call state and see if concurrent voice/data is allowed.
- if (mPhone.getCallTracker().getState() != PhoneConstants.State.IDLE
+ if (hasCalling() && mPhone.getCallTracker().getState() != PhoneConstants.State.IDLE
&& !mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
evaluation.addDataDisallowedReason(
DataDisallowedReason.CONCURRENT_VOICE_DATA_NOT_ALLOWED);
diff --git a/src/java/com/android/internal/telephony/data/DataSettingsManager.java b/src/java/com/android/internal/telephony/data/DataSettingsManager.java
index e54f6d3..51e5b7d 100644
--- a/src/java/com/android/internal/telephony/data/DataSettingsManager.java
+++ b/src/java/com/android/internal/telephony/data/DataSettingsManager.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.content.ContentResolver;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -47,6 +48,7 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.SettingsObserver;
import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.DeviceTelephonyPropertiesStats;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
@@ -57,6 +59,7 @@
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
@@ -88,6 +91,7 @@
private static final int EVENT_INITIALIZE = 11;
private final Phone mPhone;
+ private final @NonNull FeatureFlags mFeatureFlags;
private final ContentResolver mResolver;
private final SettingsObserver mSettingsObserver;
private final String mLogTag;
@@ -178,10 +182,12 @@
* @param callback Data settings manager callback.
*/
public DataSettingsManager(@NonNull Phone phone,
- @NonNull DataNetworkController dataNetworkController, @NonNull Looper looper,
+ @NonNull DataNetworkController dataNetworkController,
+ @NonNull FeatureFlags featureFlags, @NonNull Looper looper,
@NonNull DataSettingsManagerCallback callback) {
super(looper);
mPhone = phone;
+ mFeatureFlags = Objects.requireNonNull(featureFlags);
mLogTag = "DSMGR-" + mPhone.getPhoneId();
log("DataSettingsManager created.");
mSubId = mPhone.getSubId();
@@ -264,6 +270,12 @@
}
}
+ private boolean hasCalling() {
+ if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true;
+ return mPhone.getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_CALLING);
+ }
+
/**
* Called when needed to register for all events that data network controller is interested.
*/
@@ -281,9 +293,12 @@
mSettingsObserver.observe(
Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED),
EVENT_PROVISIONING_DATA_ENABLED_CHANGED);
- mPhone.getCallTracker().registerForVoiceCallStarted(this, EVENT_CALL_STATE_CHANGED, null);
- mPhone.getCallTracker().registerForVoiceCallEnded(this, EVENT_CALL_STATE_CHANGED, null);
- if (mPhone.getImsPhone() != null) {
+ if (hasCalling()) {
+ mPhone.getCallTracker().registerForVoiceCallStarted(this, EVENT_CALL_STATE_CHANGED,
+ null);
+ mPhone.getCallTracker().registerForVoiceCallEnded(this, EVENT_CALL_STATE_CHANGED, null);
+ }
+ if (hasCalling() && mPhone.getImsPhone() != null) {
mPhone.getImsPhone().getCallTracker().registerForVoiceCallStarted(
this, EVENT_CALL_STATE_CHANGED, null);
mPhone.getImsPhone().getCallTracker().registerForVoiceCallEnded(
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
index e2418c5..02dd613 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
@@ -16,10 +16,12 @@
package com.android.internal.telephony.emergency;
+import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.AsyncResult;
import android.os.Environment;
@@ -48,6 +50,7 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.EmergencyNumberStats;
import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.internal.telephony.nano.PersistAtomsProto;
@@ -102,6 +105,7 @@
private final CommandsInterface mCi;
private final Phone mPhone;
+ private final @NonNull FeatureFlags mFeatureFlags;
private int mPhoneId;
private String mCountryIso;
private String mLastKnownEmergencyCountryIso = "";
@@ -173,10 +177,20 @@
}
};
- public EmergencyNumberTracker(Phone phone, CommandsInterface ci) {
+ public EmergencyNumberTracker(Phone phone, CommandsInterface ci,
+ @NonNull FeatureFlags featureFlags) {
+ Context ctx = phone.getContext();
+
mPhone = phone;
mCi = ci;
- mResources = mPhone.getContext().getResources();
+ mFeatureFlags = featureFlags;
+ mResources = ctx.getResources();
+
+ if (mFeatureFlags.minimalTelephonyCdmCheck()
+ && !ctx.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_CALLING)) {
+ throw new UnsupportedOperationException("EmergencyNumberTracker requires calling");
+ }
if (mPhone != null) {
mPhoneId = phone.getPhoneId();
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index b5a052d..dcb3b20 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -3580,14 +3580,13 @@
ImsPhoneConnection conn = findConnection(imsCall);
// Since onCallInitiating and onCallProgressing reset mPendingMO,
// we can't depend on mPendingMO.
- if ((reasonInfo.getCode() == ImsReasonInfo.CODE_SIP_ALTERNATE_EMERGENCY_CALL
- || reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED
- || reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED)
- && conn != null) {
+ if (conn != null) {
logi("onCallStartFailed eccCategory=" + eccCategory);
- if (reasonInfo.getCode() == ImsReasonInfo.CODE_SIP_ALTERNATE_EMERGENCY_CALL
- || reasonInfo.getExtraCode()
- == ImsReasonInfo.EXTRA_CODE_CALL_RETRY_EMERGENCY) {
+ int reason = reasonInfo.getCode();
+ int extraCode = reasonInfo.getExtraCode();
+ if ((reason == ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED
+ && extraCode == ImsReasonInfo.EXTRA_CODE_CALL_RETRY_EMERGENCY)
+ || (reason == ImsReasonInfo.CODE_SIP_ALTERNATE_EMERGENCY_CALL)) {
conn.setNonDetectableEmergencyCallInfo(eccCategory);
}
conn.setImsReasonInfo(reasonInfo);
diff --git a/src/java/com/android/internal/telephony/metrics/CellularSecurityTransparencyStats.java b/src/java/com/android/internal/telephony/metrics/CellularSecurityTransparencyStats.java
new file mode 100644
index 0000000..f77474f
--- /dev/null
+++ b/src/java/com/android/internal/telephony/metrics/CellularSecurityTransparencyStats.java
@@ -0,0 +1,86 @@
+/*
+ * 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.metrics;
+
+import android.telephony.CellularIdentifierDisclosure;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.TelephonyStatsLog;
+import com.android.telephony.Rlog;
+
+/**
+ * Facilitates writing stats relating to cellular transparency features. Delegates the actual
+ * writing of stats out to {@link TelephonyStatsLog}.
+ */
+public class CellularSecurityTransparencyStats {
+
+ private static final String LOG_TAG = "CellularSecurityTransparencyStats";
+ private static final String LOG_DESCRIPTOR_SIM_MCC = "SIM MCC";
+ private static final String LOG_DESCRIPTOR_SIM_MNC = "SIM MNC";
+ private static final String LOG_DESCRIPTOR_DISCLOSURE_MCC = "disclosure MCC";
+ private static final String LOG_DESCRIPTOR_DISCLOSURE_MNC = "disclosure MNC";
+ private static final int DEFAULT_PLMN_PART = -1;
+
+ /**
+ * Log an identifier disclosure to be written out to {@link TelephonyStatsLog}
+ */
+ public void logIdentifierDisclosure(CellularIdentifierDisclosure disclosure, String simMcc,
+ String simMnc, boolean notificationsEnabled) {
+
+ int mcc = parsePlmnPartOrDefault(simMcc, LOG_DESCRIPTOR_SIM_MCC);
+ int mnc = parsePlmnPartOrDefault(simMnc, LOG_DESCRIPTOR_SIM_MNC);
+
+ int disclosureMcc = DEFAULT_PLMN_PART;
+ int disclosureMnc = DEFAULT_PLMN_PART;
+ String plmn = disclosure.getPlmn();
+ if (plmn != null) {
+ String[] plmnParts = plmn.split("-");
+ if (plmnParts.length == 2) {
+ disclosureMcc = parsePlmnPartOrDefault(plmnParts[0], LOG_DESCRIPTOR_DISCLOSURE_MCC);
+ disclosureMnc = parsePlmnPartOrDefault(plmnParts[1], LOG_DESCRIPTOR_DISCLOSURE_MNC);
+ }
+ }
+
+ writeIdentifierDisclosure(mcc, mnc, disclosureMcc, disclosureMnc,
+ disclosure.getCellularIdentifier(), disclosure.getNasProtocolMessage(),
+ disclosure.isEmergency(), notificationsEnabled);
+
+ }
+
+ private int parsePlmnPartOrDefault(String input, String logDescriptor) {
+ try {
+ return Integer.parseInt(input);
+ } catch (NumberFormatException e) {
+ Rlog.d(LOG_TAG, "Failed to parse " + logDescriptor + ": " + input);
+ }
+
+ return DEFAULT_PLMN_PART;
+ }
+
+ /**
+ * Write identifier disclosure data out to {@link TelephonyStatsLog}. This method is split
+ * out to enable testing, since {@link TelephonyStatsLog} is a final static class.
+ */
+ @VisibleForTesting
+ public void writeIdentifierDisclosure(int mcc, int mnc, int disclosureMcc, int disclosureMnc,
+ int identifier, int protocolMessage, boolean isEmergency,
+ boolean areNotificationsEnabled) {
+ TelephonyStatsLog.write(TelephonyStatsLog.CELLULAR_IDENTIFIER_DISCLOSED, mcc, mnc,
+ disclosureMcc, disclosureMnc, identifier, protocolMessage, isEmergency,
+ areNotificationsEnabled);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
index a315f1e..856045f 100644
--- a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
+++ b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
@@ -138,14 +138,6 @@
private static final long MIN_COOLDOWN_MILLIS =
DBG ? 10L * MILLIS_PER_SECOND : 23L * MILLIS_PER_HOUR;
- /**
- * Sets atom pull cool down to 4 minutes for userdebug build.
- *
- * <p>Applies to certain atoms: CellularServiceState.
- */
- private static final long CELL_SERVICE_MIN_COOLDOWN_MILLIS =
- DBG ? 10L * MILLIS_PER_SECOND :
- IS_DEBUGGABLE ? 4L * MILLIS_PER_MINUTE : 23L * MILLIS_PER_HOUR;
/**
* Buckets with less than these many calls will be dropped.
@@ -166,6 +158,13 @@
private static final long CELL_SERVICE_DURATION_BUCKET_MILLIS =
DBG || IS_DEBUGGABLE ? 2L * MILLIS_PER_SECOND : 5L * MILLIS_PER_MINUTE;
+ /**
+ * Sets atom pull cool down to 4 minutes for userdebug build, 5 hours for user build.
+ *
+ * <p>Applies to certain atoms: CellularServiceState, DataCallSession,
+ * ImsRegistrationTermination.
+ */
+ private final long mPowerCorrelatedMinCooldownMillis;
private final PersistAtomsStorage mStorage;
private final DeviceStateHelper mDeviceStateHelper;
private final StatsManager mStatsManager;
@@ -234,6 +233,9 @@
mAirplaneModeStats = new AirplaneModeStats(context);
mDefaultNetworkMonitor = new DefaultNetworkMonitor(context, featureFlags);
+ mPowerCorrelatedMinCooldownMillis = DBG ? 10L * MILLIS_PER_SECOND :
+ IS_DEBUGGABLE ? 4L * MILLIS_PER_MINUTE : (long) context.getResources().getInteger(
+ com.android.internal.R.integer.config_metrics_pull_cooldown_millis);
}
/**
@@ -516,7 +518,8 @@
private int pullDataCallSession(List<StatsEvent> data) {
// Include ongoing data call segments
concludeDataCallSessionStats();
- DataCallSession[] dataCallSessions = mStorage.getDataCallSessions(MIN_COOLDOWN_MILLIS);
+ DataCallSession[] dataCallSessions = mStorage.getDataCallSessions(
+ mPowerCorrelatedMinCooldownMillis);
if (dataCallSessions != null) {
Arrays.stream(dataCallSessions)
.forEach(dataCall -> data.add(buildStatsEvent(dataCall)));
@@ -544,8 +547,8 @@
private int pullCellularServiceState(List<StatsEvent> data) {
// Include the latest durations
concludeServiceStateStats();
- CellularServiceState[] persistAtoms =
- mStorage.getCellularServiceStates(CELL_SERVICE_MIN_COOLDOWN_MILLIS);
+ CellularServiceState[] persistAtoms = mStorage.getCellularServiceStates(
+ mPowerCorrelatedMinCooldownMillis);
if (persistAtoms != null) {
// list is already shuffled when instances were inserted
Arrays.stream(persistAtoms)
@@ -573,8 +576,8 @@
}
private int pullImsRegistrationTermination(List<StatsEvent> data) {
- ImsRegistrationTermination[] persistAtoms =
- mStorage.getImsRegistrationTerminations(MIN_COOLDOWN_MILLIS);
+ ImsRegistrationTermination[] persistAtoms = mStorage.getImsRegistrationTerminations(
+ mPowerCorrelatedMinCooldownMillis);
if (persistAtoms != null) {
// list is already shuffled when instances were inserted
Arrays.stream(persistAtoms)
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 2f28575..92d9372 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -93,6 +93,7 @@
import android.telephony.satellite.SatelliteDatagram;
import android.telephony.satellite.SatelliteManager;
import android.util.Log;
+import android.util.Pair;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.uwb.UwbManager;
@@ -2518,6 +2519,12 @@
logd("getSatellitePlmnsForCarrier: carrierEnabledSatelliteFlag is disabled");
return new ArrayList<>();
}
+
+ if (!isSatelliteSupportedViaCarrier(subId)) {
+ logd("Satellite for carrier is not supported.");
+ return new ArrayList<>();
+ }
+
synchronized (mSupportedSatelliteServicesLock) {
return mMergedPlmnListPerCarrier.get(subId, new ArrayList<>()).stream().toList();
}
@@ -2596,21 +2603,21 @@
}
/**
- * @return {@code true} if any subscription on the device is connected to satellite,
- * {@code false} otherwise.
+ * @return {@code Pair<true, subscription ID>} if any subscription on the device is connected to
+ * satellite, {@code Pair<false, null>} otherwise.
*/
- private boolean isUsingNonTerrestrialNetworkViaCarrier() {
+ private Pair<Boolean, Integer> isUsingNonTerrestrialNetworkViaCarrier() {
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
logd("isUsingNonTerrestrialNetwork: carrierEnabledSatelliteFlag is disabled");
- return false;
+ return new Pair<>(false, null);
}
for (Phone phone : PhoneFactory.getPhones()) {
ServiceState serviceState = phone.getServiceState();
if (serviceState != null && serviceState.isUsingNonTerrestrialNetwork()) {
- return true;
+ return new Pair<>(true, phone.getSubId());
}
}
- return false;
+ return new Pair<>(false, null);
}
/**
@@ -2624,7 +2631,7 @@
+ " is disabled");
return false;
}
- if (isUsingNonTerrestrialNetworkViaCarrier()) {
+ if (isUsingNonTerrestrialNetworkViaCarrier().first) {
return true;
}
for (Phone phone : PhoneFactory.getPhones()) {
@@ -3996,7 +4003,13 @@
}
private void determineSystemNotification() {
- if (isUsingNonTerrestrialNetworkViaCarrier()) {
+ if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
+ logd("determineSystemNotification: carrierEnabledSatelliteFlag is disabled");
+ return;
+ }
+
+ Pair<Boolean, Integer> isNtn = isUsingNonTerrestrialNetworkViaCarrier();
+ if (isNtn.first) {
if (mSharedPreferences == null) {
try {
mSharedPreferences = mContext.getSharedPreferences(SATELLITE_SHARED_PREF,
@@ -4006,18 +4019,18 @@
}
}
if (mSharedPreferences == null) {
- loge("handleEventServiceStateChanged: Cannot get default shared preferences");
+ loge("determineSystemNotification: Cannot get default shared preferences");
return;
}
if (!mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false)) {
- showSatelliteSystemNotification();
+ showSatelliteSystemNotification(isNtn.second);
mSharedPreferences.edit().putBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY,
true).apply();
}
}
}
- private void showSatelliteSystemNotification() {
+ private void showSatelliteSystemNotification(int subId) {
logd("showSatelliteSystemNotification");
final NotificationChannel notificationChannel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID,
@@ -4055,6 +4068,7 @@
// Add action to invoke Satellite setting activity in Settings.
Intent intentSatelliteSetting = new Intent(ACTION_SATELLITE_SETTING);
+ intentSatelliteSetting.putExtra("sub_id", subId);
PendingIntent pendingIntentSatelliteSetting = PendingIntent.getActivity(mContext, 0,
intentSatelliteSetting, PendingIntent.FLAG_IMMUTABLE);
diff --git a/src/java/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifier.java b/src/java/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifier.java
index 4540b8a..8591e86 100644
--- a/src/java/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifier.java
+++ b/src/java/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifier.java
@@ -21,6 +21,9 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.metrics.CellularSecurityTransparencyStats;
+import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.telephony.Rlog;
import java.time.Instant;
@@ -62,13 +65,13 @@
// 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;
+ private SubscriptionManagerService mSubscriptionManagerService;
+ private CellularSecurityTransparencyStats mCellularSecurityTransparencyStats;
public CellularIdentifierDisclosureNotifier(CellularNetworkSecuritySafetySource safetySource) {
- this(
- Executors.newSingleThreadScheduledExecutor(),
- DEFAULT_WINDOW_CLOSE_DURATION_IN_MINUTES,
- TimeUnit.MINUTES,
- safetySource);
+ this(Executors.newSingleThreadScheduledExecutor(), DEFAULT_WINDOW_CLOSE_DURATION_IN_MINUTES,
+ TimeUnit.MINUTES, safetySource, SubscriptionManagerService.getInstance(),
+ new CellularSecurityTransparencyStats());
}
/**
@@ -83,12 +86,16 @@
ScheduledExecutorService notificationQueue,
long windowCloseDuration,
TimeUnit windowCloseUnit,
- CellularNetworkSecuritySafetySource safetySource) {
+ CellularNetworkSecuritySafetySource safetySource,
+ SubscriptionManagerService subscriptionManagerService,
+ CellularSecurityTransparencyStats cellularSecurityTransparencyStats) {
mSerializedWorkQueue = notificationQueue;
mWindowCloseDuration = windowCloseDuration;
mWindowCloseUnit = windowCloseUnit;
mWindows = new HashMap<>();
mSafetySource = safetySource;
+ mSubscriptionManagerService = subscriptionManagerService;
+ mCellularSecurityTransparencyStats = cellularSecurityTransparencyStats;
}
/**
@@ -98,6 +105,8 @@
public void addDisclosure(Context context, int subId, CellularIdentifierDisclosure disclosure) {
Rlog.d(TAG, "Identifier disclosure reported: " + disclosure);
+ logDisclosure(subId, disclosure);
+
synchronized (mEnabledLock) {
if (!mEnabled) {
Rlog.d(TAG, "Skipping disclosure because notifier was disabled.");
@@ -123,6 +132,31 @@
} // end mEnabledLock
}
+ private void logDisclosure(int subId, CellularIdentifierDisclosure disclosure) {
+ try {
+ mSerializedWorkQueue.execute(runLogDisclosure(subId, disclosure));
+ } catch (RejectedExecutionException e) {
+ Rlog.e(TAG, "Failed to schedule runLogDisclosure: " + e.getMessage());
+ }
+ }
+
+ private Runnable runLogDisclosure(int subId,
+ CellularIdentifierDisclosure disclosure) {
+ return () -> {
+ SubscriptionInfoInternal subInfo =
+ mSubscriptionManagerService.getSubscriptionInfoInternal(subId);
+ String mcc = null;
+ String mnc = null;
+ if (subInfo != null) {
+ mcc = subInfo.getMcc();
+ mnc = subInfo.getMnc();
+ }
+
+ mCellularSecurityTransparencyStats.logIdentifierDisclosure(disclosure, mcc, mnc,
+ isEnabled());
+ };
+ }
+
/**
* Re-enable if previously disabled. This means that {@code addDisclsoure} will start tracking
* disclosures again and potentially emitting notifications.
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index 0459bf6..84e84d9 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -1799,6 +1799,8 @@
}
pw.decreaseIndent();
pw.println();
+ mCarrierServiceBindHelper.dump(fd, pw, args);
+ pw.println();
pw.println("sLocalLog= ");
pw.increaseIndent();
mPinStorage.dump(fd, pw, args);
diff --git a/src/java/com/android/internal/telephony/uicc/UiccProfile.java b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
index 0457971..a22f075 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccProfile.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
@@ -1290,6 +1290,11 @@
return -1;
}
+ if (mUiccApplications[index] == null) {
+ loge("App index " + index + " is invalid");
+ return -1;
+ }
+
if (mUiccApplications[index].getType() != expectedAppType
&& mUiccApplications[index].getType() != altExpectedAppType) {
loge("App index " + index + " is invalid since it's not "
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java
index 776715c..41fd45a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java
@@ -16,10 +16,12 @@
package com.android.internal.telephony;
+import android.content.pm.PackageManager;
import android.telephony.TelephonyManager;
import android.test.AndroidTestCase;
import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.internal.telephony.gsm.SmsMessage;
import com.android.internal.util.HexDump;
@@ -28,6 +30,12 @@
public class GsmSmsTest extends AndroidTestCase {
+ private boolean hasMessaging() {
+ final PackageManager pm = InstrumentationRegistry.getInstrumentation().getContext()
+ .getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING);
+ }
+
@SmallTest
public void testAddressing() throws Exception {
String pdu = "07914151551512f2040B916105551511f100006060605130308A04D4F29C0E";
@@ -258,8 +266,8 @@
@SmallTest
public void testFragmentText() throws Exception {
- boolean isGsmPhone = (TelephonyManager.getDefault().getPhoneType() ==
- TelephonyManager.PHONE_TYPE_GSM);
+ boolean isGsmPhoneWithMessaging = (TelephonyManager.getDefault().getPhoneType()
+ == TelephonyManager.PHONE_TYPE_GSM) && hasMessaging();
// Valid 160 character 7-bit text.
String text = "123456789012345678901234567890123456789012345678901234567890" +
@@ -271,7 +279,7 @@
assertEquals(1, ted.codeUnitSize);
assertEquals(0, ted.languageTable);
assertEquals(0, ted.languageShiftTable);
- if (isGsmPhone) {
+ if (isGsmPhoneWithMessaging) {
ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text);
assertEquals(1, fragments.size());
}
@@ -286,7 +294,7 @@
assertEquals(1, ted.codeUnitSize);
assertEquals(0, ted.languageTable);
assertEquals(0, ted.languageShiftTable);
- if (isGsmPhone) {
+ if (isGsmPhoneWithMessaging) {
ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text);
assertEquals(2, fragments.size());
assertEquals(text, fragments.get(0) + fragments.get(1));
@@ -297,8 +305,8 @@
@SmallTest
public void testFragmentTurkishText() throws Exception {
- boolean isGsmPhone = (TelephonyManager.getDefault().getPhoneType() ==
- TelephonyManager.PHONE_TYPE_GSM);
+ boolean isGsmPhoneWithMessaging = (TelephonyManager.getDefault().getPhoneType()
+ == TelephonyManager.PHONE_TYPE_GSM) && hasMessaging();
int[] oldTables = GsmAlphabet.getEnabledSingleShiftTables();
int[] turkishTable = { 1 };
@@ -313,7 +321,7 @@
assertEquals(1, ted.codeUnitSize);
assertEquals(0, ted.languageTable);
assertEquals(1, ted.languageShiftTable);
- if (isGsmPhone) {
+ if (isGsmPhoneWithMessaging) {
ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text);
assertEquals(1, fragments.size());
assertEquals(text, fragments.get(0));
@@ -329,7 +337,7 @@
assertEquals(1, ted.codeUnitSize);
assertEquals(0, ted.languageTable);
assertEquals(1, ted.languageShiftTable);
- if (isGsmPhone) {
+ if (isGsmPhoneWithMessaging) {
ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text);
assertEquals(2, fragments.size());
assertEquals(text, fragments.get(0) + fragments.get(1));
@@ -347,7 +355,7 @@
assertEquals(1, ted.codeUnitSize);
assertEquals(0, ted.languageTable);
assertEquals(1, ted.languageShiftTable);
- if (isGsmPhone) {
+ if (isGsmPhoneWithMessaging) {
ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text);
assertEquals(3, fragments.size());
assertEquals(text, fragments.get(0) + fragments.get(1) + fragments.get(2));
diff --git a/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
index 4c68e26..a7e9604 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
@@ -255,7 +255,7 @@
// Capture listener to emulate the carrier config change notification used later
ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
- mMultiSimSettingControllerUT = new MultiSimSettingController(mContext);
+ mMultiSimSettingControllerUT = new MultiSimSettingController(mContext, mFeatureFlags);
processAllMessages();
verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
listenerArgumentCaptor.capture());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
index b854535..e08abd9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
@@ -1550,7 +1550,7 @@
mNetworkTypeController.getOverrideNetworkType());
assertTrue(mNetworkTypeController.areAnyTimersActive());
- // switch to connected_rrc_idle before primary timer expires
+ // empty PCC, switch to connected_rrc_idle before primary timer expires
physicalChannelConfigs.clear();
mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */,
new AsyncResult(null, physicalChannelConfigs, null));
@@ -1571,16 +1571,40 @@
mNetworkTypeController.getOverrideNetworkType());
assertTrue(mNetworkTypeController.areAnyTimersActive());
- // 5 seconds passed during connected_mmwave -> connected_rrc_idle secondary timer
- moveTimeForward(5 * 1000);
+ // Verify secondary timer is still active after 6 seconds passed during
+ // connected_mmwave -> connected_rrc_idle secondary timer, should still keep the primary
+ // state icon.
+ moveTimeForward((5 + 1) * 1000);
processAllMessages();
assertEquals("connected_rrc_idle", getCurrentState().getName());
assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
mNetworkTypeController.getOverrideNetworkType());
assertTrue(mNetworkTypeController.areAnyTimersActive());
+ }
- // secondary timer expired
- moveTimeForward(15 * 1000);
+ @Test
+ public void testSecondaryTimerAdvanceBandReduceOnPciChange() throws Exception {
+ // The advance band secondary timer has been running for 6 seconds, 20 - 6 seconds are left.
+ testSecondaryTimerAdvanceBand();
+
+ // PCI changed from 1 to 2 for the first while the timer is running.
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */,
+ new AsyncResult(null, List.of(
+ new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(2)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .build()), null));
+ processAllMessages();
+
+ // Verify the first PCI change is exempted from triggering state change.
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // Verify the timer has been reduced from 20 - 6s(advance band) to 5s(regular).
+ moveTimeForward(5 * 1000);
processAllMessages();
assertEquals("connected_rrc_idle", getCurrentState().getName());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index 88c16ae..673acbc 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -577,6 +577,8 @@
mDomainSelectionResolver = Mockito.mock(DomainSelectionResolver.class);
mNullCipherNotifier = Mockito.mock(NullCipherNotifier.class);
+ doReturn(true).when(mFeatureFlags).minimalTelephonyCdmCheck();
+
TelephonyManager.disableServiceHandleCaching();
PropertyInvalidatedCache.disableForTestMode();
// For testing do not allow Log.WTF as it can cause test process to crash
@@ -640,7 +642,7 @@
nullable(CommandsInterface.class), nullable(FeatureFlags.class));
doReturn(mEmergencyNumberTracker).when(mTelephonyComponentFactory)
.makeEmergencyNumberTracker(nullable(Phone.class),
- nullable(CommandsInterface.class));
+ nullable(CommandsInterface.class), any(FeatureFlags.class));
doReturn(getTestEmergencyNumber()).when(mEmergencyNumberTracker)
.getEmergencyNumber(any());
doReturn(mUiccProfile).when(mTelephonyComponentFactory)
@@ -821,6 +823,12 @@
doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt());
doReturn(true).when(mTelephonyManager).isDataCapable();
+ mContextFixture.addSystemFeature(PackageManager.FEATURE_TELECOM);
+ mContextFixture.addSystemFeature(PackageManager.FEATURE_TELEPHONY_CALLING);
+ mContextFixture.addSystemFeature(PackageManager.FEATURE_TELEPHONY_DATA);
+ mContextFixture.addSystemFeature(PackageManager.FEATURE_TELEPHONY_EUICC);
+ mContextFixture.addSystemFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING);
+
doReturn(TelephonyManager.PHONE_TYPE_GSM).when(mTelephonyManager).getPhoneType();
doReturn(mServiceState).when(mSST).getServiceState();
doReturn(mServiceStateStats).when(mSST).getServiceStateStats();
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 00e6680..9423551 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -872,7 +872,7 @@
mMockSubInfo = Mockito.mock(SubscriptionInfo.class);
mFeatureFlags = Mockito.mock(FeatureFlags.class);
when(mTelephonyComponentFactory.makeDataSettingsManager(any(Phone.class),
- any(DataNetworkController.class), any(Looper.class),
+ any(DataNetworkController.class), any(FeatureFlags.class), any(Looper.class),
any(DataSettingsManager.DataSettingsManagerCallback.class))).thenCallRealMethod();
doReturn(mMockedImsMmTelManager).when(mMockedImsManager).getImsMmTelManager(anyInt());
doReturn(mMockedImsRcsManager).when(mMockedImsManager).getImsRcsManager(anyInt());
@@ -1857,7 +1857,8 @@
boolean isDataEnabled = mDataNetworkControllerUT.getDataSettingsManager().isDataEnabled();
doReturn(mDataNetworkControllerUT.getDataSettingsManager())
.when(mPhone).getDataSettingsManager();
- MultiSimSettingController controller = Mockito.spy(new MultiSimSettingController(mContext));
+ MultiSimSettingController controller = Mockito.spy(new MultiSimSettingController(mContext,
+ mFeatureFlags));
doReturn(true).when(controller).isCarrierConfigLoadedForAllSub();
replaceInstance(MultiSimSettingController.class, "sInstance", null, controller);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataSettingsManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataSettingsManagerTest.java
index fc1bf0d..3f18a3a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataSettingsManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataSettingsManagerTest.java
@@ -77,7 +77,7 @@
.when(mSubscriptionManagerService).getSubscriptionInfoInternal(anyInt());
mDataSettingsManagerUT = new DataSettingsManager(mPhone, mDataNetworkController,
- Looper.myLooper(), mMockedDataSettingsManagerCallback);
+ mFeatureFlags, Looper.myLooper(), mMockedDataSettingsManagerCallback);
logd("DataSettingsManagerTest -Setup!");
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyNumberTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyNumberTrackerTest.java
index c47eb3b..10dbfea 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyNumberTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyNumberTrackerTest.java
@@ -51,7 +51,6 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
-import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.TelephonyTest;
import com.google.i18n.phonenumbers.ShortNumberInfo;
@@ -61,6 +60,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
import java.io.BufferedInputStream;
@@ -139,7 +139,7 @@
mShortNumberInfo = mock(ShortNumberInfo.class);
mCarrierConfigManagerMock = mock(CarrierConfigManager.class);
- mContext = new ContextWrapper(InstrumentationRegistry.getTargetContext());
+ mContext = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
mMockContext = mock(Context.class);
mResources = mock(Resources.class);
@@ -151,9 +151,14 @@
doReturn(1).when(mPhone2).getPhoneId();
doReturn(SUB_ID_PHONE_2).when(mPhone2).getSubId();
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(mPackageManager).when(mMockContext).getPackageManager();
+
initializeEmergencyNumberListTestSamples();
- mEmergencyNumberTrackerMock = new EmergencyNumberTracker(mPhone, mSimulatedCommands);
- mEmergencyNumberTrackerMock2 = new EmergencyNumberTracker(mPhone2, mSimulatedCommands);
+ mEmergencyNumberTrackerMock = new EmergencyNumberTracker(mPhone, mSimulatedCommands,
+ mFeatureFlags);
+ mEmergencyNumberTrackerMock2 = new EmergencyNumberTracker(mPhone2, mSimulatedCommands,
+ mFeatureFlags);
doReturn(mEmergencyNumberTrackerMock2).when(mPhone2).getEmergencyNumberTracker();
mEmergencyNumberTrackerMock.DBG = true;
@@ -171,10 +176,13 @@
public void tearDown() throws Exception {
// Set back to single sim mode
setSinglePhone();
- Path target = Paths.get(mLocalDownloadDirectory.getPath(), EMERGENCY_NUMBER_DB_OTA_FILE);
- Files.deleteIfExists(target);
- mLocalDownloadDirectory.delete();
- mLocalDownloadDirectory = null;
+ if (mLocalDownloadDirectory != null) {
+ Path target = Paths.get(mLocalDownloadDirectory.getPath(),
+ EMERGENCY_NUMBER_DB_OTA_FILE);
+ Files.deleteIfExists(target);
+ mLocalDownloadDirectory.delete();
+ mLocalDownloadDirectory = null;
+ }
mEmergencyNumberTrackerMock = null;
mEmergencyNumberTrackerMock2 = null;
mEmergencyNumberListTestSample.clear();
@@ -361,12 +369,12 @@
@Test
public void testRegistrationForCountryChangeIntent() throws Exception {
EmergencyNumberTracker localEmergencyNumberTracker;
- Context spyContext = spy(mContext);
- doReturn(spyContext).when(mPhone).getContext();
+ Mockito.clearInvocations(mContext);
ArgumentCaptor<IntentFilter> intentCaptor = ArgumentCaptor.forClass(IntentFilter.class);
- localEmergencyNumberTracker = new EmergencyNumberTracker(mPhone, mSimulatedCommands);
- verify(spyContext, times(1)).registerReceiver(any(), intentCaptor.capture());
+ localEmergencyNumberTracker = new EmergencyNumberTracker(mPhone, mSimulatedCommands,
+ mFeatureFlags);
+ verify(mContext, times(1)).registerReceiver(any(), intentCaptor.capture());
IntentFilter ifilter = intentCaptor.getValue();
assertTrue(ifilter.hasAction(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED));
}
@@ -543,7 +551,7 @@
com.android.internal.R.bool.ignore_emergency_number_routing_from_db);
EmergencyNumberTracker emergencyNumberTrackerMock = new EmergencyNumberTracker(
- mPhone, mSimulatedCommands);
+ mPhone, mSimulatedCommands, mFeatureFlags);
emergencyNumberTrackerMock.sendMessage(
emergencyNumberTrackerMock.obtainMessage(
1 /* EVENT_UNSOL_EMERGENCY_NUMBER_LIST */,
@@ -616,7 +624,7 @@
com.android.internal.R.bool.ignore_emergency_number_routing_from_db);
EmergencyNumberTracker emergencyNumberTrackerMock = new EmergencyNumberTracker(
- mPhone, mSimulatedCommands);
+ mPhone, mSimulatedCommands, mFeatureFlags);
emergencyNumberTrackerMock.sendMessage(
emergencyNumberTrackerMock.obtainMessage(
1 /* EVENT_UNSOL_EMERGENCY_NUMBER_LIST */,
@@ -720,7 +728,7 @@
com.android.internal.R.bool.ignore_emergency_number_routing_from_db);
EmergencyNumberTracker emergencyNumberTrackerMock = new EmergencyNumberTracker(
- mPhone, mSimulatedCommands);
+ mPhone, mSimulatedCommands, mFeatureFlags);
emergencyNumberTrackerMock.sendMessage(
emergencyNumberTrackerMock.obtainMessage(
1 /* EVENT_UNSOL_EMERGENCY_NUMBER_LIST */,
@@ -843,7 +851,7 @@
ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
EmergencyNumberTracker localEmergencyNumberTracker =
- new EmergencyNumberTracker(mPhone, mSimulatedCommands);
+ new EmergencyNumberTracker(mPhone, mSimulatedCommands, mFeatureFlags);
verify(mCarrierConfigManagerMock)
.registerCarrierConfigChangeListener(any(), listenerArgumentCaptor.capture());
CarrierConfigManager.CarrierConfigChangeListener carrierConfigChangeListener =
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 79b1ada..6056112 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
@@ -2497,6 +2497,34 @@
}
@Test
+ @SmallTest
+ public void testDomainSelectionEmergencyPermFailure() {
+ doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
+ startOutgoingCall();
+ ImsPhoneConnection c = mCTUT.mForegroundCall.getFirstConnection();
+ mImsCallListener.onCallStartFailed(mSecondImsCall,
+ new ImsReasonInfo(ImsReasonInfo.CODE_EMERGENCY_PERM_FAILURE, -1));
+ processAllMessages();
+ assertNotNull(c.getImsReasonInfo());
+ assertEquals(ImsReasonInfo.CODE_EMERGENCY_PERM_FAILURE,
+ c.getImsReasonInfo().getCode());
+ }
+
+ @Test
+ @SmallTest
+ public void testDomainSelectionEmergencyTempFailure() {
+ doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
+ startOutgoingCall();
+ ImsPhoneConnection c = mCTUT.mForegroundCall.getFirstConnection();
+ mImsCallListener.onCallStartFailed(mSecondImsCall,
+ new ImsReasonInfo(ImsReasonInfo.CODE_EMERGENCY_TEMP_FAILURE, -1));
+ processAllMessages();
+ assertNotNull(c.getImsReasonInfo());
+ assertEquals(ImsReasonInfo.CODE_EMERGENCY_TEMP_FAILURE,
+ c.getImsReasonInfo().getCode());
+ }
+
+ @Test
public void testUpdateImsCallStatusIncoming() throws Exception {
// Incoming call
ImsPhoneConnection connection = setupRingingConnection();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/CellularSecurityTransparencyStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/CellularSecurityTransparencyStatsTest.java
new file mode 100644
index 0000000..2149de0
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/CellularSecurityTransparencyStatsTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.metrics;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.telephony.CellularIdentifierDisclosure;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class CellularSecurityTransparencyStatsTest {
+
+ private CellularSecurityTransparencyStats mCellularSecurityStats;
+
+ @Before
+ public void setUp() throws Exception {
+ mCellularSecurityStats = spy(new CellularSecurityTransparencyStats());
+ }
+
+ @Test
+ public void testLogIdentifierDisclosure_NullSimPlmn() {
+ CellularIdentifierDisclosure disclosure = new CellularIdentifierDisclosure(
+ CellularIdentifierDisclosure.NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST,
+ CellularIdentifierDisclosure.CELLULAR_IDENTIFIER_IMSI, "123-456", true);
+
+ mCellularSecurityStats.logIdentifierDisclosure(disclosure, null, null, true);
+
+ verify(mCellularSecurityStats).writeIdentifierDisclosure(-1, -1, 123, 456,
+ CellularIdentifierDisclosure.CELLULAR_IDENTIFIER_IMSI,
+ CellularIdentifierDisclosure.NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST, true,
+ true);
+ }
+
+ @Test
+ public void testLogIdentifierDisclosure_badSimPlmn() {
+ CellularIdentifierDisclosure disclosure = new CellularIdentifierDisclosure(
+ CellularIdentifierDisclosure.NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST,
+ CellularIdentifierDisclosure.CELLULAR_IDENTIFIER_IMSI, "123-456", true);
+
+ mCellularSecurityStats.logIdentifierDisclosure(disclosure, "INCORRECTLY", "FORMATTED",
+ true);
+
+ verify(mCellularSecurityStats).writeIdentifierDisclosure(-1, -1, 123, 456,
+ CellularIdentifierDisclosure.CELLULAR_IDENTIFIER_IMSI,
+ CellularIdentifierDisclosure.NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST, true,
+ true);
+ }
+
+ @Test
+ public void testLogIdentifierDisclosure_badDisclosurePlmn() {
+ CellularIdentifierDisclosure disclosure = new CellularIdentifierDisclosure(
+ CellularIdentifierDisclosure.NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST,
+ CellularIdentifierDisclosure.CELLULAR_IDENTIFIER_IMSI, "INCORRECT", true);
+
+ mCellularSecurityStats.logIdentifierDisclosure(disclosure, "123", "456", true);
+
+ verify(mCellularSecurityStats).writeIdentifierDisclosure(123, 456, -1, -1,
+ CellularIdentifierDisclosure.CELLULAR_IDENTIFIER_IMSI,
+ CellularIdentifierDisclosure.NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST, true,
+ true);
+ }
+
+ @Test
+ public void testLogIdentifierDisclosure_expectedGoodData() {
+ CellularIdentifierDisclosure disclosure = new CellularIdentifierDisclosure(
+ CellularIdentifierDisclosure.NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST,
+ CellularIdentifierDisclosure.CELLULAR_IDENTIFIER_IMSI, "999-666", true);
+
+ mCellularSecurityStats.logIdentifierDisclosure(disclosure, "123", "456", true);
+
+ verify(mCellularSecurityStats).writeIdentifierDisclosure(123, 456, 999, 666,
+ CellularIdentifierDisclosure.CELLULAR_IDENTIFIER_IMSI,
+ CellularIdentifierDisclosure.NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST, true,
+ true);
+
+ }
+}
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 0426737..35f1bb7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java
@@ -70,8 +70,8 @@
.setCoolDownMillis(24L * 3600L * 1000L)
.build();
private static final long MIN_COOLDOWN_MILLIS = 23L * 3600L * 1000L;
- private static final long CELL_SERVICE_MIN_COOLDOWN_MILLIS =
- IS_DEBUGGABLE ? 4L * 60L * 1000L : MIN_COOLDOWN_MILLIS;
+ private static final long POWER_CORRELATED_MIN_COOLDOWN_MILLIS =
+ IS_DEBUGGABLE ? 4L * 60L * 1000L : 5L * 3600L * 1000L;
private static final long MIN_CALLS_PER_BUCKET = 5L;
// NOTE: these fields are currently 32-bit internally and padded to 64-bit by TelephonyManager
@@ -402,6 +402,9 @@
@SmallTest
public void onPullAtom_cellularServiceState_tooFrequent() throws Exception {
doReturn(null).when(mPersistAtomsStorage).getCellularServiceStates(anyLong());
+ mContextFixture.putIntResource(
+ com.android.internal.R.integer.config_metrics_pull_cooldown_millis,
+ (int) POWER_CORRELATED_MIN_COOLDOWN_MILLIS);
List<StatsEvent> actualAtoms = new ArrayList<>();
int result = mMetricsCollector.onPullAtom(CELLULAR_SERVICE_STATE, actualAtoms);
@@ -409,7 +412,7 @@
assertThat(actualAtoms).hasSize(0);
assertThat(result).isEqualTo(StatsManager.PULL_SKIP);
verify(mPersistAtomsStorage, times(1)).getCellularServiceStates(
- eq(CELL_SERVICE_MIN_COOLDOWN_MILLIS));
+ eq(POWER_CORRELATED_MIN_COOLDOWN_MILLIS));
verifyNoMoreInteractions(mPersistAtomsStorage);
}
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 f1a8de9..aae6a2f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -1736,6 +1736,8 @@
// Trigger carrier config changed with carrierEnabledSatelliteFlag enabled
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ true);
for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
: mCarrierConfigChangedListenerList) {
pair.first.execute(() -> pair.second.onCarrierConfigChanged(
@@ -2723,8 +2725,8 @@
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.
+ // If the PlmnListPerCarrier and the overlay config plmn list are exist but
+ // KEY_SATELLITE_ATTACH_SUPPORTED_BOOL is false, verify passing to the modem.
entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "00103"}).toList();
overlayConfigPlmnList =
Arrays.stream(new String[]{"00101", "00102", "00104"}).toList();
@@ -2735,6 +2737,22 @@
entitlementPlmnList, mIIntegerConsumer);
plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(SUB_ID);
+ assertEquals(new ArrayList<>(), plmnListPerCarrier);
+ allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
+ entitlementPlmnList, overlayConfigPlmnList);
+ verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
+ eq(entitlementPlmnList), eq(allSatellitePlmnList), any(Message.class));
+
+ // If the PlmnListPerCarrier and the overlay config plmn list are exist and
+ // KEY_SATELLITE_ATTACH_SUPPORTED_BOOL is true verify passing the modem.
+ reset(mMockSatelliteModemInterface);
+ mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ true);
+
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, true,
+ entitlementPlmnList, mIIntegerConsumer);
+
+ plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(SUB_ID);
allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
plmnListPerCarrier, overlayConfigPlmnList);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifierTest.java b/tests/telephonytests/src/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifierTest.java
index 8841c7a..aba8164 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifierTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifierTest.java
@@ -29,12 +29,17 @@
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.Context;
import android.telephony.CellularIdentifierDisclosure;
import com.android.internal.telephony.TestExecutorService;
+import com.android.internal.telephony.metrics.CellularSecurityTransparencyStats;
+import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
@@ -50,6 +55,9 @@
private static final int SUB_ID_2 = 2;
private CellularIdentifierDisclosure mDislosure;
private CellularNetworkSecuritySafetySource mSafetySource;
+ private CellularSecurityTransparencyStats mStats;
+ private TestExecutorService mExecutor;
+ private SubscriptionManagerService mSubscriptionManagerService;
private Context mContext;
private InOrder mInOrder;
@@ -62,15 +70,16 @@
"001001",
false);
mSafetySource = mock(CellularNetworkSecuritySafetySource.class);
+ mStats = mock(CellularSecurityTransparencyStats.class);
+ mExecutor = new TestExecutorService();
+ mSubscriptionManagerService = mock(SubscriptionManagerService.class);
+ mContext = mock(Context.class);
mInOrder = inOrder(mSafetySource);
}
@Test
public void testInitializeDisabled() {
- TestExecutorService executor = new TestExecutorService();
- CellularIdentifierDisclosureNotifier notifier =
- new CellularIdentifierDisclosureNotifier(
- executor, 15, TimeUnit.MINUTES, mSafetySource);
+ CellularIdentifierDisclosureNotifier notifier = getNotifier();
assertFalse(notifier.isEnabled());
verify(mSafetySource, never()).setIdentifierDisclosureIssueEnabled(any(), anyBoolean());
@@ -78,10 +87,7 @@
@Test
public void testDisableAddDisclosureNop() {
- TestExecutorService executor = new TestExecutorService();
- CellularIdentifierDisclosureNotifier notifier =
- new CellularIdentifierDisclosureNotifier(
- executor, 15, TimeUnit.MINUTES, mSafetySource);
+ CellularIdentifierDisclosureNotifier notifier = getNotifier();
assertFalse(notifier.isEnabled());
notifier.addDisclosure(mContext, SUB_ID_1, mDislosure);
@@ -92,10 +98,8 @@
@Test
public void testAddDisclosureEmergencyNop() {
- TestExecutorService executor = new TestExecutorService();
- CellularIdentifierDisclosureNotifier notifier =
- new CellularIdentifierDisclosureNotifier(
- executor, 15, TimeUnit.MINUTES, mSafetySource);
+ CellularIdentifierDisclosureNotifier notifier = getNotifier();
+
CellularIdentifierDisclosure emergencyDisclosure =
new CellularIdentifierDisclosure(
CellularIdentifierDisclosure.NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST,
@@ -113,11 +117,7 @@
@Test
public void testAddDisclosureCountIncrements() {
- TestExecutorService executor = new TestExecutorService();
- CellularIdentifierDisclosureNotifier notifier =
- new CellularIdentifierDisclosureNotifier(
- executor, 15, TimeUnit.MINUTES, mSafetySource);
-
+ CellularIdentifierDisclosureNotifier notifier = getNotifier();
notifier.enable(mContext);
for (int i = 0; i < 3; i++) {
@@ -135,28 +135,20 @@
@Test
public void testSingleDisclosureStartAndEndTimesAreEqual() {
- TestExecutorService executor = new TestExecutorService();
- CellularIdentifierDisclosureNotifier notifier =
- new CellularIdentifierDisclosureNotifier(
- executor, 15, TimeUnit.MINUTES, mSafetySource);
-
+ CellularIdentifierDisclosureNotifier notifier = getNotifier();
notifier.enable(mContext);
notifier.addDisclosure(mContext, SUB_ID_1, mDislosure);
assertEquals(1, notifier.getCurrentDisclosureCount(SUB_ID_1));
- assertTrue(notifier.getFirstOpen(SUB_ID_1).equals(notifier.getCurrentEnd(SUB_ID_1)));
+ Assert.assertEquals(notifier.getFirstOpen(SUB_ID_1), notifier.getCurrentEnd(SUB_ID_1));
mInOrder.verify(mSafetySource, times(1))
.setIdentifierDisclosure(any(), eq(SUB_ID_1), eq(1), any(), any());
}
@Test
public void testMultipleDisclosuresTimeWindows() {
- TestExecutorService executor = new TestExecutorService();
- CellularIdentifierDisclosureNotifier notifier =
- new CellularIdentifierDisclosureNotifier(
- executor, 15, TimeUnit.MINUTES, mSafetySource);
-
+ CellularIdentifierDisclosureNotifier notifier = getNotifier();
notifier.enable(mContext);
notifier.addDisclosure(mContext, SUB_ID_1, mDislosure);
@@ -175,10 +167,7 @@
@Test
public void testAddDisclosureThenWindowClose() {
- TestExecutorService executor = new TestExecutorService();
- CellularIdentifierDisclosureNotifier notifier =
- new CellularIdentifierDisclosureNotifier(
- executor, 15, TimeUnit.MINUTES, mSafetySource);
+ CellularIdentifierDisclosureNotifier notifier = getNotifier();
// One round of disclosures
notifier.enable(mContext);
@@ -191,7 +180,7 @@
.setIdentifierDisclosure(any(), eq(SUB_ID_1), eq(2), any(), any());
// Window close should reset the counter
- executor.advanceTime(WINDOW_CLOSE_ADVANCE_MILLIS);
+ mExecutor.advanceTime(WINDOW_CLOSE_ADVANCE_MILLIS);
assertEquals(0, notifier.getCurrentDisclosureCount(SUB_ID_1));
// A new disclosure should increment as normal
@@ -203,10 +192,7 @@
@Test
public void testDisableClosesWindow() {
- TestExecutorService executor = new TestExecutorService();
- CellularIdentifierDisclosureNotifier notifier =
- new CellularIdentifierDisclosureNotifier(
- executor, 15, TimeUnit.MINUTES, mSafetySource);
+ CellularIdentifierDisclosureNotifier notifier = getNotifier();
// One round of disclosures
notifier.enable(mContext);
@@ -231,10 +217,7 @@
@Test
public void testMultipleSubIdsTrackedIndependently() {
- TestExecutorService executor = new TestExecutorService();
- CellularIdentifierDisclosureNotifier notifier =
- new CellularIdentifierDisclosureNotifier(
- executor, 15, TimeUnit.MINUTES, mSafetySource);
+ CellularIdentifierDisclosureNotifier notifier = getNotifier();
notifier.enable(mContext);
for (int i = 0; i < 3; i++) {
@@ -262,4 +245,27 @@
assertEquals(3, notifier.getCurrentDisclosureCount(SUB_ID_1));
assertEquals(4, notifier.getCurrentDisclosureCount(SUB_ID_2));
}
+
+ @Test
+ public void testLogDisclsoure() {
+ String mcc = "100";
+ String mnc = "200";
+
+ CellularIdentifierDisclosureNotifier notifier = getNotifier();
+ SubscriptionInfoInternal subInfoMock = mock(SubscriptionInfoInternal.class);
+ when(mSubscriptionManagerService.getSubscriptionInfoInternal(SUB_ID_1)).thenReturn(
+ subInfoMock);
+ when(subInfoMock.getMcc()).thenReturn(mcc);
+ when(subInfoMock.getMnc()).thenReturn(mnc);
+
+ notifier.addDisclosure(mContext, SUB_ID_1, mDislosure);
+
+ verify(mStats, times(1)).logIdentifierDisclosure(mDislosure, mcc, mnc,
+ mDislosure.isEmergency());
+ }
+
+ private CellularIdentifierDisclosureNotifier getNotifier() {
+ return new CellularIdentifierDisclosureNotifier(mExecutor, 15, TimeUnit.MINUTES,
+ mSafetySource, mSubscriptionManagerService, mStats);
+ }
}