Loading api/current.txt +5 −4 Original line number Diff line number Diff line Loading @@ -27167,6 +27167,7 @@ package android.net { public static class ConnectivityManager.NetworkCallback { ctor public ConnectivityManager.NetworkCallback(); method public void onAvailable(android.net.Network); method public void onBlockedStatusChanged(android.net.Network, boolean); method public void onCapabilitiesChanged(android.net.Network, android.net.NetworkCapabilities); method public void onLinkPropertiesChanged(android.net.Network, android.net.LinkProperties); method public void onLosing(android.net.Network, int); Loading Loading @@ -27438,16 +27439,16 @@ package android.net { public class NetworkInfo implements android.os.Parcelable { method public int describeContents(); method public android.net.NetworkInfo.DetailedState getDetailedState(); method public deprecated android.net.NetworkInfo.DetailedState getDetailedState(); method public java.lang.String getExtraInfo(); method public deprecated java.lang.String getReason(); method public deprecated android.net.NetworkInfo.State getState(); method public int getSubtype(); method public java.lang.String getSubtypeName(); method public deprecated int getSubtype(); method public deprecated java.lang.String getSubtypeName(); method public deprecated int getType(); method public deprecated java.lang.String getTypeName(); method public deprecated boolean isAvailable(); method public boolean isConnected(); method public deprecated boolean isConnected(); method public deprecated boolean isConnectedOrConnecting(); method public deprecated boolean isFailover(); method public deprecated boolean isRoaming(); core/java/android/net/ConnectivityManager.java +21 −3 Original line number Diff line number Diff line Loading @@ -2816,10 +2816,11 @@ public class ConnectivityManager { * @param network The {@link Network} of the satisfying network. * @param networkCapabilities The {@link NetworkCapabilities} of the satisfying network. * @param linkProperties The {@link LinkProperties} of the satisfying network. * @param blocked Whether access to the {@link Network} is blocked due to system policy. * @hide */ public void onAvailable(Network network, NetworkCapabilities networkCapabilities, LinkProperties linkProperties) { LinkProperties linkProperties, boolean blocked) { // Internally only this method is called when a new network is available, and // it calls the callback in the same way and order that older versions used // to call so as not to change the behavior. Loading @@ -2830,6 +2831,7 @@ public class ConnectivityManager { } onCapabilitiesChanged(network, networkCapabilities); onLinkPropertiesChanged(network, linkProperties); onBlockedStatusChanged(network, blocked); } /** Loading @@ -2837,7 +2839,8 @@ public class ConnectivityManager { * This callback may be called more than once if the {@link Network} that is * satisfying the request changes. This will always immediately be followed by a * call to {@link #onCapabilitiesChanged(Network, NetworkCapabilities)} then by a * call to {@link #onLinkPropertiesChanged(Network, LinkProperties)}. * call to {@link #onLinkPropertiesChanged(Network, LinkProperties)}, and a call to * {@link #onBlockedStatusChanged(Network, boolean)}. * * @param network The {@link Network} of the satisfying network. */ Loading Loading @@ -2916,6 +2919,14 @@ public class ConnectivityManager { */ public void onNetworkResumed(Network network) {} /** * Called when access to the specified network is blocked or unblocked. * * @param network The {@link Network} whose blocked status has changed. * @param blocked The blocked status of this {@link Network}. */ public void onBlockedStatusChanged(Network network, boolean blocked) {} private NetworkRequest networkRequest; } Loading Loading @@ -2962,6 +2973,8 @@ public class ConnectivityManager { public static final int CALLBACK_SUSPENDED = BASE + 9; /** @hide */ public static final int CALLBACK_RESUMED = BASE + 10; /** @hide */ public static final int CALLBACK_BLK_CHANGED = BASE + 11; /** @hide */ public static String getCallbackName(int whichCallback) { Loading @@ -2976,6 +2989,7 @@ public class ConnectivityManager { case EXPIRE_LEGACY_REQUEST: return "EXPIRE_LEGACY_REQUEST"; case CALLBACK_SUSPENDED: return "CALLBACK_SUSPENDED"; case CALLBACK_RESUMED: return "CALLBACK_RESUMED"; case CALLBACK_BLK_CHANGED: return "CALLBACK_BLK_CHANGED"; default: return Integer.toString(whichCallback); } Loading Loading @@ -3022,7 +3036,7 @@ public class ConnectivityManager { case CALLBACK_AVAILABLE: { NetworkCapabilities cap = getObject(message, NetworkCapabilities.class); LinkProperties lp = getObject(message, LinkProperties.class); callback.onAvailable(network, cap, lp); callback.onAvailable(network, cap, lp, message.arg1 != 0); break; } case CALLBACK_LOSING: { Loading Loading @@ -3055,6 +3069,10 @@ public class ConnectivityManager { callback.onNetworkResumed(network); break; } case CALLBACK_BLK_CHANGED: { boolean blocked = message.arg1 != 0; callback.onBlockedStatusChanged(network, blocked); } } } Loading core/java/android/net/NetworkCapabilities.java +10 −0 Original line number Diff line number Diff line Loading @@ -1589,4 +1589,14 @@ public final class NetworkCapabilities implements Parcelable { Preconditions.checkArgument(isValidCapability(capability), "NetworkCapability " + capability + "out of range"); } /** * Check if this {@code NetworkCapability} instance is metered. * * @return {@code true} if {@code NET_CAPABILITY_NOT_METERED} is not set on this instance. * @hide */ public boolean isMetered() { return !hasCapability(NET_CAPABILITY_NOT_METERED); } } core/java/android/net/NetworkInfo.java +20 −0 Original line number Diff line number Diff line Loading @@ -202,7 +202,9 @@ public class NetworkInfo implements Parcelable { * Return a network-type-specific integer describing the subtype * of the network. * @return the network subtype * @deprecated Use {@link android.telephony.TelephonyManager#getDataNetworkType} instead. */ @Deprecated public int getSubtype() { synchronized (this) { return mSubtype; Loading Loading @@ -243,7 +245,9 @@ public class NetworkInfo implements Parcelable { /** * Return a human-readable name describing the subtype of the network. * @return the name of the network subtype * @deprecated Use {@link android.telephony.TelephonyManager#getDataNetworkType} instead. */ @Deprecated public String getSubtypeName() { synchronized (this) { return mSubtypeName; Loading Loading @@ -278,7 +282,15 @@ public class NetworkInfo implements Parcelable { * connections and pass data. * <p>Always call this before attempting to perform data transactions. * @return {@code true} if network connectivity exists, {@code false} otherwise. * @deprecated Apps should instead use the * {@link android.net.ConnectivityManager.NetworkCallback} API to * learn about connectivity changes. See * {@link ConnectivityManager#registerDefaultNetworkCallback} and * {@link ConnectivityManager#registerNetworkCallback}. These will * give a more accurate picture of the connectivity state of * the device and let apps react more easily and quickly to changes. */ @Deprecated public boolean isConnected() { synchronized (this) { return mState == State.CONNECTED; Loading Loading @@ -411,7 +423,15 @@ public class NetworkInfo implements Parcelable { /** * Reports the current fine-grained state of the network. * @return the fine-grained state * @deprecated Apps should instead use the * {@link android.net.ConnectivityManager.NetworkCallback} API to * learn about connectivity changes. See * {@link ConnectivityManager#registerDefaultNetworkCallback} and * {@link ConnectivityManager#registerNetworkCallback}. These will * give a more accurate picture of the connectivity state of * the device and let apps react more easily and quickly to changes. */ @Deprecated public DetailedState getDetailedState() { synchronized (this) { return mDetailedState; Loading services/core/java/com/android/server/ConnectivityService.java +204 −10 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkPolicyManager.RULE_NONE; import static android.net.NetworkPolicyManager.uidRulesToString; import static android.os.Process.INVALID_UID; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; Loading Loading @@ -189,6 +191,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.ConcurrentModificationException; import java.util.HashMap; import java.util.HashSet; import java.util.List; Loading Loading @@ -257,6 +260,14 @@ public class ConnectivityService extends IConnectivityManager.Stub @GuardedBy("mVpns") private LockdownVpnTracker mLockdownTracker; /** * Stale copy of uid rules provided by NPMS. As long as they are accessed only in internal * handler thread, they don't need a lock. */ private SparseIntArray mUidRules = new SparseIntArray(); /** Flag indicating if background data is restricted. */ private boolean mRestrictBackground; final private Context mContext; // 0 is full bad, 100 is full good private int mDefaultInetConditionPublished = 0; Loading Loading @@ -419,6 +430,16 @@ public class ConnectivityService extends IConnectivityManager.Stub // Handle private DNS validation status updates. private static final int EVENT_PRIVATE_DNS_VALIDATION_UPDATE = 38; /** * Used to handle onUidRulesChanged event from NetworkPolicyManagerService. */ private static final int EVENT_UID_RULES_CHANGED = 39; /** * Used to handle onRestrictBackgroundChanged event from NetworkPolicyManagerService. */ private static final int EVENT_DATA_SAVER_CHANGED = 40; private static String eventName(int what) { return sMagicDecoderRing.get(what, Integer.toString(what)); } Loading Loading @@ -780,6 +801,9 @@ public class ConnectivityService extends IConnectivityManager.Stub mKeyStore = KeyStore.getInstance(); mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); // To ensure uid rules are synchronized with Network Policy, register for // NetworkPolicyManagerService events must happen prior to NetworkPolicyManagerService // reading existing policy from disk. try { mPolicyManager.registerListener(mPolicyListener); } catch (RemoteException e) { Loading Loading @@ -1116,11 +1140,6 @@ public class ConnectivityService extends IConnectivityManager.Stub if (ignoreBlocked) { return false; } // Networks are never blocked for system services // TODO: consider moving this check to NetworkPolicyManagerInternal.isUidNetworkingBlocked. if (isSystem(uid)) { return false; } synchronized (mVpns) { final Vpn vpn = mVpns.get(UserHandle.getUserId(uid)); if (vpn != null && vpn.isBlockingUid(uid)) { Loading Loading @@ -1150,6 +1169,17 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetworkInfoBlockingLogs.log(action + " " + uid); } private void maybeLogBlockedStatusChanged(NetworkRequestInfo nri, Network net, boolean blocked) { if (nri == null || net == null || !LOGD_BLOCKED_NETWORKINFO) { return; } String action = blocked ? "BLOCKED" : "UNBLOCKED"; log(String.format("Blocked status changed to %s for %d(%d) on netId %d", blocked, nri.mUid, nri.request.requestId, net.netId)); mNetworkInfoBlockingLogs.log(action + " " + nri.mUid); } /** * Apply any relevant filters to {@link NetworkState} for the given UID. For * example, this may mark the network as {@link DetailedState#BLOCKED} based Loading Loading @@ -1651,10 +1681,17 @@ public class ConnectivityService extends IConnectivityManager.Stub private final INetworkPolicyListener mPolicyListener = new NetworkPolicyManager.Listener() { @Override public void onUidRulesChanged(int uid, int uidRules) { // TODO: notify UID when it has requested targeted updates mHandler.sendMessage(mHandler.obtainMessage(EVENT_UID_RULES_CHANGED, uid, uidRules)); } @Override public void onRestrictBackgroundChanged(boolean restrictBackground) { // caller is NPMS, since we only register with them if (LOGD_BLOCKED_NETWORKINFO) { log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")"); } mHandler.sendMessage(mHandler.obtainMessage( EVENT_DATA_SAVER_CHANGED, restrictBackground ? 1 : 0, 0)); // TODO: relocate this specific callback in Tethering. if (restrictBackground) { log("onRestrictBackgroundChanged(true): disabling tethering"); Loading @@ -1663,6 +1700,50 @@ public class ConnectivityService extends IConnectivityManager.Stub } }; void handleUidRulesChanged(int uid, int newRules) { // skip update when we've already applied rules final int oldRules = mUidRules.get(uid, RULE_NONE); if (oldRules == newRules) return; maybeNotifyNetworkBlockedForNewUidRules(uid, newRules); if (newRules == RULE_NONE) { mUidRules.delete(uid); } else { mUidRules.put(uid, newRules); } } void handleRestrictBackgroundChanged(boolean restrictBackground) { if (mRestrictBackground == restrictBackground) return; for (final NetworkAgentInfo nai : mNetworkAgentInfos.values()) { final boolean curMetered = nai.networkCapabilities.isMetered(); maybeNotifyNetworkBlocked(nai, curMetered, curMetered, mRestrictBackground, restrictBackground); } mRestrictBackground = restrictBackground; } private boolean isUidNetworkingWithVpnBlocked(int uid, int uidRules, boolean isNetworkMetered, boolean isBackgroundRestricted) { synchronized (mVpns) { final Vpn vpn = mVpns.get(UserHandle.getUserId(uid)); // Because the return value of this function depends on the list of UIDs the // always-on VPN blocks when in lockdown mode, when the always-on VPN changes that // list all state depending on the return value of this function has to be recomputed. // TODO: add a trigger when the always-on VPN sets its blocked UIDs to reevaluate and // send the necessary onBlockedStatusChanged callbacks. if (vpn != null && vpn.isBlockingUid(uid)) { return true; } } return mPolicyManagerInternal.isUidNetworkingBlocked(uid, uidRules, isNetworkMetered, isBackgroundRestricted); } /** * Require that the caller is either in the same user or has appropriate permission to interact * across users. Loading Loading @@ -2118,6 +2199,28 @@ public class ConnectivityService extends IConnectivityManager.Stub pw.decreaseIndent(); pw.println(); pw.print("Restrict background: "); pw.println(mRestrictBackground); pw.println(); pw.println("Status for known UIDs:"); pw.increaseIndent(); final int size = mUidRules.size(); for (int i = 0; i < size; i++) { // Don't crash if the array is modified while dumping in bugreports. try { final int uid = mUidRules.keyAt(i); final int uidRules = mUidRules.get(uid, RULE_NONE); pw.println("UID=" + uid + " rules=" + uidRulesToString(uidRules)); } catch (ArrayIndexOutOfBoundsException e) { pw.println(" ArrayIndexOutOfBoundsException"); } catch (ConcurrentModificationException e) { pw.println(" ConcurrentModificationException"); } } pw.println(); pw.decreaseIndent(); pw.println("Network Requests:"); pw.increaseIndent(); dumpNetworkRequests(pw); Loading Loading @@ -3195,6 +3298,12 @@ public class ConnectivityService extends IConnectivityManager.Stub handlePrivateDnsValidationUpdate( (PrivateDnsValidationUpdate) msg.obj); break; case EVENT_UID_RULES_CHANGED: handleUidRulesChanged(msg.arg1, msg.arg2); break; case EVENT_DATA_SAVER_CHANGED: handleRestrictBackgroundChanged(toBool(msg.arg1)); break; } } } Loading Loading @@ -3783,6 +3892,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private void setLockdownTracker(LockdownVpnTracker tracker) { // Shutdown any existing tracker final LockdownVpnTracker existing = mLockdownTracker; // TODO: Add a trigger when the always-on VPN enable/disable to reevaluate and send the // necessary onBlockedStatusChanged callbacks. mLockdownTracker = null; if (existing != null) { existing.shutdown(); Loading Loading @@ -4893,12 +5004,20 @@ public class ConnectivityService extends IConnectivityManager.Stub notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED); } // Report changes that are interesting for network statistics tracking. if (prevNc != null) { final boolean meteredChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_METERED) != newNc.hasCapability(NET_CAPABILITY_NOT_METERED); final boolean oldMetered = prevNc.isMetered(); final boolean newMetered = newNc.isMetered(); final boolean meteredChanged = oldMetered != newMetered; if (meteredChanged) { maybeNotifyNetworkBlocked(nai, oldMetered, newMetered, mRestrictBackground, mRestrictBackground); } final boolean roamingChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING) != newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING); // Report changes that are interesting for network statistics tracking. if (meteredChanged || roamingChanged) { notifyIfacesChangedForNetworkStats(); } Loading Loading @@ -5028,6 +5147,8 @@ public class ConnectivityService extends IConnectivityManager.Stub case ConnectivityManager.CALLBACK_AVAILABLE: { putParcelable(bundle, new NetworkCapabilities(networkAgent.networkCapabilities)); putParcelable(bundle, new LinkProperties(networkAgent.linkProperties)); // For this notification, arg1 contains the blocked status. msg.arg1 = arg1; break; } case ConnectivityManager.CALLBACK_LOSING: { Loading @@ -5045,6 +5166,10 @@ public class ConnectivityService extends IConnectivityManager.Stub putParcelable(bundle, new LinkProperties(networkAgent.linkProperties)); break; } case ConnectivityManager.CALLBACK_BLK_CHANGED: { msg.arg1 = arg1; break; } } msg.what = notificationType; msg.setData(bundle); Loading Loading @@ -5600,7 +5725,76 @@ public class ConnectivityService extends IConnectivityManager.Stub return; } callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE, 0); final boolean metered = nai.networkCapabilities.isMetered(); final boolean blocked = isUidNetworkingWithVpnBlocked(nri.mUid, mUidRules.get(nri.mUid), metered, mRestrictBackground); callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE, blocked ? 1 : 0); } /** * Notify of the blocked state apps with a registered callback matching a given NAI. * * Unlike other callbacks, blocked status is different between each individual uid. So for * any given nai, all requests need to be considered according to the uid who filed it. * * @param nai The target NetworkAgentInfo. * @param oldMetered True if the previous network capabilities is metered. * @param newRestrictBackground True if data saver is enabled. */ private void maybeNotifyNetworkBlocked(NetworkAgentInfo nai, boolean oldMetered, boolean newMetered, boolean oldRestrictBackground, boolean newRestrictBackground) { for (int i = 0; i < nai.numNetworkRequests(); i++) { NetworkRequest nr = nai.requestAt(i); NetworkRequestInfo nri = mNetworkRequests.get(nr); final int uidRules = mUidRules.get(nri.mUid); final boolean oldBlocked, newBlocked; // mVpns lock needs to be hold here to ensure that the active VPN cannot be changed // between these two calls. synchronized (mVpns) { oldBlocked = isUidNetworkingWithVpnBlocked(nri.mUid, uidRules, oldMetered, oldRestrictBackground); newBlocked = isUidNetworkingWithVpnBlocked(nri.mUid, uidRules, newMetered, newRestrictBackground); } if (oldBlocked != newBlocked) { callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_BLK_CHANGED, encodeBool(newBlocked)); } } } /** * Notify apps with a given UID of the new blocked state according to new uid rules. * @param uid The uid for which the rules changed. * @param newRules The new rules to apply. */ private void maybeNotifyNetworkBlockedForNewUidRules(int uid, int newRules) { for (final NetworkAgentInfo nai : mNetworkAgentInfos.values()) { final boolean metered = nai.networkCapabilities.isMetered(); final boolean oldBlocked, newBlocked; // TODO: Consider that doze mode or turn on/off battery saver would deliver lots of uid // rules changed event. And this function actually loop through all connected nai and // its requests. It seems that mVpns lock will be grabbed frequently in this case. // Reduce the number of locking or optimize the use of lock are likely needed in future. synchronized (mVpns) { oldBlocked = isUidNetworkingWithVpnBlocked( uid, mUidRules.get(uid), metered, mRestrictBackground); newBlocked = isUidNetworkingWithVpnBlocked( uid, newRules, metered, mRestrictBackground); } if (oldBlocked == newBlocked) { return; } final int arg = encodeBool(newBlocked); for (int i = 0; i < nai.numNetworkRequests(); i++) { NetworkRequest nr = nai.requestAt(i); NetworkRequestInfo nri = mNetworkRequests.get(nr); if (nri != null && nri.mUid == uid) { callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_BLK_CHANGED, arg); } } } } private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type) { Loading Loading
api/current.txt +5 −4 Original line number Diff line number Diff line Loading @@ -27167,6 +27167,7 @@ package android.net { public static class ConnectivityManager.NetworkCallback { ctor public ConnectivityManager.NetworkCallback(); method public void onAvailable(android.net.Network); method public void onBlockedStatusChanged(android.net.Network, boolean); method public void onCapabilitiesChanged(android.net.Network, android.net.NetworkCapabilities); method public void onLinkPropertiesChanged(android.net.Network, android.net.LinkProperties); method public void onLosing(android.net.Network, int); Loading Loading @@ -27438,16 +27439,16 @@ package android.net { public class NetworkInfo implements android.os.Parcelable { method public int describeContents(); method public android.net.NetworkInfo.DetailedState getDetailedState(); method public deprecated android.net.NetworkInfo.DetailedState getDetailedState(); method public java.lang.String getExtraInfo(); method public deprecated java.lang.String getReason(); method public deprecated android.net.NetworkInfo.State getState(); method public int getSubtype(); method public java.lang.String getSubtypeName(); method public deprecated int getSubtype(); method public deprecated java.lang.String getSubtypeName(); method public deprecated int getType(); method public deprecated java.lang.String getTypeName(); method public deprecated boolean isAvailable(); method public boolean isConnected(); method public deprecated boolean isConnected(); method public deprecated boolean isConnectedOrConnecting(); method public deprecated boolean isFailover(); method public deprecated boolean isRoaming();
core/java/android/net/ConnectivityManager.java +21 −3 Original line number Diff line number Diff line Loading @@ -2816,10 +2816,11 @@ public class ConnectivityManager { * @param network The {@link Network} of the satisfying network. * @param networkCapabilities The {@link NetworkCapabilities} of the satisfying network. * @param linkProperties The {@link LinkProperties} of the satisfying network. * @param blocked Whether access to the {@link Network} is blocked due to system policy. * @hide */ public void onAvailable(Network network, NetworkCapabilities networkCapabilities, LinkProperties linkProperties) { LinkProperties linkProperties, boolean blocked) { // Internally only this method is called when a new network is available, and // it calls the callback in the same way and order that older versions used // to call so as not to change the behavior. Loading @@ -2830,6 +2831,7 @@ public class ConnectivityManager { } onCapabilitiesChanged(network, networkCapabilities); onLinkPropertiesChanged(network, linkProperties); onBlockedStatusChanged(network, blocked); } /** Loading @@ -2837,7 +2839,8 @@ public class ConnectivityManager { * This callback may be called more than once if the {@link Network} that is * satisfying the request changes. This will always immediately be followed by a * call to {@link #onCapabilitiesChanged(Network, NetworkCapabilities)} then by a * call to {@link #onLinkPropertiesChanged(Network, LinkProperties)}. * call to {@link #onLinkPropertiesChanged(Network, LinkProperties)}, and a call to * {@link #onBlockedStatusChanged(Network, boolean)}. * * @param network The {@link Network} of the satisfying network. */ Loading Loading @@ -2916,6 +2919,14 @@ public class ConnectivityManager { */ public void onNetworkResumed(Network network) {} /** * Called when access to the specified network is blocked or unblocked. * * @param network The {@link Network} whose blocked status has changed. * @param blocked The blocked status of this {@link Network}. */ public void onBlockedStatusChanged(Network network, boolean blocked) {} private NetworkRequest networkRequest; } Loading Loading @@ -2962,6 +2973,8 @@ public class ConnectivityManager { public static final int CALLBACK_SUSPENDED = BASE + 9; /** @hide */ public static final int CALLBACK_RESUMED = BASE + 10; /** @hide */ public static final int CALLBACK_BLK_CHANGED = BASE + 11; /** @hide */ public static String getCallbackName(int whichCallback) { Loading @@ -2976,6 +2989,7 @@ public class ConnectivityManager { case EXPIRE_LEGACY_REQUEST: return "EXPIRE_LEGACY_REQUEST"; case CALLBACK_SUSPENDED: return "CALLBACK_SUSPENDED"; case CALLBACK_RESUMED: return "CALLBACK_RESUMED"; case CALLBACK_BLK_CHANGED: return "CALLBACK_BLK_CHANGED"; default: return Integer.toString(whichCallback); } Loading Loading @@ -3022,7 +3036,7 @@ public class ConnectivityManager { case CALLBACK_AVAILABLE: { NetworkCapabilities cap = getObject(message, NetworkCapabilities.class); LinkProperties lp = getObject(message, LinkProperties.class); callback.onAvailable(network, cap, lp); callback.onAvailable(network, cap, lp, message.arg1 != 0); break; } case CALLBACK_LOSING: { Loading Loading @@ -3055,6 +3069,10 @@ public class ConnectivityManager { callback.onNetworkResumed(network); break; } case CALLBACK_BLK_CHANGED: { boolean blocked = message.arg1 != 0; callback.onBlockedStatusChanged(network, blocked); } } } Loading
core/java/android/net/NetworkCapabilities.java +10 −0 Original line number Diff line number Diff line Loading @@ -1589,4 +1589,14 @@ public final class NetworkCapabilities implements Parcelable { Preconditions.checkArgument(isValidCapability(capability), "NetworkCapability " + capability + "out of range"); } /** * Check if this {@code NetworkCapability} instance is metered. * * @return {@code true} if {@code NET_CAPABILITY_NOT_METERED} is not set on this instance. * @hide */ public boolean isMetered() { return !hasCapability(NET_CAPABILITY_NOT_METERED); } }
core/java/android/net/NetworkInfo.java +20 −0 Original line number Diff line number Diff line Loading @@ -202,7 +202,9 @@ public class NetworkInfo implements Parcelable { * Return a network-type-specific integer describing the subtype * of the network. * @return the network subtype * @deprecated Use {@link android.telephony.TelephonyManager#getDataNetworkType} instead. */ @Deprecated public int getSubtype() { synchronized (this) { return mSubtype; Loading Loading @@ -243,7 +245,9 @@ public class NetworkInfo implements Parcelable { /** * Return a human-readable name describing the subtype of the network. * @return the name of the network subtype * @deprecated Use {@link android.telephony.TelephonyManager#getDataNetworkType} instead. */ @Deprecated public String getSubtypeName() { synchronized (this) { return mSubtypeName; Loading Loading @@ -278,7 +282,15 @@ public class NetworkInfo implements Parcelable { * connections and pass data. * <p>Always call this before attempting to perform data transactions. * @return {@code true} if network connectivity exists, {@code false} otherwise. * @deprecated Apps should instead use the * {@link android.net.ConnectivityManager.NetworkCallback} API to * learn about connectivity changes. See * {@link ConnectivityManager#registerDefaultNetworkCallback} and * {@link ConnectivityManager#registerNetworkCallback}. These will * give a more accurate picture of the connectivity state of * the device and let apps react more easily and quickly to changes. */ @Deprecated public boolean isConnected() { synchronized (this) { return mState == State.CONNECTED; Loading Loading @@ -411,7 +423,15 @@ public class NetworkInfo implements Parcelable { /** * Reports the current fine-grained state of the network. * @return the fine-grained state * @deprecated Apps should instead use the * {@link android.net.ConnectivityManager.NetworkCallback} API to * learn about connectivity changes. See * {@link ConnectivityManager#registerDefaultNetworkCallback} and * {@link ConnectivityManager#registerNetworkCallback}. These will * give a more accurate picture of the connectivity state of * the device and let apps react more easily and quickly to changes. */ @Deprecated public DetailedState getDetailedState() { synchronized (this) { return mDetailedState; Loading
services/core/java/com/android/server/ConnectivityService.java +204 −10 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkPolicyManager.RULE_NONE; import static android.net.NetworkPolicyManager.uidRulesToString; import static android.os.Process.INVALID_UID; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; Loading Loading @@ -189,6 +191,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.ConcurrentModificationException; import java.util.HashMap; import java.util.HashSet; import java.util.List; Loading Loading @@ -257,6 +260,14 @@ public class ConnectivityService extends IConnectivityManager.Stub @GuardedBy("mVpns") private LockdownVpnTracker mLockdownTracker; /** * Stale copy of uid rules provided by NPMS. As long as they are accessed only in internal * handler thread, they don't need a lock. */ private SparseIntArray mUidRules = new SparseIntArray(); /** Flag indicating if background data is restricted. */ private boolean mRestrictBackground; final private Context mContext; // 0 is full bad, 100 is full good private int mDefaultInetConditionPublished = 0; Loading Loading @@ -419,6 +430,16 @@ public class ConnectivityService extends IConnectivityManager.Stub // Handle private DNS validation status updates. private static final int EVENT_PRIVATE_DNS_VALIDATION_UPDATE = 38; /** * Used to handle onUidRulesChanged event from NetworkPolicyManagerService. */ private static final int EVENT_UID_RULES_CHANGED = 39; /** * Used to handle onRestrictBackgroundChanged event from NetworkPolicyManagerService. */ private static final int EVENT_DATA_SAVER_CHANGED = 40; private static String eventName(int what) { return sMagicDecoderRing.get(what, Integer.toString(what)); } Loading Loading @@ -780,6 +801,9 @@ public class ConnectivityService extends IConnectivityManager.Stub mKeyStore = KeyStore.getInstance(); mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); // To ensure uid rules are synchronized with Network Policy, register for // NetworkPolicyManagerService events must happen prior to NetworkPolicyManagerService // reading existing policy from disk. try { mPolicyManager.registerListener(mPolicyListener); } catch (RemoteException e) { Loading Loading @@ -1116,11 +1140,6 @@ public class ConnectivityService extends IConnectivityManager.Stub if (ignoreBlocked) { return false; } // Networks are never blocked for system services // TODO: consider moving this check to NetworkPolicyManagerInternal.isUidNetworkingBlocked. if (isSystem(uid)) { return false; } synchronized (mVpns) { final Vpn vpn = mVpns.get(UserHandle.getUserId(uid)); if (vpn != null && vpn.isBlockingUid(uid)) { Loading Loading @@ -1150,6 +1169,17 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetworkInfoBlockingLogs.log(action + " " + uid); } private void maybeLogBlockedStatusChanged(NetworkRequestInfo nri, Network net, boolean blocked) { if (nri == null || net == null || !LOGD_BLOCKED_NETWORKINFO) { return; } String action = blocked ? "BLOCKED" : "UNBLOCKED"; log(String.format("Blocked status changed to %s for %d(%d) on netId %d", blocked, nri.mUid, nri.request.requestId, net.netId)); mNetworkInfoBlockingLogs.log(action + " " + nri.mUid); } /** * Apply any relevant filters to {@link NetworkState} for the given UID. For * example, this may mark the network as {@link DetailedState#BLOCKED} based Loading Loading @@ -1651,10 +1681,17 @@ public class ConnectivityService extends IConnectivityManager.Stub private final INetworkPolicyListener mPolicyListener = new NetworkPolicyManager.Listener() { @Override public void onUidRulesChanged(int uid, int uidRules) { // TODO: notify UID when it has requested targeted updates mHandler.sendMessage(mHandler.obtainMessage(EVENT_UID_RULES_CHANGED, uid, uidRules)); } @Override public void onRestrictBackgroundChanged(boolean restrictBackground) { // caller is NPMS, since we only register with them if (LOGD_BLOCKED_NETWORKINFO) { log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")"); } mHandler.sendMessage(mHandler.obtainMessage( EVENT_DATA_SAVER_CHANGED, restrictBackground ? 1 : 0, 0)); // TODO: relocate this specific callback in Tethering. if (restrictBackground) { log("onRestrictBackgroundChanged(true): disabling tethering"); Loading @@ -1663,6 +1700,50 @@ public class ConnectivityService extends IConnectivityManager.Stub } }; void handleUidRulesChanged(int uid, int newRules) { // skip update when we've already applied rules final int oldRules = mUidRules.get(uid, RULE_NONE); if (oldRules == newRules) return; maybeNotifyNetworkBlockedForNewUidRules(uid, newRules); if (newRules == RULE_NONE) { mUidRules.delete(uid); } else { mUidRules.put(uid, newRules); } } void handleRestrictBackgroundChanged(boolean restrictBackground) { if (mRestrictBackground == restrictBackground) return; for (final NetworkAgentInfo nai : mNetworkAgentInfos.values()) { final boolean curMetered = nai.networkCapabilities.isMetered(); maybeNotifyNetworkBlocked(nai, curMetered, curMetered, mRestrictBackground, restrictBackground); } mRestrictBackground = restrictBackground; } private boolean isUidNetworkingWithVpnBlocked(int uid, int uidRules, boolean isNetworkMetered, boolean isBackgroundRestricted) { synchronized (mVpns) { final Vpn vpn = mVpns.get(UserHandle.getUserId(uid)); // Because the return value of this function depends on the list of UIDs the // always-on VPN blocks when in lockdown mode, when the always-on VPN changes that // list all state depending on the return value of this function has to be recomputed. // TODO: add a trigger when the always-on VPN sets its blocked UIDs to reevaluate and // send the necessary onBlockedStatusChanged callbacks. if (vpn != null && vpn.isBlockingUid(uid)) { return true; } } return mPolicyManagerInternal.isUidNetworkingBlocked(uid, uidRules, isNetworkMetered, isBackgroundRestricted); } /** * Require that the caller is either in the same user or has appropriate permission to interact * across users. Loading Loading @@ -2118,6 +2199,28 @@ public class ConnectivityService extends IConnectivityManager.Stub pw.decreaseIndent(); pw.println(); pw.print("Restrict background: "); pw.println(mRestrictBackground); pw.println(); pw.println("Status for known UIDs:"); pw.increaseIndent(); final int size = mUidRules.size(); for (int i = 0; i < size; i++) { // Don't crash if the array is modified while dumping in bugreports. try { final int uid = mUidRules.keyAt(i); final int uidRules = mUidRules.get(uid, RULE_NONE); pw.println("UID=" + uid + " rules=" + uidRulesToString(uidRules)); } catch (ArrayIndexOutOfBoundsException e) { pw.println(" ArrayIndexOutOfBoundsException"); } catch (ConcurrentModificationException e) { pw.println(" ConcurrentModificationException"); } } pw.println(); pw.decreaseIndent(); pw.println("Network Requests:"); pw.increaseIndent(); dumpNetworkRequests(pw); Loading Loading @@ -3195,6 +3298,12 @@ public class ConnectivityService extends IConnectivityManager.Stub handlePrivateDnsValidationUpdate( (PrivateDnsValidationUpdate) msg.obj); break; case EVENT_UID_RULES_CHANGED: handleUidRulesChanged(msg.arg1, msg.arg2); break; case EVENT_DATA_SAVER_CHANGED: handleRestrictBackgroundChanged(toBool(msg.arg1)); break; } } } Loading Loading @@ -3783,6 +3892,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private void setLockdownTracker(LockdownVpnTracker tracker) { // Shutdown any existing tracker final LockdownVpnTracker existing = mLockdownTracker; // TODO: Add a trigger when the always-on VPN enable/disable to reevaluate and send the // necessary onBlockedStatusChanged callbacks. mLockdownTracker = null; if (existing != null) { existing.shutdown(); Loading Loading @@ -4893,12 +5004,20 @@ public class ConnectivityService extends IConnectivityManager.Stub notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED); } // Report changes that are interesting for network statistics tracking. if (prevNc != null) { final boolean meteredChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_METERED) != newNc.hasCapability(NET_CAPABILITY_NOT_METERED); final boolean oldMetered = prevNc.isMetered(); final boolean newMetered = newNc.isMetered(); final boolean meteredChanged = oldMetered != newMetered; if (meteredChanged) { maybeNotifyNetworkBlocked(nai, oldMetered, newMetered, mRestrictBackground, mRestrictBackground); } final boolean roamingChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING) != newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING); // Report changes that are interesting for network statistics tracking. if (meteredChanged || roamingChanged) { notifyIfacesChangedForNetworkStats(); } Loading Loading @@ -5028,6 +5147,8 @@ public class ConnectivityService extends IConnectivityManager.Stub case ConnectivityManager.CALLBACK_AVAILABLE: { putParcelable(bundle, new NetworkCapabilities(networkAgent.networkCapabilities)); putParcelable(bundle, new LinkProperties(networkAgent.linkProperties)); // For this notification, arg1 contains the blocked status. msg.arg1 = arg1; break; } case ConnectivityManager.CALLBACK_LOSING: { Loading @@ -5045,6 +5166,10 @@ public class ConnectivityService extends IConnectivityManager.Stub putParcelable(bundle, new LinkProperties(networkAgent.linkProperties)); break; } case ConnectivityManager.CALLBACK_BLK_CHANGED: { msg.arg1 = arg1; break; } } msg.what = notificationType; msg.setData(bundle); Loading Loading @@ -5600,7 +5725,76 @@ public class ConnectivityService extends IConnectivityManager.Stub return; } callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE, 0); final boolean metered = nai.networkCapabilities.isMetered(); final boolean blocked = isUidNetworkingWithVpnBlocked(nri.mUid, mUidRules.get(nri.mUid), metered, mRestrictBackground); callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE, blocked ? 1 : 0); } /** * Notify of the blocked state apps with a registered callback matching a given NAI. * * Unlike other callbacks, blocked status is different between each individual uid. So for * any given nai, all requests need to be considered according to the uid who filed it. * * @param nai The target NetworkAgentInfo. * @param oldMetered True if the previous network capabilities is metered. * @param newRestrictBackground True if data saver is enabled. */ private void maybeNotifyNetworkBlocked(NetworkAgentInfo nai, boolean oldMetered, boolean newMetered, boolean oldRestrictBackground, boolean newRestrictBackground) { for (int i = 0; i < nai.numNetworkRequests(); i++) { NetworkRequest nr = nai.requestAt(i); NetworkRequestInfo nri = mNetworkRequests.get(nr); final int uidRules = mUidRules.get(nri.mUid); final boolean oldBlocked, newBlocked; // mVpns lock needs to be hold here to ensure that the active VPN cannot be changed // between these two calls. synchronized (mVpns) { oldBlocked = isUidNetworkingWithVpnBlocked(nri.mUid, uidRules, oldMetered, oldRestrictBackground); newBlocked = isUidNetworkingWithVpnBlocked(nri.mUid, uidRules, newMetered, newRestrictBackground); } if (oldBlocked != newBlocked) { callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_BLK_CHANGED, encodeBool(newBlocked)); } } } /** * Notify apps with a given UID of the new blocked state according to new uid rules. * @param uid The uid for which the rules changed. * @param newRules The new rules to apply. */ private void maybeNotifyNetworkBlockedForNewUidRules(int uid, int newRules) { for (final NetworkAgentInfo nai : mNetworkAgentInfos.values()) { final boolean metered = nai.networkCapabilities.isMetered(); final boolean oldBlocked, newBlocked; // TODO: Consider that doze mode or turn on/off battery saver would deliver lots of uid // rules changed event. And this function actually loop through all connected nai and // its requests. It seems that mVpns lock will be grabbed frequently in this case. // Reduce the number of locking or optimize the use of lock are likely needed in future. synchronized (mVpns) { oldBlocked = isUidNetworkingWithVpnBlocked( uid, mUidRules.get(uid), metered, mRestrictBackground); newBlocked = isUidNetworkingWithVpnBlocked( uid, newRules, metered, mRestrictBackground); } if (oldBlocked == newBlocked) { return; } final int arg = encodeBool(newBlocked); for (int i = 0; i < nai.numNetworkRequests(); i++) { NetworkRequest nr = nai.requestAt(i); NetworkRequestInfo nri = mNetworkRequests.get(nr); if (nri != null && nri.mUid == uid) { callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_BLK_CHANGED, arg); } } } } private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type) { Loading