Loading core/api/system-current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -6235,6 +6235,7 @@ package android.net { } public final class NetworkCapabilities implements android.os.Parcelable { ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, boolean); method @NonNull public int[] getAdministratorUids(); method @Nullable public String getSsid(); method @NonNull public int[] getTransportTypes(); Loading Loading @@ -6457,6 +6458,11 @@ package android.net { field public static final int TAG_SYSTEM_IMPERSONATION_RANGE_START = -256; // 0xffffff00 } public interface TransportInfo { method public default boolean hasLocationSensitiveFields(); method @NonNull public default android.net.TransportInfo makeCopy(boolean); } public abstract class Uri implements java.lang.Comparable<android.net.Uri> android.os.Parcelable { method @NonNull public String toSafeString(); } Loading core/java/android/net/NetworkAgent.java +5 −2 Original line number Diff line number Diff line Loading @@ -408,7 +408,8 @@ public abstract class NetworkAgent { throw new IllegalArgumentException(); } mInitialConfiguration = new InitialConfiguration(context, new NetworkCapabilities(nc), mInitialConfiguration = new InitialConfiguration(context, new NetworkCapabilities(nc, /* parcelLocationSensitiveFields */ true), new LinkProperties(lp), score, config, ni); } Loading Loading @@ -818,7 +819,9 @@ public abstract class NetworkAgent { Objects.requireNonNull(networkCapabilities); mBandwidthUpdatePending.set(false); mLastBwRefreshTime = System.currentTimeMillis(); final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities, /* parcelLocationSensitiveFields */ true); queueOrSendMessage(reg -> reg.sendNetworkCapabilities(nc)); } Loading core/java/android/net/NetworkCapabilities.java +34 −1 Original line number Diff line number Diff line Loading @@ -76,12 +76,33 @@ public final class NetworkCapabilities implements Parcelable { */ private String mRequestorPackageName; /** * Indicates whether parceling should preserve fields that are set based on permissions of * the process receiving the {@link NetworkCapabilities}. */ private final boolean mParcelLocationSensitiveFields; public NetworkCapabilities() { mParcelLocationSensitiveFields = false; clearAll(); mNetworkCapabilities = DEFAULT_CAPABILITIES; } public NetworkCapabilities(NetworkCapabilities nc) { this(nc, false /* parcelLocationSensitiveFields */); } /** * Make a copy of NetworkCapabilities. * * @param nc Original NetworkCapabilities * @param parcelLocationSensitiveFields Whether to parcel location sensitive data or not. * @hide */ @SystemApi public NetworkCapabilities( @Nullable NetworkCapabilities nc, boolean parcelLocationSensitiveFields) { mParcelLocationSensitiveFields = parcelLocationSensitiveFields; if (nc != null) { set(nc); } Loading @@ -93,6 +114,12 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public void clearAll() { // Ensures that the internal copies maintained by the connectivity stack does not set // this bit. if (mParcelLocationSensitiveFields) { throw new UnsupportedOperationException( "Cannot clear NetworkCapabilities when parcelLocationSensitiveFields is set"); } mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0; mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; mNetworkSpecifier = null; Loading @@ -109,6 +136,8 @@ public final class NetworkCapabilities implements Parcelable { /** * Set all contents of this object to the contents of a NetworkCapabilities. * * @param nc Original NetworkCapabilities * @hide */ public void set(@NonNull NetworkCapabilities nc) { Loading @@ -117,7 +146,11 @@ public final class NetworkCapabilities implements Parcelable { mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps; mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps; mNetworkSpecifier = nc.mNetworkSpecifier; mTransportInfo = nc.mTransportInfo; if (nc.getTransportInfo() != null) { setTransportInfo(nc.getTransportInfo().makeCopy(mParcelLocationSensitiveFields)); } else { setTransportInfo(null); } mSignalStrength = nc.mSignalStrength; setUids(nc.mUids); // Will make the defensive copy setAdministratorUids(nc.getAdministratorUids()); Loading core/java/android/net/TransportInfo.java +38 −0 Original line number Diff line number Diff line Loading @@ -16,10 +16,48 @@ package android.net; import android.annotation.NonNull; import android.annotation.SystemApi; /** * A container for transport-specific capabilities which is returned by * {@link NetworkCapabilities#getTransportInfo()}. Specific networks * may provide concrete implementations of this interface. * @see android.net.wifi.aware.WifiAwareNetworkInfo * @see android.net.wifi.WifiInfo */ public interface TransportInfo { /** * Create a copy of a {@link TransportInfo} that will preserve location sensitive fields that * were set based on the permissions of the process that originally received it. * * <p>By default {@link TransportInfo} does not preserve such fields during parceling, as * they should not be shared outside of the process that receives them without appropriate * checks. * * @param parcelLocationSensitiveFields Whether the location sensitive fields should be kept * when parceling * @return Copy of this instance. * @hide */ @SystemApi @NonNull default TransportInfo makeCopy(boolean parcelLocationSensitiveFields) { return this; } /** * Returns whether this TransportInfo type has location sensitive fields or not (helps * to determine whether to perform a location permission check or not before sending to * apps). * * @return {@code true} if this instance contains location sensitive info, {@code false} * otherwise. * @hide */ @SystemApi default boolean hasLocationSensitiveFields() { return false; } } services/core/java/com/android/server/ConnectivityService.java +37 −21 Original line number Diff line number Diff line Loading @@ -1569,7 +1569,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (nc != null) { result.put( nai.network, maybeSanitizeLocationInfoForCaller( createWithLocationInfoSanitizedIfNecessaryWhenParceled( nc, mDeps.getCallingUid(), callingPackageName)); } Loading @@ -1579,7 +1579,9 @@ public class ConnectivityService extends IConnectivityManager.Stub for (Network network : networks) { nc = getNetworkCapabilitiesInternal(network); if (nc != null) { result.put(network, maybeSanitizeLocationInfoForCaller( result.put( network, createWithLocationInfoSanitizedIfNecessaryWhenParceled( nc, mDeps.getCallingUid(), callingPackageName)); } } Loading Loading @@ -1661,7 +1663,7 @@ public class ConnectivityService extends IConnectivityManager.Stub public NetworkCapabilities getNetworkCapabilities(Network network, String callingPackageName) { mAppOpsManager.checkPackage(mDeps.getCallingUid(), callingPackageName); enforceAccessPermission(); return maybeSanitizeLocationInfoForCaller( return createWithLocationInfoSanitizedIfNecessaryWhenParceled( getNetworkCapabilitiesInternal(network), mDeps.getCallingUid(), callingPackageName); } Loading @@ -1682,37 +1684,51 @@ public class ConnectivityService extends IConnectivityManager.Stub return newNc; } private boolean hasLocationPermission(int callerUid, @NonNull String callerPkgName) { final long token = Binder.clearCallingIdentity(); try { return mLocationPermissionChecker.checkLocationPermission( callerPkgName, null /* featureId */, callerUid, null /* message */); } finally { Binder.restoreCallingIdentity(token); } } @VisibleForTesting @Nullable NetworkCapabilities maybeSanitizeLocationInfoForCaller( NetworkCapabilities createWithLocationInfoSanitizedIfNecessaryWhenParceled( @Nullable NetworkCapabilities nc, int callerUid, @NonNull String callerPkgName) { if (nc == null) { return null; } final NetworkCapabilities newNc = new NetworkCapabilities(nc); if (callerUid != newNc.getOwnerUid()) { Boolean hasLocationPermission = null; final NetworkCapabilities newNc; // Avoid doing location permission check if the transport info has no location sensitive // data. if (nc.getTransportInfo() != null && nc.getTransportInfo().hasLocationSensitiveFields()) { hasLocationPermission = hasLocationPermission(callerUid, callerPkgName); newNc = new NetworkCapabilities(nc, hasLocationPermission); } else { newNc = new NetworkCapabilities(nc, false /* parcelLocationSensitiveFields */); } // Reset owner uid if not destined for the owner app. if (callerUid != nc.getOwnerUid()) { newNc.setOwnerUid(INVALID_UID); return newNc; } // Allow VPNs to see ownership of their own VPN networks - not location sensitive. if (nc.hasTransport(TRANSPORT_VPN)) { // Owner UIDs already checked above. No need to re-check. return newNc; } final long token = Binder.clearCallingIdentity(); try { if (!mLocationPermissionChecker.checkLocationPermission( callerPkgName, null /* featureId */, callerUid, null /* message */)) { // Caller does not have the requisite location permissions. Reset the // owner's UID in the NetworkCapabilities. newNc.setOwnerUid(INVALID_UID); if (hasLocationPermission == null) { // Location permission not checked yet, check now for masking owner UID. hasLocationPermission = hasLocationPermission(callerUid, callerPkgName); } } finally { Binder.restoreCallingIdentity(token); // Reset owner uid if the app has no location permission. if (!hasLocationPermission) { newNc.setOwnerUid(INVALID_UID); } return newNc; } Loading Loading @@ -6976,7 +6992,7 @@ public class ConnectivityService extends IConnectivityManager.Stub networkAgent.networkCapabilities, nri.mPid, nri.mUid); putParcelable( bundle, maybeSanitizeLocationInfoForCaller( createWithLocationInfoSanitizedIfNecessaryWhenParceled( nc, nri.mUid, nri.request.getRequestorPackageName())); putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions( networkAgent.linkProperties, nri.mPid, nri.mUid)); Loading @@ -6995,7 +7011,7 @@ public class ConnectivityService extends IConnectivityManager.Stub networkAgent.networkCapabilities, nri.mPid, nri.mUid); putParcelable( bundle, maybeSanitizeLocationInfoForCaller( createWithLocationInfoSanitizedIfNecessaryWhenParceled( netCap, nri.mUid, nri.request.getRequestorPackageName())); break; } Loading Loading
core/api/system-current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -6235,6 +6235,7 @@ package android.net { } public final class NetworkCapabilities implements android.os.Parcelable { ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, boolean); method @NonNull public int[] getAdministratorUids(); method @Nullable public String getSsid(); method @NonNull public int[] getTransportTypes(); Loading Loading @@ -6457,6 +6458,11 @@ package android.net { field public static final int TAG_SYSTEM_IMPERSONATION_RANGE_START = -256; // 0xffffff00 } public interface TransportInfo { method public default boolean hasLocationSensitiveFields(); method @NonNull public default android.net.TransportInfo makeCopy(boolean); } public abstract class Uri implements java.lang.Comparable<android.net.Uri> android.os.Parcelable { method @NonNull public String toSafeString(); } Loading
core/java/android/net/NetworkAgent.java +5 −2 Original line number Diff line number Diff line Loading @@ -408,7 +408,8 @@ public abstract class NetworkAgent { throw new IllegalArgumentException(); } mInitialConfiguration = new InitialConfiguration(context, new NetworkCapabilities(nc), mInitialConfiguration = new InitialConfiguration(context, new NetworkCapabilities(nc, /* parcelLocationSensitiveFields */ true), new LinkProperties(lp), score, config, ni); } Loading Loading @@ -818,7 +819,9 @@ public abstract class NetworkAgent { Objects.requireNonNull(networkCapabilities); mBandwidthUpdatePending.set(false); mLastBwRefreshTime = System.currentTimeMillis(); final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities, /* parcelLocationSensitiveFields */ true); queueOrSendMessage(reg -> reg.sendNetworkCapabilities(nc)); } Loading
core/java/android/net/NetworkCapabilities.java +34 −1 Original line number Diff line number Diff line Loading @@ -76,12 +76,33 @@ public final class NetworkCapabilities implements Parcelable { */ private String mRequestorPackageName; /** * Indicates whether parceling should preserve fields that are set based on permissions of * the process receiving the {@link NetworkCapabilities}. */ private final boolean mParcelLocationSensitiveFields; public NetworkCapabilities() { mParcelLocationSensitiveFields = false; clearAll(); mNetworkCapabilities = DEFAULT_CAPABILITIES; } public NetworkCapabilities(NetworkCapabilities nc) { this(nc, false /* parcelLocationSensitiveFields */); } /** * Make a copy of NetworkCapabilities. * * @param nc Original NetworkCapabilities * @param parcelLocationSensitiveFields Whether to parcel location sensitive data or not. * @hide */ @SystemApi public NetworkCapabilities( @Nullable NetworkCapabilities nc, boolean parcelLocationSensitiveFields) { mParcelLocationSensitiveFields = parcelLocationSensitiveFields; if (nc != null) { set(nc); } Loading @@ -93,6 +114,12 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public void clearAll() { // Ensures that the internal copies maintained by the connectivity stack does not set // this bit. if (mParcelLocationSensitiveFields) { throw new UnsupportedOperationException( "Cannot clear NetworkCapabilities when parcelLocationSensitiveFields is set"); } mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0; mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; mNetworkSpecifier = null; Loading @@ -109,6 +136,8 @@ public final class NetworkCapabilities implements Parcelable { /** * Set all contents of this object to the contents of a NetworkCapabilities. * * @param nc Original NetworkCapabilities * @hide */ public void set(@NonNull NetworkCapabilities nc) { Loading @@ -117,7 +146,11 @@ public final class NetworkCapabilities implements Parcelable { mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps; mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps; mNetworkSpecifier = nc.mNetworkSpecifier; mTransportInfo = nc.mTransportInfo; if (nc.getTransportInfo() != null) { setTransportInfo(nc.getTransportInfo().makeCopy(mParcelLocationSensitiveFields)); } else { setTransportInfo(null); } mSignalStrength = nc.mSignalStrength; setUids(nc.mUids); // Will make the defensive copy setAdministratorUids(nc.getAdministratorUids()); Loading
core/java/android/net/TransportInfo.java +38 −0 Original line number Diff line number Diff line Loading @@ -16,10 +16,48 @@ package android.net; import android.annotation.NonNull; import android.annotation.SystemApi; /** * A container for transport-specific capabilities which is returned by * {@link NetworkCapabilities#getTransportInfo()}. Specific networks * may provide concrete implementations of this interface. * @see android.net.wifi.aware.WifiAwareNetworkInfo * @see android.net.wifi.WifiInfo */ public interface TransportInfo { /** * Create a copy of a {@link TransportInfo} that will preserve location sensitive fields that * were set based on the permissions of the process that originally received it. * * <p>By default {@link TransportInfo} does not preserve such fields during parceling, as * they should not be shared outside of the process that receives them without appropriate * checks. * * @param parcelLocationSensitiveFields Whether the location sensitive fields should be kept * when parceling * @return Copy of this instance. * @hide */ @SystemApi @NonNull default TransportInfo makeCopy(boolean parcelLocationSensitiveFields) { return this; } /** * Returns whether this TransportInfo type has location sensitive fields or not (helps * to determine whether to perform a location permission check or not before sending to * apps). * * @return {@code true} if this instance contains location sensitive info, {@code false} * otherwise. * @hide */ @SystemApi default boolean hasLocationSensitiveFields() { return false; } }
services/core/java/com/android/server/ConnectivityService.java +37 −21 Original line number Diff line number Diff line Loading @@ -1569,7 +1569,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (nc != null) { result.put( nai.network, maybeSanitizeLocationInfoForCaller( createWithLocationInfoSanitizedIfNecessaryWhenParceled( nc, mDeps.getCallingUid(), callingPackageName)); } Loading @@ -1579,7 +1579,9 @@ public class ConnectivityService extends IConnectivityManager.Stub for (Network network : networks) { nc = getNetworkCapabilitiesInternal(network); if (nc != null) { result.put(network, maybeSanitizeLocationInfoForCaller( result.put( network, createWithLocationInfoSanitizedIfNecessaryWhenParceled( nc, mDeps.getCallingUid(), callingPackageName)); } } Loading Loading @@ -1661,7 +1663,7 @@ public class ConnectivityService extends IConnectivityManager.Stub public NetworkCapabilities getNetworkCapabilities(Network network, String callingPackageName) { mAppOpsManager.checkPackage(mDeps.getCallingUid(), callingPackageName); enforceAccessPermission(); return maybeSanitizeLocationInfoForCaller( return createWithLocationInfoSanitizedIfNecessaryWhenParceled( getNetworkCapabilitiesInternal(network), mDeps.getCallingUid(), callingPackageName); } Loading @@ -1682,37 +1684,51 @@ public class ConnectivityService extends IConnectivityManager.Stub return newNc; } private boolean hasLocationPermission(int callerUid, @NonNull String callerPkgName) { final long token = Binder.clearCallingIdentity(); try { return mLocationPermissionChecker.checkLocationPermission( callerPkgName, null /* featureId */, callerUid, null /* message */); } finally { Binder.restoreCallingIdentity(token); } } @VisibleForTesting @Nullable NetworkCapabilities maybeSanitizeLocationInfoForCaller( NetworkCapabilities createWithLocationInfoSanitizedIfNecessaryWhenParceled( @Nullable NetworkCapabilities nc, int callerUid, @NonNull String callerPkgName) { if (nc == null) { return null; } final NetworkCapabilities newNc = new NetworkCapabilities(nc); if (callerUid != newNc.getOwnerUid()) { Boolean hasLocationPermission = null; final NetworkCapabilities newNc; // Avoid doing location permission check if the transport info has no location sensitive // data. if (nc.getTransportInfo() != null && nc.getTransportInfo().hasLocationSensitiveFields()) { hasLocationPermission = hasLocationPermission(callerUid, callerPkgName); newNc = new NetworkCapabilities(nc, hasLocationPermission); } else { newNc = new NetworkCapabilities(nc, false /* parcelLocationSensitiveFields */); } // Reset owner uid if not destined for the owner app. if (callerUid != nc.getOwnerUid()) { newNc.setOwnerUid(INVALID_UID); return newNc; } // Allow VPNs to see ownership of their own VPN networks - not location sensitive. if (nc.hasTransport(TRANSPORT_VPN)) { // Owner UIDs already checked above. No need to re-check. return newNc; } final long token = Binder.clearCallingIdentity(); try { if (!mLocationPermissionChecker.checkLocationPermission( callerPkgName, null /* featureId */, callerUid, null /* message */)) { // Caller does not have the requisite location permissions. Reset the // owner's UID in the NetworkCapabilities. newNc.setOwnerUid(INVALID_UID); if (hasLocationPermission == null) { // Location permission not checked yet, check now for masking owner UID. hasLocationPermission = hasLocationPermission(callerUid, callerPkgName); } } finally { Binder.restoreCallingIdentity(token); // Reset owner uid if the app has no location permission. if (!hasLocationPermission) { newNc.setOwnerUid(INVALID_UID); } return newNc; } Loading Loading @@ -6976,7 +6992,7 @@ public class ConnectivityService extends IConnectivityManager.Stub networkAgent.networkCapabilities, nri.mPid, nri.mUid); putParcelable( bundle, maybeSanitizeLocationInfoForCaller( createWithLocationInfoSanitizedIfNecessaryWhenParceled( nc, nri.mUid, nri.request.getRequestorPackageName())); putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions( networkAgent.linkProperties, nri.mPid, nri.mUid)); Loading @@ -6995,7 +7011,7 @@ public class ConnectivityService extends IConnectivityManager.Stub networkAgent.networkCapabilities, nri.mPid, nri.mUid); putParcelable( bundle, maybeSanitizeLocationInfoForCaller( createWithLocationInfoSanitizedIfNecessaryWhenParceled( netCap, nri.mUid, nri.request.getRequestorPackageName())); break; } Loading