diff options
7 files changed, 292 insertions, 95 deletions
diff --git a/packages/Connectivity/framework/api/current.txt b/packages/Connectivity/framework/api/current.txt index ab5d969f5d3e..b7cdb56ef484 100644 --- a/packages/Connectivity/framework/api/current.txt +++ b/packages/Connectivity/framework/api/current.txt @@ -143,6 +143,7 @@ package android.net { public static class ConnectivityManager.NetworkCallback { ctor public ConnectivityManager.NetworkCallback(); + ctor public ConnectivityManager.NetworkCallback(int); method public void onAvailable(@NonNull android.net.Network); method public void onBlockedStatusChanged(@NonNull android.net.Network, boolean); method public void onCapabilitiesChanged(@NonNull android.net.Network, @NonNull android.net.NetworkCapabilities); @@ -150,6 +151,7 @@ package android.net { method public void onLosing(@NonNull android.net.Network, int); method public void onLost(@NonNull android.net.Network); method public void onUnavailable(); + field public static final int FLAG_INCLUDE_LOCATION_INFO = 1; // 0x1 } public static interface ConnectivityManager.OnNetworkActiveListener { diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java index 72928da15d32..e9107b67e4ef 100644 --- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java +++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java @@ -44,6 +44,7 @@ import android.net.SocketKeepalive.Callback; import android.net.TetheringManager.StartTetheringCallback; import android.net.TetheringManager.TetheringEventCallback; import android.net.TetheringManager.TetheringRequest; +import android.net.wifi.WifiNetworkSuggestion; import android.os.Binder; import android.os.Build; import android.os.Build.VERSION_CODES; @@ -1315,7 +1316,7 @@ public class ConnectivityManager { } /** - * Returns an array of {@link android.net.NetworkCapabilities} objects, representing + * Returns an array of {@link NetworkCapabilities} objects, representing * the Networks that applications run by the given user will use by default. * @hide */ @@ -1395,11 +1396,19 @@ public class ConnectivityManager { } /** - * Get the {@link android.net.NetworkCapabilities} for the given {@link Network}. This + * Get the {@link NetworkCapabilities} for the given {@link Network}. This * will return {@code null} if the network is unknown. * + * This will remove any location sensitive data in {@link TransportInfo} embedded in + * {@link NetworkCapabilities#getTransportInfo()}. Some transport info instances like + * {@link android.net.wifi.WifiInfo} contain location sensitive information. Retrieving + * this location sensitive information (subject to app's location permissions) will be + * noted by system. To include any location sensitive data in {@link TransportInfo}, + * use a {@link NetworkCallback} with + * {@link NetworkCallback#FLAG_INCLUDE_LOCATION_INFO} flag. + * * @param network The {@link Network} object identifying the network in question. - * @return The {@link android.net.NetworkCapabilities} for the network, or {@code null}. + * @return The {@link NetworkCapabilities} for the network, or {@code null}. */ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @Nullable @@ -3245,6 +3254,54 @@ public class ConnectivityManager { */ public static class NetworkCallback { /** + * No flags associated with this callback. + * @hide + */ + public static final int FLAG_NONE = 0; + /** + * Use this flag to include any location sensitive data in {@link NetworkCapabilities} sent + * via {@link #onCapabilitiesChanged(Network, NetworkCapabilities)}. + * <p> + * These include: + * <li> Some transport info instances (retrieved via + * {@link NetworkCapabilities#getTransportInfo()}) like {@link android.net.wifi.WifiInfo} + * contain location sensitive information. + * <li> OwnerUid (retrieved via {@link NetworkCapabilities#getOwnerUid()} is location + * sensitive for wifi suggestor apps (i.e using {@link WifiNetworkSuggestion}).</li> + * </p> + * <p> + * Note: + * <li> Retrieving this location sensitive information (subject to app's location + * permissions) will be noted by system. </li> + * <li> Without this flag any {@link NetworkCapabilities} provided via the callback does + * not include location sensitive info. + * </p> + */ + public static final int FLAG_INCLUDE_LOCATION_INFO = 1 << 0; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, prefix = "FLAG_", value = { + FLAG_NONE, + FLAG_INCLUDE_LOCATION_INFO + }) + public @interface Flag { } + + /** + * All the valid flags for error checking. + */ + private static final int VALID_FLAGS = FLAG_INCLUDE_LOCATION_INFO; + + public NetworkCallback() { + this(FLAG_NONE); + } + + public NetworkCallback(@Flag int flags) { + Preconditions.checkArgument((flags & VALID_FLAGS) == flags); + mFlags = flags; + } + + /** * Called when the framework connects to a new network to evaluate whether it satisfies this * request. If evaluation succeeds, this callback may be followed by an {@link #onAvailable} * callback. There is no guarantee that this new network will satisfy any requests, or that @@ -3381,7 +3438,7 @@ public class ConnectivityManager { * calling these methods while in a callback may return an outdated or even a null object. * * @param network The {@link Network} whose capabilities have changed. - * @param networkCapabilities The new {@link android.net.NetworkCapabilities} for this + * @param networkCapabilities The new {@link NetworkCapabilities} for this * network. */ public void onCapabilitiesChanged(@NonNull Network network, @@ -3450,6 +3507,7 @@ public class ConnectivityManager { public void onBlockedStatusChanged(@NonNull Network network, boolean blocked) {} private NetworkRequest networkRequest; + private final int mFlags; } /** @@ -3639,14 +3697,15 @@ public class ConnectivityManager { } Messenger messenger = new Messenger(handler); Binder binder = new Binder(); + final int callbackFlags = callback.mFlags; if (reqType == LISTEN) { request = mService.listenForNetwork( - need, messenger, binder, callingPackageName, + need, messenger, binder, callbackFlags, callingPackageName, getAttributionTag()); } else { request = mService.requestNetwork( need, reqType.ordinal(), messenger, timeoutMs, binder, legacyType, - callingPackageName, getAttributionTag()); + callbackFlags, callingPackageName, getAttributionTag()); } if (request != null) { sCallbacks.put(request, callback); @@ -3693,7 +3752,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}. + * Request a network to satisfy a set of {@link NetworkCapabilities}. * * <p>This method will attempt to find the best network that matches the passed * {@link NetworkRequest}, and to bring up one that does if none currently satisfies the @@ -3777,7 +3836,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}. + * Request a network to satisfy a set of {@link NetworkCapabilities}. * * This method behaves identically to {@link #requestNetwork(NetworkRequest, NetworkCallback)} * but runs all the callbacks on the passed Handler. @@ -3799,7 +3858,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited + * Request a network to satisfy a set of {@link NetworkCapabilities}, limited * by a timeout. * * This function behaves identically to the non-timed-out version @@ -3834,7 +3893,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited + * Request a network to satisfy a set of {@link NetworkCapabilities}, limited * by a timeout. * * This method behaves identically to @@ -3879,7 +3938,7 @@ public class ConnectivityManager { /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}. + * Request a network to satisfy a set of {@link NetworkCapabilities}. * * This function behaves identically to the version that takes a NetworkCallback, but instead * of {@link NetworkCallback} a {@link PendingIntent} is used. This means @@ -4911,7 +4970,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, but + * Request a network to satisfy a set of {@link NetworkCapabilities}, but * does not cause any networks to retain the NET_CAPABILITY_FOREGROUND capability. This can * be used to request that the system provide a network without causing the network to be * in the foreground. diff --git a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl index cd49258d1c47..f9393e315b83 100644 --- a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl +++ b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl @@ -143,7 +143,7 @@ interface IConnectivityManager NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, int reqType, in Messenger messenger, int timeoutSec, in IBinder binder, int legacy, - String callingPackageName, String callingAttributionTag); + int callbackFlags, String callingPackageName, String callingAttributionTag); NetworkRequest pendingRequestForNetwork(in NetworkCapabilities networkCapabilities, in PendingIntent operation, String callingPackageName, String callingAttributionTag); @@ -151,7 +151,7 @@ interface IConnectivityManager void releasePendingNetworkRequest(in PendingIntent operation); NetworkRequest listenForNetwork(in NetworkCapabilities networkCapabilities, - in Messenger messenger, in IBinder binder, String callingPackageName, + in Messenger messenger, in IBinder binder, int callbackFlags, String callingPackageName, String callingAttributionTag); void pendingListenForNetwork(in NetworkCapabilities networkCapabilities, diff --git a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java index c82cd3b4f357..7fe479474503 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java +++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java @@ -25,6 +25,7 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.ConnectivityManager.NetworkCallback; +import android.net.wifi.WifiNetworkSuggestion; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -1048,6 +1049,16 @@ public final class NetworkCapabilities implements Parcelable { * * Instances of NetworkCapabilities sent to apps without the appropriate permissions will have * this field cleared out. + * + * <p> + * This field will only be populated for VPN and wifi network suggestor apps (i.e using + * {@link WifiNetworkSuggestion}), and only for the network they own. + * In the case of wifi network suggestors apps, this field is also location sensitive, so the + * app needs to hold {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission. If the + * app targets SDK version greater than or equal to {@link Build.VERSION_CODES#S}, then they + * also need to use {@link NetworkCallback#FLAG_INCLUDE_LOCATION_INFO} to get the info in their + * callback. The app will be blamed for location access if this field is included. + * </p> */ public int getOwnerUid() { return mOwnerUid; diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index c363478e29b6..afa3bd1da6e7 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -85,6 +85,7 @@ import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager.ConnectivityReport; import android.net.ConnectivityDiagnosticsManager.DataStallReport; import android.net.ConnectivityManager; +import android.net.ConnectivityManager.NetworkCallback; import android.net.DataStallReportParcelable; import android.net.DnsResolverServiceManager; import android.net.ICaptivePortal; @@ -1098,7 +1099,8 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetworkRanker = new NetworkRanker(); final NetworkRequest defaultInternetRequest = createDefaultRequest(); mDefaultRequest = new NetworkRequestInfo( - defaultInternetRequest, null, new Binder(), + defaultInternetRequest, null, + new Binder(), NetworkCallback.FLAG_INCLUDE_LOCATION_INFO, null /* attributionTags */); mNetworkRequests.put(defaultInternetRequest, mDefaultRequest); mDefaultNetworkRequests.add(mDefaultRequest); @@ -1354,7 +1356,9 @@ public class ConnectivityService extends IConnectivityManager.Stub if (enable) { handleRegisterNetworkRequest(new NetworkRequestInfo( - networkRequest, null, new Binder(), + networkRequest, null, + new Binder(), + NetworkCallback.FLAG_INCLUDE_LOCATION_INFO, null /* attributionTags */)); } else { handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID, @@ -1715,8 +1719,8 @@ public class ConnectivityService extends IConnectivityManager.Stub result.put( nai.network, createWithLocationInfoSanitizedIfNecessaryWhenParceled( - nc, mDeps.getCallingUid(), callingPackageName, - callingAttributionTag)); + nc, false /* includeLocationSensitiveInfo */, + mDeps.getCallingUid(), callingPackageName, callingAttributionTag)); } } @@ -1729,7 +1733,9 @@ public class ConnectivityService extends IConnectivityManager.Stub result.put( network, createWithLocationInfoSanitizedIfNecessaryWhenParceled( - nc, mDeps.getCallingUid(), callingPackageName, + nc, + false /* includeLocationSensitiveInfo */, + mDeps.getCallingUid(), callingPackageName, callingAttributionTag)); } } @@ -1811,6 +1817,7 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceAccessPermission(); return createWithLocationInfoSanitizedIfNecessaryWhenParceled( getNetworkCapabilitiesInternal(network), + false /* includeLocationSensitiveInfo */, mDeps.getCallingUid(), callingPackageName, callingAttributionTag); } @@ -1844,8 +1851,8 @@ public class ConnectivityService extends IConnectivityManager.Stub @VisibleForTesting @Nullable NetworkCapabilities createWithLocationInfoSanitizedIfNecessaryWhenParceled( - @Nullable NetworkCapabilities nc, int callerUid, @NonNull String callerPkgName, - @Nullable String callingAttributionTag) { + @Nullable NetworkCapabilities nc, boolean includeLocationSensitiveInfo, + int callerUid, @NonNull String callerPkgName, @Nullable String callingAttributionTag) { if (nc == null) { return null; } @@ -1853,7 +1860,9 @@ public class ConnectivityService extends IConnectivityManager.Stub final NetworkCapabilities newNc; // Avoid doing location permission check if the transport info has no location sensitive // data. - if (nc.getTransportInfo() != null && nc.getTransportInfo().hasLocationSensitiveFields()) { + if (includeLocationSensitiveInfo + && nc.getTransportInfo() != null + && nc.getTransportInfo().hasLocationSensitiveFields()) { hasLocationPermission = hasLocationPermission(callerUid, callerPkgName, callingAttributionTag); newNc = new NetworkCapabilities(nc, hasLocationPermission); @@ -1870,6 +1879,16 @@ public class ConnectivityService extends IConnectivityManager.Stub // Owner UIDs already checked above. No need to re-check. return newNc; } + // If the caller does not want location sensitive data & target SDK >= S, then mask info. + // Else include the owner UID iff the caller has location permission to provide backwards + // compatibility for older apps. + if (!includeLocationSensitiveInfo + && isTargetSdkAtleast( + Build.VERSION_CODES.S, callerUid, callerPkgName)) { + newNc.setOwnerUid(INVALID_UID); + return newNc; + } + if (hasLocationPermission == null) { // Location permission not checked yet, check now for masking owner UID. hasLocationPermission = @@ -5208,6 +5227,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private final IBinder mBinder; final int mPid; final int mUid; + final @NetworkCallback.Flag int mCallbackFlags; @Nullable final String mCallingAttributionTag; // In order to preserve the mapping of NetworkRequest-to-callback when apps register @@ -5255,17 +5275,26 @@ public class ConnectivityService extends IConnectivityManager.Stub mPid = getCallingPid(); mUid = mDeps.getCallingUid(); mNetworkRequestCounter.incrementCountOrThrow(mUid); + /** + * Location sensitive data not included in pending intent. Only included in + * {@link NetworkCallback}. + */ + mCallbackFlags = NetworkCallback.FLAG_NONE; mCallingAttributionTag = callingAttributionTag; } NetworkRequestInfo(@NonNull final NetworkRequest r, @Nullable final Messenger m, - @Nullable final IBinder binder, @Nullable String callingAttributionTag) { - this(Collections.singletonList(r), r, m, binder, callingAttributionTag); + @Nullable final IBinder binder, + @NetworkCallback.Flag int callbackFlags, + @Nullable String callingAttributionTag) { + this(Collections.singletonList(r), r, m, binder, callbackFlags, callingAttributionTag); } NetworkRequestInfo(@NonNull final List<NetworkRequest> r, @NonNull final NetworkRequest requestForCallback, @Nullable final Messenger m, - @Nullable final IBinder binder, @Nullable String callingAttributionTag) { + @Nullable final IBinder binder, + @NetworkCallback.Flag int callbackFlags, + @Nullable String callingAttributionTag) { super(); ensureAllNetworkRequestsHaveType(r); mRequests = initializeRequests(r); @@ -5276,6 +5305,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mUid = mDeps.getCallingUid(); mPendingIntent = null; mNetworkRequestCounter.incrementCountOrThrow(mUid); + mCallbackFlags = callbackFlags; mCallingAttributionTag = callingAttributionTag; try { @@ -5317,6 +5347,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mUid = nri.mUid; mPendingIntent = nri.mPendingIntent; mNetworkRequestCounter.incrementCountOrThrow(mUid); + mCallbackFlags = nri.mCallbackFlags; mCallingAttributionTag = nri.mCallingAttributionTag; } @@ -5366,7 +5397,8 @@ public class ConnectivityService extends IConnectivityManager.Stub + " callback request Id: " + mNetworkRequestForCallback.requestId + " " + mRequests - + (mPendingIntent == null ? "" : " to trigger " + mPendingIntent); + + (mPendingIntent == null ? "" : " to trigger " + mPendingIntent) + + "callback flags: " + mCallbackFlags; } } @@ -5450,13 +5482,13 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private boolean checkUnsupportedStartingFrom(int version, String callingPackageName) { - final UserHandle user = UserHandle.getUserHandleForUid(mDeps.getCallingUid()); + private boolean isTargetSdkAtleast(int version, int callingUid, + @NonNull String callingPackageName) { + final UserHandle user = UserHandle.getUserHandleForUid(callingUid); final PackageManager pm = mContext.createContextAsUser(user, 0 /* flags */).getPackageManager(); try { - final int callingVersion = pm.getApplicationInfo( - callingPackageName, 0 /* flags */).targetSdkVersion; + final int callingVersion = pm.getTargetSdkVersion(callingPackageName); if (callingVersion < version) return false; } catch (PackageManager.NameNotFoundException e) { } return true; @@ -5465,10 +5497,11 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities, int reqTypeInt, Messenger messenger, int timeoutMs, IBinder binder, - int legacyType, @NonNull String callingPackageName, + int legacyType, int callbackFlags, @NonNull String callingPackageName, @Nullable String callingAttributionTag) { if (legacyType != TYPE_NONE && !checkNetworkStackPermission()) { - if (checkUnsupportedStartingFrom(Build.VERSION_CODES.M, callingPackageName)) { + if (isTargetSdkAtleast(Build.VERSION_CODES.M, mDeps.getCallingUid(), + callingPackageName)) { throw new SecurityException("Insufficient permissions to specify legacy type"); } } @@ -5530,7 +5563,7 @@ public class ConnectivityService extends IConnectivityManager.Stub final NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType, nextNetworkRequestId(), reqType); final NetworkRequestInfo nri = getNriToRegister( - networkRequest, messenger, binder, callingAttributionTag); + networkRequest, messenger, binder, callbackFlags, callingAttributionTag); if (DBG) log("requestNetwork for " + nri); // For TRACK_SYSTEM_DEFAULT callbacks, the capabilities have been modified since they were @@ -5565,6 +5598,7 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private NetworkRequestInfo getNriToRegister(@NonNull final NetworkRequest nr, @Nullable final Messenger msgr, @Nullable final IBinder binder, + @NetworkCallback.Flag int callbackFlags, @Nullable String callingAttributionTag) { final List<NetworkRequest> requests; if (NetworkRequest.Type.TRACK_DEFAULT == nr.type) { @@ -5573,7 +5607,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } else { requests = Collections.singletonList(nr); } - return new NetworkRequestInfo(requests, nr, msgr, binder, callingAttributionTag); + return new NetworkRequestInfo( + requests, nr, msgr, binder, callbackFlags, callingAttributionTag); } private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities, @@ -5699,8 +5734,9 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities, - Messenger messenger, IBinder binder, @NonNull String callingPackageName, - @Nullable String callingAttributionTag) { + Messenger messenger, IBinder binder, + @NetworkCallback.Flag int callbackFlags, + @NonNull String callingPackageName, @NonNull String callingAttributionTag) { final int callingUid = mDeps.getCallingUid(); if (!hasWifiNetworkListenPermission(networkCapabilities)) { enforceAccessPermission(); @@ -5721,7 +5757,8 @@ public class ConnectivityService extends IConnectivityManager.Stub NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(), NetworkRequest.Type.LISTEN); NetworkRequestInfo nri = - new NetworkRequestInfo(networkRequest, messenger, binder, callingAttributionTag); + new NetworkRequestInfo(networkRequest, messenger, binder, callbackFlags, + callingAttributionTag); if (VDBG) log("listenForNetwork for " + nri); mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri)); @@ -7049,6 +7086,8 @@ public class ConnectivityService extends IConnectivityManager.Stub if (notificationType != ConnectivityManager.CALLBACK_UNAVAIL) { putParcelable(bundle, networkAgent.network); } + final boolean includeLocationSensitiveInfo = + (nri.mCallbackFlags & NetworkCallback.FLAG_INCLUDE_LOCATION_INFO) != 0; switch (notificationType) { case ConnectivityManager.CALLBACK_AVAILABLE: { final NetworkCapabilities nc = @@ -7057,7 +7096,8 @@ public class ConnectivityService extends IConnectivityManager.Stub putParcelable( bundle, createWithLocationInfoSanitizedIfNecessaryWhenParceled( - nc, nri.mUid, nrForCallback.getRequestorPackageName(), + nc, includeLocationSensitiveInfo, nri.mUid, + nrForCallback.getRequestorPackageName(), nri.mCallingAttributionTag)); putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions( networkAgent.linkProperties, nri.mPid, nri.mUid)); @@ -7077,7 +7117,8 @@ public class ConnectivityService extends IConnectivityManager.Stub putParcelable( bundle, createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, nri.mUid, nrForCallback.getRequestorPackageName(), + netCap, includeLocationSensitiveInfo, nri.mUid, + nrForCallback.getRequestorPackageName(), nri.mCallingAttributionTag)); break; } diff --git a/tests/net/java/android/net/ConnectivityManagerTest.java b/tests/net/java/android/net/ConnectivityManagerTest.java index 098b029b75e6..6fc605e269fe 100644 --- a/tests/net/java/android/net/ConnectivityManagerTest.java +++ b/tests/net/java/android/net/ConnectivityManagerTest.java @@ -220,7 +220,7 @@ public class ConnectivityManagerTest { // register callback when(mService.requestNetwork(any(), anyInt(), captor.capture(), anyInt(), any(), anyInt(), - any(), nullable(String.class))).thenReturn(request); + anyInt(), any(), nullable(String.class))).thenReturn(request); manager.requestNetwork(request, callback, handler); // callback triggers @@ -248,7 +248,7 @@ public class ConnectivityManagerTest { // register callback when(mService.requestNetwork(any(), anyInt(), captor.capture(), anyInt(), any(), anyInt(), - any(), nullable(String.class))).thenReturn(req1); + anyInt(), any(), nullable(String.class))).thenReturn(req1); manager.requestNetwork(req1, callback, handler); // callback triggers @@ -266,7 +266,7 @@ public class ConnectivityManagerTest { // callback can be registered again when(mService.requestNetwork(any(), anyInt(), captor.capture(), anyInt(), any(), anyInt(), - any(), nullable(String.class))).thenReturn(req2); + anyInt(), any(), nullable(String.class))).thenReturn(req2); manager.requestNetwork(req2, callback, handler); // callback triggers @@ -289,8 +289,8 @@ public class ConnectivityManagerTest { info.targetSdkVersion = VERSION_CODES.N_MR1 + 1; when(mCtx.getApplicationInfo()).thenReturn(info); - when(mService.requestNetwork(any(), anyInt(), any(), anyInt(), any(), anyInt(), any(), - nullable(String.class))).thenReturn(request); + when(mService.requestNetwork(any(), anyInt(), any(), anyInt(), any(), anyInt(), anyInt(), + any(), nullable(String.class))).thenReturn(request); Handler handler = new Handler(Looper.getMainLooper()); manager.requestNetwork(request, callback, handler); @@ -358,34 +358,34 @@ public class ConnectivityManagerTest { manager.requestNetwork(request, callback); verify(mService).requestNetwork(eq(request.networkCapabilities), - eq(REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), + eq(REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(), eq(testPkgName), eq(testAttributionTag)); reset(mService); // Verify that register network callback does not calls requestNetwork at all. manager.registerNetworkCallback(request, callback); - verify(mService, never()).requestNetwork(any(), anyInt(), any(), anyInt(), any(), + verify(mService, never()).requestNetwork(any(), anyInt(), any(), anyInt(), any(), anyInt(), anyInt(), any(), any()); - verify(mService).listenForNetwork(eq(request.networkCapabilities), any(), any(), + verify(mService).listenForNetwork(eq(request.networkCapabilities), any(), any(), anyInt(), eq(testPkgName), eq(testAttributionTag)); reset(mService); manager.registerDefaultNetworkCallback(callback); verify(mService).requestNetwork(eq(null), - eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), + eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(), eq(testPkgName), eq(testAttributionTag)); reset(mService); Handler handler = new Handler(ConnectivityThread.getInstanceLooper()); manager.requestBackgroundNetwork(request, handler, callback); verify(mService).requestNetwork(eq(request.networkCapabilities), - eq(BACKGROUND_REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), + eq(BACKGROUND_REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(), eq(testPkgName), eq(testAttributionTag)); reset(mService); manager.registerSystemDefaultNetworkCallback(callback, handler); verify(mService).requestNetwork(eq(null), - eq(TRACK_SYSTEM_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), + eq(TRACK_SYSTEM_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(), eq(testPkgName), eq(testAttributionTag)); reset(mService); } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index a6b20fb73e25..2c8c8a6409ea 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -1454,6 +1454,8 @@ public class ConnectivityServiceTest { applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q; when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) .thenReturn(applicationInfo); + when(mPackageManager.getTargetSdkVersion(anyString())) + .thenReturn(applicationInfo.targetSdkVersion); when(mSystemConfigManager.getSystemPermissionUids(anyString())).thenReturn(new int[0]); // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not. @@ -3749,8 +3751,8 @@ public class ConnectivityServiceTest { networkCapabilities.addTransportType(TRANSPORT_WIFI) .setNetworkSpecifier(new MatchAllNetworkSpecifier()); mService.requestNetwork(networkCapabilities, NetworkRequest.Type.REQUEST.ordinal(), - null, 0, null, ConnectivityManager.TYPE_WIFI, mContext.getPackageName(), - getAttributionTag()); + null, 0, null, ConnectivityManager.TYPE_WIFI, NetworkCallback.FLAG_NONE, + mContext.getPackageName(), getAttributionTag()); }); class NonParcelableSpecifier extends NetworkSpecifier { @@ -8756,6 +8758,7 @@ public class ConnectivityServiceTest { applicationInfo.targetSdkVersion = targetSdk; when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) .thenReturn(applicationInfo); + when(mPackageManager.getTargetSdkVersion(any())).thenReturn(targetSdk); when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle); @@ -8770,102 +8773,183 @@ public class ConnectivityServiceTest { } } - private int getOwnerUidNetCapsForCallerPermission(int ownerUid, int callerUid) { + private int getOwnerUidNetCapsPermission(int ownerUid, int callerUid, + boolean includeLocationSensitiveInfo) { final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid); return mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, callerUid, mContext.getPackageName(), getAttributionTag()).getOwnerUid(); + netCap, includeLocationSensitiveInfo, callerUid, + mContext.getPackageName(), getAttributionTag()) + .getOwnerUid(); } - private void verifyWifiInfoCopyNetCapsForCallerPermission( - int callerUid, boolean shouldMakeCopyWithLocationSensitiveFieldsParcelable) { + private void verifyWifiInfoCopyNetCapsPermission( + int callerUid, boolean includeLocationSensitiveInfo, + boolean shouldMakeCopyWithLocationSensitiveFieldsParcelable) { final WifiInfo wifiInfo = mock(WifiInfo.class); when(wifiInfo.hasLocationSensitiveFields()).thenReturn(true); final NetworkCapabilities netCap = new NetworkCapabilities().setTransportInfo(wifiInfo); mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, callerUid, mContext.getPackageName(), getAttributionTag()); + netCap, includeLocationSensitiveInfo, callerUid, + mContext.getPackageName(), getAttributionTag()); verify(wifiInfo).makeCopy(eq(shouldMakeCopyWithLocationSensitiveFieldsParcelable)); } + private void verifyOwnerUidAndWifiInfoNetCapsPermission( + boolean shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag, + boolean shouldInclLocationSensitiveOwnerUidWithIncludeFlag, + boolean shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag, + boolean shouldInclLocationSensitiveWifiInfoWithIncludeFlag) { + final int myUid = Process.myUid(); + + final int expectedOwnerUidWithoutIncludeFlag = + shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag + ? Process.myUid() : INVALID_UID; + assertEquals(expectedOwnerUidWithoutIncludeFlag, getOwnerUidNetCapsPermission( + myUid, myUid, false /* includeLocationSensitiveInfo */)); + + final int expectedOwnerUidWithIncludeFlag = + shouldInclLocationSensitiveOwnerUidWithIncludeFlag ? myUid : INVALID_UID; + assertEquals(expectedOwnerUidWithIncludeFlag, getOwnerUidNetCapsPermission( + myUid, myUid, true /* includeLocationSensitiveInfo */)); + + verifyWifiInfoCopyNetCapsPermission(myUid, + false, /* includeLocationSensitiveInfo */ + shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag); + + verifyWifiInfoCopyNetCapsPermission(myUid, + true, /* includeLocationSensitiveInfo */ + shouldInclLocationSensitiveWifiInfoWithIncludeFlag); + + } + @Test - public void testCreateForCallerWithLocationInfoSanitizedWithFineLocationAfterQ() + public void testCreateWithLocationInfoSanitizedWithFineLocationAfterQ() throws Exception { setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); - final int myUid = Process.myUid(); - assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); + verifyOwnerUidAndWifiInfoNetCapsPermission( + // Ensure that we include owner uid even if the request asks to remove it since the + // app has necessary permissions and targetSdk < S. + true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ + true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ + false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + // Ensure that we remove location info if the request asks to remove it even if the + // app has necessary permissions. + true /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + ); + } + + @Test + public void testCreateWithLocationInfoSanitizedWithFineLocationPreSWithAndWithoutCallbackFlag() + throws Exception { + setupLocationPermissions(Build.VERSION_CODES.R, true, AppOpsManager.OPSTR_FINE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION); - verifyWifiInfoCopyNetCapsForCallerPermission(myUid, - true /* shouldMakeCopyWithLocationSensitiveFieldsParcelable */); + verifyOwnerUidAndWifiInfoNetCapsPermission( + // Ensure that we include owner uid even if the request asks to remove it since the + // app has necessary permissions and targetSdk < S. + true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ + true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ + false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + // Ensure that we remove location info if the request asks to remove it even if the + // app has necessary permissions. + true /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + ); } @Test - public void testCreateForCallerWithLocationInfoSanitizedWithCoarseLocationPreQ() + public void + testCreateWithLocationInfoSanitizedWithFineLocationAfterSWithAndWithoutCallbackFlag() + throws Exception { + setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION); + + verifyOwnerUidAndWifiInfoNetCapsPermission( + // Ensure that we owner UID if the request asks us to remove it even if the app + // has necessary permissions since targetSdk >= S. + false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ + true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ + false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + // Ensure that we remove location info if the request asks to remove it even if the + // app has necessary permissions. + true /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + ); + } + + @Test + public void testCreateWithLocationInfoSanitizedWithCoarseLocationPreQ() throws Exception { setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION); - final int myUid = Process.myUid(); - assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); - - verifyWifiInfoCopyNetCapsForCallerPermission(myUid, - true /* shouldMakeCopyWithLocationSensitiveFieldsParcelable */); + verifyOwnerUidAndWifiInfoNetCapsPermission( + // Ensure that we owner UID if the request asks us to remove it even if the app + // has necessary permissions since targetSdk >= S. + true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ + true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ + false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + // Ensure that we remove location info if the request asks to remove it even if the + // app has necessary permissions. + true /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + ); } @Test - public void testCreateForCallerWithLocationInfoSanitizedLocationOff() throws Exception { + public void testCreateWithLocationInfoSanitizedLocationOff() throws Exception { // Test that even with fine location permission, and UIDs matching, the UID is sanitized. setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); - final int myUid = Process.myUid(); - assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); - - verifyWifiInfoCopyNetCapsForCallerPermission(myUid, - false/* shouldMakeCopyWithLocationSensitiveFieldsParcelable */); + verifyOwnerUidAndWifiInfoNetCapsPermission( + false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ + false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ + false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + false /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + ); } @Test - public void testCreateForCallerWithLocationInfoSanitizedWrongUid() throws Exception { + public void testCreateWithLocationInfoSanitizedWrongUid() throws Exception { // Test that even with fine location permission, not being the owner leads to sanitization. setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); final int myUid = Process.myUid(); - assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid + 1, myUid)); - - verifyWifiInfoCopyNetCapsForCallerPermission(myUid, - true /* shouldMakeCopyWithLocationSensitiveFieldsParcelable */); + assertEquals(Process.INVALID_UID, + getOwnerUidNetCapsPermission(myUid + 1, myUid, + true /* includeLocationSensitiveInfo */)); } @Test - public void testCreateForCallerWithLocationInfoSanitizedWithCoarseLocationAfterQ() + public void testCreateWithLocationInfoSanitizedWithCoarseLocationAfterQ() throws Exception { // Test that not having fine location permission leads to sanitization. setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION); - // Test that without the location permission, the owner field is sanitized. - final int myUid = Process.myUid(); - assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); - - verifyWifiInfoCopyNetCapsForCallerPermission(myUid, - false/* shouldMakeCopyWithLocationSensitiveFieldsParcelable */); + verifyOwnerUidAndWifiInfoNetCapsPermission( + false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ + false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ + false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + false /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + ); } @Test - public void testCreateForCallerWithLocationInfoSanitizedWithoutLocationPermission() + public void testCreateWithLocationInfoSanitizedWithoutLocationPermission() throws Exception { + // Test that not having fine location permission leads to sanitization. setupLocationPermissions(Build.VERSION_CODES.Q, true, null /* op */, null /* perm */); - // Test that without the location permission, the owner field is sanitized. - final int myUid = Process.myUid(); - assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); - - verifyWifiInfoCopyNetCapsForCallerPermission(myUid, - false/* shouldMakeCopyWithLocationSensitiveFieldsParcelable */); + verifyOwnerUidAndWifiInfoNetCapsPermission( + false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ + false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ + false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + false /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + ); } private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType) @@ -9456,8 +9540,8 @@ public class ConnectivityServiceTest { assertThrows("Expect throws for invalid request type " + reqTypeInt, IllegalArgumentException.class, () -> mService.requestNetwork(nc, reqTypeInt, null, 0, null, - ConnectivityManager.TYPE_NONE, mContext.getPackageName(), - getAttributionTag()) + ConnectivityManager.TYPE_NONE, NetworkCallback.FLAG_NONE, + mContext.getPackageName(), getAttributionTag()) ); } } |