Support bringing up restricted wifi

This CL allows the Carrier Config app to request restricted WiFi nework
by setting the correspoding subscription ID in the network request.

Bug: 315835605
Test: atest android.net.cts.NetworkRequestTest
      atest ConnectivityCoverageTests:android.net.connectivity.com.android.server.connectivity.CarrierPrivilegeAuthenticatorTest
      atest ConnectivityCoverageTests:android.net.connectivity.com.android.server.ConnectivityServiceTest

Change-Id: I237e692d092ff5f969ce4b7962f6d58099a6f3a9
This commit is contained in:
Ying Xu 2024-01-15 18:40:15 -08:00
commit 7cabd32bc5
12 changed files with 382 additions and 31 deletions

View file

@ -315,6 +315,7 @@ package android.net {
method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
method public int getOwnerUid();
method public int getSignalStrength();
method @FlaggedApi("com.android.net.flags.request_restricted_wifi") @NonNull public java.util.Set<java.lang.Integer> getSubscriptionIds();
method @Nullable public android.net.TransportInfo getTransportInfo();
method public boolean hasCapability(int);
method public boolean hasEnterpriseId(int);
@ -419,6 +420,7 @@ package android.net {
method public int describeContents();
method @NonNull public int[] getCapabilities();
method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
method @FlaggedApi("com.android.net.flags.request_restricted_wifi") @NonNull public java.util.Set<java.lang.Integer> getSubscriptionIds();
method @NonNull public int[] getTransportTypes();
method public boolean hasCapability(int);
method public boolean hasTransport(int);
@ -438,6 +440,7 @@ package android.net {
method @NonNull public android.net.NetworkRequest.Builder setIncludeOtherUidNetworks(boolean);
method @Deprecated public android.net.NetworkRequest.Builder setNetworkSpecifier(String);
method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier);
method @FlaggedApi("com.android.net.flags.request_restricted_wifi") @NonNull public android.net.NetworkRequest.Builder setSubscriptionIds(@NonNull java.util.Set<java.lang.Integer>);
}
public class ParseException extends java.lang.RuntimeException {

View file

@ -307,7 +307,6 @@ package android.net {
method @NonNull public int[] getAdministratorUids();
method @Nullable public static String getCapabilityCarrierName(int);
method @Nullable public String getSsid();
method @NonNull public java.util.Set<java.lang.Integer> getSubscriptionIds();
method @NonNull public int[] getTransportTypes();
method @Nullable public java.util.List<android.net.Network> getUnderlyingNetworks();
method public boolean isPrivateDnsBroken();
@ -373,7 +372,6 @@ package android.net {
public static class NetworkRequest.Builder {
method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkRequest.Builder setSignalStrength(int);
method @NonNull public android.net.NetworkRequest.Builder setSubscriptionIds(@NonNull java.util.Set<java.lang.Integer>);
}
public final class NetworkScore implements android.os.Parcelable {

View file

@ -130,6 +130,8 @@ public final class NetworkCapabilities implements Parcelable {
"com.android.net.flags.forbidden_capability";
static final String FLAG_NET_CAPABILITY_LOCAL_NETWORK =
"com.android.net.flags.net_capability_local_network";
static final String REQUEST_RESTRICTED_WIFI =
"com.android.net.flags.request_restricted_wifi";
}
/**
@ -2790,10 +2792,9 @@ public final class NetworkCapabilities implements Parcelable {
* receiver holds the NETWORK_FACTORY permission. In all other cases, it will be the empty set.
*
* @return
* @hide
*/
@NonNull
@SystemApi
@FlaggedApi(Flags.REQUEST_RESTRICTED_WIFI)
public Set<Integer> getSubscriptionIds() {
return new ArraySet<>(mSubIds);
}

View file

@ -34,6 +34,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@ -145,6 +146,12 @@ import java.util.Set;
* Look up the specific capability to learn whether its usage requires this self-certification.
*/
public class NetworkRequest implements Parcelable {
/** @hide */
public static class Flags {
static final String REQUEST_RESTRICTED_WIFI =
"com.android.net.flags.request_restricted_wifi";
}
/**
* The first requestId value that will be allocated.
* @hide only used by ConnectivityService.
@ -630,10 +637,9 @@ public class NetworkRequest implements Parcelable {
* NETWORK_FACTORY permission.
*
* @param subIds A {@code Set} that represents subscription IDs.
* @hide
*/
@NonNull
@SystemApi
@FlaggedApi(Flags.REQUEST_RESTRICTED_WIFI)
public Builder setSubscriptionIds(@NonNull Set<Integer> subIds) {
mNetworkCapabilities.setSubscriptionIds(subIds);
return this;
@ -890,4 +896,17 @@ public class NetworkRequest implements Parcelable {
// a new array.
return networkCapabilities.getTransportTypes();
}
/**
* Gets all the subscription ids set on this {@code NetworkRequest} instance.
*
* @return Set of Integer values for this instance.
*/
@NonNull
@FlaggedApi(Flags.REQUEST_RESTRICTED_WIFI)
public Set<Integer> getSubscriptionIds() {
// No need to make a defensive copy here as NC#getSubscriptionIds() already returns
// a new set.
return networkCapabilities.getSubscriptionIds();
}
}

View file

@ -113,6 +113,8 @@ import static com.android.net.module.util.PermissionUtils.enforceNetworkStackPer
import static com.android.net.module.util.PermissionUtils.enforceNetworkStackPermissionOr;
import static com.android.net.module.util.PermissionUtils.hasAnyPermissionOf;
import static com.android.server.ConnectivityStatsLog.CONNECTIVITY_STATE_SAMPLE;
import static com.android.server.connectivity.CarrierPrivilegeAuthenticator.CarrierPrivilegesLostListener;
import static com.android.server.connectivity.ConnectivityFlags.REQUEST_RESTRICTED_WIFI;
import android.Manifest;
import android.annotation.CheckResult;
@ -467,6 +469,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
private volatile boolean mLockdownEnabled;
private final boolean mRequestRestrictedWifiEnabled;
/**
* Stale copy of uid blocked reasons provided by NPMS. As long as they are accessed only in
* internal handler thread, they don't need a lock.
@ -831,6 +835,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/
private static final int EVENT_UID_FROZEN_STATE_CHANGED = 61;
/**
* Event to inform the ConnectivityService handler when a uid has lost carrier privileges.
*/
private static final int EVENT_UID_CARRIER_PRIVILEGES_LOST = 62;
/**
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
* should be shown.
@ -1270,6 +1279,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
private final LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker(this);
private final CarrierPrivilegesLostListenerImpl mCarrierPrivilegesLostListenerImpl =
new CarrierPrivilegesLostListenerImpl();
private class CarrierPrivilegesLostListenerImpl implements CarrierPrivilegesLostListener {
@Override
public void onCarrierPrivilegesLost(int uid) {
if (mRequestRestrictedWifiEnabled) {
mHandler.sendMessage(mHandler.obtainMessage(
EVENT_UID_CARRIER_PRIVILEGES_LOST, uid, 0 /* arg2 */));
}
}
}
final LocalPriorityDump mPriorityDumper = new LocalPriorityDump();
/**
* Helper class which parses out priority arguments and dumps sections according to their
@ -1328,6 +1349,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
@VisibleForTesting
CarrierPrivilegesLostListener getCarrierPrivilegesLostListener() {
return mCarrierPrivilegesLostListenerImpl;
}
/**
* Dependencies of ConnectivityService, for injection in tests.
*/
@ -1488,9 +1514,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/
@Nullable
public CarrierPrivilegeAuthenticator makeCarrierPrivilegeAuthenticator(
@NonNull final Context context, @NonNull final TelephonyManager tm) {
@NonNull final Context context,
@NonNull final TelephonyManager tm,
boolean requestRestrictedWifiEnabled,
@NonNull CarrierPrivilegesLostListener listener) {
if (isAtLeastT()) {
return new CarrierPrivilegeAuthenticator(context, tm);
return new CarrierPrivilegeAuthenticator(
context, tm, requestRestrictedWifiEnabled, listener);
} else {
return null;
}
@ -1759,8 +1789,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext);
mCarrierPrivilegeAuthenticator =
mDeps.makeCarrierPrivilegeAuthenticator(mContext, mTelephonyManager);
mRequestRestrictedWifiEnabled = mDeps.isAtLeastU()
&& mDeps.isFeatureEnabled(context, REQUEST_RESTRICTED_WIFI);
mCarrierPrivilegeAuthenticator = mDeps.makeCarrierPrivilegeAuthenticator(
mContext, mTelephonyManager, mRequestRestrictedWifiEnabled,
mCarrierPrivilegesLostListenerImpl);
// To ensure uid state is synchronized with Network Policy, register for
// NetworkPolicyManagerService events must happen prior to NetworkPolicyManagerService
@ -6410,6 +6443,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
UidFrozenStateChangedArgs args = (UidFrozenStateChangedArgs) msg.obj;
handleFrozenUids(args.mUids, args.mFrozenStates);
break;
case EVENT_UID_CARRIER_PRIVILEGES_LOST:
handleUidCarrierPrivilegesLost(msg.arg1);
break;
}
}
}
@ -7490,9 +7526,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
mAppOpsManager.checkPackage(callerUid, callerPackageName);
if (!nc.getSubscriptionIds().isEmpty()) {
enforceNetworkFactoryPermission();
if (nc.getSubscriptionIds().isEmpty()) {
return;
}
if (mRequestRestrictedWifiEnabled
&& canRequestRestrictedNetworkDueToCarrierPrivileges(nc, callerUid)) {
return;
}
enforceNetworkFactoryPermission();
}
private int[] getSignalStrengthThresholds(@NonNull final NetworkAgentInfo nai) {
@ -7772,6 +7813,22 @@ public class ConnectivityService extends IConnectivityManager.Stub
applicationNetworkCapabilities.enforceSelfCertifiedNetworkCapabilitiesDeclared(
networkCapabilities);
}
private boolean canRequestRestrictedNetworkDueToCarrierPrivileges(
NetworkCapabilities networkCapabilities, int callingUid) {
if (mRequestRestrictedWifiEnabled) {
// For U+ devices, callers with carrier privilege could request restricted networks
// with CBS capabilities, or any restricted WiFi networks.
return ((networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)
|| networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
&& hasCarrierPrivilegeForNetworkCaps(callingUid, networkCapabilities));
} else {
// For T+ devices, callers with carrier privilege could request with CBS
// capabilities.
return (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)
&& hasCarrierPrivilegeForNetworkCaps(callingUid, networkCapabilities));
}
}
private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities,
String callingPackageName, String callingAttributionTag, final int callingUid) {
if (shouldCheckCapabilitiesDeclaration(networkCapabilities, callingUid,
@ -7779,13 +7836,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
enforceRequestCapabilitiesDeclaration(callingPackageName, networkCapabilities,
callingUid);
}
if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) == false) {
// For T+ devices, callers with carrier privilege could request with CBS capabilities.
if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)
&& hasCarrierPrivilegeForNetworkCaps(callingUid, networkCapabilities)) {
return;
if (!networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
if (!canRequestRestrictedNetworkDueToCarrierPrivileges(
networkCapabilities, callingUid)) {
enforceConnectivityRestrictedNetworksPermission(true /* checkUidsAllowedList */);
}
enforceConnectivityRestrictedNetworksPermission(true /* checkUidsAllowedList */);
} else {
enforceChangePermission(callingPackageName, callingAttributionTag);
}
@ -9052,6 +9107,38 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
private void handleUidCarrierPrivilegesLost(int uid) {
ensureRunningOnConnectivityServiceThread();
// A NetworkRequest needs to be revoked when all the conditions are met
// 1. It requests restricted network
// 2. The requestor uid matches the uid with the callback
// 3. The app doesn't have Carrier Privileges
// 4. The app doesn't have permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS
for (final NetworkRequest nr : mNetworkRequests.keySet()) {
if ((nr.isRequest() || nr.isListen())
&& !nr.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
&& nr.getRequestorUid() == uid
&& !hasConnectivityRestrictedNetworksPermission(uid, true)) {
declareNetworkRequestUnfulfillable(nr);
}
}
// A NetworkAgent's allowedUids may need to be updated if the app has lost
// carrier config
for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
if (nai.networkCapabilities.getAllowedUidsNoCopy().contains(uid)) {
final NetworkCapabilities nc = new NetworkCapabilities(nai.networkCapabilities);
NetworkAgentInfo.restrictCapabilitiesFromNetworkAgent(
nc,
uid,
false /* hasAutomotiveFeature (irrelevant) */,
mDeps,
mCarrierPrivilegeAuthenticator);
updateCapabilities(nai.getScore(), nai, nc);
}
}
}
/**
* Update the NetworkCapabilities for {@code nai} to {@code nc}. Specifically:
*
@ -9499,7 +9586,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
final ArraySet<Integer> toAdd = new ArraySet<>(newUids);
toRemove.removeAll(newUids);
toAdd.removeAll(prevUids);
try {
if (!toAdd.isEmpty()) {
mNetd.networkAddUidRangesParcel(new NativeUidRangeConfig(

View file

@ -79,11 +79,16 @@ public class CarrierPrivilegeAuthenticator {
@NonNull
private final List<PrivilegeListener> mCarrierPrivilegesChangedListeners = new ArrayList<>();
private final boolean mUseCallbacksForServiceChanged;
private final boolean mRequestRestrictedWifiEnabled;
@NonNull
private final CarrierPrivilegesLostListener mListener;
public CarrierPrivilegeAuthenticator(@NonNull final Context c,
@NonNull final Dependencies deps,
@NonNull final TelephonyManager t,
@NonNull final TelephonyManagerShim telephonyManagerShim) {
@NonNull final TelephonyManagerShim telephonyManagerShim,
final boolean requestRestrictedWifiEnabled,
@NonNull CarrierPrivilegesLostListener listener) {
mContext = c;
mTelephonyManager = t;
mTelephonyManagerShim = telephonyManagerShim;
@ -92,6 +97,8 @@ public class CarrierPrivilegeAuthenticator {
mHandler = new Handler(thread.getLooper());
mUseCallbacksForServiceChanged = deps.isFeatureEnabled(
c, CARRIER_SERVICE_CHANGED_USE_CALLBACK);
mRequestRestrictedWifiEnabled = requestRestrictedWifiEnabled;
mListener = listener;
final IntentFilter filter = new IntentFilter();
filter.addAction(TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED);
synchronized (mLock) {
@ -113,8 +120,10 @@ public class CarrierPrivilegeAuthenticator {
}
public CarrierPrivilegeAuthenticator(@NonNull final Context c,
@NonNull final TelephonyManager t) {
this(c, new Dependencies(), t, TelephonyManagerShimImpl.newInstance(t));
@NonNull final TelephonyManager t, final boolean requestRestrictedWifiEnabled,
@NonNull CarrierPrivilegesLostListener listener) {
this(c, new Dependencies(), t, TelephonyManagerShimImpl.newInstance(t),
requestRestrictedWifiEnabled, listener);
}
public static class Dependencies {
@ -133,6 +142,18 @@ public class CarrierPrivilegeAuthenticator {
}
}
/**
* Listener interface to get a notification when the carrier App lost its privileges.
*/
public interface CarrierPrivilegesLostListener {
/**
* Called when the carrier App lost its privileges.
*
* @param uid The uid of the carrier app which has lost its privileges.
*/
void onCarrierPrivilegesLost(int uid);
}
private void simConfigChanged() {
synchronized (mLock) {
unregisterCarrierPrivilegesListeners();
@ -171,7 +192,11 @@ public class CarrierPrivilegeAuthenticator {
return;
}
synchronized (mLock) {
int oldUid = mCarrierServiceUid.get(mLogicalSlot);
mCarrierServiceUid.put(mLogicalSlot, carrierServiceUid);
if (oldUid != 0 && oldUid != carrierServiceUid) {
mListener.onCarrierPrivilegesLost(oldUid);
}
}
}
}
@ -193,7 +218,11 @@ public class CarrierPrivilegeAuthenticator {
private void unregisterCarrierPrivilegesListeners() {
for (PrivilegeListener carrierPrivilegesListener : mCarrierPrivilegesChangedListeners) {
removeCarrierPrivilegesListener(carrierPrivilegesListener);
int oldUid = mCarrierServiceUid.get(carrierPrivilegesListener.mLogicalSlot);
mCarrierServiceUid.delete(carrierPrivilegesListener.mLogicalSlot);
if (oldUid != 0) {
mListener.onCarrierPrivilegesLost(oldUid);
}
}
mCarrierPrivilegesChangedListeners.clear();
}
@ -231,7 +260,7 @@ public class CarrierPrivilegeAuthenticator {
public boolean isCarrierServiceUidForNetworkCapabilities(int callingUid,
@NonNull NetworkCapabilities networkCapabilities) {
if (callingUid == Process.INVALID_UID) return false;
final int subId;
int subId;
if (networkCapabilities.hasSingleTransportBesidesTest(TRANSPORT_CELLULAR)) {
subId = getSubIdFromTelephonySpecifier(networkCapabilities.getNetworkSpecifier());
} else if (networkCapabilities.hasSingleTransportBesidesTest(TRANSPORT_WIFI)) {
@ -239,6 +268,12 @@ public class CarrierPrivilegeAuthenticator {
} else {
subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
&& mRequestRestrictedWifiEnabled
&& networkCapabilities.getSubscriptionIds().size() == 1) {
subId = networkCapabilities.getSubscriptionIds().toArray(new Integer[0])[0];
}
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
&& !networkCapabilities.getSubscriptionIds().contains(subId)) {
// Ideally, the code above should just use networkCapabilities.getSubscriptionIds()
@ -257,10 +292,16 @@ public class CarrierPrivilegeAuthenticator {
@VisibleForTesting
void updateCarrierServiceUid() {
synchronized (mLock) {
SparseIntArray oldCarrierServiceUid = mCarrierServiceUid.clone();
mCarrierServiceUid.clear();
for (int i = 0; i < mModemCount; i++) {
mCarrierServiceUid.put(i, getCarrierServicePackageUidForSlot(i));
}
for (int i = 0; i < oldCarrierServiceUid.size(); i++) {
if (mCarrierServiceUid.indexOfValue(oldCarrierServiceUid.valueAt(i)) < 0) {
mListener.onCarrierPrivilegesLost(oldCarrierServiceUid.valueAt(i));
}
}
}
}
@ -340,6 +381,7 @@ public class CarrierPrivilegeAuthenticator {
public void dump(IndentingPrintWriter pw) {
pw.println("CarrierPrivilegeAuthenticator:");
pw.println("mRequestRestrictedWifiEnabled = " + mRequestRestrictedWifiEnabled);
synchronized (mLock) {
final int size = mCarrierServiceUid.size();
for (int i = 0; i < size; ++i) {

View file

@ -36,6 +36,8 @@ public final class ConnectivityFlags {
public static final String CARRIER_SERVICE_CHANGED_USE_CALLBACK =
"carrier_service_changed_use_callback_version";
public static final String REQUEST_RESTRICTED_WIFI =
"request_restricted_wifi";
private boolean mNoRematchAllRequestsOnRegister;
/**

View file

@ -1551,7 +1551,7 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
* @param hasAutomotiveFeature true if this device has the automotive feature, false otherwise
* @param authenticator the carrier privilege authenticator to check for telephony constraints
*/
public void restrictCapabilitiesFromNetworkAgent(@NonNull final NetworkCapabilities nc,
public static void restrictCapabilitiesFromNetworkAgent(@NonNull final NetworkCapabilities nc,
final int creatorUid, final boolean hasAutomotiveFeature,
@NonNull final ConnectivityService.Dependencies deps,
@Nullable final CarrierPrivilegeAuthenticator authenticator) {
@ -1564,7 +1564,7 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
}
}
private boolean areAllowedUidsAcceptableFromNetworkAgent(
private static boolean areAllowedUidsAcceptableFromNetworkAgent(
@NonNull final NetworkCapabilities nc, final boolean hasAutomotiveFeature,
@NonNull final ConnectivityService.Dependencies deps,
@Nullable final CarrierPrivilegeAuthenticator carrierPrivilegeAuthenticator) {

View file

@ -56,6 +56,7 @@ import com.android.server.ConnectivityService
import com.android.server.NetworkAgentWrapper
import com.android.server.TestNetIdManager
import com.android.server.connectivity.CarrierPrivilegeAuthenticator
import com.android.server.connectivity.CarrierPrivilegeAuthenticator.CarrierPrivilegesLostListener
import com.android.server.connectivity.ConnectivityResources
import com.android.server.connectivity.MockableSystemProperties
import com.android.server.connectivity.MultinetworkPolicyTracker
@ -240,14 +241,17 @@ class ConnectivityServiceIntegrationTest {
override fun makeCarrierPrivilegeAuthenticator(
context: Context,
tm: TelephonyManager
tm: TelephonyManager,
requestRestrictedWifiEnabled: Boolean,
listener: CarrierPrivilegesLostListener
): CarrierPrivilegeAuthenticator {
return CarrierPrivilegeAuthenticator(context,
object : CarrierPrivilegeAuthenticator.Dependencies() {
override fun makeHandlerThread(): HandlerThread =
super.makeHandlerThread().also { handlerThreads.add(it) }
},
tm, TelephonyManagerShimImpl.newInstance(tm))
tm, TelephonyManagerShimImpl.newInstance(tm),
requestRestrictedWifiEnabled, listener)
}
}

View file

@ -172,6 +172,7 @@ import static com.android.server.ConnectivityService.makeNflogPrefix;
import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyType;
import static com.android.server.NetworkAgentWrapper.CallbackType.OnQosCallbackRegister;
import static com.android.server.NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister;
import static com.android.server.connectivity.CarrierPrivilegeAuthenticator.CarrierPrivilegesLostListener;
import static com.android.testutils.Cleanup.testAndCleanup;
import static com.android.testutils.ConcurrentUtils.await;
import static com.android.testutils.ConcurrentUtils.durationOf;
@ -2053,7 +2054,9 @@ public class ConnectivityServiceTest {
@Override
public CarrierPrivilegeAuthenticator makeCarrierPrivilegeAuthenticator(
@NonNull final Context context,
@NonNull final TelephonyManager tm) {
@NonNull final TelephonyManager tm,
final boolean requestRestrictedWifiEnabled,
CarrierPrivilegesLostListener listener) {
return mDeps.isAtLeastT() ? mCarrierPrivilegeAuthenticator : null;
}
@ -2147,6 +2150,8 @@ public class ConnectivityServiceTest {
case ConnectivityFlags.NO_REMATCH_ALL_REQUESTS_ON_REGISTER:
case ConnectivityFlags.CARRIER_SERVICE_CHANGED_USE_CALLBACK:
return true;
case ConnectivityFlags.REQUEST_RESTRICTED_WIFI:
return true;
case KEY_DESTROY_FROZEN_SOCKETS_VERSION:
return true;
case DELAY_DESTROY_FROZEN_SOCKETS_VERSION:
@ -17353,6 +17358,14 @@ public class ConnectivityServiceTest {
.build();
}
private NetworkRequest getRestrictedRequestForWifiWithSubIds() {
return new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.setSubscriptionIds(Collections.singleton(Process.myUid()))
.build();
}
@Test
public void testNetworkRequestWithSubIdsWithNetworkFactoryPermission() throws Exception {
mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
@ -17385,6 +17398,134 @@ public class ConnectivityServiceTest {
() -> mCm.registerNetworkCallback(getRequestWithSubIds(), new NetworkCallback()));
}
@Test
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
public void testCarrierConfigAppSendNetworkRequestForRestrictedWifi() throws Exception {
mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
doReturn(true).when(mCarrierPrivilegeAuthenticator)
.isCarrierServiceUidForNetworkCapabilities(anyInt(), any());
final PendingIntent pendingIntent = PendingIntent.getBroadcast(
mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
final NetworkCallback networkCallback1 = new NetworkCallback();
final NetworkCallback networkCallback2 = new NetworkCallback();
mCm.requestNetwork(getRestrictedRequestForWifiWithSubIds(), networkCallback1);
mCm.requestNetwork(getRestrictedRequestForWifiWithSubIds(), pendingIntent);
mCm.registerNetworkCallback(getRestrictedRequestForWifiWithSubIds(), networkCallback2);
mCm.unregisterNetworkCallback(networkCallback1);
mCm.releaseNetworkRequest(pendingIntent);
mCm.unregisterNetworkCallback(networkCallback2);
}
@Test
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
public void testRestrictedRequestRemovedDueToCarrierPrivilegesLost() throws Exception {
mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
NetworkCapabilities filter = getRestrictedRequestForWifiWithSubIds().networkCapabilities;
final HandlerThread handlerThread = new HandlerThread("testRestrictedFactoryRequests");
handlerThread.start();
final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
mServiceContext, "testFactory", filter, mCsHandlerThread);
testFactory.register();
testFactory.assertRequestCountEquals(0);
doReturn(true).when(mCarrierPrivilegeAuthenticator)
.isCarrierServiceUidForNetworkCapabilities(eq(Process.myUid()), any());
final TestNetworkCallback networkCallback1 = new TestNetworkCallback();
final NetworkRequest networkrequest1 = getRestrictedRequestForWifiWithSubIds();
mCm.requestNetwork(networkrequest1, networkCallback1);
testFactory.expectRequestAdd();
testFactory.assertRequestCountEquals(1);
NetworkCapabilities nc = new NetworkCapabilities.Builder(filter)
.setAllowedUids(Set.of(Process.myUid()))
.build();
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), nc);
mWiFiAgent.connect(true);
networkCallback1.expectAvailableThenValidatedCallbacks(mWiFiAgent);
final NetworkAgentInfo nai = mService.getNetworkAgentInfoForNetwork(
mWiFiAgent.getNetwork());
doReturn(false).when(mCarrierPrivilegeAuthenticator)
.isCarrierServiceUidForNetworkCapabilities(eq(Process.myUid()), any());
final CarrierPrivilegesLostListener carrierPrivilegesLostListener =
mService.getCarrierPrivilegesLostListener();
carrierPrivilegesLostListener.onCarrierPrivilegesLost(Process.myUid());
waitForIdle();
testFactory.expectRequestRemove();
testFactory.assertRequestCountEquals(0);
assertTrue(nai.networkCapabilities.getAllowedUidsNoCopy().isEmpty());
networkCallback1.expect(NETWORK_CAPS_UPDATED);
networkCallback1.expect(UNAVAILABLE);
handlerThread.quitSafely();
handlerThread.join();
}
@Test
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
public void testRequestNotRemoved_MismatchUid() throws Exception {
mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
NetworkCapabilities filter = getRestrictedRequestForWifiWithSubIds().networkCapabilities;
final HandlerThread handlerThread = new HandlerThread("testRestrictedFactoryRequests");
handlerThread.start();
final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
mServiceContext, "testFactory", filter, mCsHandlerThread);
testFactory.register();
doReturn(true).when(mCarrierPrivilegeAuthenticator)
.isCarrierServiceUidForNetworkCapabilities(anyInt(), any());
final TestNetworkCallback networkCallback1 = new TestNetworkCallback();
final NetworkRequest networkrequest1 = getRestrictedRequestForWifiWithSubIds();
mCm.requestNetwork(networkrequest1, networkCallback1);
testFactory.expectRequestAdd();
testFactory.assertRequestCountEquals(1);
doReturn(false).when(mCarrierPrivilegeAuthenticator)
.isCarrierServiceUidForNetworkCapabilities(eq(Process.myUid()), any());
final CarrierPrivilegesLostListener carrierPrivilegesLostListener =
mService.getCarrierPrivilegesLostListener();
carrierPrivilegesLostListener.onCarrierPrivilegesLost(Process.myUid() + 1);
expectNoRequestChanged(testFactory);
handlerThread.quitSafely();
handlerThread.join();
}
@Test
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
public void testRequestNotRemoved_HasRestrictedNetworkPermission() throws Exception {
mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_GRANTED);
NetworkCapabilities filter = getRestrictedRequestForWifiWithSubIds().networkCapabilities;
final HandlerThread handlerThread = new HandlerThread("testRestrictedFactoryRequests");
handlerThread.start();
final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
mServiceContext, "testFactory", filter, mCsHandlerThread);
testFactory.register();
doReturn(true).when(mCarrierPrivilegeAuthenticator)
.isCarrierServiceUidForNetworkCapabilities(anyInt(), any());
final TestNetworkCallback networkCallback1 = new TestNetworkCallback();
final NetworkRequest networkrequest1 = getRestrictedRequestForWifiWithSubIds();
mCm.requestNetwork(networkrequest1, networkCallback1);
testFactory.expectRequestAdd();
testFactory.assertRequestCountEquals(1);
doReturn(false).when(mCarrierPrivilegeAuthenticator)
.isCarrierServiceUidForNetworkCapabilities(eq(Process.myUid()), any());
final CarrierPrivilegesLostListener carrierPrivilegesLostListener =
mService.getCarrierPrivilegesLostListener();
carrierPrivilegesLostListener.onCarrierPrivilegesLost(Process.myUid());
expectNoRequestChanged(testFactory);
handlerThread.quitSafely();
handlerThread.join();
}
@Test
public void testAllowedUids() throws Exception {
final int preferenceOrder =

View file

@ -20,6 +20,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.telephony.TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED;
import static com.android.server.connectivity.CarrierPrivilegeAuthenticator.CarrierPrivilegesLostListener;
import static com.android.server.connectivity.ConnectivityFlags.CARRIER_SERVICE_CHANGED_USE_CALLBACK;
import static org.junit.Assert.assertEquals;
@ -54,10 +55,12 @@ import com.android.networkstack.apishim.TelephonyManagerShimImpl;
import com.android.networkstack.apishim.common.TelephonyManagerShim.CarrierPrivilegesListenerShim;
import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
import com.android.server.connectivity.CarrierPrivilegeAuthenticator.Dependencies;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@ -67,6 +70,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
/**
* Tests for CarrierPrivilegeAuthenticatorTest.
@ -77,6 +81,9 @@ import java.util.Map;
@RunWith(DevSdkIgnoreRunner.class)
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class CarrierPrivilegeAuthenticatorTest {
@Rule
public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
private static final int SUBSCRIPTION_COUNT = 2;
private static final int TEST_SUBSCRIPTION_ID = 1;
@ -85,7 +92,9 @@ public class CarrierPrivilegeAuthenticatorTest {
@NonNull private final TelephonyManagerShimImpl mTelephonyManagerShim;
@NonNull private final PackageManager mPackageManager;
@NonNull private TestCarrierPrivilegeAuthenticator mCarrierPrivilegeAuthenticator;
@NonNull private final CarrierPrivilegesLostListener mListener;
private final int mCarrierConfigPkgUid = 12345;
private final boolean mUseCallbacks;
private final String mTestPkg = "com.android.server.connectivity.test";
private final BroadcastReceiver mMultiSimBroadcastReceiver;
@NonNull private final HandlerThread mHandlerThread;
@ -94,7 +103,8 @@ public class CarrierPrivilegeAuthenticatorTest {
TestCarrierPrivilegeAuthenticator(@NonNull final Context c,
@NonNull final Dependencies deps,
@NonNull final TelephonyManager t) {
super(c, deps, t, mTelephonyManagerShim);
super(c, deps, t, mTelephonyManagerShim, true /* requestRestrictedWifiEnabled */,
mListener);
}
@Override
protected int getSlotIndex(int subId) {
@ -119,7 +129,9 @@ public class CarrierPrivilegeAuthenticatorTest {
mTelephonyManager = mock(TelephonyManager.class);
mTelephonyManagerShim = mock(TelephonyManagerShimImpl.class);
mPackageManager = mock(PackageManager.class);
mListener = mock(CarrierPrivilegesLostListener.class);
mHandlerThread = new HandlerThread(CarrierPrivilegeAuthenticatorTest.class.getSimpleName());
mUseCallbacks = useCallbacks;
final Dependencies deps = mock(Dependencies.class);
doReturn(useCallbacks).when(deps).isFeatureEnabled(any() /* context */,
eq(CARRIER_SERVICE_CHANGED_USE_CALLBACK));
@ -219,6 +231,18 @@ public class CarrierPrivilegeAuthenticatorTest {
mCarrierConfigPkgUid + 1, nc));
}
@Test
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
public void testCarrierPrivilegesLostDueToCarrierServiceUpdate() throws Exception {
final CarrierPrivilegesListenerShim l = getCarrierPrivilegesListeners().get(0);
l.onCarrierServiceChanged(null, mCarrierConfigPkgUid);
l.onCarrierServiceChanged(null, mCarrierConfigPkgUid + 1);
if (mUseCallbacks) {
verify(mListener).onCarrierPrivilegesLost(eq(mCarrierConfigPkgUid));
}
}
@Test
public void testOnCarrierPrivilegesChanged() throws Exception {
final CarrierPrivilegesListenerShim listener = getCarrierPrivilegesListeners().get(0);
@ -264,4 +288,32 @@ public class CarrierPrivilegeAuthenticatorTest {
assertFalse(mCarrierPrivilegeAuthenticator.isCarrierServiceUidForNetworkCapabilities(
mCarrierConfigPkgUid, ncBuilder.build()));
}
@Test
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
public void testNetworkCapabilitiesContainOneSubId() throws Exception {
final CarrierPrivilegesListenerShim listener = getCarrierPrivilegesListeners().get(0);
listener.onCarrierServiceChanged(null, mCarrierConfigPkgUid);
final NetworkCapabilities.Builder ncBuilder = new NetworkCapabilities.Builder();
ncBuilder.addTransportType(TRANSPORT_WIFI);
ncBuilder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
ncBuilder.setSubscriptionIds(Set.of(0));
assertTrue(mCarrierPrivilegeAuthenticator.isCarrierServiceUidForNetworkCapabilities(
mCarrierConfigPkgUid, ncBuilder.build()));
}
@Test
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
public void testNetworkCapabilitiesContainTwoSubIds() throws Exception {
final CarrierPrivilegesListenerShim listener = getCarrierPrivilegesListeners().get(0);
listener.onCarrierServiceChanged(null, mCarrierConfigPkgUid);
final NetworkCapabilities.Builder ncBuilder = new NetworkCapabilities.Builder();
ncBuilder.addTransportType(TRANSPORT_WIFI);
ncBuilder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
ncBuilder.setSubscriptionIds(Set.of(0, 1));
assertFalse(mCarrierPrivilegeAuthenticator.isCarrierServiceUidForNetworkCapabilities(
mCarrierConfigPkgUid, ncBuilder.build()));
}
}

View file

@ -59,6 +59,7 @@ import com.android.net.module.util.ArrayTrackRecord
import com.android.networkstack.apishim.common.UnsupportedApiLevelException
import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker
import com.android.server.connectivity.CarrierPrivilegeAuthenticator
import com.android.server.connectivity.CarrierPrivilegeAuthenticator.CarrierPrivilegesLostListener
import com.android.server.connectivity.ClatCoordinator
import com.android.server.connectivity.ConnectivityFlags
import com.android.server.connectivity.MulticastRoutingCoordinatorService
@ -66,7 +67,6 @@ import com.android.server.connectivity.MultinetworkPolicyTracker
import com.android.server.connectivity.MultinetworkPolicyTrackerTestDependencies
import com.android.server.connectivity.NetworkRequestStateStatsMetrics
import com.android.server.connectivity.ProxyTracker
import com.android.server.connectivity.RoutingCoordinatorService
import com.android.testutils.visibleOnHandlerThread
import com.android.testutils.waitForIdle
import java.util.concurrent.Executors
@ -133,6 +133,7 @@ open class CSTest {
// permissions using static contexts.
val enabledFeatures = HashMap<String, Boolean>().also {
it[ConnectivityFlags.NO_REMATCH_ALL_REQUESTS_ON_REGISTER] = true
it[ConnectivityFlags.REQUEST_RESTRICTED_WIFI] = true
it[ConnectivityService.KEY_DESTROY_FROZEN_SOCKETS_VERSION] = true
it[ConnectivityService.DELAY_DESTROY_FROZEN_SOCKETS_VERSION] = true
it[ConnectivityService.ALLOW_SYSUI_CONNECTIVITY_REPORTS] = true
@ -200,7 +201,9 @@ open class CSTest {
override fun makeCarrierPrivilegeAuthenticator(
context: Context,
tm: TelephonyManager
tm: TelephonyManager,
requestRestrictedWifiEnabled: Boolean,
listener: CarrierPrivilegesLostListener
) = if (SdkLevel.isAtLeastT()) mock<CarrierPrivilegeAuthenticator>() else null
private inner class AOOKTDeps(c: Context) : AutomaticOnOffKeepaliveTracker.Dependencies(c) {