aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-06-15 08:10:18 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-06-15 08:10:18 +0000
commit7c77830cb277ae12c40ccc83fe2e2a700e0462a6 (patch)
tree2e082d09eede6b444ff6e9653c0930e4ee9cd8f1
parent3fa75d9b27ed5db8bde6014746296c39b1585941 (diff)
parent1018e40f2dea81997b3420352d4349b7c78d1696 (diff)
downloadtelephony-7c77830cb277ae12c40ccc83fe2e2a700e0462a6.tar.gz
Snap for 8727584 from 1018e40f2dea81997b3420352d4349b7c78d1696 to mainline-tzdata3-release
Change-Id: I45e2878ae1f9125a537e37bf654b37841b94448b
-rw-r--r--src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java58
-rw-r--r--src/java/com/android/internal/telephony/CarrierServiceBindHelper.java52
-rw-r--r--src/java/com/android/internal/telephony/NetworkTypeController.java78
-rw-r--r--src/java/com/android/internal/telephony/RIL.java28
-rw-r--r--src/java/com/android/internal/telephony/SubscriptionController.java64
-rw-r--r--src/java/com/android/internal/telephony/data/DataConfigManager.java14
-rw-r--r--src/java/com/android/internal/telephony/data/DataNetwork.java97
-rw-r--r--src/java/com/android/internal/telephony/data/DataNetworkController.java64
-rw-r--r--src/java/com/android/internal/telephony/data/DataProfileManager.java11
-rw-r--r--src/java/com/android/internal/telephony/data/DataSettingsManager.java45
-rw-r--r--src/java/com/android/internal/telephony/data/PhoneSwitcher.java74
-rw-r--r--src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java11
-rw-r--r--src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java67
-rw-r--r--src/java/com/android/internal/telephony/uicc/UiccController.java11
-rw-r--r--src/java/com/android/internal/telephony/uicc/UiccProfile.java8
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java10
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java43
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java94
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java193
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java49
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java61
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/data/DataProfileTest.java43
22 files changed, 851 insertions, 324 deletions
diff --git a/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java b/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
index dd9faa81ab..31442297b1 100644
--- a/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
+++ b/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
@@ -31,6 +31,8 @@ import static android.telephony.TelephonyManager.SIM_STATE_NOT_READY;
import static android.telephony.TelephonyManager.SIM_STATE_READY;
import static android.telephony.TelephonyManager.SIM_STATE_UNKNOWN;
+import static com.android.internal.telephony.SubscriptionInfoUpdater.simStateString;
+
import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -106,11 +108,14 @@ public class CarrierPrivilegesTracker extends Handler {
private static final String SHA_1 = "SHA-1";
private static final String SHA_256 = "SHA-256";
+ // TODO(b/232273884): Turn feature on when find solution to handle the inter-carriers switching
/**
* Time delay to clear UICC rules after UICC is gone.
* This introduces the grace period to retain carrier privileges when SIM is removed.
+ *
+ * This feature is off by default due to the security concern during inter-carriers switching.
*/
- private static final long CLEAR_UICC_RULES_DELAY_MILLIS = TimeUnit.SECONDS.toMillis(30);
+ private static final long CLEAR_UICC_RULES_DELAY_MILLIS = TimeUnit.SECONDS.toMillis(0);
/**
* PackageManager flags used to query installed packages.
@@ -178,6 +183,11 @@ public class CarrierPrivilegesTracker extends Handler {
*/
private static final int ACTION_CLEAR_UICC_RULES = 9;
+ /**
+ * Action to handle the case when UiccAccessRules has been loaded.
+ */
+ private static final int ACTION_UICC_ACCESS_RULES_LOADED = 10;
+
private final Context mContext;
private final Phone mPhone;
private final PackageManager mPackageManager;
@@ -430,6 +440,10 @@ public class CarrierPrivilegesTracker extends Handler {
handleClearUiccRules();
break;
}
+ case ACTION_UICC_ACCESS_RULES_LOADED: {
+ handleUiccAccessRulesLoaded();
+ break;
+ }
default: {
Rlog.e(TAG, "Received unknown msg type: " + msg.what);
break;
@@ -502,16 +516,8 @@ public class CarrierPrivilegesTracker extends Handler {
// Only include the UICC rules if the SIM is fully loaded
if (simState == SIM_STATE_LOADED) {
- mClearUiccRulesUptimeMillis = CLEAR_UICC_RULE_NOT_SCHEDULED;
- removeMessages(ACTION_CLEAR_UICC_RULES);
-
- updatedUiccRules = getSimRules();
-
- mLocalLog.log("SIM fully loaded:"
- + " slotId=" + slotId
- + " simState=" + simState
- + " updated SIM-loaded rules=" + updatedUiccRules);
- maybeUpdateRulesAndNotifyRegistrants(mUiccRules, updatedUiccRules);
+ mLocalLog.log("SIM fully loaded, handleUiccAccessRulesLoaded.");
+ handleUiccAccessRulesLoaded();
} else {
if (!mUiccRules.isEmpty()
&& mClearUiccRulesUptimeMillis == CLEAR_UICC_RULE_NOT_SCHEDULED) {
@@ -519,7 +525,8 @@ public class CarrierPrivilegesTracker extends Handler {
SystemClock.uptimeMillis() + CLEAR_UICC_RULES_DELAY_MILLIS;
sendMessageAtTime(obtainMessage(ACTION_CLEAR_UICC_RULES),
mClearUiccRulesUptimeMillis);
- mLocalLog.log("SIM is gone. Delay " + TimeUnit.MILLISECONDS.toSeconds(
+ mLocalLog.log("SIM is gone, simState=" + simStateString(simState)
+ + ". Delay " + TimeUnit.MILLISECONDS.toSeconds(
CLEAR_UICC_RULES_DELAY_MILLIS) + " seconds to clear UICC rules.");
} else {
mLocalLog.log(
@@ -528,6 +535,21 @@ public class CarrierPrivilegesTracker extends Handler {
}
}
+ private void handleUiccAccessRulesLoaded() {
+ mClearUiccRulesUptimeMillis = CLEAR_UICC_RULE_NOT_SCHEDULED;
+ removeMessages(ACTION_CLEAR_UICC_RULES);
+
+ List<UiccAccessRule> updatedUiccRules = getSimRules();
+ mLocalLog.log("UiccAccessRules loaded:"
+ + " updated SIM-loaded rules=" + updatedUiccRules);
+ maybeUpdateRulesAndNotifyRegistrants(mUiccRules, updatedUiccRules);
+ }
+
+ /** Called when UiccAccessRules has been loaded */
+ public void onUiccAccessRulesLoaded() {
+ sendEmptyMessage(ACTION_UICC_ACCESS_RULES_LOADED);
+ }
+
private void handleClearUiccRules() {
mClearUiccRulesUptimeMillis = CLEAR_UICC_RULE_NOT_SCHEDULED;
removeMessages(ACTION_CLEAR_UICC_RULES);
@@ -574,9 +596,11 @@ public class CarrierPrivilegesTracker extends Handler {
// installed for a user it wasn't installed in before, which means there will be an
// additional UID.
getUidsForPackage(pkg.packageName, /* invalidateCache= */ true);
- mLocalLog.log("Package added/replaced/changed:"
- + " pkg=" + Rlog.pii(TAG, pkgName)
- + " cert hashes=" + mInstalledPackageCerts.get(pkgName));
+ if (VDBG) {
+ Rlog.d(TAG, "Package added/replaced/changed:"
+ + " pkg=" + Rlog.pii(TAG, pkgName)
+ + " cert hashes=" + mInstalledPackageCerts.get(pkgName));
+ }
maybeUpdatePrivilegedPackagesAndNotifyRegistrants();
}
@@ -603,7 +627,9 @@ public class CarrierPrivilegesTracker extends Handler {
return;
}
- mLocalLog.log("Package removed or disabled by user: pkg=" + Rlog.pii(TAG, pkgName));
+ if (VDBG) {
+ Rlog.d(TAG, "Package removed or disabled by user: pkg=" + Rlog.pii(TAG, pkgName));
+ }
maybeUpdatePrivilegedPackagesAndNotifyRegistrants();
}
diff --git a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
index 16d0dd9d29..dfa53b3958 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
@@ -29,6 +29,7 @@ import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.Message;
import android.os.Process;
@@ -47,6 +48,8 @@ import com.android.internal.telephony.util.TelephonyUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Set;
/**
* Manages long-lived bindings to carrier services
@@ -71,6 +74,8 @@ public class CarrierServiceBindHelper {
public SparseArray<AppBinding> mBindings = new SparseArray();
@VisibleForTesting
public SparseArray<String> mLastSimState = new SparseArray<>();
+ // TODO(b/201423849): Clean up PackageChangeReceiver/UserUnlockedReceiver/SIM State change if
+ // CarrierServiceChangeCallback can cover the cases
private final PackageChangeReceiver mPackageMonitor = new CarrierServicePackageMonitor();
private final LocalLog mLocalLog = new LocalLog(100);
@@ -90,6 +95,30 @@ public class CarrierServiceBindHelper {
}
};
+ private class CarrierServiceChangeCallback implements
+ TelephonyManager.CarrierPrivilegesCallback {
+ final int mPhoneId;
+
+ CarrierServiceChangeCallback(int phoneId) {
+ this.mPhoneId = phoneId;
+ }
+
+ @Override
+ public void onCarrierPrivilegesChanged(Set<String> privilegedPackageNames,
+ Set<Integer> privilegedUids) {
+ // Ignored, not interested here
+ }
+
+ @Override
+ public void onCarrierServiceChanged(String carrierServicePackageName,
+ int carrierServiceUid) {
+ logdWithLocalLog("onCarrierServiceChanged, carrierServicePackageName="
+ + carrierServicePackageName + ", carrierServiceUid=" + carrierServiceUid
+ + ", mPhoneId=" + mPhoneId);
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_REBIND, mPhoneId));
+ }
+ }
+
private static final int EVENT_REBIND = 0;
@VisibleForTesting
public static final int EVENT_PERFORM_IMMEDIATE_UNBIND = 1;
@@ -123,6 +152,8 @@ public class CarrierServiceBindHelper {
case EVENT_MULTI_SIM_CONFIG_CHANGED:
updateBindingsAndSimStates();
break;
+ default:
+ Log.e(LOG_TAG, "Unsupported event received: " + msg.what);
}
}
};
@@ -162,6 +193,7 @@ public class CarrierServiceBindHelper {
// If prevLen > newLen, dispose AppBinding and simState objects.
for (int phoneId = newLen; phoneId < prevLen; phoneId++) {
+ mBindings.get(phoneId).tearDown();
mBindings.get(phoneId).unbind(true);
mBindings.delete(phoneId);
mLastSimState.delete(phoneId);
@@ -193,9 +225,23 @@ public class CarrierServiceBindHelper {
private String carrierPackage;
private String carrierServiceClass;
private long mUnbindScheduledUptimeMillis = -1;
+ private final CarrierServiceChangeCallback mCarrierServiceChangeCallback;
public AppBinding(int phoneId) {
this.phoneId = phoneId;
+ this.mCarrierServiceChangeCallback = new CarrierServiceChangeCallback(phoneId);
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ if (tm != null) {
+ tm.registerCarrierPrivilegesCallback(phoneId, new HandlerExecutor(mHandler),
+ mCarrierServiceChangeCallback);
+ }
+ }
+
+ public void tearDown() {
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ if (tm != null && mCarrierServiceChangeCallback != null) {
+ tm.unregisterCarrierPrivilegesCallback(mCarrierServiceChangeCallback);
+ }
}
public int getPhoneId() {
@@ -365,6 +411,7 @@ public class CarrierServiceBindHelper {
pw.println(" unbindCount: " + unbindCount);
pw.println(" lastUnbindMillis: " + lastUnbindMillis);
pw.println(" mUnbindScheduledUptimeMillis: " + mUnbindScheduledUptimeMillis);
+ pw.println(" mCarrierServiceChangeCallback: " + mCarrierServiceChangeCallback);
pw.println();
}
}
@@ -405,27 +452,32 @@ public class CarrierServiceBindHelper {
private class CarrierServicePackageMonitor extends PackageChangeReceiver {
@Override
public void onPackageAdded(String packageName) {
+ logdWithLocalLog("onPackageAdded: " + packageName);
evaluateBinding(packageName, true /* forceUnbind */);
}
@Override
public void onPackageRemoved(String packageName) {
+ logdWithLocalLog("onPackageRemoved: " + packageName);
evaluateBinding(packageName, true /* forceUnbind */);
}
@Override
public void onPackageUpdateFinished(String packageName) {
+ logdWithLocalLog("onPackageUpdateFinished: " + packageName);
evaluateBinding(packageName, true /* forceUnbind */);
}
@Override
public void onPackageModified(String packageName) {
+ logdWithLocalLog("onPackageModified: " + packageName);
evaluateBinding(packageName, false /* forceUnbind */);
}
@Override
public void onHandleForceStop(String[] packages, boolean doit) {
if (doit) {
+ logdWithLocalLog("onHandleForceStop: " + Arrays.toString(packages));
for (String packageName : packages) {
evaluateBinding(packageName, true /* forceUnbind */);
}
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index af9d233e9a..2260d3456a 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -543,10 +543,12 @@ public class NetworkTypeController extends StateMachine {
switch (msg.what) {
case EVENT_UPDATE:
case EVENT_PREFERRED_NETWORK_MODE_CHANGED:
+ if (DBG) log("Reset timers since preferred network mode changed.");
resetAllTimers();
transitionToCurrentState();
break;
case EVENT_QUIT:
+ if (DBG) log("Reset timers on state machine quitting.");
resetAllTimers();
unRegisterForAllEvents();
quit();
@@ -585,25 +587,32 @@ public class NetworkTypeController extends StateMachine {
log("mIsPhysicalChannelConfigOn changed to: " + mIsPhysicalChannelConfigOn);
}
if (!mIsPhysicalChannelConfigOn) {
+ if (DBG) {
+ log("Reset timers since physical channel config indications are off.");
+ }
resetAllTimers();
}
transitionToCurrentState();
break;
case EVENT_CARRIER_CONFIG_CHANGED:
parseCarrierConfigs();
+ if (DBG) log("Reset timers since carrier configurations changed.");
resetAllTimers();
transitionToCurrentState();
break;
case EVENT_PRIMARY_TIMER_EXPIRED:
+ if (DBG) log("Primary timer expired for state: " + mPrimaryTimerState);
transitionWithSecondaryTimerTo((IState) msg.obj);
break;
case EVENT_SECONDARY_TIMER_EXPIRED:
+ if (DBG) log("Secondary timer expired for state: " + mSecondaryTimerState);
mIsSecondaryTimerActive = false;
mSecondaryTimerState = "";
updateTimers();
updateOverrideNetworkType();
break;
case EVENT_RADIO_OFF_OR_UNAVAILABLE:
+ if (DBG) log("Reset timers since radio is off or unavailable.");
resetAllTimers();
transitionTo(mLegacyState);
break;
@@ -614,6 +623,7 @@ public class NetworkTypeController extends StateMachine {
log("mIsDeviceIdleMode changed to: " + mIsDeviceIdleMode);
}
if (mIsDeviceIdleMode) {
+ if (DBG) log("Reset timers since device is in idle mode.");
resetAllTimers();
}
transitionToCurrentState();
@@ -637,7 +647,7 @@ public class NetworkTypeController extends StateMachine {
* This is the initial state.
*/
private final class LegacyState extends State {
- private Boolean mIsNrRestricted = false;
+ private boolean mIsNrRestricted = false;
@Override
public void enter() {
@@ -664,7 +674,7 @@ public class NetworkTypeController extends StateMachine {
? mLteConnectedState : mIdleState);
} else {
if (!isLte(rat)) {
- // Rat is 3G or 2G, and it doesn't need NR timer.
+ if (DBG) log("Reset timers since 2G and 3G don't need NR timers.");
resetAllTimers();
}
updateOverrideNetworkType();
@@ -689,6 +699,7 @@ public class NetworkTypeController extends StateMachine {
if (isUsingPhysicalChannelConfigForRrcDetection()) {
mPhysicalLinkStatus = getPhysicalLinkStatusFromPhysicalChannelConfig();
if (mIsTimerResetEnabledForLegacyStateRRCIdle && !isPhysicalLinkActive()) {
+ if (DBG) log("Reset timers since timer reset is enabled for RRC idle.");
resetAllTimers();
}
}
@@ -699,6 +710,7 @@ public class NetworkTypeController extends StateMachine {
AsyncResult ar = (AsyncResult) msg.obj;
mPhysicalLinkStatus = (int) ar.result;
if (mIsTimerResetEnabledForLegacyStateRRCIdle && !isPhysicalLinkActive()) {
+ if (DBG) log("Reset timers since timer reset is enabled for RRC idle.");
resetAllTimers();
updateOverrideNetworkType();
}
@@ -714,7 +726,7 @@ public class NetworkTypeController extends StateMachine {
@Override
public String getName() {
- return mIsNrRestricted ? STATE_RESTRICTED : STATE_LEGACY;
+ return mIsNrRestricted ? STATE_RESTRICTED : STATE_LEGACY;
}
}
@@ -889,14 +901,14 @@ public class NetworkTypeController extends StateMachine {
private final LteConnectedState mLteConnectedState = new LteConnectedState();
/**
- * Device is connected to 5G NR as the secondary cell.
+ * Device is connected to 5G NR as the primary or secondary cell.
*/
private final class NrConnectedState extends State {
- private Boolean mIsNrAdvanced = false;
+ private boolean mIsNrAdvanced = false;
@Override
public void enter() {
- if (DBG) log("Entering NrConnectedState");
+ if (DBG) log("Entering NrConnectedState(" + getName() + ")");
updateTimers();
updateOverrideNetworkType();
if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
@@ -907,7 +919,7 @@ public class NetworkTypeController extends StateMachine {
@Override
public boolean processMessage(Message msg) {
- if (DBG) log("NrConnectedState: process " + getEventName(msg.what));
+ if (DBG) log("NrConnectedState(" + getName() + "): process " + getEventName(msg.what));
updateTimers();
int rat = getDataNetworkType();
switch (msg.what) {
@@ -974,10 +986,10 @@ public class NetworkTypeController extends StateMachine {
return;
}
if (!isNrAdvanced()) {
- // STATE_CONNECTED_NR_ADVANCED -> STATE_CONNECTED
+ if (DBG) log("updateNrAdvancedState: CONNECTED_NR_ADVANCED -> CONNECTED");
transitionWithTimerTo(mNrConnectedState);
} else {
- // STATE_CONNECTED -> STATE_CONNECTED_NR_ADVANCED
+ if (DBG) log("updateNrAdvancedState: CONNECTED -> CONNECTED_NR_ADVANCED");
transitionTo(mNrConnectedState);
}
mIsNrAdvanced = isNrAdvanced();
@@ -1002,10 +1014,10 @@ public class NetworkTypeController extends StateMachine {
&& mNrAdvancedCapablePcoId > 0
&& pcodata.pcoId == mNrAdvancedCapablePcoId
) {
- log("EVENT_PCO_DATA_CHANGED: Nr Advanced is allowed by PCO. length:"
+ log("EVENT_PCO_DATA_CHANGED: NR_ADVANCED is allowed by PCO. length:"
+ pcodata.contents.length + ",value: " + Arrays.toString(pcodata.contents));
- mIsNrAdvancedAllowedByPco = (pcodata.contents.length > 0)
- ? pcodata.contents[pcodata.contents.length - 1] == 1 : false;
+ mIsNrAdvancedAllowedByPco = pcodata.contents.length > 0
+ && pcodata.contents[pcodata.contents.length - 1] == 1;
updateNrAdvancedState();
}
}
@@ -1015,14 +1027,15 @@ public class NetworkTypeController extends StateMachine {
private void transitionWithTimerTo(IState destState) {
String destName = destState.getName();
+ if (DBG) log("Transition with primary timer from " + mPreviousState + " to " + destName);
OverrideTimerRule rule = mOverrideTimerRules.get(mPreviousState);
if (!mIsDeviceIdleMode && rule != null && rule.getTimer(destName) > 0) {
- if (DBG) log("Primary timer started for state: " + mPreviousState);
+ int duration = rule.getTimer(destName);
+ if (DBG) log(duration + "s primary timer started for state: " + mPreviousState);
mPrimaryTimerState = mPreviousState;
mPreviousState = getCurrentState().getName();
mIsPrimaryTimerActive = true;
- sendMessageDelayed(EVENT_PRIMARY_TIMER_EXPIRED, destState,
- rule.getTimer(destName) * 1000L);
+ sendMessageDelayed(EVENT_PRIMARY_TIMER_EXPIRED, destState, duration * 1000L);
}
transitionTo(destState);
}
@@ -1030,13 +1043,17 @@ public class NetworkTypeController extends StateMachine {
private void transitionWithSecondaryTimerTo(IState destState) {
String currentName = getCurrentState().getName();
OverrideTimerRule rule = mOverrideTimerRules.get(mPrimaryTimerState);
+ if (DBG) {
+ log("Transition with secondary timer from " + currentName + " to "
+ + destState.getName());
+ }
if (!mIsDeviceIdleMode && rule != null && rule.getSecondaryTimer(currentName) > 0) {
- if (DBG) log("Secondary timer started for state: " + currentName);
+ int duration = rule.getSecondaryTimer(currentName);
+ if (DBG) log(duration + "s secondary timer started for state: " + currentName);
mSecondaryTimerState = currentName;
mPreviousState = currentName;
mIsSecondaryTimerActive = true;
- sendMessageDelayed(EVENT_SECONDARY_TIMER_EXPIRED, destState,
- rule.getSecondaryTimer(currentName) * 1000L);
+ sendMessageDelayed(EVENT_SECONDARY_TIMER_EXPIRED, destState, duration * 1000L);
}
mIsPrimaryTimerActive = false;
transitionTo(getCurrentState());
@@ -1070,6 +1087,7 @@ public class NetworkTypeController extends StateMachine {
private void updateTimers() {
if ((mPhone.getCachedAllowedNetworkTypesBitmask()
& TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) {
+ if (DBG) log("Reset timers since NR is not allowed.");
resetAllTimers();
return;
}
@@ -1098,21 +1116,21 @@ public class NetworkTypeController extends StateMachine {
mSecondaryTimerState = "";
}
- if (currentState.equals(STATE_CONNECTED_NR_ADVANCED)) {
- resetAllTimers();
- }
+ if (mIsPrimaryTimerActive || mIsSecondaryTimerActive) {
+ if (currentState.equals(STATE_CONNECTED_NR_ADVANCED)) {
+ if (DBG) log("Reset timers since state is NR_ADVANCED.");
+ resetAllTimers();
+ }
- int rat = getDataNetworkType();
- if (!isLte(rat) && rat != TelephonyManager.NETWORK_TYPE_NR) {
- // Rat is 3G or 2G, and it doesn't need NR timer.
- resetAllTimers();
+ int rat = getDataNetworkType();
+ if (!isLte(rat) && rat != TelephonyManager.NETWORK_TYPE_NR) {
+ if (DBG) log("Reset timers since 2G and 3G don't need NR timers.");
+ resetAllTimers();
+ }
}
}
private void resetAllTimers() {
- if (DBG) {
- log("Remove all timers");
- }
removeMessages(EVENT_PRIMARY_TIMER_EXPIRED);
removeMessages(EVENT_SECONDARY_TIMER_EXPIRED);
mIsPrimaryTimerActive = false;
@@ -1125,7 +1143,7 @@ public class NetworkTypeController extends StateMachine {
* Private class defining timer rules between states to prevent flickering. These rules are
* created in {@link #parseCarrierConfigs()} based on various carrier configs.
*/
- private class OverrideTimerRule {
+ private static class OverrideTimerRule {
/** The 5G state this timer rule applies for. See {@link #ALL_STATES}. */
final String mState;
@@ -1320,7 +1338,7 @@ public class NetworkTypeController extends StateMachine {
+ ", mPrimaryTimerState=" + mPrimaryTimerState
+ ", mSecondaryTimerState=" + mSecondaryTimerState
+ ", mPreviousState=" + mPreviousState
- + ", misNrAdvanced=" + isNrAdvanced();
+ + ", mIsNrAdvanced=" + isNrAdvanced();
}
@Override
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 00e88fc0cc..49e8297c45 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -186,7 +186,7 @@ public class RIL extends BaseCommands implements CommandsInterface {
int mLastRadioPowerResult = RadioError.NONE;
- boolean mHidlSetResponseFunctionsCalled = false;
+ boolean mIsRadioProxyInitialized = false;
// When we are testing emergency calls using ril.test.emergencynumber, this will trigger test
// ECbM when the call is ended.
@@ -354,7 +354,7 @@ public class RIL extends BaseCommands implements CommandsInterface {
+ ", service = " + serviceToString(service) + ", service cookie = "
+ mServiceCookies.get(service));
if ((long) msg.obj == mServiceCookies.get(service).get()) {
- mHidlSetResponseFunctionsCalled = false;
+ mIsRadioProxyInitialized = false;
resetProxyAndRequestList(service);
}
break;
@@ -366,7 +366,7 @@ public class RIL extends BaseCommands implements CommandsInterface {
+ ", service = " + serviceToString(aidlService) + ", cookie = "
+ mServiceCookies.get(aidlService));
if (obj.get() == mServiceCookies.get(aidlService).get()) {
- mHidlSetResponseFunctionsCalled = false;
+ mIsRadioProxyInitialized = false;
resetProxyAndRequestList(aidlService);
}
break;
@@ -526,7 +526,7 @@ public class RIL extends BaseCommands implements CommandsInterface {
}
if (serviceBound) {
- mHidlSetResponseFunctionsCalled = false;
+ mIsRadioProxyInitialized = false;
for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) {
resetProxyAndRequestList(service);
}
@@ -668,10 +668,10 @@ public class RIL extends BaseCommands implements CommandsInterface {
}
if (mRadioProxy != null) {
- mRadioProxy.linkToDeath(mRadioProxyDeathRecipient,
- mServiceCookies.get(RADIO_SERVICE).incrementAndGet());
- if (!mHidlSetResponseFunctionsCalled) {
- mHidlSetResponseFunctionsCalled = true;
+ if (!mIsRadioProxyInitialized) {
+ mIsRadioProxyInitialized = true;
+ mRadioProxy.linkToDeath(mRadioProxyDeathRecipient,
+ mServiceCookies.get(RADIO_SERVICE).incrementAndGet());
mRadioProxy.setResponseFunctions(mRadioResponse, mRadioIndication);
}
} else {
@@ -964,10 +964,10 @@ public class RIL extends BaseCommands implements CommandsInterface {
if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_2_0)) {
throw new AssertionError("serviceProxy shouldn't be HIDL with HAL 2.0");
}
- serviceProxy.getHidl().linkToDeath(mRadioProxyDeathRecipient,
- mServiceCookies.get(service).incrementAndGet());
- if (!mHidlSetResponseFunctionsCalled) {
- mHidlSetResponseFunctionsCalled = true;
+ if (!mIsRadioProxyInitialized) {
+ mIsRadioProxyInitialized = true;
+ serviceProxy.getHidl().linkToDeath(mRadioProxyDeathRecipient,
+ mServiceCookies.get(service).incrementAndGet());
serviceProxy.getHidl().setResponseFunctions(
mRadioResponse, mRadioIndication);
}
@@ -998,7 +998,7 @@ public class RIL extends BaseCommands implements CommandsInterface {
@Override
public synchronized void onSlotActiveStatusChange(boolean active) {
- mHidlSetResponseFunctionsCalled = false;
+ mIsRadioProxyInitialized = false;
for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) {
if (active) {
// Try to connect to RIL services and set response functions.
@@ -1184,7 +1184,7 @@ public class RIL extends BaseCommands implements CommandsInterface {
private void handleRadioProxyExceptionForRR(int service, String caller, Exception e) {
riljLoge(caller + ": " + e);
e.printStackTrace();
- mHidlSetResponseFunctionsCalled = false;
+ mIsRadioProxyInitialized = false;
resetProxyAndRequestList(service);
}
diff --git a/src/java/com/android/internal/telephony/SubscriptionController.java b/src/java/com/android/internal/telephony/SubscriptionController.java
index d0c0b624fb..7e762d7af0 100644
--- a/src/java/com/android/internal/telephony/SubscriptionController.java
+++ b/src/java/com/android/internal/telephony/SubscriptionController.java
@@ -28,9 +28,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.PendingIntent;
-import android.app.compat.CompatChanges;
-import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -170,15 +167,6 @@ public class SubscriptionController extends ISub.Stub {
// Allows test mocks to avoid SELinux failures on invalidate calls.
private static boolean sCachingEnabled = true;
- /**
- * Apps targeting on Android T and beyond will get exception if there is no
- * {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} permission
- * when calling SubscriptionManager#getSubscriptionsInGroup.
- */
- @ChangeId
- @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
- public static final long REQUIRE_ICC_AUTH_DEVICE_IDENTIFIERS_FOR_GROUP_UUID = 213902861L;
-
// Each slot can have multiple subs.
private static class WatchedSlotIndexToSubIds {
private Map<Integer, ArrayList<Integer>> mSlotIndexToSubIds = new ConcurrentHashMap<>();
@@ -473,11 +461,10 @@ public class SubscriptionController extends ISub.Stub {
/**
* Returns whether the {@code callingPackage} has access to subscriber identifiers on the
* specified {@code subId} using the provided {@code message} in any resulting
- * SecurityException. {@code throwException} flag to indicate if throw exception.
+ * SecurityException.
*/
private boolean hasSubscriberIdentifierAccess(int subId, String callingPackage,
- String callingFeatureId, String message, boolean reportFailure,
- boolean throwException) {
+ String callingFeatureId, String message, boolean reportFailure) {
try {
return TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers(mContext, subId,
callingPackage, callingFeatureId, message, reportFailure);
@@ -485,9 +472,6 @@ public class SubscriptionController extends ISub.Stub {
// A SecurityException indicates that the calling package is targeting at least the
// minimum level that enforces identifier access restrictions and the new access
// requirements are not met.
- if (throwException) {
- throw e;
- }
return false;
}
}
@@ -2845,7 +2829,8 @@ public class SubscriptionController extends ISub.Stub {
if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
throw new RuntimeException("setDefaultVoiceSubId called with DEFAULT_SUB_ID");
}
- if (DBG) logdl("[setDefaultVoiceSubId] subId=" + subId);
+
+ logdl("[setDefaultVoiceSubId] subId=" + subId);
int previousDefaultSub = getDefaultSubId();
@@ -3975,21 +3960,10 @@ public class SubscriptionController extends ISub.Stub {
* Get subscriptionInfo list of subscriptions that are in the same group of given subId.
* See {@link #createSubscriptionGroup(int[], String)} for more details.
*
- * Caller must have {@link android.Manifest.permission#READ_PHONE_STATE}
- * or carrier privilege permission on the subscription.
+ * Caller will either have {@link android.Manifest.permission#READ_PHONE_STATE}
+ * permission or had carrier privilege permission on the subscription.
* {@link TelephonyManager#hasCarrierPrivileges(int)}
*
- * <p>Starting with API level 33, the caller needs the additional permission
- * {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER}
- * to get the list of subscriptions associated with a group UUID.
- * This method can be invoked if one of the following requirements is met:
- * <ul>
- * <li>If the app has carrier privilege permission.
- * {@link TelephonyManager#hasCarrierPrivileges()}
- * <li>If the app has {@link android.Manifest.permission#READ_PHONE_STATE} and
- * {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} permission.
- * </ul>
- *
* @throws SecurityException if the caller doesn't meet the requirements
* outlined above.
*
@@ -4017,29 +3991,15 @@ public class SubscriptionController extends ISub.Stub {
}
return subInfoList.stream().filter(info -> {
- int subId = info.getSubscriptionId();
- boolean permission = checkPermissionForGroupUuid(subId, callingPackage,
- callingFeatureId, Binder.getCallingUid());
if (!groupUuid.equals(info.getGroupUuid())) return false;
- return permission || info.canManageSubscription(mContext, callingPackage);
+ int subId = info.getSubscriptionId();
+ return TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subId,
+ callingPackage, callingFeatureId, "getSubscriptionsInGroup")
+ || info.canManageSubscription(mContext, callingPackage);
}).map(subscriptionInfo -> conditionallyRemoveIdentifiers(subscriptionInfo,
callingPackage, callingFeatureId, "getSubscriptionsInGroup"))
.collect(Collectors.toList());
- }
-
- private boolean checkPermissionForGroupUuid(int subId, String callingPackage,
- String callingFeatureId, int uid) {
- if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subId,
- callingPackage, callingFeatureId, "getSubscriptionsInGroup")) {
- return false;
- }
- if (CompatChanges.isChangeEnabled(
- REQUIRE_ICC_AUTH_DEVICE_IDENTIFIERS_FOR_GROUP_UUID, uid)) {
- return hasSubscriberIdentifierAccess(subId, callingPackage,
- callingFeatureId, "getSubscriptionsInGroup", true, true);
- }
- return true;
}
/**
@@ -4353,7 +4313,7 @@ public class SubscriptionController extends ISub.Stub {
if (canReadPhoneState) {
canReadIdentifiers = hasSubscriberIdentifierAccess(
SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage,
- callingFeatureId, "getSubscriptionInfoList", false, false);
+ callingFeatureId, "getSubscriptionInfoList", false);
canReadPhoneNumber = hasPhoneNumberAccess(
SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage,
callingFeatureId, "getSubscriptionInfoList");
@@ -4405,7 +4365,7 @@ public class SubscriptionController extends ISub.Stub {
SubscriptionInfo result = subInfo;
int subId = subInfo.getSubscriptionId();
boolean hasIdentifierAccess = hasSubscriberIdentifierAccess(subId, callingPackage,
- callingFeatureId, message, true, false);
+ callingFeatureId, message, true);
boolean hasPhoneNumberAccess = hasPhoneNumberAccess(subId, callingPackage, callingFeatureId,
message);
return conditionallyRemoveIdentifiers(subInfo, hasIdentifierAccess, hasPhoneNumberAccess);
diff --git a/src/java/com/android/internal/telephony/data/DataConfigManager.java b/src/java/com/android/internal/telephony/data/DataConfigManager.java
index 1504960581..82a4ccdce6 100644
--- a/src/java/com/android/internal/telephony/data/DataConfigManager.java
+++ b/src/java/com/android/internal/telephony/data/DataConfigManager.java
@@ -70,6 +70,9 @@ import java.util.stream.Collectors;
* {@link CarrierConfigManager}. All the data config will be loaded once and stored here.
*/
public class DataConfigManager extends Handler {
+ /** The default timeout in ms for data network stuck in a transit state. */
+ private static final int DEFAULT_NETWORK_TRANSIT_STATE_TIMEOUT_MS = 300000;
+
/** Event for carrier config changed. */
private static final int EVENT_CARRIER_CONFIG_CHANGED = 1;
@@ -347,22 +350,23 @@ public class DataConfigManager extends Handler {
mImsReleaseRequestAnomalyReportThreshold = parseSlidingWindowCounterThreshold(
properties.getString(KEY_ANOMALY_IMS_RELEASE_REQUEST, null),
- 300000,
+ 0,
12);
mNetworkUnwantedAnomalyReportThreshold = parseSlidingWindowCounterThreshold(
properties.getString(KEY_ANOMALY_NETWORK_UNWANTED, null),
- 300000,
+ 0,
12);
mSetupDataCallAnomalyReportThreshold = parseSlidingWindowCounterThreshold(
properties.getString(KEY_ANOMALY_SETUP_DATA_CALL_FAILURE, null),
0,
2);
mNetworkConnectingTimeout = properties.getInt(
- KEY_ANOMALY_NETWORK_CONNECTING_TIMEOUT, 86400000);
+ KEY_ANOMALY_NETWORK_CONNECTING_TIMEOUT, DEFAULT_NETWORK_TRANSIT_STATE_TIMEOUT_MS);
mNetworkDisconnectingTimeout = properties.getInt(
- KEY_ANOMALY_NETWORK_DISCONNECTING_TIMEOUT, 86400000);
+ KEY_ANOMALY_NETWORK_DISCONNECTING_TIMEOUT,
+ DEFAULT_NETWORK_TRANSIT_STATE_TIMEOUT_MS);
mNetworkHandoverTimeout = properties.getInt(
- KEY_ANOMALY_NETWORK_HANDOVER_TIMEOUT, 86400000);
+ KEY_ANOMALY_NETWORK_HANDOVER_TIMEOUT, DEFAULT_NETWORK_TRANSIT_STATE_TIMEOUT_MS);
}
/**
diff --git a/src/java/com/android/internal/telephony/data/DataNetwork.java b/src/java/com/android/internal/telephony/data/DataNetwork.java
index 0d4b210e9c..f85bc13cae 100644
--- a/src/java/com/android/internal/telephony/data/DataNetwork.java
+++ b/src/java/com/android/internal/telephony/data/DataNetwork.java
@@ -59,6 +59,7 @@ import android.telephony.NetworkRegistrationInfo;
import android.telephony.PcoData;
import android.telephony.PreciseDataConnectionState;
import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionPlan;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
@@ -230,12 +231,6 @@ public class DataNetwork extends StateMachine {
/** Event for CSS indicator changed. */
private static final int EVENT_CSS_INDICATOR_CHANGED = 24;
- /** The default MTU for IPv4 network. */
- private static final int DEFAULT_MTU_V4 = 1280;
-
- /** The default MTU for IPv6 network. */
- private static final int DEFAULT_MTU_V6 = 1280;
-
/** Invalid context id. */
private static final int INVALID_CID = -1;
@@ -280,6 +275,7 @@ public class DataNetwork extends StateMachine {
TEAR_DOWN_REASON_NOT_ALLOWED_BY_POLICY,
TEAR_DOWN_REASON_ILLEGAL_STATE,
TEAR_DOWN_REASON_ONLY_ALLOWED_SINGLE_NETWORK,
+ TEAR_DOWN_REASON_PREFERRED_DATA_SWITCHED,
})
public @interface TearDownReason {}
@@ -369,6 +365,9 @@ public class DataNetwork extends StateMachine {
/** Data network tear down due to only allowed single network. */
public static final int TEAR_DOWN_REASON_ONLY_ALLOWED_SINGLE_NETWORK = 29;
+ /** Data network tear down due to preferred data switched to another phone. */
+ public static final int TEAR_DOWN_REASON_PREFERRED_DATA_SWITCHED = 30;
+
@IntDef(prefix = {"BANDWIDTH_SOURCE_"},
value = {
BANDWIDTH_SOURCE_UNKNOWN,
@@ -467,6 +466,9 @@ public class DataNetwork extends StateMachine {
*/
private final int mSubId;
+ /** The network score of this network. */
+ private int mNetworkScore;
+
/**
* Indicates that
* {@link DataService.DataServiceProvider#deactivateDataCall(int, int, DataServiceCallback)}
@@ -955,8 +957,10 @@ public class DataNetwork extends StateMachine {
mPhone.getPhoneId());
final NetworkProvider provider = (null == factory) ? null : factory.getProvider();
+ mNetworkScore = getNetworkScore();
return new TelephonyNetworkAgent(mPhone, getHandler().getLooper(), this,
- getNetworkScore(), configBuilder.build(), provider,
+ new NetworkScore.Builder().setLegacyInt(mNetworkScore).build(),
+ configBuilder.build(), provider,
new TelephonyNetworkAgentCallback(getHandler()::post) {
@Override
public void onValidationStatus(@ValidationStatus int status,
@@ -1047,13 +1051,12 @@ public class DataNetwork extends StateMachine {
}
case EVENT_ATTACH_NETWORK_REQUEST: {
onAttachNetworkRequests((NetworkRequestList) msg.obj);
+ updateNetworkScore();
break;
}
case EVENT_DETACH_NETWORK_REQUEST: {
- TelephonyNetworkRequest networkRequest = (TelephonyNetworkRequest) msg.obj;
- mAttachedNetworkRequestList.remove(networkRequest);
- networkRequest.setState(TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED);
- networkRequest.setAttachedNetwork(null);
+ onDetachNetworkRequest((TelephonyNetworkRequest) msg.obj);
+ updateNetworkScore();
break;
}
case EVENT_DETACH_ALL_NETWORK_REQUESTS: {
@@ -1291,8 +1294,6 @@ public class DataNetwork extends StateMachine {
case EVENT_VOICE_CALL_STARTED:
case EVENT_VOICE_CALL_ENDED:
case EVENT_CSS_INDICATOR_CHANGED:
- // We might entered non-VoPS network. Need to update the network capability to
- // remove MMTEL capability.
updateSuspendState();
updateNetworkCapabilities();
break;
@@ -1469,8 +1470,6 @@ public class DataNetwork extends StateMachine {
case EVENT_CSS_INDICATOR_CHANGED:
case EVENT_VOICE_CALL_STARTED:
case EVENT_VOICE_CALL_ENDED:
- // We might entered non-VoPS network. Need to update the network capability to
- // remove MMTEL capability.
updateSuspendState();
updateNetworkCapabilities();
break;
@@ -1619,6 +1618,31 @@ public class DataNetwork extends StateMachine {
}
/**
+ * Called when detaching the network request from this data network.
+ *
+ * @param networkRequest Network request to detach.
+ */
+ private void onDetachNetworkRequest(@NonNull TelephonyNetworkRequest networkRequest) {
+ mAttachedNetworkRequestList.remove(networkRequest);
+ networkRequest.setState(TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED);
+ networkRequest.setAttachedNetwork(null);
+
+ if (mAttachedNetworkRequestList.isEmpty()) {
+ log("All network requests are detached.");
+
+ // If there is no network request attached, and we are not preferred data phone, then
+ // this detach is likely due to temp DDS switch. We should tear down the network when
+ // all requests are detached so the other network on preferred data sub can be
+ // established properly.
+ int preferredDataPhoneId = PhoneSwitcher.getInstance().getPreferredDataPhoneId();
+ if (preferredDataPhoneId != SubscriptionManager.INVALID_PHONE_INDEX
+ && preferredDataPhoneId != mPhone.getPhoneId()) {
+ tearDown(TEAR_DOWN_REASON_PREFERRED_DATA_SWITCHED);
+ }
+ }
+ }
+
+ /**
* Detach the network request from this data network. Note that this will not tear down the
* network.
*
@@ -1777,14 +1801,13 @@ public class DataNetwork extends StateMachine {
}
}
- // If voice call is on-going, do not change MMTEL capability, which is an immutable
- // capability. Changing it will result in CS tearing down IMS network, and the voice
- // call will drop.
- if (shouldDelayImsTearDown() && mNetworkCapabilities != null
+ // Once we set the MMTEL capability, we should never remove it because it's an immutable
+ // capability defined by connectivity service. When the device enters from VoPS to non-VoPS,
+ // we should perform grace tear down from data network controller if needed.
+ if (mNetworkCapabilities != null
&& mNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL)) {
// Previous capability has MMTEL, so add it again.
builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL);
- log("Delayed IMS tear down. Reporting MMTEL capability for now.");
} else {
// Always add MMTEL capability on IMS network unless network explicitly indicates VoPS
// not supported.
@@ -2191,7 +2214,7 @@ public class DataNetwork extends StateMachine {
mtuV4 = mDataProfile.getApnSetting().getMtuV4();
}
if (mtuV4 <= 0) {
- mtuV4 = DEFAULT_MTU_V4;
+ mtuV4 = mDataConfigManager.getDefaultMtu();
}
}
@@ -2203,7 +2226,7 @@ public class DataNetwork extends StateMachine {
mtuV6 = mDataProfile.getApnSetting().getMtuV6();
}
if (mtuV6 <= 0) {
- mtuV6 = DEFAULT_MTU_V6;
+ mtuV6 = mDataConfigManager.getDefaultMtu();
}
}
@@ -2440,7 +2463,7 @@ public class DataNetwork extends StateMachine {
public boolean shouldDelayImsTearDown() {
return mDataConfigManager.isImsDelayTearDownEnabled()
&& mNetworkCapabilities != null
- && mNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
+ && mNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL)
&& mPhone.getImsPhone() != null
&& mPhone.getImsPhone().getCallTracker().getState()
!= PhoneConstants.State.IDLE;
@@ -2759,16 +2782,27 @@ public class DataNetwork extends StateMachine {
}
/**
+ * Update the network score and report to connectivity service if necessary.
+ */
+ private void updateNetworkScore() {
+ int networkScore = getNetworkScore();
+ if (networkScore != mNetworkScore) {
+ logl("Updating score from " + mNetworkScore + " to " + networkScore);
+ mNetworkScore = networkScore;
+ mNetworkAgent.sendNetworkScore(mNetworkScore);
+ }
+ }
+
+ /**
* @return The network score. The higher score of the network has higher chance to be
* selected by the connectivity service as active network.
*/
- private @NonNull NetworkScore getNetworkScore() {
+ private int getNetworkScore() {
// If it's serving a network request that asks NET_CAPABILITY_INTERNET and doesn't have
// specify a sub id, this data network is considered to be default internet data
// connection. In this case we assign a slightly higher score of 50. The intention is
// it will not be replaced by other data networks accidentally in DSDS use case.
int score = OTHER_NETWORK_SCORE;
- // TODO: Should update the score when attached list changed.
for (TelephonyNetworkRequest networkRequest : mAttachedNetworkRequestList) {
if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
&& networkRequest.getNetworkSpecifier() == null) {
@@ -2776,7 +2810,7 @@ public class DataNetwork extends StateMachine {
}
}
- return new NetworkScore.Builder().setLegacyInt(score).build();
+ return score;
}
/**
@@ -2935,6 +2969,14 @@ public class DataNetwork extends StateMachine {
}
/**
+ * @return {@code true} if this network was setup for SUPL during emergency call. {@code false}
+ * otherwise.
+ */
+ public boolean isEmergencySupl() {
+ return mDataAllowedReason == DataAllowedReason.EMERGENCY_SUPL;
+ }
+
+ /**
* Get precise data connection state
*
* @return The {@link PreciseDataConnectionState}
@@ -3207,6 +3249,8 @@ public class DataNetwork extends StateMachine {
return "TEAR_DOWN_REASON_ILLEGAL_STATE";
case TEAR_DOWN_REASON_ONLY_ALLOWED_SINGLE_NETWORK:
return "TEAR_DOWN_REASON_ONLY_ALLOWED_SINGLE_NETWORK";
+ case TEAR_DOWN_REASON_PREFERRED_DATA_SWITCHED:
+ return "TEAR_DOWN_REASON_PREFERRED_DATA_SWITCHED";
default:
return "UNKNOWN(" + reason + ")";
}
@@ -3351,6 +3395,7 @@ public class DataNetwork extends StateMachine {
pw.println("mTransport=" + AccessNetworkConstants.transportTypeToString(mTransport));
pw.println("WWAN cid=" + mCid.get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN));
pw.println("WLAN cid=" + mCid.get(AccessNetworkConstants.TRANSPORT_TYPE_WLAN));
+ pw.println("mNetworkScore=" + mNetworkScore);
pw.println("mDataAllowedReason=" + mDataAllowedReason);
pw.println("mPduSessionId=" + mPduSessionId);
pw.println("mDataProfile=" + mDataProfile);
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index 2b0507c4a6..7be0a4d8de 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -934,8 +934,13 @@ public class DataNetworkController extends Handler {
+ DataUtils.networkCapabilityToString(capability) + " preferred on "
+ AccessNetworkConstants.transportTypeToString(preferredTransport));
DataNetworkController.this.onEvaluatePreferredTransport(capability);
- sendMessage(obtainMessage(EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS,
- DataEvaluationReason.PREFERRED_TRANSPORT_CHANGED));
+ if (!hasMessages(EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS)) {
+ sendMessage(obtainMessage(EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS,
+ DataEvaluationReason.PREFERRED_TRANSPORT_CHANGED));
+ } else {
+ log("onPreferredTransportChanged: Skipped evaluating unsatisfied network "
+ + "requests because another evaluation was already scheduled.");
+ }
}
});
@@ -1649,6 +1654,31 @@ public class DataNetworkController extends Handler {
}
}
+ // If the data network is IMS that supports voice call, and has MMTEL request (client
+ // specified VoPS is required.)
+ if (dataNetwork.getAttachedNetworkRequestList().get(
+ new int[]{NetworkCapabilities.NET_CAPABILITY_MMTEL}) != null) {
+ // When reaching here, it means the network supports MMTEL, and also has MMTEL request
+ // attached to it.
+ if (!dataNetwork.shouldDelayImsTearDown()) {
+ if (dataNetwork.getTransport() == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
+ NetworkRegistrationInfo nri = mServiceState.getNetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_PS,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+ if (nri != null) {
+ DataSpecificRegistrationInfo dsri = nri.getDataSpecificInfo();
+ if (dsri != null && dsri.getVopsSupportInfo() != null
+ && !dsri.getVopsSupportInfo().isVopsSupported()) {
+ evaluation.addDataDisallowedReason(
+ DataDisallowedReason.VOPS_NOT_SUPPORTED);
+ }
+ }
+ }
+ } else {
+ log("Ignored VoPS check due to delay IMS tear down until call ends.");
+ }
+ }
+
// Check if data is disabled
boolean dataDisabled = false;
if (!mDataSettingsManager.isDataEnabled()) {
@@ -1716,9 +1746,7 @@ public class DataNetworkController extends Handler {
// If there are reasons we should tear down the network, check if those are hard reasons
// or soft reasons. In some scenarios, we can make exceptions if they are soft
// disallowed reasons.
- if ((mPhone.isInEmergencyCall() || mPhone.isInEcm())
- && dataNetwork.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_SUPL)) {
+ if ((mPhone.isInEmergencyCall() || mPhone.isInEcm()) && dataNetwork.isEmergencySupl()) {
// Check if it's SUPL during emergency call.
evaluation.addDataAllowedReason(DataAllowedReason.EMERGENCY_SUPL);
} else if (!dataNetwork.getNetworkCapabilities().hasCapability(
@@ -1989,16 +2017,24 @@ public class DataNetworkController extends Handler {
sendMessage(obtainMessage(EVENT_REMOVE_NETWORK_REQUEST, networkRequest));
}
- private void onRemoveNetworkRequest(@NonNull TelephonyNetworkRequest networkRequest) {
+ private void onRemoveNetworkRequest(@NonNull TelephonyNetworkRequest request) {
+ // The request generated from telephony network factory does not contain the information
+ // the original request has, for example, attached data network. We need to find the
+ // original one.
+ TelephonyNetworkRequest networkRequest = mAllNetworkRequestList.stream()
+ .filter(r -> r.equals(request))
+ .findFirst()
+ .orElse(null);
+ if (networkRequest == null || !mAllNetworkRequestList.remove(networkRequest)) {
+ loge("onRemoveNetworkRequest: Network request does not exist. " + networkRequest);
+ return;
+ }
+
if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
mImsThrottleCounter.addOccurrence();
mLastReleasedImsRequestCapabilities = networkRequest.getCapabilities();
mLastImsOperationIsRelease = true;
}
- if (!mAllNetworkRequestList.remove(networkRequest)) {
- loge("onRemoveNetworkRequest: Network request does not exist. " + networkRequest);
- return;
- }
if (networkRequest.getAttachedNetwork() != null) {
networkRequest.getAttachedNetwork().detachNetworkRequest(networkRequest);
@@ -3376,8 +3412,12 @@ public class DataNetworkController extends Handler {
+ (mRegisteredImsFeatures.contains(ImsFeature.FEATURE_RCS)
? "registered" : "not registered")
);
- mPendingImsDeregDataNetworks.put(dataNetwork,
- dataNetwork.tearDownWhenConditionMet(reason, deregDelay));
+ Runnable runnable = dataNetwork.tearDownWhenConditionMet(reason, deregDelay);
+ if (runnable != null) {
+ mPendingImsDeregDataNetworks.put(dataNetwork, runnable);
+ } else {
+ log(dataNetwork + " is being torn down already.");
+ }
} else {
// Graceful tear down is not turned on. Tear down the network immediately.
log("tearDownGracefully: Safe to tear down " + dataNetwork);
diff --git a/src/java/com/android/internal/telephony/data/DataProfileManager.java b/src/java/com/android/internal/telephony/data/DataProfileManager.java
index f459b82e71..1ec345c943 100644
--- a/src/java/com/android/internal/telephony/data/DataProfileManager.java
+++ b/src/java/com/android/internal/telephony/data/DataProfileManager.java
@@ -273,7 +273,7 @@ public class DataProfileManager extends Handler {
}
// Check if any of the profile already supports IMS, if not, add the default one.
- DataProfile dataProfile = profiles.stream()
+ dataProfile = profiles.stream()
.filter(dp -> dp.canSatisfy(NetworkCapabilities.NET_CAPABILITY_IMS))
.findFirst()
.orElse(null);
@@ -312,14 +312,15 @@ public class DataProfileManager extends Handler {
profilesChanged = true;
}
+ // Reload the latest preferred data profile from either database or config.
+ profilesChanged |= updatePreferredDataProfile();
+
int setId = getPreferredDataProfileSetId();
if (setId != mPreferredDataProfileSetId) {
logl("Changed preferred data profile set id to " + setId);
mPreferredDataProfileSetId = setId;
profilesChanged = true;
}
- // Reload the latest preferred data profile from either database or config.
- profilesChanged |= updatePreferredDataProfile();
updateDataProfilesAtModem();
updateInitialAttachDataProfileAtModem();
@@ -461,6 +462,10 @@ public class DataProfileManager extends Handler {
preferredDataProfile = getPreferredDataProfileFromDb();
if (preferredDataProfile == null) {
preferredDataProfile = getPreferredDataProfileFromConfig();
+ if (preferredDataProfile != null) {
+ // Save the carrier specified preferred data profile into database
+ setPreferredDataProfile(preferredDataProfile);
+ }
}
} else {
preferredDataProfile = null;
diff --git a/src/java/com/android/internal/telephony/data/DataSettingsManager.java b/src/java/com/android/internal/telephony/data/DataSettingsManager.java
index 68c1b5d110..e2c1aff05a 100644
--- a/src/java/com/android/internal/telephony/data/DataSettingsManager.java
+++ b/src/java/com/android/internal/telephony/data/DataSettingsManager.java
@@ -228,14 +228,8 @@ public class DataSettingsManager extends Handler {
}
case EVENT_SET_DATA_ROAMING_ENABLED: {
boolean enabled = (boolean) msg.obj;
- // Will trigger handleDataOnRoamingChange() through observer
- boolean changed = GlobalSettingsHelper.setBoolean(mPhone.getContext(),
- Settings.Global.DATA_ROAMING, mSubId, enabled);
- if (changed) {
- logl("DataRoamingEnabled changed to " + enabled);
- mDataSettingsManagerCallbacks.forEach(callback -> callback.invokeFromExecutor(
- () -> callback.onDataRoamingEnabledChanged(enabled)));
- }
+ setDataRoamingEnabledInternal(enabled);
+ setDataRoamingFromUserAction();
break;
}
case EVENT_SET_ALWAYS_ALLOW_MMS_DATA: {
@@ -501,7 +495,7 @@ public class DataSettingsManager extends Handler {
}
/**
- * Enable or disable data roaming.
+ * Enable or disable data roaming from user settings.
* @param enabled {@code true} to enable data roaming and {@code false} to disable.
*/
public void setDataRoamingEnabled(boolean enabled) {
@@ -509,6 +503,21 @@ public class DataSettingsManager extends Handler {
}
/**
+ * Enable or disable data roaming.
+ * @param enabled {@code true} to enable data roaming and {@code false} to disable.
+ */
+ private void setDataRoamingEnabledInternal(boolean enabled) {
+ // Will trigger handleDataOnRoamingChange() through observer
+ boolean changed = GlobalSettingsHelper.setBoolean(mPhone.getContext(),
+ Settings.Global.DATA_ROAMING, mSubId, enabled);
+ if (changed) {
+ logl("DataRoamingEnabled changed to " + enabled);
+ mDataSettingsManagerCallbacks.forEach(callback -> callback.invokeFromExecutor(
+ () -> callback.onDataRoamingEnabledChanged(enabled)));
+ }
+ }
+
+ /**
* Check whether data roaming is enabled for the device based on the current
* {@link Settings.Global#DATA_ROAMING} value.
* @return {@code true} if data roaming is enabled and {@code false} otherwise.
@@ -537,7 +546,7 @@ public class DataSettingsManager extends Handler {
public void setDefaultDataRoamingEnabled() {
// For SSSS, this is a per-phone property from DATA_ROAMING_IS_USER_SETTING_KEY.
// For DSDS, this is a per-sub property from Settings.Global.DATA_ROAMING + subId.
- // If the user has not manually set the value, use the default from carrier configurations.
+ // If the user has not manually set the value, use the default value.
boolean useCarrierSpecificDefault = false;
if (mPhone.getContext().getSystemService(TelephonyManager.class).getSimCount() != 1) {
String setting = Settings.Global.DATA_ROAMING + mPhone.getSubId();
@@ -554,7 +563,7 @@ public class DataSettingsManager extends Handler {
log("setDefaultDataRoamingEnabled: useCarrierSpecificDefault=" + useCarrierSpecificDefault);
if (useCarrierSpecificDefault) {
boolean defaultVal = isDefaultDataRoamingEnabled();
- setDataRoamingEnabled(defaultVal);
+ setDataRoamingEnabledInternal(defaultVal);
}
}
@@ -573,6 +582,17 @@ public class DataSettingsManager extends Handler {
return sp.getBoolean(Phone.DATA_ROAMING_IS_USER_SETTING_KEY, true);
}
+ /**
+ * Indicate that the user has manually enabled or disabled the data roaming value from settings.
+ * If the user has not manually set the data roaming value, the default value from
+ * {@link #isDefaultDataRoamingEnabled()} will continue to be used.
+ */
+ private void setDataRoamingFromUserAction() {
+ final SharedPreferences.Editor sp = PreferenceManager
+ .getDefaultSharedPreferences(mPhone.getContext()).edit();
+ sp.putBoolean(Phone.DATA_ROAMING_IS_USER_SETTING_KEY, true).commit();
+ }
+
private @NonNull DataEnabledOverride getDataEnabledOverride() {
return new DataEnabledOverride(SubscriptionController.getInstance()
.getDataEnabledOverrideRules(mSubId));
@@ -724,6 +744,9 @@ public class DataSettingsManager extends Handler {
pw.println("isDataEnabled(internet)=" + isDataEnabled(ApnSetting.TYPE_DEFAULT));
pw.println("isDataEnabled(mms)=" + isDataEnabled(ApnSetting.TYPE_MMS));
pw.println("isUserDataEnabled=" + isUserDataEnabled());
+ pw.println("isDataRoamingEnabled=" + isDataRoamingEnabled());
+ pw.println("isDefaultDataRoamingEnabled=" + isDefaultDataRoamingEnabled());
+ pw.println("isDataRoamingFromUserAction=" + isDataRoamingFromUserAction());
pw.println("device_provisioned=" + Settings.Global.getInt(
mResolver, Settings.Global.DEVICE_PROVISIONED, 0));
pw.println("isProvisioningDataEnabled=" + isProvisioningDataEnabled());
diff --git a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
index bb0ee8b793..cc5f44738b 100644
--- a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
@@ -312,7 +312,7 @@ public class PhoneSwitcher extends Handler {
protected RadioConfig mRadioConfig;
- private static final int MAX_LOCAL_LOG_LINES = 32;
+ private static final int MAX_LOCAL_LOG_LINES = 256;
// Default timeout value of network validation in millisecond.
private final static int DEFAULT_VALIDATION_EXPIRATION_TIME = 2000;
@@ -958,7 +958,7 @@ public class PhoneSwitcher extends Handler {
mPrioritizedDcRequests.add(dcRequest);
Collections.sort(mPrioritizedDcRequests);
onEvaluate(REQUESTS_CHANGED, "netRequest");
- log("Added DcRequest, size: " + mPrioritizedDcRequests.size());
+ if (VDBG) log("Added DcRequest, size: " + mPrioritizedDcRequests.size());
}
}
}
@@ -979,7 +979,7 @@ public class PhoneSwitcher extends Handler {
if (mPrioritizedDcRequests.remove(dcRequest)) {
onEvaluate(REQUESTS_CHANGED, "netReleased");
collectReleaseNetworkMetrics(networkRequest);
- log("Removed DcRequest, size: " + mPrioritizedDcRequests.size());
+ if (VDBG) log("Removed DcRequest, size: " + mPrioritizedDcRequests.size());
}
}
}
@@ -1264,7 +1264,7 @@ public class PhoneSwitcher extends Handler {
protected void sendRilCommands(int phoneId) {
if (!SubscriptionManager.isValidPhoneId(phoneId)) {
- log("sendRilCommands: skip dds switch due to invalid phoneid=" + phoneId);
+ log("sendRilCommands: skip dds switch due to invalid phoneId=" + phoneId);
return;
}
@@ -1674,8 +1674,54 @@ public class PhoneSwitcher extends Handler {
mLocalLog.log(l);
}
+ /**
+ * Convert data switch reason into string.
+ *
+ * @param reason The switch reason.
+ * @return The switch reason in string format.
+ */
+ private static @NonNull String switchReasonToString(int reason) {
+ switch(reason) {
+ case TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN:
+ return "UNKNOWN";
+ case TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_MANUAL:
+ return "MANUAL";
+ case TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL:
+ return "IN_CALL";
+ case TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_CBRS:
+ return "CBRS";
+ default: return "UNKNOWN(" + reason + ")";
+ }
+ }
+
+ /**
+ * Concert switching state to string
+ *
+ * @param state The switching state.
+ * @return The switching state in string format.
+ */
+ private static @NonNull String switchStateToString(int state) {
+ switch(state) {
+ case TelephonyEvent.EventState.EVENT_STATE_UNKNOWN:
+ return "UNKNOWN";
+ case TelephonyEvent.EventState.EVENT_STATE_START:
+ return "START";
+ case TelephonyEvent.EventState.EVENT_STATE_END:
+ return "END";
+ default: return "UNKNOWN(" + state + ")";
+ }
+ }
+
+ /**
+ * Log data switch event
+ *
+ * @param subId Subscription index.
+ * @param state The switching state.
+ * @param reason The switching reason.
+ */
private void logDataSwitchEvent(int subId, int state, int reason) {
- log("logDataSwitchEvent subId " + subId + " state " + state + " reason " + reason);
+ log("Data switch event. subId=" + subId + ", state=" + switchStateToString(state)
+ + ", reason=" + switchReasonToString(reason));
DataSwitch dataSwitch = new DataSwitch();
dataSwitch.state = state;
dataSwitch.reason = reason;
@@ -1708,6 +1754,7 @@ public class PhoneSwitcher extends Handler {
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
pw.println("PhoneSwitcher:");
+ pw.increaseIndent();
Calendar c = Calendar.getInstance();
for (int i = 0; i < mActiveModemCount; i++) {
PhoneState ps = mPhoneStates[i];
@@ -1716,14 +1763,29 @@ public class PhoneSwitcher extends Handler {
(ps.lastRequested == 0 ? "never" :
String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c)));
}
+ pw.println("mPreferredDataPhoneId=" + mPreferredDataPhoneId);
+ pw.println("mPreferredDataSubId=" + mPreferredDataSubId.get());
+ pw.println("DefaultDataSubId=" + mSubscriptionController.getDefaultDataSubId());
+ pw.println("DefaultDataPhoneId=" + mSubscriptionController.getPhoneId(
+ mSubscriptionController.getDefaultDataSubId()));
+ pw.println("mPrimaryDataSubId=" + mPrimaryDataSubId);
+ pw.println("mOpptDataSubId=" + mOpptDataSubId);
+ pw.println("mIsRegisteredForImsRadioTechChange=" + mIsRegisteredForImsRadioTechChange);
+ pw.println("mPendingSwitchNeedValidation=" + mPendingSwitchNeedValidation);
+ pw.println("mMaxDataAttachModemCount=" + mMaxDataAttachModemCount);
+ pw.println("mActiveModemCount=" + mActiveModemCount);
+ pw.println("mPhoneIdInVoiceCall=" + mPhoneIdInVoiceCall);
+ pw.println("mCurrentDdsSwitchFailure=" + mCurrentDdsSwitchFailure);
+ pw.println("Local logs:");
pw.increaseIndent();
mLocalLog.dump(fd, pw, args);
pw.decreaseIndent();
+ pw.decreaseIndent();
}
private boolean isAnyVoiceCallActiveOnDevice() {
boolean ret = mPhoneIdInVoiceCall != SubscriptionManager.INVALID_PHONE_INDEX;
- log("isAnyVoiceCallActiveOnDevice: " + ret);
+ if (VDBG) log("isAnyVoiceCallActiveOnDevice: " + ret);
return ret;
}
diff --git a/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java b/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java
index a56bbcdba1..85f0ae1f0d 100644
--- a/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java
+++ b/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java
@@ -58,7 +58,7 @@ public class TelephonyNetworkFactory extends NetworkFactory {
public final String LOG_TAG;
protected static final boolean DBG = true;
- private static final int REQUEST_LOG_SIZE = 32;
+ private static final int REQUEST_LOG_SIZE = 256;
private static final int ACTION_NO_OP = 0;
private static final int ACTION_REQUEST = 1;
@@ -302,6 +302,7 @@ public class TelephonyNetworkFactory extends NetworkFactory {
// apply or revoke requests if our active-ness changes
private void onActivePhoneSwitch() {
+ logl("onActivePhoneSwitch");
for (Map.Entry<TelephonyNetworkRequest, Integer> entry : mNetworkRequests.entrySet()) {
TelephonyNetworkRequest networkRequest = entry.getKey();
boolean applied = entry.getValue() != AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
@@ -338,7 +339,7 @@ public class TelephonyNetworkFactory extends NetworkFactory {
final int newSubscriptionId = mSubscriptionController.getSubIdUsingPhoneId(
mPhone.getPhoneId());
if (mSubscriptionId != newSubscriptionId) {
- if (DBG) log("onSubIdChange " + mSubscriptionId + "->" + newSubscriptionId);
+ if (DBG) logl("onSubIdChange " + mSubscriptionId + "->" + newSubscriptionId);
mSubscriptionId = newSubscriptionId;
setCapabilityFilter(makeNetworkFilter(mSubscriptionId));
}
@@ -535,6 +536,8 @@ public class TelephonyNetworkFactory extends NetworkFactory {
*/
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
+ pw.println("TelephonyNetworkFactory-" + mPhone.getPhoneId());
+ pw.increaseIndent();
pw.println("Network Requests:");
pw.increaseIndent();
for (Map.Entry<TelephonyNetworkRequest, Integer> entry : mNetworkRequests.entrySet()) {
@@ -543,7 +546,11 @@ public class TelephonyNetworkFactory extends NetworkFactory {
pw.println(nr + (transport != AccessNetworkConstants.TRANSPORT_TYPE_INVALID
? (" applied on " + transport) : " not applied"));
}
+ pw.decreaseIndent();
+ pw.print("Local logs:");
+ pw.increaseIndent();
mLocalLog.dump(fd, pw, args);
pw.decreaseIndent();
+ pw.decreaseIndent();
}
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index ce2198de33..cc8af38cdd 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -220,6 +220,7 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
isUssd |= extras.getBoolean(ImsManager.EXTRA_USSD, false);
if (isUssd) {
if (DBG) log("processIncomingCall: USSD");
+ mOperationLocalLog.log("processIncomingCall: USSD");
mUssdSession = mImsManager.takeCall(c, mImsUssdListener);
if (mUssdSession != null) {
mUssdSession.accept(ImsCallProfile.CALL_TYPE_VOICE);
@@ -271,6 +272,7 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
if (cause == DisconnectCause.INCOMING_AUTO_REJECTED) {
conn.setDisconnectCause(cause);
if (DBG) log("onIncomingCall : incoming call auto rejected");
+ mOperationLocalLog.log("processIncomingCall: auto rejected");
}
} catch (NumberFormatException e) {
Rlog.e(LOG_TAG, "Exception in parsing Integer Data: " + e);
@@ -310,9 +312,9 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
updatePhoneState();
mPhone.notifyPreciseCallStateChanged();
- } catch (ImsException e) {
+ } catch (ImsException | RemoteException e) {
loge("processIncomingCall: exception " + e);
- } catch (RemoteException e) {
+ mOperationLocalLog.log("onIncomingCall: exception processing: " + e);
}
}
@@ -504,6 +506,8 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
PENDING_RESUME_FOREGROUND_AFTER_FAILURE,
// Pending holding a call to dial another outgoing call
HOLDING_TO_DIAL_OUTGOING,
+ // Pending resuming the foreground call after it has completed an ongoing hold operation.
+ PENDING_RESUME_FOREGROUND_AFTER_HOLD
}
//***** Instance Variables
@@ -1451,7 +1455,6 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
int videoState = dialArgs.videoState;
if (DBG) log("dial clirMode=" + clirMode);
- mOperationLocalLog.log("dial requested.");
String origNumber = dialString;
if (isEmergencyNumber) {
clirMode = CommandsInterface.CLIR_SUPPRESSION;
@@ -1483,6 +1486,7 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
mLastDialArgs = dialArgs;
mPendingMO = new ImsPhoneConnection(mPhone, dialString, this, mForegroundCall,
isEmergencyNumber, isWpsCall);
+ mOperationLocalLog.log("dial requested. connId=" + System.identityHashCode(mPendingMO));
if (isEmergencyNumber && dialArgs != null && dialArgs.intentExtras != null) {
Rlog.i(LOG_TAG, "dial ims emergency dialer: " + dialArgs.intentExtras.getBoolean(
TelecomManager.EXTRA_IS_USER_INTENT_EMERGENCY_CALL));
@@ -2066,9 +2070,15 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
//they were switched before holding
ImsCall imsCall = mForegroundCall.getImsCall();
if (imsCall != null) {
- imsCall.resume();
- mMetrics.writeOnImsCommand(mPhone.getPhoneId(), imsCall.getSession(),
- ImsCommand.IMS_CMD_RESUME);
+ if (!imsCall.isPendingHold()) {
+ imsCall.resume();
+ mMetrics.writeOnImsCommand(mPhone.getPhoneId(), imsCall.getSession(),
+ ImsCommand.IMS_CMD_RESUME);
+ } else {
+ mHoldSwitchingState =
+ HoldSwapState.PENDING_RESUME_FOREGROUND_AFTER_HOLD;
+ logHoldSwapState("resumeForegroundCall - unhold pending; resume request again");
+ }
}
}
@@ -2525,34 +2535,33 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
}
ImsCall imsCall = call.getImsCall();
+ ImsPhoneConnection conn = findConnection(imsCall);
boolean rejectCall = false;
+ String logResult = "(undefined)";
if (call == mRingingCall) {
- if (Phone.DEBUG_PHONE) log("(ringing) hangup incoming");
+ logResult = "(ringing) hangup incoming";
rejectCall = true;
} else if (call == mForegroundCall) {
if (call.isDialingOrAlerting()) {
- if (Phone.DEBUG_PHONE) {
- log("(foregnd) hangup dialing or alerting...");
- }
+ logResult = "(foregnd) hangup dialing or alerting...";
} else {
- if (Phone.DEBUG_PHONE) {
- log("(foregnd) hangup foreground");
- }
+ logResult = "(foregnd) hangup foreground";
//held call will be resumed by onCallTerminated
}
} else if (call == mBackgroundCall) {
- if (Phone.DEBUG_PHONE) {
- log("(backgnd) hangup waiting or background");
- }
+ logResult = "(backgnd) hangup waiting or background";
} else if (call == mHandoverCall) {
- if (Phone.DEBUG_PHONE) {
- log("(handover) hangup handover (SRVCC) call");
- }
+ logResult = "(handover) hangup handover (SRVCC) call";
} else {
+ mOperationLocalLog.log("hangup: ImsPhoneCall " + System.identityHashCode(conn)
+ + " does not belong to ImsPhoneCallTracker " + this);
throw new CallStateException ("ImsPhoneCall " + call +
"does not belong to ImsPhoneCallTracker " + this);
}
+ if (Phone.DEBUG_PHONE) log(logResult);
+ mOperationLocalLog.log("hangup: " + logResult + ", connId="
+ + System.identityHashCode(conn));
call.onHangupLocal();
@@ -2581,6 +2590,7 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
removeMessages(EVENT_DIAL_PENDINGMO);
}
} catch (ImsException e) {
+ mOperationLocalLog.log("hangup: ImsException=" + e);
throw new CallStateException(e.getMessage());
}
@@ -2754,6 +2764,10 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
return;
}
+ // Do not log operations that do not change the state
+ mOperationLocalLog.log("processCallStateChange: state=" + state + " cause=" + cause
+ + " connId=" + System.identityHashCode(conn));
+
changed = conn.update(imsCall, state);
if (state == ImsPhoneCall.State.DISCONNECTED) {
changed = conn.onDisconnect(cause) || changed;
@@ -3443,7 +3457,12 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
// processCallStateChange above may have caused the mBackgroundCall and
// mForegroundCall references below to change meaning. Watch out for this if you
// are reading through this code.
- if (oldState == ImsPhoneCall.State.ACTIVE) {
+ if (mHoldSwitchingState
+ == HoldSwapState.PENDING_RESUME_FOREGROUND_AFTER_HOLD) {
+ sendEmptyMessage(EVENT_RESUME_NOW_FOREGROUND_CALL);
+ mHoldSwitchingState = HoldSwapState.INACTIVE;
+ mCallExpectedToResume = null;
+ } else if (oldState == ImsPhoneCall.State.ACTIVE) {
// Note: This case comes up when we have just held a call in response to a
// switchWaitingOrHoldingAndActive. We now need to resume the background call.
if (mForegroundCall.getState() == ImsPhoneCall.State.HOLDING
@@ -3488,7 +3507,10 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
synchronized (mSyncHold) {
ImsPhoneCall.State bgState = mBackgroundCall.getState();
- if (reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED) {
+ if (mHoldSwitchingState
+ == HoldSwapState.PENDING_RESUME_FOREGROUND_AFTER_HOLD) {
+ mHoldSwitchingState = HoldSwapState.INACTIVE;
+ } else if (reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED) {
// disconnected while processing hold
if (mPendingMO != null) {
dialPendingMO();
@@ -4585,6 +4607,9 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
case HOLDING_TO_DIAL_OUTGOING:
holdSwapState = "HOLDING_TO_DIAL_OUTGOING";
break;
+ case PENDING_RESUME_FOREGROUND_AFTER_HOLD:
+ holdSwapState = "PENDING_RESUME_FOREGROUND_AFTER_HOLD";
+ break;
}
logi("holdSwapState set to " + holdSwapState + " at " + loc);
}
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index 9ce271ea54..70cfce00b6 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -36,6 +36,7 @@ import android.os.Registrant;
import android.os.RegistrantList;
import android.preference.PreferenceManager;
import android.sysprop.TelephonyProperties;
+import android.telephony.AnomalyReporter;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -65,6 +66,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.UUID;
import java.util.stream.IntStream;
/**
@@ -910,8 +912,13 @@ public class UiccController extends Handler {
cardId = convertToPublicCardId(eid);
} else {
// In case of non Euicc, use default port index to get the IccId.
- String iccId = card.getUiccPort(TelephonyManager.DEFAULT_PORT_INDEX).getIccId();
- // leave eid null if the UICC is not embedded
+ UiccPort port = card.getUiccPort(TelephonyManager.DEFAULT_PORT_INDEX);
+ if (port == null) {
+ AnomalyReporter.reportAnomaly(
+ UUID.fromString("92885ba7-98bb-490a-ba19-987b1c8b2055"),
+ "UiccController: Found UiccPort Null object.");
+ }
+ String iccId = (port != null) ? port.getIccId() : null;
cardId = convertToPublicCardId(iccId);
}
} else {
diff --git a/src/java/com/android/internal/telephony/uicc/UiccProfile.java b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
index 864b3cdc2d..2809895309 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccProfile.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
@@ -53,6 +53,7 @@ import android.util.ArraySet;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.CarrierAppUtils;
+import com.android.internal.telephony.CarrierPrivilegesTracker;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.IccCardConstants;
@@ -238,6 +239,13 @@ public class UiccProfile extends IccCard {
case EVENT_CARRIER_PRIVILEGES_LOADED:
if (VDBG) log("handleMessage: EVENT_CARRIER_PRIVILEGES_LOADED");
+ Phone phone = PhoneFactory.getPhone(mPhoneId);
+ if (phone != null) {
+ CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
+ if (cpt != null) {
+ cpt.onUiccAccessRulesLoaded();
+ }
+ }
onCarrierPrivilegesLoadedMessage();
updateExternalState();
break;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java
index 92faabd1d8..221b2b525e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java
@@ -73,6 +73,7 @@ import com.android.internal.telephony.uicc.IccUtils;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
@@ -549,7 +550,8 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
List.of(new Pair<>(PRIVILEGED_PACKAGES, PRIVILEGED_UIDS_SET)));
}
- @Test
+ // TODO(b/232273884): turn UT case on when grace period is on
+ @Ignore
public void testSimStateChangedSimStateNotReady() throws Exception {
// Start with privileges, verify clearing certs clears UIDs
setupCarrierPrivilegesTrackerWithSimLoadedUids();
@@ -573,7 +575,8 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
new Pair<>(Set.of(), Set.of())));
}
- @Test
+ // TODO(b/232273884): turn UT case on when grace period is on
+ @Ignore
public void testSimStateChangedSimStateAbsentThenLoadedWithSameRules() throws Exception {
// Start with privileges
setupCarrierPrivilegesTrackerWithSimLoadedUids();
@@ -642,7 +645,8 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
List.of(new Pair<>(Set.of(), Set.of())));
}
- @Test
+ // TODO(b/232273884): turn UT case on when grace period is on
+ @Ignore
public void testSimStateChangedSimStateAbsentThenLoadedWithUpdatedRules() throws Exception {
// Start with privileges
setupCarrierPrivilegesTrackerWithSimLoadedUids();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
index acae8592f3..8ce11aef7a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
@@ -18,10 +18,15 @@ package com.android.internal.telephony;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import android.os.Message;
+import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -30,10 +35,14 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class CarrierServiceBindHelperTest extends TelephonyTest {
+ private static final int PHONE_ID_0 = 0;
+ private static final int PHONE_ID_1 = 1;
+
CarrierServiceBindHelper mCarrierServiceBindHelper;
@Before
public void setUp() throws Exception {
@@ -90,4 +99,38 @@ public class CarrierServiceBindHelperTest extends TelephonyTest {
CarrierServiceBindHelper.EVENT_PERFORM_IMMEDIATE_UNBIND,
new Integer(0)));
}
+
+ @Test
+ public void testCarrierPrivilegesCallbackRegistration() {
+ // Device starts with DSDS mode
+ doReturn(2).when(mTelephonyManager).getActiveModemCount();
+ mCarrierServiceBindHelper = new CarrierServiceBindHelper(mContext);
+ processAllMessages();
+
+ // Verify that CarrierPrivilegesCallbacks are registered on both phones.
+ // Capture the callbacks for further verification
+ ArgumentCaptor<CarrierPrivilegesCallback> phone0CallbackCaptor = ArgumentCaptor.forClass(
+ CarrierPrivilegesCallback.class);
+ verify(mTelephonyManager).registerCarrierPrivilegesCallback(eq(PHONE_ID_0), any(),
+ phone0CallbackCaptor.capture());
+ CarrierPrivilegesCallback phone0Callback = phone0CallbackCaptor.getAllValues().get(0);
+ assertNotNull(phone0Callback);
+
+ ArgumentCaptor<CarrierPrivilegesCallback> phone1CallbackCaptor = ArgumentCaptor.forClass(
+ CarrierPrivilegesCallback.class);
+ verify(mTelephonyManager).registerCarrierPrivilegesCallback(eq(PHONE_ID_1), any(),
+ phone1CallbackCaptor.capture());
+ CarrierPrivilegesCallback phone1Callback = phone1CallbackCaptor.getAllValues().get(0);
+ assertNotNull(phone1Callback);
+
+ // Switch back to single SIM.
+ doReturn(1).when(mTelephonyManager).getActiveModemCount();
+ PhoneConfigurationManager.notifyMultiSimConfigChange(1);
+ processAllMessages();
+
+ // Verify the callback for phone1 had been unregistered while phone0 didn't.
+ verify(mTelephonyManager).unregisterCarrierPrivilegesCallback(eq(phone1Callback));
+ verify(mTelephonyManager, never()).unregisterCarrierPrivilegesCallback(eq(phone0Callback));
+ }
+ // TODO (b/232461097): Add UT cases to cover more scenarios (user unlock, SIM state change...)
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java
index 14e58c75d5..6a4c9c2010 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java
@@ -17,7 +17,6 @@ package com.android.internal.telephony;
import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION;
-import static com.android.internal.telephony.SubscriptionController.REQUIRE_ICC_AUTH_DEVICE_IDENTIFIERS_FOR_GROUP_UUID;
import static com.android.internal.telephony.uicc.IccCardStatus.CardState.CARDSTATE_PRESENT;
import static org.junit.Assert.assertEquals;
@@ -34,9 +33,7 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -44,7 +41,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.Manifest;
-import android.compat.testing.PlatformCompatChangeRule;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
@@ -72,14 +68,9 @@ import com.android.internal.telephony.uicc.IccCardStatus;
import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.telephony.uicc.UiccSlot;
-import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
-import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
-
import org.junit.After;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
-import org.junit.rules.TestRule;
import org.mockito.ArgumentCaptor;
import java.util.ArrayList;
@@ -117,9 +108,6 @@ public class SubscriptionControllerTest extends TelephonyTest {
private static final String DISPLAY_NUMBER = "123456";
private static final String DISPLAY_NAME = "testing_display_name";
- @Rule
- public TestRule mCompatChangeRule = new PlatformCompatChangeRule();
-
@Before
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
@@ -1111,7 +1099,6 @@ public class SubscriptionControllerTest extends TelephonyTest {
@Test
@SmallTest
- @EnableCompatChanges({REQUIRE_ICC_AUTH_DEVICE_IDENTIFIERS_FOR_GROUP_UUID})
public void testAddSubscriptionIntoGroupWithCarrierPrivilegePermission() throws Exception {
testInsertSim();
// Adding a second profile and mark as embedded.
@@ -1163,7 +1150,6 @@ public class SubscriptionControllerTest extends TelephonyTest {
@Test
@SmallTest
- @EnableCompatChanges({REQUIRE_ICC_AUTH_DEVICE_IDENTIFIERS_FOR_GROUP_UUID})
public void testUpdateSubscriptionGroupWithCarrierPrivilegePermission() throws Exception {
testInsertSim();
// Adding a second profile and mark as embedded.
@@ -1285,7 +1271,6 @@ public class SubscriptionControllerTest extends TelephonyTest {
@Test
@SmallTest
- @EnableCompatChanges({REQUIRE_ICC_AUTH_DEVICE_IDENTIFIERS_FOR_GROUP_UUID})
public void testSetSubscriptionGroup() throws Exception {
testInsertSim();
// Adding a second profile and mark as embedded.
@@ -1720,81 +1705,42 @@ public class SubscriptionControllerTest extends TelephonyTest {
}
@Test
- @DisableCompatChanges({REQUIRE_ICC_AUTH_DEVICE_IDENTIFIERS_FOR_GROUP_UUID})
- public void testGetSubscriptionsInGroupWithReadPhoneState() throws Exception {
- // For backward compatibility test
- ParcelUuid groupUuid = setupGetSubscriptionsInGroupTest();
- setupReadPhoneNumbersTest();
- setIdentifierAccess(false);
-
- List<SubscriptionInfo> subInfoList = mSubscriptionControllerUT.getSubscriptionsInGroup(
- groupUuid, mCallingPackage, mCallingFeature);
-
- assertTrue(subInfoList.size() > 0);
- for (SubscriptionInfo info : subInfoList) {
- assertEquals(UNAVAILABLE_ICCID, info.getIccId());
- assertEquals(UNAVAILABLE_ICCID, info.getCardString());
- assertEquals(UNAVAILABLE_NUMBER, info.getNumber());
- }
- }
-
- @Test
- @EnableCompatChanges({REQUIRE_ICC_AUTH_DEVICE_IDENTIFIERS_FOR_GROUP_UUID})
- public void testGetSubscriptionsInGroupWithoutAppropriatePermission() throws Exception {
+ public void testGetSubscriptionsInGroupWithNoPermission() throws Exception {
+ // If the calling package does not have the READ_PHONE_STATE permission or carrier
+ // privileges then getSubscriptionsInGroup should throw a SecurityException when the
+ // READ_PHONE_STATE permission check is performed.
ParcelUuid groupUuid = setupGetSubscriptionsInGroupTest();
+ mContextFixture.removeCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL);
- // no permission
- setNoPermission();
try {
mSubscriptionControllerUT.getSubscriptionsInGroup(groupUuid, mCallingPackage,
mCallingFeature);
fail("getSubscriptionsInGroup should fail when invoked with no permissions");
} catch (SecurityException expected) {
}
-
- // only has the USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER permission
- setIdentifierAccess(true);
- try {
- mSubscriptionControllerUT.getSubscriptionsInGroup(groupUuid, mCallingPackage,
- mCallingFeature);
- fail("getSubscriptionsInGroup should fail when invoked with no"
- + "READ_PHONE_STATE permissions");
- } catch (SecurityException expected) {
- }
-
- // only has the READ_PHONE_STATE permission
- setIdentifierAccess(false);
- setReadPhoneState();
- try {
- mSubscriptionControllerUT.getSubscriptionsInGroup(groupUuid, mCallingPackage,
- mCallingFeature);
- fail("getSubscriptionsInGroup should fail when invoked with no "
- + "USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER permissions");
- } catch (SecurityException expected) {
- }
}
@Test
- @EnableCompatChanges({REQUIRE_ICC_AUTH_DEVICE_IDENTIFIERS_FOR_GROUP_UUID})
- public void testGetSubscriptionsInGroupWithReadDeviceIdentifier() throws Exception {
+ public void testGetSubscriptionsInGroupWithReadPhoneState() throws Exception {
+ // If the calling package only has the READ_PHONE_STATE permission then
+ // getSubscriptionsInGroup should still return the list of SubscriptionInfo objects
+ // but the ICC ID should not be available via getIccId or getCardString.
ParcelUuid groupUuid = setupGetSubscriptionsInGroupTest();
- setNoPermission();
- setCarrierPrivileges(false);
- setIdentifierAccess(true);
- setReadPhoneState();
+ setupReadPhoneNumbersTest();
+ setIdentifierAccess(false);
List<SubscriptionInfo> subInfoList = mSubscriptionControllerUT.getSubscriptionsInGroup(
groupUuid, mCallingPackage, mCallingFeature);
assertTrue(subInfoList.size() > 0);
for (SubscriptionInfo info : subInfoList) {
- assertTrue(info.getIccId().length() > 0);
- assertTrue(info.getCardString().length() > 0);
+ assertEquals(UNAVAILABLE_ICCID, info.getIccId());
+ assertEquals(UNAVAILABLE_ICCID, info.getCardString());
+ assertEquals(UNAVAILABLE_NUMBER, info.getNumber());
}
}
@Test
- @EnableCompatChanges({REQUIRE_ICC_AUTH_DEVICE_IDENTIFIERS_FOR_GROUP_UUID})
public void testGetSubscriptionInGroupWithPhoneNumberAccess() throws Exception {
// If the calling package meets any of the requirements for the
// LegacyPermissionManager#checkPhoneNumberAccess test then the number should be available
@@ -1812,7 +1758,6 @@ public class SubscriptionControllerTest extends TelephonyTest {
}
@Test
- @EnableCompatChanges({REQUIRE_ICC_AUTH_DEVICE_IDENTIFIERS_FOR_GROUP_UUID})
public void testGetSubscriptionsInGroupWithCarrierPrivileges() throws Exception {
// If the calling package has the READ_PRIVILEGED_PHONE_STATE permission or carrier
// privileges the ICC ID should be available in the SubscriptionInfo objects in the List.
@@ -1830,7 +1775,6 @@ public class SubscriptionControllerTest extends TelephonyTest {
}
@Test
- @EnableCompatChanges({REQUIRE_ICC_AUTH_DEVICE_IDENTIFIERS_FOR_GROUP_UUID})
public void testGetSubscriptionsInGroupWithPrivilegedPermission() throws Exception {
// If the calling package has the READ_PRIVILEGED_PHONE_STATE permission or carrier
// privileges the ICC ID should be available in the SubscriptionInfo objects in the List.
@@ -2110,14 +2054,4 @@ public class SubscriptionControllerTest extends TelephonyTest {
assertTrue(mSubscriptionControllerUT.checkPhoneIdAndIccIdMatch(0, "test2"));
assertFalse(mSubscriptionControllerUT.checkPhoneIdAndIccIdMatch(0, "test3"));
}
-
- private void setNoPermission() {
- doThrow(new SecurityException()).when(mContext)
- .enforcePermission(anyString(), anyInt(), anyInt(), anyString());
- }
-
- private void setReadPhoneState() {
- doNothing().when(mContext).enforcePermission(
- eq(android.Manifest.permission.READ_PHONE_STATE), anyInt(), anyInt(), anyString());
- }
}
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 e05ec09f40..52b487af00 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -2706,6 +2706,25 @@ public class DataNetworkControllerTest extends TelephonyTest {
}
@Test
+ public void testEmergencyCallDataDisabled() throws Exception {
+ doReturn(true).when(mPhone).isInEmergencyCall();
+ mDataNetworkControllerUT.addNetworkRequest(
+ createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+ processAllMessages();
+
+ verifyInternetConnected();
+
+ // Data disabled
+ mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
+ TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
+ processAllMessages();
+
+ // Make sure internet is not connected. (Previously it has a bug due to incorrect logic
+ // to determine it's for emergency SUPL).
+ verifyAllDataDisconnected();
+ }
+
+ @Test
public void testDataActivity() {
doReturn(TelephonyManager.DATA_ACTIVITY_IN).when(mLinkBandwidthEstimator).getDataActivity();
mLinkBandwidthEstimatorCallback.onDataActivityChanged(TelephonyManager.DATA_ACTIVITY_IN);
@@ -2880,7 +2899,7 @@ public class DataNetworkControllerTest extends TelephonyTest {
createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS));
processAllMessages();
- // Even though the network request deos not have MMTEL, but the network support it, so
+ // Even though the network request does not have MMTEL, but the network support it, so
// the network capabilities should still have MMTEL.
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
@@ -2894,12 +2913,138 @@ public class DataNetworkControllerTest extends TelephonyTest {
any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
any(), any(), anyBoolean(), any(Message.class));
- // The IMS network should only have IMS, but no MMTEL.
+ // The IMS network should still have IMS and MMTEL.
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS);
+ verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_MMTEL);
+ }
+
+ @Test
+ public void testMmtelImsDataNetworkMovingToNonVops() throws Exception {
+ ServiceState ss = new ServiceState();
+
+ // VoPS network
+ DataSpecificRegistrationInfo dsri = new DataSpecificRegistrationInfo(8, false, true, true,
+ new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_SUPPORTED,
+ LteVopsSupportInfo.LTE_STATUS_SUPPORTED));
+
+ ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setDataSpecificInfo(dsri)
+ .build());
+
+ ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .build());
+
+ ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+ .setDomain(NetworkRegistrationInfo.DOMAIN_CS)
+ .build());
+ doReturn(ss).when(mSST).getServiceState();
+ doReturn(ss).when(mPhone).getServiceState();
+
+ doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mAccessNetworksManager)
+ .getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
+
+ mDataNetworkControllerUT.obtainMessage(17/*EVENT_SERVICE_STATE_CHANGED*/).sendToTarget();
+ processAllMessages();
+
+ // Bring up the IMS network that does require MMTEL
+ mDataNetworkControllerUT.addNetworkRequest(
+ createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS,
+ NetworkCapabilities.NET_CAPABILITY_MMTEL));
+ processAllMessages();
+
+ // the network capabilities should have IMS and MMTEL.
+ verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
+ NetworkCapabilities.NET_CAPABILITY_MMTEL);
+
+ ss = new ServiceState();
+ // Non VoPS network
+ dsri = new DataSpecificRegistrationInfo(8, false, true, true,
+ new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED,
+ LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED));
+
+ ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setDataSpecificInfo(dsri)
+ .build());
+
+ ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .build());
+
+ ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+ .setDomain(NetworkRegistrationInfo.DOMAIN_CS)
+ .build());
+ doReturn(ss).when(mSST).getServiceState();
+ doReturn(ss).when(mPhone).getServiceState();
+
+ mDataNetworkControllerUT.obtainMessage(17/*EVENT_SERVICE_STATE_CHANGED*/).sendToTarget();
+ processAllMessages();
+
+ // The IMS network should be torn down by data network controller.
+ verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL);
}
@Test
+ public void testVoPStoNonVoPSDelayImsTearDown() throws Exception {
+ mCarrierConfig.putBoolean(CarrierConfigManager.KEY_DELAY_IMS_TEAR_DOWN_UNTIL_CALL_END_BOOL,
+ true);
+ carrierConfigChanged();
+
+ // VoPS supported
+ DataSpecificRegistrationInfo dsri = new DataSpecificRegistrationInfo(8, false, true, true,
+ new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_SUPPORTED,
+ LteVopsSupportInfo.LTE_STATUS_SUPPORTED));
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri);
+
+ mDataNetworkControllerUT.addNetworkRequest(
+ createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS,
+ NetworkCapabilities.NET_CAPABILITY_MMTEL));
+ processAllMessages();
+ verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS);
+
+ doReturn(PhoneConstants.State.OFFHOOK).when(mCT).getState();
+
+ dsri = new DataSpecificRegistrationInfo(8, false, true, true,
+ new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED,
+ LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED));
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri);
+
+ // Make sure IMS is still connected.
+ verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
+ NetworkCapabilities.NET_CAPABILITY_MMTEL);
+
+ // Call ends
+ doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
+ mDataNetworkControllerUT.obtainMessage(18/*EVENT_VOICE_CALL_ENDED*/).sendToTarget();
+ processAllMessages();
+
+ verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
+ }
+
+ @Test
public void testDeactivateDataOnOldHal() throws Exception {
doAnswer(invocation -> {
// Only send the deactivation data response, no data call list changed event.
@@ -2957,4 +3102,48 @@ public class DataNetworkControllerTest extends TelephonyTest {
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
NetworkCapabilities.NET_CAPABILITY_MMTEL);
}
+
+ @Test
+ public void testRemoveNetworkRequest() throws Exception {
+ NetworkCapabilities netCaps = new NetworkCapabilities();
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+
+ NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
+ ConnectivityManager.TYPE_MOBILE, 0, NetworkRequest.Type.REQUEST);
+
+ mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
+ nativeNetworkRequest, mPhone));
+ processAllMessages();
+
+ // Intentionally create a new telephony request with the original native network request.
+ TelephonyNetworkRequest request = new TelephonyNetworkRequest(nativeNetworkRequest, mPhone);
+
+ mDataNetworkControllerUT.removeNetworkRequest(request);
+ processAllFutureMessages();
+
+ List<DataNetwork> dataNetworkList = getDataNetworks();
+ // The data network should not be torn down after network request removal.
+ assertThat(dataNetworkList).hasSize(1);
+ // But should be detached from the data network.
+ assertThat(dataNetworkList.get(0).getAttachedNetworkRequestList()).isEmpty();
+ assertThat(dataNetworkList.get(0).isConnected()).isTrue();
+ }
+
+ @Test
+ public void testTempDdsSwitchTearDown() throws Exception {
+ TelephonyNetworkRequest request = createNetworkRequest(
+ NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ mDataNetworkControllerUT.addNetworkRequest(request);
+ processAllMessages();
+
+ // Now DDS temporarily switched to phone 1
+ doReturn(1).when(mMockedPhoneSwitcher).getPreferredDataPhoneId();
+
+ // Simulate telephony network factory remove request due to switch.
+ mDataNetworkControllerUT.removeNetworkRequest(request);
+ processAllMessages();
+
+ // Data should be torn down on this non-preferred sub.
+ verifyAllDataDisconnected();
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
index 6ae8f66e87..f53298d770 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
@@ -102,6 +102,8 @@ public class DataNetworkTest extends TelephonyTest {
private static final int ADMIN_UID1 = 1234;
private static final int ADMIN_UID2 = 5678;
+ private static final int DEFAULT_MTU = 1501;
+
private static final String FAKE_IMSI = "123456789";
private DataNetwork mDataNetworkUT;
@@ -181,6 +183,7 @@ public class DataNetworkTest extends TelephonyTest {
// Mocked classes
private DataNetworkCallback mDataNetworkCallback;
private DataCallSessionStats mDataCallSessionStats;
+ private PhoneSwitcher mMockedPhoneSwitcher;
private final NetworkRegistrationInfo mIwlanNetworkRegistrationInfo =
new NetworkRegistrationInfo.Builder()
@@ -217,7 +220,6 @@ public class DataNetworkTest extends TelephonyTest {
InetAddresses.parseNumericAddress("fd00:976a:c202:1d::7"),
InetAddresses.parseNumericAddress("fd00:976a:c305:1d::5")))
.setMtuV4(1234)
- .setMtuV6(5678)
.setPduSessionId(1)
.setQosBearerSessions(new ArrayList<>())
.setTrafficDescriptors(tds)
@@ -300,6 +302,8 @@ public class DataNetworkTest extends TelephonyTest {
mDataNetworkCallback = Mockito.mock(DataNetworkCallback.class);
mDataCallSessionStats = Mockito.mock(DataCallSessionStats.class);
+ mMockedPhoneSwitcher = Mockito.mock(PhoneSwitcher.class);
+ replaceInstance(PhoneSwitcher.class, "sPhoneSwitcher", null, mMockedPhoneSwitcher);
doAnswer(invocation -> {
((Runnable) invocation.getArguments()[0]).run();
return null;
@@ -315,6 +319,7 @@ public class DataNetworkTest extends TelephonyTest {
.when(mDataConfigManager).getBandwidthEstimateSource();
doReturn(true).when(mDataConfigManager).isTempNotMeteredSupportedByCarrier();
doReturn(true).when(mDataConfigManager).isImsDelayTearDownEnabled();
+ doReturn(DEFAULT_MTU).when(mDataConfigManager).getDefaultMtu();
doReturn(FAKE_IMSI).when(mPhone).getSubscriberId();
doReturn(true).when(mDataNetworkController)
.isNetworkRequestExisting(any(TelephonyNetworkRequest.class));
@@ -399,9 +404,10 @@ public class DataNetworkTest extends TelephonyTest {
assertThat(lp.getRoutes().get(0).getMtu()).isEqualTo(1234);
assertThat(lp.getRoutes().get(1).getGateway()).isEqualTo(
InetAddresses.parseNumericAddress("fe80::2"));
- assertThat(lp.getRoutes().get(1).getMtu()).isEqualTo(5678);
+ // The default from carrier configs should be used if MTU is not set.
+ assertThat(lp.getRoutes().get(1).getMtu()).isEqualTo(DEFAULT_MTU);
// The higher value of v4 and v6 should be used.
- assertThat(lp.getMtu()).isEqualTo(5678);
+ assertThat(lp.getMtu()).isEqualTo(DEFAULT_MTU);
ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor =
ArgumentCaptor.forClass(PreciseDataConnectionState.class);
@@ -1213,46 +1219,11 @@ public class DataNetworkTest extends TelephonyTest {
logd("Trigger non VoPS");
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri);
- assertThat(mDataNetworkUT.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_MMTEL)).isFalse();
- }
-
- @Test
- public void testMovingToNonVopsVoiceCallOngoing() throws Exception {
- DataSpecificRegistrationInfo dsri = new DataSpecificRegistrationInfo(8, false, true, true,
- new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_SUPPORTED,
- LteVopsSupportInfo.LTE_STATUS_SUPPORTED));
- serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
- NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri);
- testCreateImsDataNetwork();
-
+ // MMTEL should not be removed.
assertThat(mDataNetworkUT.getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_MMTEL)).isTrue();
-
- // Voice call ongoing.
- doReturn(PhoneConstants.State.OFFHOOK).when(mImsCT).getState();
-
- dsri = new DataSpecificRegistrationInfo(8, false, true, true,
- new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED,
- LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED));
- serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
- NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri);
-
- // Should not lose MMTEL since voice call is ongoing
- assertThat(mDataNetworkUT.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_MMTEL)).isTrue();
-
- // Voice call ended.
- doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState();
- mDataNetworkUT.sendMessage(23/*EVENT_VOICE_CALL_ENDED*/);
- processAllMessages();
-
- // MMTEL should be removed.
- assertThat(mDataNetworkUT.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_MMTEL)).isFalse();
}
-
@Test
public void testCssIndicatorChanged() throws Exception {
setupDataNetwork();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
index c96d76dcc7..783df82e39 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
@@ -59,11 +59,13 @@ import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
+import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.stream.Collectors;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -361,6 +363,16 @@ public class DataProfileManagerTest extends TelephonyTest {
logd("ApnSettingContentProvider: uri=" + uri + ", values=" + values);
if (uri.isPathPrefixMatch(Telephony.Carriers.PREFERRED_APN_URI)) {
mPreferredApnId = values.getAsInteger(Telephony.Carriers.APN_ID);
+ if (mPreferredApnId != -1) {
+ for (Object apnSetting : mAllApnSettings) {
+ int id = (int) ((Object[]) apnSetting)[0];
+ if (id == mPreferredApnId) {
+ mPreferredApnSet = (int) ((Object[]) apnSetting)[28]; //update setId too
+ }
+ }
+ } else {
+ mPreferredApnSet = 0; // db is emptied
+ }
logd("mPreferredApnId=" + mPreferredApnId);
}
return null;
@@ -400,6 +412,12 @@ public class DataProfileManagerTest extends TelephonyTest {
method.invoke(mDataProfileManagerUT, dataProfiles);
}
+ private @NonNull List<DataProfile> getAllDataProfiles() throws Exception {
+ Field field = DataProfileManager.class.getDeclaredField("mAllDataProfiles");
+ field.setAccessible(true);
+ return (List<DataProfile>) field.get(mDataProfileManagerUT);
+ }
+
@Before
public void setUp() throws Exception {
logd("DataProfileManagerTest +Setup!");
@@ -856,6 +874,38 @@ public class DataProfileManagerTest extends TelephonyTest {
}
@Test
+ public void testResetApnWithPreferredConfig() {
+ // carrier configured preferred data profile should be picked
+ doReturn(GENERAL_PURPOSE_APN1).when(mDataConfigManager).getDefaultPreferredApn();
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(
+ new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .build(), mPhone);
+ mSimInserted = true;
+ mDataProfileManagerUT.obtainMessage(2 /*EVENT_APN_DATABASE_CHANGED*/).sendToTarget();
+ processAllMessages();
+
+ // The carrier configured data profile should be the preferred APN after APN reset
+ DataProfile dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
+ tnr, TelephonyManager.NETWORK_TYPE_LTE);
+
+ assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo(GENERAL_PURPOSE_APN1);
+ assertThat(mDataProfileManagerUT.isDataProfilePreferred(dataProfile)).isTrue();
+
+ // APN reset
+ mPreferredApnId = -1;
+ mDataProfileManagerUT.obtainMessage(2 /*EVENT_APN_DATABASE_CHANGED*/).sendToTarget();
+ Mockito.clearInvocations(mDataConfigManager);
+ processAllMessages();
+
+ // The carrier configured data profile should be the preferred APN after APN reset
+ dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
+ tnr, TelephonyManager.NETWORK_TYPE_LTE);
+ assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo(GENERAL_PURPOSE_APN1);
+ assertThat(mDataProfileManagerUT.isDataProfilePreferred(dataProfile)).isTrue();
+ }
+
+ @Test
public void testTetheringApnExisting() {
assertThat(mDataProfileManagerUT.isTetheringDataProfileExisting(
TelephonyManager.NETWORK_TYPE_NR)).isTrue();
@@ -886,4 +936,15 @@ public class DataProfileManagerTest extends TelephonyTest {
assertThat(mDataProfileManagerUT.isTetheringDataProfileExisting(
TelephonyManager.NETWORK_TYPE_NR)).isFalse();
}
+
+ @Test
+ public void testNoDefaultIms() throws Exception {
+ List<DataProfile> dataProfiles = getAllDataProfiles();
+
+ // Since the database already had IMS, there should not be default IMS created in the
+ // database.
+ assertThat(dataProfiles.stream()
+ .filter(dp -> dp.canSatisfy(NetworkCapabilities.NET_CAPABILITY_IMS))
+ .collect(Collectors.toList())).hasSize(1);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileTest.java
index 86f8f907ff..4a2eb38702 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileTest.java
@@ -22,6 +22,7 @@ import android.net.NetworkCapabilities;
import android.os.Parcel;
import android.telephony.data.ApnSetting;
import android.telephony.data.DataProfile;
+import android.telephony.data.TrafficDescriptor;
import org.junit.Test;
@@ -99,6 +100,26 @@ public class DataProfileTest {
.setMaxConnsTime(789)
.build();
+ // Disabled APN
+ private ApnSetting mApn5 = new ApnSetting.Builder()
+ .setId(2163)
+ .setOperatorNumeric("12345")
+ .setEntryName("fake_apn")
+ .setApnName("fake_apn")
+ .setUser("user")
+ .setPassword("passwd")
+ .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_SUPL)
+ .setProtocol(ApnSetting.PROTOCOL_IPV6)
+ .setRoamingProtocol(ApnSetting.PROTOCOL_IP)
+ .setCarrierEnabled(false)
+ .setNetworkTypeBitmask(0)
+ .setProfileId(1234)
+ .setMaxConns(321)
+ .setWaitTime(456)
+ .setMaxConnsTime(789)
+ .build();
+
+
@Test
public void testCreateFromApnSetting() throws Exception {
DataProfile dp = new DataProfile.Builder()
@@ -196,4 +217,26 @@ public class DataProfileTest {
parcel.recycle();
}
+
+ @Test
+ public void testIsEnabled() {
+ TrafficDescriptor td = new TrafficDescriptor(null, new TrafficDescriptor.OsAppId(
+ TrafficDescriptor.OsAppId.ANDROID_OS_ID, "ENTERPRISE", 1).getBytes());
+
+ DataProfile dp = new DataProfile.Builder()
+ .setApnSetting(mApn5)
+ .setPreferred(false)
+ .build();
+ assertThat(dp.isEnabled()).isFalse();
+
+ dp = new DataProfile.Builder()
+ .setApnSetting(mApn1)
+ .build();
+ assertThat(dp.isEnabled()).isTrue();
+
+ dp = new DataProfile.Builder()
+ .setTrafficDescriptor(td)
+ .build();
+ assertThat(dp.isEnabled()).isTrue();
+ }
}