Merge changes Ia5022310,Ia4529d08
* changes: Remove VCN Carrier Privilege grace period Update TelephonySubscriptionTracker to use CarrierPrivilegesListener
This commit is contained in:
@@ -24,7 +24,6 @@ import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
|
|||||||
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_INACTIVE;
|
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_INACTIVE;
|
||||||
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED;
|
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED;
|
||||||
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
|
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
|
||||||
import static android.telephony.SubscriptionManager.isValidSubscriptionId;
|
|
||||||
|
|
||||||
import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
||||||
import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback;
|
import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback;
|
||||||
@@ -164,10 +163,6 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
static final String VCN_CONFIG_FILE = "/data/system/vcn/configs.xml";
|
static final String VCN_CONFIG_FILE = "/data/system/vcn/configs.xml";
|
||||||
|
|
||||||
// TODO(b/176956496): Directly use CarrierServiceBindHelper.UNBIND_DELAY_MILLIS
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
|
||||||
static final long CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS = TimeUnit.SECONDS.toMillis(30);
|
|
||||||
|
|
||||||
/* Binder context for this service */
|
/* Binder context for this service */
|
||||||
@NonNull private final Context mContext;
|
@NonNull private final Context mContext;
|
||||||
@NonNull private final Dependencies mDeps;
|
@NonNull private final Dependencies mDeps;
|
||||||
@@ -372,12 +367,15 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
|
|
||||||
/** Notifies the VcnManagementService that external dependencies can be set up. */
|
/** Notifies the VcnManagementService that external dependencies can be set up. */
|
||||||
public void systemReady() {
|
public void systemReady() {
|
||||||
mNetworkProvider.register();
|
// Always run on the handler thread to ensure consistency.
|
||||||
mContext.getSystemService(ConnectivityManager.class)
|
mHandler.post(() -> {
|
||||||
.registerNetworkCallback(
|
mNetworkProvider.register();
|
||||||
new NetworkRequest.Builder().clearCapabilities().build(),
|
mContext.getSystemService(ConnectivityManager.class)
|
||||||
mTrackingNetworkCallback);
|
.registerNetworkCallback(
|
||||||
mTelephonySubscriptionTracker.register();
|
new NetworkRequest.Builder().clearCapabilities().build(),
|
||||||
|
mTrackingNetworkCallback);
|
||||||
|
mTelephonySubscriptionTracker.register();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enforcePrimaryUser() {
|
private void enforcePrimaryUser() {
|
||||||
@@ -471,22 +469,15 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
if (!mVcns.containsKey(subGrp)) {
|
if (!mVcns.containsKey(subGrp)) {
|
||||||
startVcnLocked(subGrp, entry.getValue());
|
startVcnLocked(subGrp, entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cancel any scheduled teardowns for active subscriptions
|
|
||||||
mHandler.removeCallbacksAndMessages(mVcns.get(subGrp));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schedule teardown of any VCN instances that have lost carrier privileges (after a
|
// Schedule teardown of any VCN instances that have lost carrier privileges
|
||||||
// delay)
|
|
||||||
for (Entry<ParcelUuid, Vcn> entry : mVcns.entrySet()) {
|
for (Entry<ParcelUuid, Vcn> entry : mVcns.entrySet()) {
|
||||||
final ParcelUuid subGrp = entry.getKey();
|
final ParcelUuid subGrp = entry.getKey();
|
||||||
final VcnConfig config = mConfigs.get(subGrp);
|
final VcnConfig config = mConfigs.get(subGrp);
|
||||||
|
|
||||||
final boolean isActiveSubGrp = isActiveSubGroup(subGrp, snapshot);
|
final boolean isActiveSubGrp = isActiveSubGroup(subGrp, snapshot);
|
||||||
final boolean isValidActiveDataSubIdNotInVcnSubGrp =
|
|
||||||
isValidSubscriptionId(snapshot.getActiveDataSubscriptionId())
|
|
||||||
&& !isActiveSubGroup(subGrp, snapshot);
|
|
||||||
|
|
||||||
// TODO(b/193687515): Support multiple VCNs active at the same time
|
// TODO(b/193687515): Support multiple VCNs active at the same time
|
||||||
if (config == null
|
if (config == null
|
||||||
@@ -496,31 +487,12 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
final ParcelUuid uuidToTeardown = subGrp;
|
final ParcelUuid uuidToTeardown = subGrp;
|
||||||
final Vcn instanceToTeardown = entry.getValue();
|
final Vcn instanceToTeardown = entry.getValue();
|
||||||
|
|
||||||
// TODO(b/193687515): Support multiple VCNs active at the same time
|
stopVcnLocked(uuidToTeardown);
|
||||||
// If directly switching to a subscription not in the current group,
|
|
||||||
// teardown immediately to prevent other subscription's network from being
|
|
||||||
// outscored by the VCN. Otherwise, teardown after a delay to ensure that
|
|
||||||
// SIM profile switches do not trigger the VCN to cycle.
|
|
||||||
final long teardownDelayMs =
|
|
||||||
isValidActiveDataSubIdNotInVcnSubGrp
|
|
||||||
? 0
|
|
||||||
: CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS;
|
|
||||||
mHandler.postDelayed(() -> {
|
|
||||||
synchronized (mLock) {
|
|
||||||
// Guard against case where this is run after a old instance was
|
|
||||||
// torn down, and a new instance was started. Verify to ensure
|
|
||||||
// correct instance is torn down. This could happen as a result of a
|
|
||||||
// Carrier App manually removing/adding a VcnConfig.
|
|
||||||
if (mVcns.get(uuidToTeardown) == instanceToTeardown) {
|
|
||||||
stopVcnLocked(uuidToTeardown);
|
|
||||||
|
|
||||||
// TODO(b/181789060): invoke asynchronously after Vcn notifies
|
// TODO(b/181789060): invoke asynchronously after Vcn notifies
|
||||||
// through VcnCallback
|
// through VcnCallback
|
||||||
notifyAllPermissionedStatusCallbacksLocked(
|
notifyAllPermissionedStatusCallbacksLocked(
|
||||||
uuidToTeardown, VCN_STATUS_CODE_INACTIVE);
|
uuidToTeardown, VCN_STATUS_CODE_INACTIVE);
|
||||||
}
|
|
||||||
}
|
|
||||||
}, instanceToTeardown, teardownDelayMs);
|
|
||||||
} else {
|
} else {
|
||||||
// If this VCN's status has not changed, update it with the new snapshot
|
// If this VCN's status has not changed, update it with the new snapshot
|
||||||
entry.getValue().updateSubscriptionSnapshot(mLastSnapshot);
|
entry.getValue().updateSubscriptionSnapshot(mLastSnapshot);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import static android.telephony.CarrierConfigManager.EXTRA_SLOT_INDEX;
|
|||||||
import static android.telephony.CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX;
|
import static android.telephony.CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX;
|
||||||
import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
|
import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
|
||||||
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||||
|
import static android.telephony.TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
@@ -38,15 +39,19 @@ import android.telephony.SubscriptionManager;
|
|||||||
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
|
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
|
||||||
import android.telephony.TelephonyCallback;
|
import android.telephony.TelephonyCallback;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
|
import android.telephony.TelephonyManager.CarrierPrivilegesListener;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
|
import android.util.Slog;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.annotations.VisibleForTesting.Visibility;
|
import com.android.internal.annotations.VisibleForTesting.Visibility;
|
||||||
import com.android.internal.util.IndentingPrintWriter;
|
import com.android.internal.util.IndentingPrintWriter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
@@ -92,6 +97,10 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
|
|||||||
@NonNull private final Map<Integer, Integer> mReadySubIdsBySlotId = new HashMap<>();
|
@NonNull private final Map<Integer, Integer> mReadySubIdsBySlotId = new HashMap<>();
|
||||||
@NonNull private final OnSubscriptionsChangedListener mSubscriptionChangedListener;
|
@NonNull private final OnSubscriptionsChangedListener mSubscriptionChangedListener;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private final List<CarrierPrivilegesListener> mCarrierPrivilegesChangedListeners =
|
||||||
|
new ArrayList<>();
|
||||||
|
|
||||||
@NonNull private TelephonySubscriptionSnapshot mCurrentSnapshot;
|
@NonNull private TelephonySubscriptionSnapshot mCurrentSnapshot;
|
||||||
|
|
||||||
public TelephonySubscriptionTracker(
|
public TelephonySubscriptionTracker(
|
||||||
@@ -126,22 +135,71 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Registers the receivers, and starts tracking subscriptions. */
|
/**
|
||||||
|
* Registers the receivers, and starts tracking subscriptions.
|
||||||
|
*
|
||||||
|
* <p>Must always be run on the VcnManagementService thread.
|
||||||
|
*/
|
||||||
public void register() {
|
public void register() {
|
||||||
final HandlerExecutor executor = new HandlerExecutor(mHandler);
|
final HandlerExecutor executor = new HandlerExecutor(mHandler);
|
||||||
|
final IntentFilter filter = new IntentFilter();
|
||||||
|
filter.addAction(ACTION_CARRIER_CONFIG_CHANGED);
|
||||||
|
filter.addAction(ACTION_MULTI_SIM_CONFIG_CHANGED);
|
||||||
|
|
||||||
mContext.registerReceiver(
|
mContext.registerReceiver(this, filter, null, mHandler);
|
||||||
this, new IntentFilter(ACTION_CARRIER_CONFIG_CHANGED), null, mHandler);
|
|
||||||
mSubscriptionManager.addOnSubscriptionsChangedListener(
|
mSubscriptionManager.addOnSubscriptionsChangedListener(
|
||||||
executor, mSubscriptionChangedListener);
|
executor, mSubscriptionChangedListener);
|
||||||
mTelephonyManager.registerTelephonyCallback(executor, mActiveDataSubIdListener);
|
mTelephonyManager.registerTelephonyCallback(executor, mActiveDataSubIdListener);
|
||||||
|
|
||||||
|
registerCarrierPrivilegesListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Unregisters the receivers, and stops tracking subscriptions. */
|
private void registerCarrierPrivilegesListeners() {
|
||||||
|
final HandlerExecutor executor = new HandlerExecutor(mHandler);
|
||||||
|
final int modemCount = mTelephonyManager.getActiveModemCount();
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < modemCount; i++) {
|
||||||
|
CarrierPrivilegesListener carrierPrivilegesListener =
|
||||||
|
new CarrierPrivilegesListener() {
|
||||||
|
@Override
|
||||||
|
public void onCarrierPrivilegesChanged(
|
||||||
|
@NonNull List<String> privilegedPackageNames,
|
||||||
|
@NonNull int[] privilegedUids) {
|
||||||
|
// Re-trigger the synchronous check (which is also very cheap due
|
||||||
|
// to caching in CarrierPrivilegesTracker). This allows consistency
|
||||||
|
// with the onSubscriptionsChangedListener and broadcasts.
|
||||||
|
handleSubscriptionsChanged();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mTelephonyManager.addCarrierPrivilegesListener(
|
||||||
|
i, executor, carrierPrivilegesListener);
|
||||||
|
mCarrierPrivilegesChangedListeners.add(carrierPrivilegesListener);
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
Slog.wtf(TAG, "Encounted exception registering carrier privileges listeners", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters the receivers, and stops tracking subscriptions.
|
||||||
|
*
|
||||||
|
* <p>Must always be run on the VcnManagementService thread.
|
||||||
|
*/
|
||||||
public void unregister() {
|
public void unregister() {
|
||||||
mContext.unregisterReceiver(this);
|
mContext.unregisterReceiver(this);
|
||||||
mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionChangedListener);
|
mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionChangedListener);
|
||||||
mTelephonyManager.unregisterTelephonyCallback(mActiveDataSubIdListener);
|
mTelephonyManager.unregisterTelephonyCallback(mActiveDataSubIdListener);
|
||||||
|
|
||||||
|
unregisterCarrierPrivilegesListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unregisterCarrierPrivilegesListeners() {
|
||||||
|
for (CarrierPrivilegesListener carrierPrivilegesListener :
|
||||||
|
mCarrierPrivilegesChangedListeners) {
|
||||||
|
mTelephonyManager.removeCarrierPrivilegesListener(carrierPrivilegesListener);
|
||||||
|
}
|
||||||
|
mCarrierPrivilegesChangedListeners.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -178,8 +236,6 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
|
|||||||
// group.
|
// group.
|
||||||
if (subInfo.getSimSlotIndex() != INVALID_SIM_SLOT_INDEX
|
if (subInfo.getSimSlotIndex() != INVALID_SIM_SLOT_INDEX
|
||||||
&& mReadySubIdsBySlotId.values().contains(subInfo.getSubscriptionId())) {
|
&& mReadySubIdsBySlotId.values().contains(subInfo.getSubscriptionId())) {
|
||||||
// TODO (b/172619301): Cache based on callbacks from CarrierPrivilegesTracker
|
|
||||||
|
|
||||||
final TelephonyManager subIdSpecificTelephonyManager =
|
final TelephonyManager subIdSpecificTelephonyManager =
|
||||||
mTelephonyManager.createForSubscriptionId(subInfo.getSubscriptionId());
|
mTelephonyManager.createForSubscriptionId(subInfo.getSubscriptionId());
|
||||||
|
|
||||||
@@ -214,12 +270,39 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
// Accept sticky broadcasts; if CARRIER_CONFIG_CHANGED was previously broadcast and it
|
switch (intent.getAction()) {
|
||||||
// already was for an identified carrier, we can stop waiting for initial load to complete
|
case ACTION_CARRIER_CONFIG_CHANGED:
|
||||||
if (!ACTION_CARRIER_CONFIG_CHANGED.equals(intent.getAction())) {
|
handleActionCarrierConfigChanged(context, intent);
|
||||||
return;
|
break;
|
||||||
|
case ACTION_MULTI_SIM_CONFIG_CHANGED:
|
||||||
|
handleActionMultiSimConfigChanged(context, intent);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Slog.v(TAG, "Unknown intent received with action: " + intent.getAction());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleActionMultiSimConfigChanged(Context context, Intent intent) {
|
||||||
|
unregisterCarrierPrivilegesListeners();
|
||||||
|
|
||||||
|
// Clear invalid slotIds from the mReadySubIdsBySlotId map.
|
||||||
|
final int modemCount = mTelephonyManager.getActiveModemCount();
|
||||||
|
final Iterator<Integer> slotIdIterator = mReadySubIdsBySlotId.keySet().iterator();
|
||||||
|
while (slotIdIterator.hasNext()) {
|
||||||
|
final int slotId = slotIdIterator.next();
|
||||||
|
|
||||||
|
if (slotId >= modemCount) {
|
||||||
|
slotIdIterator.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerCarrierPrivilegesListeners();
|
||||||
|
handleSubscriptionsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleActionCarrierConfigChanged(Context context, Intent intent) {
|
||||||
|
// Accept sticky broadcasts; if CARRIER_CONFIG_CHANGED was previously broadcast and it
|
||||||
|
// already was for an identified carrier, we can stop waiting for initial load to complete
|
||||||
final int subId = intent.getIntExtra(EXTRA_SUBSCRIPTION_INDEX, INVALID_SUBSCRIPTION_ID);
|
final int subId = intent.getIntExtra(EXTRA_SUBSCRIPTION_INDEX, INVALID_SUBSCRIPTION_ID);
|
||||||
final int slotId = intent.getIntExtra(EXTRA_SLOT_INDEX, INVALID_SIM_SLOT_INDEX);
|
final int slotId = intent.getIntExtra(EXTRA_SLOT_INDEX, INVALID_SIM_SLOT_INDEX);
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
|||||||
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
||||||
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
|
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
|
||||||
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
|
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
|
||||||
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
|
||||||
import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
|
import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
|
||||||
import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
|
import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
|
||||||
|
|
||||||
@@ -264,6 +263,7 @@ public class VcnManagementServiceTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSystemReady() throws Exception {
|
public void testSystemReady() throws Exception {
|
||||||
mVcnMgmtSvc.systemReady();
|
mVcnMgmtSvc.systemReady();
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
verify(mConnMgr).registerNetworkProvider(any(VcnNetworkProvider.class));
|
verify(mConnMgr).registerNetworkProvider(any(VcnNetworkProvider.class));
|
||||||
verify(mSubscriptionTracker).register();
|
verify(mSubscriptionTracker).register();
|
||||||
@@ -475,10 +475,8 @@ public class VcnManagementServiceTest {
|
|||||||
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
|
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
|
||||||
|
|
||||||
triggerSubscriptionTrackerCbAndGetSnapshot(null, Collections.emptySet());
|
triggerSubscriptionTrackerCbAndGetSnapshot(null, Collections.emptySet());
|
||||||
|
|
||||||
// Verify teardown after delay
|
|
||||||
mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS);
|
|
||||||
mTestLooper.dispatchAll();
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
verify(vcn).teardownAsynchronously();
|
verify(vcn).teardownAsynchronously();
|
||||||
verify(mMockPolicyListener).onPolicyChanged();
|
verify(mMockPolicyListener).onPolicyChanged();
|
||||||
}
|
}
|
||||||
@@ -504,92 +502,6 @@ public class VcnManagementServiceTest {
|
|||||||
assertEquals(0, mVcnMgmtSvc.getAllVcns().size());
|
assertEquals(0, mVcnMgmtSvc.getAllVcns().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests an intermediate state where carrier privileges are marked as lost before active data
|
|
||||||
* subId changes during a SIM ejection.
|
|
||||||
*
|
|
||||||
* <p>The expected outcome is that the VCN is torn down after a delay, as opposed to
|
|
||||||
* immediately.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testTelephonyNetworkTrackerCallbackLostCarrierPrivilegesBeforeActiveDataSubChanges()
|
|
||||||
throws Exception {
|
|
||||||
setupActiveSubscription(TEST_UUID_2);
|
|
||||||
|
|
||||||
final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback();
|
|
||||||
final Vcn vcn = startAndGetVcnInstance(TEST_UUID_2);
|
|
||||||
|
|
||||||
// Simulate privileges lost
|
|
||||||
triggerSubscriptionTrackerCbAndGetSnapshot(
|
|
||||||
TEST_SUBSCRIPTION_ID,
|
|
||||||
TEST_UUID_2,
|
|
||||||
Collections.emptySet(),
|
|
||||||
Collections.emptyMap(),
|
|
||||||
false /* hasCarrierPrivileges */);
|
|
||||||
|
|
||||||
// Verify teardown after delay
|
|
||||||
mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS);
|
|
||||||
mTestLooper.dispatchAll();
|
|
||||||
verify(vcn).teardownAsynchronously();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testTelephonyNetworkTrackerCallbackSimSwitchesDoNotKillVcnInstances()
|
|
||||||
throws Exception {
|
|
||||||
setupActiveSubscription(TEST_UUID_2);
|
|
||||||
|
|
||||||
final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback();
|
|
||||||
final Vcn vcn = startAndGetVcnInstance(TEST_UUID_2);
|
|
||||||
|
|
||||||
// Simulate SIM unloaded
|
|
||||||
triggerSubscriptionTrackerCbAndGetSnapshot(
|
|
||||||
INVALID_SUBSCRIPTION_ID,
|
|
||||||
null /* activeDataSubscriptionGroup */,
|
|
||||||
Collections.emptySet(),
|
|
||||||
Collections.emptyMap(),
|
|
||||||
false /* hasCarrierPrivileges */);
|
|
||||||
|
|
||||||
// Simulate new SIM loaded right during teardown delay.
|
|
||||||
mTestLooper.moveTimeForward(
|
|
||||||
VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS / 2);
|
|
||||||
mTestLooper.dispatchAll();
|
|
||||||
triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_2, Collections.singleton(TEST_UUID_2));
|
|
||||||
|
|
||||||
// Verify that even after the full timeout duration, the VCN instance is not torn down
|
|
||||||
mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS);
|
|
||||||
mTestLooper.dispatchAll();
|
|
||||||
verify(vcn, never()).teardownAsynchronously();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testTelephonyNetworkTrackerCallbackDoesNotKillNewVcnInstances() throws Exception {
|
|
||||||
setupActiveSubscription(TEST_UUID_2);
|
|
||||||
|
|
||||||
final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback();
|
|
||||||
final Vcn oldInstance = startAndGetVcnInstance(TEST_UUID_2);
|
|
||||||
|
|
||||||
// Simulate SIM unloaded
|
|
||||||
triggerSubscriptionTrackerCbAndGetSnapshot(null, Collections.emptySet());
|
|
||||||
|
|
||||||
// Config cleared, SIM reloaded & config re-added right before teardown delay, staring new
|
|
||||||
// vcnInstance.
|
|
||||||
mTestLooper.moveTimeForward(
|
|
||||||
VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS / 2);
|
|
||||||
mTestLooper.dispatchAll();
|
|
||||||
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2, TEST_PACKAGE_NAME);
|
|
||||||
triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_2, Collections.singleton(TEST_UUID_2));
|
|
||||||
final Vcn newInstance = startAndGetVcnInstance(TEST_UUID_2);
|
|
||||||
|
|
||||||
// Verify that new instance was different, and the old one was torn down
|
|
||||||
assertTrue(oldInstance != newInstance);
|
|
||||||
verify(oldInstance).teardownAsynchronously();
|
|
||||||
|
|
||||||
// Verify that even after the full timeout duration, the new VCN instance is not torn down
|
|
||||||
mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS);
|
|
||||||
mTestLooper.dispatchAll();
|
|
||||||
verify(newInstance, never()).teardownAsynchronously();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPackageChangeListenerRegistered() throws Exception {
|
public void testPackageChangeListenerRegistered() throws Exception {
|
||||||
verify(mMockContext).registerReceiver(any(BroadcastReceiver.class), argThat(filter -> {
|
verify(mMockContext).registerReceiver(any(BroadcastReceiver.class), argThat(filter -> {
|
||||||
@@ -925,6 +837,8 @@ public class VcnManagementServiceTest {
|
|||||||
private void setupSubscriptionAndStartVcn(
|
private void setupSubscriptionAndStartVcn(
|
||||||
int subId, ParcelUuid subGrp, boolean isVcnActive, boolean hasCarrierPrivileges) {
|
int subId, ParcelUuid subGrp, boolean isVcnActive, boolean hasCarrierPrivileges) {
|
||||||
mVcnMgmtSvc.systemReady();
|
mVcnMgmtSvc.systemReady();
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
triggerSubscriptionTrackerCbAndGetSnapshot(
|
triggerSubscriptionTrackerCbAndGetSnapshot(
|
||||||
subGrp,
|
subGrp,
|
||||||
Collections.singleton(subGrp),
|
Collections.singleton(subGrp),
|
||||||
@@ -1020,6 +934,7 @@ public class VcnManagementServiceTest {
|
|||||||
|
|
||||||
private void setupTrackedCarrierWifiNetwork(NetworkCapabilities caps) {
|
private void setupTrackedCarrierWifiNetwork(NetworkCapabilities caps) {
|
||||||
mVcnMgmtSvc.systemReady();
|
mVcnMgmtSvc.systemReady();
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
final ArgumentCaptor<NetworkCallback> captor =
|
final ArgumentCaptor<NetworkCallback> captor =
|
||||||
ArgumentCaptor.forClass(NetworkCallback.class);
|
ArgumentCaptor.forClass(NetworkCallback.class);
|
||||||
@@ -1264,15 +1179,14 @@ public class VcnManagementServiceTest {
|
|||||||
true /* isActive */,
|
true /* isActive */,
|
||||||
true /* hasCarrierPrivileges */);
|
true /* hasCarrierPrivileges */);
|
||||||
|
|
||||||
// VCN is currently active. Lose carrier privileges for TEST_PACKAGE and hit teardown
|
// VCN is currently active. Lose carrier privileges for TEST_PACKAGE so the VCN goes
|
||||||
// timeout so the VCN goes inactive.
|
// inactive.
|
||||||
final TelephonySubscriptionSnapshot snapshot =
|
final TelephonySubscriptionSnapshot snapshot =
|
||||||
triggerSubscriptionTrackerCbAndGetSnapshot(
|
triggerSubscriptionTrackerCbAndGetSnapshot(
|
||||||
TEST_UUID_1,
|
TEST_UUID_1,
|
||||||
Collections.singleton(TEST_UUID_1),
|
Collections.singleton(TEST_UUID_1),
|
||||||
Collections.singletonMap(TEST_SUBSCRIPTION_ID, TEST_UUID_1),
|
Collections.singletonMap(TEST_SUBSCRIPTION_ID, TEST_UUID_1),
|
||||||
false /* hasCarrierPrivileges */);
|
false /* hasCarrierPrivileges */);
|
||||||
mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS);
|
|
||||||
mTestLooper.dispatchAll();
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
// Giving TEST_PACKAGE privileges again will restart the VCN (which will indicate ACTIVE
|
// Giving TEST_PACKAGE privileges again will restart the VCN (which will indicate ACTIVE
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import static android.telephony.CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX;
|
|||||||
import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
|
import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
|
||||||
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||||
import static android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener;
|
import static android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener;
|
||||||
|
import static android.telephony.TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED;
|
||||||
|
|
||||||
import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
||||||
import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback;
|
import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback;
|
||||||
@@ -34,8 +35,10 @@ import static org.mockito.ArgumentMatchers.any;
|
|||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.argThat;
|
import static org.mockito.ArgumentMatchers.argThat;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.atLeastOnce;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
|
|
||||||
@@ -57,6 +60,8 @@ import android.telephony.SubscriptionManager;
|
|||||||
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
|
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
|
||||||
import android.telephony.TelephonyCallback;
|
import android.telephony.TelephonyCallback;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
|
import android.telephony.TelephonyManager.CarrierPrivilegesListener;
|
||||||
|
import android.util.ArrayMap;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
@@ -83,7 +88,7 @@ public class TelephonySubscriptionTrackerTest {
|
|||||||
private static final String PACKAGE_NAME =
|
private static final String PACKAGE_NAME =
|
||||||
TelephonySubscriptionTrackerTest.class.getPackage().getName();
|
TelephonySubscriptionTrackerTest.class.getPackage().getName();
|
||||||
private static final ParcelUuid TEST_PARCEL_UUID = new ParcelUuid(UUID.randomUUID());
|
private static final ParcelUuid TEST_PARCEL_UUID = new ParcelUuid(UUID.randomUUID());
|
||||||
private static final int TEST_SIM_SLOT_INDEX = 1;
|
private static final int TEST_SIM_SLOT_INDEX = 0;
|
||||||
private static final int TEST_SUBSCRIPTION_ID_1 = 2;
|
private static final int TEST_SUBSCRIPTION_ID_1 = 2;
|
||||||
private static final SubscriptionInfo TEST_SUBINFO_1 = mock(SubscriptionInfo.class);
|
private static final SubscriptionInfo TEST_SUBINFO_1 = mock(SubscriptionInfo.class);
|
||||||
private static final int TEST_SUBSCRIPTION_ID_2 = 3;
|
private static final int TEST_SUBSCRIPTION_ID_2 = 3;
|
||||||
@@ -151,6 +156,8 @@ public class TelephonySubscriptionTrackerTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
|
doReturn(2).when(mTelephonyManager).getActiveModemCount();
|
||||||
|
|
||||||
mCallback = mock(TelephonySubscriptionTrackerCallback.class);
|
mCallback = mock(TelephonySubscriptionTrackerCallback.class);
|
||||||
mTelephonySubscriptionTracker =
|
mTelephonySubscriptionTracker =
|
||||||
new TelephonySubscriptionTracker(mContext, mHandler, mCallback, mDeps);
|
new TelephonySubscriptionTracker(mContext, mHandler, mCallback, mDeps);
|
||||||
@@ -180,6 +187,15 @@ public class TelephonySubscriptionTrackerTest {
|
|||||||
return captor.getValue();
|
return captor.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<CarrierPrivilegesListener> getCarrierPrivilegesListeners() {
|
||||||
|
final ArgumentCaptor<CarrierPrivilegesListener> captor =
|
||||||
|
ArgumentCaptor.forClass(CarrierPrivilegesListener.class);
|
||||||
|
verify(mTelephonyManager, atLeastOnce())
|
||||||
|
.addCarrierPrivilegesListener(anyInt(), any(), captor.capture());
|
||||||
|
|
||||||
|
return captor.getAllValues();
|
||||||
|
}
|
||||||
|
|
||||||
private ActiveDataSubscriptionIdListener getActiveDataSubscriptionIdListener() {
|
private ActiveDataSubscriptionIdListener getActiveDataSubscriptionIdListener() {
|
||||||
final ArgumentCaptor<TelephonyCallback> captor =
|
final ArgumentCaptor<TelephonyCallback> captor =
|
||||||
ArgumentCaptor.forClass(TelephonyCallback.class);
|
ArgumentCaptor.forClass(TelephonyCallback.class);
|
||||||
@@ -188,6 +204,11 @@ public class TelephonySubscriptionTrackerTest {
|
|||||||
return (ActiveDataSubscriptionIdListener) captor.getValue();
|
return (ActiveDataSubscriptionIdListener) captor.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Intent buildTestMultiSimConfigBroadcastIntent() {
|
||||||
|
Intent intent = new Intent(ACTION_MULTI_SIM_CONFIG_CHANGED);
|
||||||
|
return intent;
|
||||||
|
}
|
||||||
|
|
||||||
private Intent buildTestBroadcastIntent(boolean hasValidSubscription) {
|
private Intent buildTestBroadcastIntent(boolean hasValidSubscription) {
|
||||||
Intent intent = new Intent(ACTION_CARRIER_CONFIG_CHANGED);
|
Intent intent = new Intent(ACTION_CARRIER_CONFIG_CHANGED);
|
||||||
intent.putExtra(EXTRA_SLOT_INDEX, TEST_SIM_SLOT_INDEX);
|
intent.putExtra(EXTRA_SLOT_INDEX, TEST_SIM_SLOT_INDEX);
|
||||||
@@ -239,12 +260,21 @@ public class TelephonySubscriptionTrackerTest {
|
|||||||
any(),
|
any(),
|
||||||
eq(mHandler));
|
eq(mHandler));
|
||||||
final IntentFilter filter = getIntentFilter();
|
final IntentFilter filter = getIntentFilter();
|
||||||
assertEquals(1, filter.countActions());
|
assertEquals(2, filter.countActions());
|
||||||
assertTrue(filter.hasAction(ACTION_CARRIER_CONFIG_CHANGED));
|
assertTrue(filter.hasAction(ACTION_CARRIER_CONFIG_CHANGED));
|
||||||
|
assertTrue(filter.hasAction(ACTION_MULTI_SIM_CONFIG_CHANGED));
|
||||||
|
|
||||||
verify(mSubscriptionManager)
|
verify(mSubscriptionManager)
|
||||||
.addOnSubscriptionsChangedListener(any(HandlerExecutor.class), any());
|
.addOnSubscriptionsChangedListener(any(HandlerExecutor.class), any());
|
||||||
assertNotNull(getOnSubscriptionsChangedListener());
|
assertNotNull(getOnSubscriptionsChangedListener());
|
||||||
|
|
||||||
|
verify(mTelephonyManager, times(2))
|
||||||
|
.addCarrierPrivilegesListener(anyInt(), any(HandlerExecutor.class), any());
|
||||||
|
verify(mTelephonyManager)
|
||||||
|
.addCarrierPrivilegesListener(eq(0), any(HandlerExecutor.class), any());
|
||||||
|
verify(mTelephonyManager)
|
||||||
|
.addCarrierPrivilegesListener(eq(1), any(HandlerExecutor.class), any());
|
||||||
|
assertEquals(2, getCarrierPrivilegesListeners().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -255,6 +285,49 @@ public class TelephonySubscriptionTrackerTest {
|
|||||||
|
|
||||||
final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener();
|
final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener();
|
||||||
verify(mSubscriptionManager).removeOnSubscriptionsChangedListener(eq(listener));
|
verify(mSubscriptionManager).removeOnSubscriptionsChangedListener(eq(listener));
|
||||||
|
|
||||||
|
for (CarrierPrivilegesListener carrierPrivilegesListener :
|
||||||
|
getCarrierPrivilegesListeners()) {
|
||||||
|
verify(mTelephonyManager)
|
||||||
|
.removeCarrierPrivilegesListener(eq(carrierPrivilegesListener));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultiSimConfigChanged() throws Exception {
|
||||||
|
final ArrayMap<Integer, Integer> readySubIdsBySlotId = new ArrayMap<>();
|
||||||
|
readySubIdsBySlotId.put(TEST_SIM_SLOT_INDEX, TEST_SUBSCRIPTION_ID_1);
|
||||||
|
readySubIdsBySlotId.put(TEST_SIM_SLOT_INDEX + 1, TEST_SUBSCRIPTION_ID_1);
|
||||||
|
|
||||||
|
mTelephonySubscriptionTracker.setReadySubIdsBySlotId(readySubIdsBySlotId);
|
||||||
|
doReturn(1).when(mTelephonyManager).getActiveModemCount();
|
||||||
|
|
||||||
|
List<CarrierPrivilegesListener> carrierPrivilegesListeners =
|
||||||
|
getCarrierPrivilegesListeners();
|
||||||
|
|
||||||
|
mTelephonySubscriptionTracker.onReceive(mContext, buildTestMultiSimConfigBroadcastIntent());
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
for (CarrierPrivilegesListener carrierPrivilegesListener : carrierPrivilegesListeners) {
|
||||||
|
verify(mTelephonyManager)
|
||||||
|
.removeCarrierPrivilegesListener(eq(carrierPrivilegesListener));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expect cache cleared for inactive slots.
|
||||||
|
assertNull(
|
||||||
|
mTelephonySubscriptionTracker
|
||||||
|
.getReadySubIdsBySlotId()
|
||||||
|
.get(TEST_SIM_SLOT_INDEX + 1));
|
||||||
|
|
||||||
|
// Expect a new CarrierPrivilegesListener to have been registered for slot 0, and none other
|
||||||
|
// (2 previously registered during startup, for slots 0 & 1)
|
||||||
|
verify(mTelephonyManager, times(3))
|
||||||
|
.addCarrierPrivilegesListener(anyInt(), any(HandlerExecutor.class), any());
|
||||||
|
verify(mTelephonyManager, times(2))
|
||||||
|
.addCarrierPrivilegesListener(eq(0), any(HandlerExecutor.class), any());
|
||||||
|
|
||||||
|
// Verify that this triggers a re-evaluation
|
||||||
|
verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -313,6 +386,17 @@ public class TelephonySubscriptionTrackerTest {
|
|||||||
verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES)));
|
verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnCarrierPrivilegesChanged() throws Exception {
|
||||||
|
setupReadySubIds();
|
||||||
|
|
||||||
|
final CarrierPrivilegesListener listener = getCarrierPrivilegesListeners().get(0);
|
||||||
|
listener.onCarrierPrivilegesChanged(Collections.emptyList(), new int[] {});
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES)));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReceiveBroadcast_ConfigReadyWithSubscriptions() throws Exception {
|
public void testReceiveBroadcast_ConfigReadyWithSubscriptions() throws Exception {
|
||||||
mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
|
mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
|
||||||
|
|||||||
Reference in New Issue
Block a user